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
66 lines
2.9 KiB
TypeScript
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, " ");
|
|
}
|