תפריט הסטטוס-הידני הכיל 17 סטטוסים שמתוכם ~9 דקורציה טהורה — שלבי-ביניים שאף קוד בפייפליין לא קבע ושום לוגיקה לא הסתעפה לפיהם, עם רשימות כפולות לא-עקביות ב-6+ קבצים (UI-B1) ו-exported כסטטוס-רפאים (באג agent-audit). הליבה (10): new, processing, documents_ready, outcome_set, direction_approved, qa_review, drafted, exported, reviewed, final. - SSoT חדש web-ui/src/lib/api/case-status.ts (רשימה/שלבים/תוויות/statusLabel); כל הצרכנים (badge/changer/timeline/guide/donut/kpi/compose) מייבאים משם. - statusLabel() מבטיח תווית עברית תמיד — גם לערך-מורשת (נפילה עברית, לא סלאג). - בקאנד: STATUS_ORDER 10, models.CaseStatus מיושר, set_outcome קובע outcome_set/direction_approved (במקום in_progress) כמו endpoint ה-web. - exported מוקשח אחרי export-DOCX מוצלח (forward-only); widget "נכשל ב-QA" עודכן ל-qa_review (הסטטוס שנקבע בפועל בכשל-QA). - scripts/backfill_case_status_trim.py: מיפוי שורות-מורשת לסטטוס-הליבה הקודם. Invariants: UI-B1 (מקור-אמת יחיד) ✅ · G2 (אין מסלול מקביל) ✅ · GAP-42 (חלקי). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
62 lines
2.4 KiB
TypeScript
62 lines
2.4 KiB
TypeScript
import { Badge } from "@/components/ui/badge";
|
|
import {
|
|
FilePlus2, Loader2, FileCheck, Target,
|
|
Compass, SearchCheck, FileText,
|
|
FileOutput, CheckCircle2, Award,
|
|
} from "lucide-react";
|
|
import {
|
|
STATUS_LABELS, STATUS_DESCRIPTIONS, statusLabel, type CaseStatus,
|
|
} from "@/lib/api/case-status";
|
|
import type { LucideIcon } from "lucide-react";
|
|
|
|
/* Labels + descriptions come from the SSoT (@/lib/api/case-status).
|
|
* Icons + color tones are view-layer concerns and live here, keyed off the
|
|
* same 10 core statuses. */
|
|
|
|
const STATUS_ICONS: Record<CaseStatus, LucideIcon> = {
|
|
new: FilePlus2,
|
|
processing: Loader2,
|
|
documents_ready: FileCheck,
|
|
outcome_set: Target,
|
|
direction_approved: Compass,
|
|
qa_review: SearchCheck,
|
|
drafted: FileText,
|
|
exported: FileOutput,
|
|
reviewed: CheckCircle2,
|
|
final: Award,
|
|
};
|
|
|
|
/* Status color groups:
|
|
* intake → new, processing (muted parchment / info)
|
|
* prep → documents_ready (info blue)
|
|
* thinking→ outcome_set, direction_approved (gold)
|
|
* writing → qa_review, drafted (warn amber)
|
|
* done → exported, reviewed, final (success green) */
|
|
const STATUS_TONE: Record<CaseStatus, string> = {
|
|
new: "bg-rule-soft text-ink-muted border-rule",
|
|
processing: "bg-info-bg text-info border-info/30",
|
|
documents_ready: "bg-info-bg text-info border-info/40",
|
|
outcome_set: "bg-gold-wash text-gold-deep border-gold/40",
|
|
direction_approved:"bg-gold-wash text-gold-deep border-gold/50",
|
|
qa_review: "bg-warn-bg text-warn border-warn/40",
|
|
drafted: "bg-warn-bg text-warn border-warn/50",
|
|
exported: "bg-success-bg text-success border-success/40",
|
|
reviewed: "bg-success-bg text-success border-success/50",
|
|
final: "bg-success-bg text-success border-success/60 font-semibold",
|
|
};
|
|
|
|
export function StatusBadge({ status }: { status: CaseStatus }) {
|
|
const Icon = STATUS_ICONS[status];
|
|
return (
|
|
<Badge
|
|
variant="outline"
|
|
className={`rounded-full px-2.5 py-0.5 text-[0.72rem] font-medium inline-flex items-center gap-1 ${STATUS_TONE[status] ?? ""}`}
|
|
>
|
|
{Icon && <Icon className="w-3 h-3 shrink-0" />}
|
|
{statusLabel(status)}
|
|
</Badge>
|
|
);
|
|
}
|
|
|
|
export { STATUS_LABELS, STATUS_ICONS, STATUS_DESCRIPTIONS, STATUS_TONE };
|