import type { Freight } from "@edr/types"; export interface ApprovalProgressSummary { label: string; detail: string; complete: boolean; } function nextPending( steps: Freight.IContractApprovalStep[], ): Freight.IContractApprovalStep | undefined { return steps.find((s) => s.status === "PENDING"); } /** Compact approval-chain summary for contract list rows (mirrors bookings). */ export function formatContractApprovalProgress( status: string, steps?: Freight.IContractApprovalStep[] | null, ): ApprovalProgressSummary { const sorted = [...(steps ?? [])].sort((a, b) => a.stepOrder - b.stepOrder); if (sorted.length === 0) { if (status === "SUBMITTED") { return { label: "Awaiting accept", detail: "Staff must accept intake", complete: false, }; } if ( status === "PENDING_APPROVAL" || status === "APPROVED_PENDING_SIGNATURE" ) { return { label: "No steps", detail: "Approval chain not started", complete: false, }; } if ( [ "APPROVED", "CONTRACT_READY", "SIGNED_CUSTOMER", "FULLY_EXECUTED", "CONTRACT_ACTIVE", "CLEARANCE_READY_FOR_BOOKING", "ACTIVE_SHIPMENT_IN_PROGRESS", "CONTRACT_CLOSED", ].includes(status) ) { return { label: "Approved", detail: "Internal approval complete", complete: true, }; } return { label: "—", detail: "", complete: false }; } const approved = sorted.filter((s) => s.status === "APPROVED").length; const total = sorted.length; const next = nextPending(sorted); if (!next && approved === total) { return { label: `${approved}/${total} done`, detail: sorted.map((s) => `${s.requiredRole} ✓`).join(" · "), complete: true, }; } if (next) { return { label: `${approved}/${total}`, detail: `Next: ${next.requiredRole} (step ${next.stepOrder})`, complete: false, }; } return { label: `${approved}/${total}`, detail: sorted.map((s) => `${s.requiredRole}: ${s.status}`).join(" · "), complete: approved === total, }; }