WFDASH-WEBAPP/src/lib/quote-status.ts
SJCoetz 7f924ccc45 refactor: switch hardcoded UI colors to semantic theme tokens
Overhaul the app's color system by replacing all hardcoded Tailwind color classes with semantic theme variables to ensure consistent theming across all components, pages, and tests.

Additional changes:
- Add assigned date support for order item status updates: add `assignedDate` field to the order item status PATCH API, implement server-side normalization/validation, and add corresponding tests
- Refactor purchase order PDF workflows to use the consolidated `purchase_orders.documents` field instead of the legacy separate `purchase_order_pdfs` collection
- Fix quote number parsing and formatting to support both dashed (Q-YYYY-MM-NNN) and dashless (QYYYYMMNNN) formats
- Rename `driver_pool` item status to `collection_pool` across the codebase
- Add null handling for order item quantities and pricing to display "—" for missing values
- Improve filter tab styling: make mobile tabs scrollable, prevent text wrapping, hide scrollbar
- Add new utility scripts, API routes, migrations, and polish small UI/UX fixes including tsconfig updates and theme hook improvements
2026-07-07 17:22:03 +02:00

66 lines
2.9 KiB
TypeScript

/**
* Theme-driven status palettes. Every entry uses semantic tokens
* (--info / --warn / --success / --destructive) so the colour
* palette follows the active theme — switching from crisp→nvidia→neon
* changes which exact hue "approved" renders as, but the *meaning*
* (success = green, warning = amber, etc.) stays consistent.
*
* Keeping the semantic names intentional: they're named after what
* the status MEANS to the operator, not after a Tailwind palette
* name. That way the suite works across every theme in the picker.
*/
const quoteStatusClasses: Record<string, string> = {
// In-flight / awaiting further action — info (cool blue)
new: "border-info/30 bg-info/10 text-info",
claimed: "border-info/30 bg-info/10 text-info",
processed: "border-info/30 bg-info/10 text-info",
emailed: "border-info/30 bg-info/10 text-info",
sending: "border-info/40 bg-info/15 text-info",
template: "border-info/30 bg-info/10 text-info",
// Soft warning — needs operator attention soon
approval_pending: "border-warn/40 bg-warn/15 text-warn-foreground",
follow_up: "border-warn/40 bg-warn/15 text-warn-foreground",
// Terminal-positive
approved: "border-success/30 bg-success/10 text-success",
complete: "border-success/30 bg-success/10 text-success",
// Terminal-negative
rejected: "border-destructive/30 bg-destructive/10 text-destructive",
email_failed: "border-destructive/30 bg-destructive/10 text-destructive",
mail_failed: "border-destructive/40 bg-destructive/15 text-destructive",
unmatched_bounce: "border-destructive/30 bg-destructive/10 text-destructive",
problem: "border-destructive/30 bg-destructive/10 text-destructive",
// Neutral terminal
cancelled: "border-muted bg-muted text-muted-foreground",
};
export function quoteStatusClassName(status: string) {
return quoteStatusClasses[status] || "border-muted bg-muted text-muted-foreground";
}
/**
* Human-friendly status label. Most statuses just replace underscores
* with spaces ("approval_pending" → "approval pending"), but a handful
* of legacy PB status strings render better with bespoke labels so the
* operator reads them as workflow states rather than raw enum values:
*
* emailed → "Awaiting reply"
* (the email was sent to the customer; we're waiting for them to come back.
* The legacy enum `emailed` doesn't read like a state on its own.)
* sending → "Sending…"
* (transient — outbound send in flight, n8n is processing.)
* follow_up → "Follow up"
* (just title-case it for nicer rendering.)
*/
const STATUS_LABELS: Record<string, string> = {
emailed: "Awaiting reply",
sending: "Sending…",
follow_up: "Follow up",
approval_pending: "Pending approval",
unmatched_bounce: "Unmatched bounce",
email_failed: "Email failed",
mail_failed: "Mail failed",
};
export function formatQuoteStatus(status: string) {
return STATUS_LABELS[status] || status.replace(/_/g, " ");
}