refactor(ui): single shared documentStatus map across offers/invoices/orders (fix issued color drift, add offers status chip)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
101
src/admin/lib/documentStatus.ts
Normal file
101
src/admin/lib/documentStatus.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* 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<string, StatusMeta> = {
|
||||
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<string, StatusMeta> = {
|
||||
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<string, StatusMeta> = {
|
||||
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<string, StatusMeta> = {
|
||||
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<string, StatusMeta> = {
|
||||
unpaid: { label: "Neuhrazena", color: "warning" },
|
||||
paid: { label: "Uhrazena", color: "success" },
|
||||
};
|
||||
|
||||
/** Label with a safe fallback for an unknown/empty key. */
|
||||
export const statusLabel = (
|
||||
m: Record<string, StatusMeta>,
|
||||
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<string, StatusMeta>,
|
||||
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<string, StatusMeta>,
|
||||
allOption?: { value: string; label: string },
|
||||
): { value: string; label: string }[] => {
|
||||
const opts = Object.entries(m).map(([value, { label }]) => ({
|
||||
value,
|
||||
label,
|
||||
}));
|
||||
return allOption ? [allOption, ...opts] : opts;
|
||||
};
|
||||
Reference in New Issue
Block a user