import type { BookingApprovalStep, BookingStatus } from "@/types/booking"; import { getNextPendingApprovalStep } from "@/features/bookings/booking-actions.config"; export interface ApprovalProgressSummary { label: string; detail: string; complete: boolean; } /** Compact approval chain summary for list rows and badges. */ export function formatApprovalProgress( status: BookingStatus | string, steps?: BookingApprovalStep[] | 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", "PAID", "COMPLETED", ].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 = getNextPendingApprovalStep(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, }; }