This commit is contained in:
marshal
2026-09-08 22:34:56 +00:00
parent 54f76d4779
commit 37ef0f9cac
6 changed files with 158 additions and 0 deletions

View File

@@ -38,6 +38,7 @@ import {
Stack,
Tabs,
Text,
Title,
} from "@mantine/core";
import { PageContainer, PageHeader, KpiStrip } from "@/components/page";
@@ -285,6 +286,11 @@ export default function BookingRequestDetailPage() {
const hasSignableContract = booking.isGovernment && booking.contractSummary;
// The voyage (sailing) number of the schedule this booking rides. Null until
// a train is allocated (or requested at day-commit), and on legacy schedules
// created before voyage numbers were captured.
const voyageNumber = booking.trainScheduleSummary?.voyageNumber ?? null;
return (
<PageContainer>
<PageHeader
@@ -296,6 +302,13 @@ export default function BookingRequestDetailPage() {
title={booking.reference}
meta={
<Group gap={6} wrap="wrap">
{voyageNumber ? (
// Sits at title weight beside the reference: yards and customs
// quote the voyage, so it is the second thing staff look for.
<Title order={2} c="dimmed" style={{ whiteSpace: "nowrap" }}>
· {voyageNumber}
</Title>
) : null}
<BookingStatusBadge status={booking.status} />
<BookingPriorityBadge score={booking.priorityScore} />
{booking.schedulingStatus ? (

View File

@@ -16,6 +16,7 @@ import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
import { ContractReferenceLink } from "@/components/bookings/ContractReferenceLink";
import { bookingTable } from "@/components/bookings/booking-ui.styles";
import { PageContainer, PageHeader } from "@/components/page";
import { formatDateTime } from "@/lib/format";
import { bookingsService, type BookingListFilter } from "@/services/bookings.service";
import type { BookingDetail } from "@/types/booking";
import {
@@ -210,6 +211,28 @@ export default function ClearanceDocumentsPage() {
);
},
},
{
id: "documentsSubmittedAt",
header: () => (
<span className={bookingTable.headerCell}>Documents submitted</span>
),
cell: ({ row }) => {
const submittedAt = row.original.documentsSubmittedAt;
return submittedAt ? (
<Text size="sm">{formatDateTime(submittedAt)}</Text>
) : (
<Text size="sm" c="dimmed">
Not submitted
</Text>
);
},
// The table caps cells at 100px; a date needs its own width or it wraps
// to three lines.
meta: {
headerClassName: "min-w-[9rem]",
cellClassName: "min-w-[9rem]",
},
},
{
id: "status",
size: 200,

View File

@@ -139,6 +139,8 @@ export interface BookingTrainScheduleSummary {
id: string;
reference: string | null;
trainNumber: string | null;
/** Voyage (sailing) number for THIS departure — the schedule's own, not the train's. */
voyageNumber?: string | null;
status: string | null;
scheduledDepartureDate: string | null;
scheduledArrivalDate: string | null;
@@ -252,6 +254,13 @@ export interface BookingDetail {
allDocsApproved?: boolean;
/** ET clearance queue: a customer document is PENDING or QUERIED. */
hasDocumentsAwaitingReview?: boolean;
/**
* Newest customer clearance-document upload on this booking, attached by the
* LIST endpoint for the clearance worklists' "Documents submitted" column. A
* re-upload answering a query moves it forward; null until the customer has
* submitted anything.
*/
documentsSubmittedAt?: string | null;
/**
* ET clearance queue: id of an unspent wagon-cancellation credit on this
* booking (CREDIT_AVAILABLE, worth > 0, not yet rebooked). Null when there is