/** * Single source of truth for document status labels (Czech) + chip colors * (MUI semantic) across the Offers / Invoices / Orders modules. * * Previously every list AND detail page defined its own `STATUS_LABELS` + * `STATUS_COLORS` maps. They drifted — most notably the issued-invoice status * was `warning` in the list but `info` in the detail. This module consolidates * them so the chip color/label for a given status is identical everywhere. * * Status KEYS are the ACTUAL values stored in the database and are kept AS-IS * (e.g. customer orders are still keyed in Czech: `prijata` / `v_realizaci` / * …). A Czech→English rename is a separate, deferred DB migration. * * The color union matches the kit `StatusChip` (src/admin/ui/StatusChip.tsx). */ export type StatusColor = "default" | "info" | "warning" | "success" | "error"; export interface StatusMeta { label: string; color: StatusColor; } /** * OFFER / quotations. Stored statuses are `active` (default) / `ordered` / * `invalidated` (see offers.service.ts). Labels are taken from the Offers * filter tabs; colors are synthesized to match the list row tints * (active = neutral-active info, ordered = success, invalidated = error). * `expired` is a defensive entry — it is a FRONT-END derived state (computed * from `valid_until`), not a stored status, but mapping it keeps any future * stored value rendering consistently (warning, matching the expired row wash). */ export const OFFER_STATUS: Record = { draft: { label: "Koncept", color: "default" }, active: { label: "Aktivní", color: "info" }, ordered: { label: "Objednaná", color: "success" }, invalidated: { label: "Zneplatněná", color: "error" }, expired: { label: "Po platnosti", color: "warning" }, }; /** * CUSTOMER ORDER / objednávka přijatá (orders). Czech-keyed (legacy-PHP * carryover; rename is a deferred migration). */ export const ORDER_STATUS: Record = { prijata: { label: "Přijatá", color: "info" }, v_realizaci: { label: "V realizaci", color: "warning" }, dokoncena: { label: "Dokončená", color: "success" }, stornovana: { label: "Stornována", color: "error" }, }; /** ISSUED ORDER / objednávka vydaná (issued_orders). */ export const ISSUED_ORDER_STATUS: Record = { draft: { label: "Koncept", color: "default" }, sent: { label: "Odeslaná", color: "info" }, confirmed: { label: "Potvrzená", color: "warning" }, completed: { label: "Dokončená", color: "success" }, cancelled: { label: "Stornovaná", color: "error" }, }; /** * ISSUED INVOICE (invoices). `issued` resolves to `warning` (payment-pending * = warning, NOT info) — this fixes the list↔detail color drift. */ export const INVOICE_STATUS: Record = { draft: { label: "Koncept", color: "default" }, issued: { label: "Vystavena", color: "warning" }, overdue: { label: "Po splatnosti", color: "error" }, paid: { label: "Zaplacena", color: "success" }, }; /** RECEIVED INVOICE (received_invoices). */ export const RECEIVED_INVOICE_STATUS: Record = { unpaid: { label: "Neuhrazena", color: "warning" }, paid: { label: "Uhrazena", color: "success" }, }; /** * Display label for a document's official number. Drafts (deferred numbering) * have a NULL/empty number until they are finalized — show "Koncept" instead * of an empty/`null` heading. */ export function documentNumberLabel(num: string | null | undefined): string { return num && String(num).trim() ? String(num) : "Koncept"; } /** Label with a safe fallback for an unknown/empty key. */ export const statusLabel = ( m: Record, k: string | null | undefined, ): string => (k && m[k]?.label) || k || "—"; /** Chip color with a safe fallback for an unknown/empty key. */ export const statusColor = ( m: Record, k: string | null | undefined, ): StatusColor => (k && m[k]?.color) || "default"; /** * Build `{ value, label }` filter options from a status map, optionally * prefixed with an "all" entry. Used by list-page status filters. */ export const statusOptions = ( m: Record, allOption?: { value: string; label: string }, ): { value: string; label: string }[] => { const opts = Object.entries(m).map(([value, { label }]) => ({ value, label, })); return allOption ? [allOption, ...opts] : opts; };