import type { Band, ReadinessState } from './types' export const clearanceLabel: Record = { unknown: 'Unknown', none: 'None', confidential: 'Confidential', secret: 'Secret', top_secret: 'Top Secret', ts_sci: 'TS/SCI', } export const statusLabel: Record = { unknown: 'Unknown', active: 'Active', expired: 'Expired', inactive: 'Inactive', } export function bandColor(band: Band): string { return band === 'green' ? 'var(--color-ok)' : band === 'yellow' ? 'var(--color-warn)' : 'var(--color-risk)' } // winImpactColor maps the Win Impact level to a theme color: gold for HIGH, blue for MEDIUM, muted // for LOW. export function winImpactColor(level: string): string { return level === 'HIGH' ? 'var(--color-gold)' : level === 'MEDIUM' ? 'var(--color-blue)' : 'var(--color-muted)' } // proposalColor maps the Proposal Ready gate to a theme color: green for YES, orange for REVIEW. export function proposalColor(value: string): string { return value === 'YES' ? 'var(--color-ok)' : 'var(--color-warn)' } // missionRecColor maps the Mission Check advisory to a band color. DO NOT SUBMIT is the red default. export function missionRecColor(value: string): string { if (value === 'SUBMIT') return 'var(--color-ok)' if (value === 'REVIEW') return 'var(--color-warn)' return 'var(--color-risk)' } export function stateColor(s: ReadinessState): string { return s === 'ready' ? 'var(--color-ok)' : s === 'partial' ? 'var(--color-warn)' : 'var(--color-risk)' } export function num(s: string): number { const n = Number(s) return Number.isFinite(n) ? n : 0 } // flagRatio colors a four fifths impact ratio: risk red below 0.80, ok green at or above. A non // numeric ratio (the value n/a for the unknown bucket) renders muted. export function flagRatio(ratio: string): string { const n = Number(ratio) if (!Number.isFinite(n)) return 'var(--color-muted)' return n < 0.8 ? 'var(--color-risk)' : 'var(--color-ok)' } // timeAgo renders a coarse relative time for the "synced {relative}" badge. export function timeAgo(iso: string): string { if (!iso) return 'never' const t = new Date(iso).getTime() if (!Number.isFinite(t)) return 'never' const s = Math.max(0, Math.floor((Date.now() - t) / 1000)) if (s < 60) return 'just now' const m = Math.floor(s / 60) if (m < 60) return `${m}m ago` const h = Math.floor(m / 60) if (h < 24) return `${h}h ago` const d = Math.floor(h / 24) return d === 1 ? 'yesterday' : `${d}d ago` } // fmtDate renders an ISO date or datetime as e.g. "Jul 15, 2026" (or "n/a" when empty or invalid). export function fmtDate(iso: string): string { if (!iso) return 'n/a' const d = new Date(iso) if (Number.isNaN(d.getTime())) return 'n/a' return d.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }) } // fmtUSD renders a dollar string compactly, for example "$2.50B", "$31.2M", or "$840K". It is the one // money formatter for the app; an absent or zero value renders as n/a. export function fmtUSD(s: string | null | undefined): string { if (!s) return 'n/a' const n = Number(s) if (!Number.isFinite(n) || n === 0) return 'n/a' if (n >= 1_000_000_000) return '$' + (n / 1_000_000_000).toFixed(2) + 'B' if (n >= 1_000_000) return '$' + (n / 1_000_000).toFixed(1) + 'M' if (n >= 1_000) return '$' + Math.round(n / 1_000) + 'K' return '$' + Math.round(n) } // Galapagos Federal Systems demo profile, defaults the opportunity feed to relevant federal work. export const GALAPAGOS = { naics: ['541511', '541512', '541513', '541519', '541330', '541690', '517410'], states: ['HI', 'NM'], setAside: ['8A'], departments: ['DEPT OF DEFENSE'], subAgencies: ['AIR FORCE', 'SPACE FORCE'], } as const export const NAICS_LABELS: Record = { '541511': 'Custom Programming', '541512': 'Computer Systems Design', '541513': 'Computer Facilities Mgmt', '541519': 'Other Computer Services', '541330': 'Engineering Services', '541690': 'Technical Consulting', '517410': 'Satellite Telecom', }