import { useQuery } from "@tanstack/react-query"; import { History } from "lucide-react"; import { Badge, Group, Loader, Stack, Text, Timeline } from "@mantine/core"; import type { Freight } from "@edr/types"; import { contractsService } from "@/services/contracts.service"; import { SectionCard } from "@/components/bookings/detail/SectionCard"; interface ContractRevisionTimelineProps { contractId: string; } type Change = Freight.IContractDocumentChange; /** Badge colour + verb per change kind, so a revision reads at a glance. */ const CHANGE_STYLES: Record = { ARTICLE_ADDED: { color: "green", label: "Added" }, ARTICLE_REMOVED: { color: "red", label: "Removed" }, ARTICLE_RENAMED: { color: "violet", label: "Renamed" }, ARTICLE_BODY_CHANGED: { color: "blue", label: "Edited" }, ARTICLE_REORDERED: { color: "gray", label: "Reordered" }, DOCUMENT_TITLE_CHANGED: { color: "grape", label: "Title" }, WHEREAS_CHANGED: { color: "teal", label: "Recitals" }, }; /** What the change applies to — an article title, or the document itself. */ function changeSubject(change: Change): string { switch (change.kind) { case "DOCUMENT_TITLE_CHANGED": return change.fromTitle ? `“${change.fromTitle}” → “${change.title}”` : change.title; case "WHEREAS_CHANGED": { const parts: string[] = []; if (change.added) parts.push(`+${change.added}`); if (change.removed) parts.push(`−${change.removed}`); return parts.join(" ") || "changed"; } case "ARTICLE_RENAMED": return `“${change.fromTitle}” → “${change.title}”`; case "ARTICLE_REORDERED": return `${change.title} (${change.fromOrder} → ${change.toOrder})`; default: return change.title; } } function formatWhen(iso: string): string { const date = new Date(iso); return date.toLocaleString(undefined, { dateStyle: "medium", timeStyle: "short", }); } /** * Audit trail of edits to the contract document. The document stays editable * through the approval chain, so this is the record of who changed what. */ export function ContractRevisionTimeline({ contractId, }: ContractRevisionTimelineProps) { const { data: revisions, isLoading } = useQuery({ queryKey: ["contracts", contractId, "document-revisions"], queryFn: () => contractsService.getContractDocumentRevisions(contractId), }); return ( {isLoading ? ( Loading history… ) : !revisions?.length ? ( No edits recorded yet. Changes made to the contract articles during approval will appear here. ) : ( {revisions.map((revision) => ( {revision.actorRole ?? "Staff"} {formatWhen(revision.createdAt)} } > {revision.summary && ( {revision.summary} )} {revision.changes.map((change, index) => { const style = CHANGE_STYLES[change.kind]; return ( {style?.label ?? change.kind} {changeSubject(change)} ); })} ))} )} ); }