mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 07:51:02 +00:00
87 lines
2.1 KiB
TypeScript
87 lines
2.1 KiB
TypeScript
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,
|
|
};
|
|
}
|