1// ============================================================================ 2// Tender state iconography â Stage-8 V5 (Dan's ruling, 2026-07-09). 3// THE canonical map: every tenders-module status gets a PAIRED icon + badge 4// class + label, defined ONCE. The calendar formula: color to FIND, icon+text 5// to CONFIRM â badges render icon+text so the eye scans shape before words, 6// and colorblind users lose the shortcut but never the meaning. 7// 8// Consumers spread the entry into their row objects: 9// const s = tenderStatus('bidShortlisted'); 10// row.statusLabel = s.label; row.statusClass = s.cls; row.statusIcon = s.icon; 11// Templates render: <span class="badge-st {{:statusClass}}"> 12// {{if statusIcon}}<i data-lucide="{{:statusIcon}}"></i>{{/if}}{{:statusLabel}} 13// </span> 14// Badge svg sizing lives on the .badge-st family in tailwind.css. 15// Do NOT hand-roll statusâclass maps in page modules â extend THIS map. 16// ============================================================================ 17 18export const TENDER_STATUS = { 19 // Tender lifecycle (list cards + the dashboard's derived status) 20 active: { label: 'Active', icon: 'gavel', cls: 'badge-st-success' }, 21 open: { label: 'Open', icon: 'gavel', cls: 'badge-st-info' }, 22 draft: { label: 'Draft', icon: 'pencil', cls: 'badge-st-secondary' }, 23 review: { label: 'Under Review', icon: 'hourglass', cls: 'badge-st-warning' }, 24 awarded: { label: 'Awarded', icon: 'trophy', cls: 'badge-st-success' }, 25 closed: { label: 'Closed', icon: 'flag', cls: 'badge-st-secondary' }, 26 archived: { label: 'Archived', icon: 'archive', cls: 'badge-st-error' }, 27 28 // Bid lifecycle (admin labels = the shipped E6 wording; portal re-words via its own register) 29 bidReceived: { label: 'Received', icon: 'inbox', cls: 'badge-st-secondary' }, 30 bidUnderReview: { label: 'Under Review',icon: 'hourglass', cls: 'badge-st-warning' }, 31 bidShortlisted: { label: 'Shortlisted', icon: 'star', cls: 'badge-st-info' }, 32 bidWon: { label: 'Won', icon: 'trophy', cls: 'badge-st-success' }, // E6 â set only via the Award action 33 bidLost: { label: 'Lost', icon: 'x', cls: 'badge-st-secondary' },// E6 â muted, not an error: simply out 34 assembling: { label: 'Assembling', icon: 'hammer', cls: 'badge-st-secondary' }, 35 late: { label: 'Late', icon: 'clock', cls: 'badge-st-error' }, 36 37 // Clarifications 38 tcOpen: { label: 'Open', icon: 'message-circle', cls: 'badge-st-warning' }, 39 tcAnswered: { label: 'Answered', icon: 'check-circle-2', cls: 'badge-st-success' }, 40 tcAddendum: { label: 'Addendum Issued', icon: 'file-plus', cls: 'badge-st-info' }, 41 42 // Invites / confirm answers (roster + invites tab share these) 43 invConfirmed: { label: 'Confirmed', icon: 'check', cls: 'badge-st-success' }, 44 invDeclined: { label: 'Declined', icon: 'x', cls: 'badge-st-error' }, 45 invMaybe: { label: 'Maybe', icon: 'help-circle', cls: 'badge-st-warning' }, 46 invSent: { label: 'Sent', icon: 'mail', cls: 'badge-st-info' }, 47 invPending: { label: 'Pending', icon: 'clock', cls: 'badge-st-secondary' }, 48 invBounced: { label: 'Bounced', icon: 'mail-x', cls: 'badge-st-error' }, 49 50 // Portal register (Stage-8 sweep) â the bidder-facing wording EXACTLY as shipped 51 // (labels/colors unchanged; V5 adds the icon channel). Consumed by portal-format.js 52 // + portal-tender-detail.js â the portal hand-rolled maps are dead. 53 pInvited: { label: 'Invited', icon: 'mail', cls: 'badge-st-warning' }, 54 pBidding: { label: 'Bidding', icon: 'hammer', cls: 'badge-st-info' }, 55 pSubmitted: { label: 'Submitted', icon: 'send', cls: 'badge-st-info' }, 56 pDeclined: { label: 'Declined', icon: 'x', cls: 'badge-st-secondary' }, 57 pAwarded: { label: 'Awarded', icon: 'trophy', cls: 'badge-st-success' }, 58 pUnsuccessful: { label: 'Unsuccessful', icon: 'x', cls: 'badge-st-secondary' }, 59 pBidInProgress: { label: 'Bid in progress', icon: 'hammer', cls: 'badge-st-warning' }, 60 pBidSubmitted: { label: 'Bid submitted', icon: 'send', cls: 'badge-st-success' }, 61 pShortlisted: { label: 'Shortlisted', icon: 'star', cls: 'badge-st-info' }, 62 pBidReceived: { label: 'Received', icon: 'inbox', cls: 'badge-st-success' }, 63 pBidUnderReview: { label: 'Under review', icon: 'hourglass', cls: 'badge-st-warning' }, 64 pConfirmYes: { label: 'Bidding', icon: 'check', cls: 'badge-st-success' }, 65 pConfirmMaybe: { label: 'Maybe', icon: 'help-circle', cls: 'badge-st-warning' }, 66 pConfirmNo: { label: 'Not bidding', icon: 'x', cls: 'badge-st-secondary' }, 67 pConfirmNone: { label: 'Not answered', icon: 'clock', cls: 'badge-st-info' }, 68 pTcAwaiting: { label: 'Awaiting answer', icon: 'message-circle', cls: 'badge-st-warning' }, 69 pTcAnswered: { label: 'Answered', icon: 'check-circle-2', cls: 'badge-st-success' }, 70 pTcAddendum: { label: 'Addendum issued', icon: 'file-plus', cls: 'badge-st-info' }, 71}; 72 73// Lookup with a safe neutral fallback (unknown key renders as a plain gray badge). 74export function tenderStatus(key) { 75 return TENDER_STATUS[key] || { label: String(key ?? 'â'), icon: null, cls: 'badge-st-secondary' }; 76} 77 78// Convenience: the three template fields in one spread-ready object. 79export function statusFields(key) { 80 const s = tenderStatus(key); 81 return { statusLabel: s.label, statusClass: s.cls, statusIcon: s.icon }; 82}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.