From 17dc505d503ec604bb878a22fbf2863da7d2bfdf Mon Sep 17 00:00:00 2001 From: Marshal Date: Sun, 19 Jul 2026 07:06:58 +0000 Subject: [PATCH] streamline booking detail components and enhance journey visualization - Removed the BookingClearanceWorkflowBanner from ClearanceCard as the clearance progress is now integrated into the unified journey wizard. - Eliminated the MilestoneTimeline component from DocumentsTab, consolidating customs progress into the JourneyWizard. - Updated PageHeader to include a ContractReferenceLink for better navigation to contract details. - Simplified ShipmentTrackingCard to focus on duty/tax payment slip upload, removing unnecessary milestone display. - Integrated JourneyWizard component to visualize the booking journey, replacing the previous progress tracker. - Enhanced ContractDetailPage to better categorize documents and improve user experience with clearer sections for profile, business license, clearance, and other documents. - Introduced CSS for contracts table to manage column sizing and sticky headers effectively. - Added ContractReferenceLink component for backoffice to link to contract details, ensuring consistent navigation across applications. --- .../bookings/ContractReferenceLink.tsx | 43 ++++ .../bookings/detail/BookingRequestHero.tsx | 13 +- .../features/bookings/mapBookingListRow.ts | 1 + .../backoffice/src/lib/queryClient.ts | 3 +- .../pages/bookings/BookingRequestsPage.tsx | 13 +- .../backoffice/src/types/booking.ts | 2 + .../MyPortalPage/components/BookingRow.tsx | 2 + .../components/ClearanceCard.tsx | 6 +- .../components/DocumentsTab.tsx | 124 +--------- .../components/JourneyWizard.tsx | 211 ++++++++++++++++++ .../components/PageHeader.tsx | 14 +- .../components/ShipmentTrackingCard.tsx | 99 +------- .../components/StatusHero.tsx | 140 ++---------- .../src/pages/bookings/booking-display.tsx | 35 +++ .../pages/contracts/ContractDetailPage.tsx | 171 ++++++++------ .../src/pages/contracts/ContractsList.tsx | 14 +- .../src/pages/contracts/NewShipmentPage.tsx | 1 - .../src/pages/contracts/contracts-table.css | 78 +++++++ 18 files changed, 548 insertions(+), 422 deletions(-) create mode 100644 apps/edr-freight-web/backoffice/src/components/bookings/ContractReferenceLink.tsx create mode 100644 apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/JourneyWizard.tsx create mode 100644 apps/edr-freight-web/portal/src/pages/contracts/contracts-table.css diff --git a/apps/edr-freight-web/backoffice/src/components/bookings/ContractReferenceLink.tsx b/apps/edr-freight-web/backoffice/src/components/bookings/ContractReferenceLink.tsx new file mode 100644 index 000000000..94061eee2 --- /dev/null +++ b/apps/edr-freight-web/backoffice/src/components/bookings/ContractReferenceLink.tsx @@ -0,0 +1,43 @@ +import { Link } from "react-router-dom"; + +/** + * The parent contract's reference, linking to that contract's detail page. + * + * Backoffice-local on purpose: the contract detail route differs per app + * (`/dashboard/contract-requests/:id` here vs `/contracts/:id` in the portal), + * so the portal keeps its own copy in `pages/bookings/booking-display.tsx` + * rather than the two sharing a component that would have to take the route as + * a prop at every call site. + * + * Renders nothing when either field is missing: `contractId` is nullable on the + * booking, and only the bookings list/detail endpoints join `contractReference` + * — other endpoints (warehouse, fleet, payments) return booking rows without it, + * and a link with no id would be a dead one. + * + * `stopPropagation` matters: booking rows are click-to-navigate, so without it a + * click here would race the row handler and land on the booking instead. + */ +export function ContractReferenceLink({ + contractId, + contractReference, + className, +}: { + contractId?: string | null; + contractReference?: string | null; + className?: string; +}) { + if (!contractId || !contractReference) return null; + + return ( + e.stopPropagation()} + className={ + className ?? + "block truncate font-mono text-xs text-muted-foreground underline underline-offset-2 hover:text-foreground" + } + > + {contractReference} + + ); +} diff --git a/apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingRequestHero.tsx b/apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingRequestHero.tsx index aa14fe8cd..3ee5d72a0 100644 --- a/apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingRequestHero.tsx +++ b/apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingRequestHero.tsx @@ -24,6 +24,7 @@ import type { LucideIcon } from "lucide-react"; import type { BookingDetail } from "@/types/booking"; import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge"; import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge"; +import { ContractReferenceLink } from "@/components/bookings/ContractReferenceLink"; import { SchedulingStatusBadge } from "@/components/trainScheduling/ScheduleStatusBadge"; import { NextStepBanner } from "@/components/bookings/NextStepBanner"; @@ -94,9 +95,15 @@ export function BookingRequestHero({ Booking reference - - {booking.reference} - + + + {booking.reference} + + + {booking.schedulingStatus ? ( diff --git a/apps/edr-freight-web/backoffice/src/features/bookings/mapBookingListRow.ts b/apps/edr-freight-web/backoffice/src/features/bookings/mapBookingListRow.ts index bc10fd064..a0594094c 100644 --- a/apps/edr-freight-web/backoffice/src/features/bookings/mapBookingListRow.ts +++ b/apps/edr-freight-web/backoffice/src/features/bookings/mapBookingListRow.ts @@ -19,6 +19,7 @@ export function toBookingListRow(booking: BookingDetail): BookingListRow { id: booking.id, reference: booking.reference, contractReference: booking.contractReference ?? null, + contractId: booking.contractId ?? null, approvalSteps: booking.approvalSteps, customerLabel: booking.isGovernment ? (booking.governmentInstitution ?? "Government") diff --git a/apps/edr-freight-web/backoffice/src/lib/queryClient.ts b/apps/edr-freight-web/backoffice/src/lib/queryClient.ts index 5b2bcb255..0a270372e 100644 --- a/apps/edr-freight-web/backoffice/src/lib/queryClient.ts +++ b/apps/edr-freight-web/backoffice/src/lib/queryClient.ts @@ -27,7 +27,8 @@ export const queryClient = new QueryClient({ defaultOptions: { queries: { retry: 1, - staleTime: 30_000, + // staleTime: 30_000, + staleTime:0, // Data freshness is driven by mutation invalidation (MutationCache above), // socket pushes, and explicit polling — not by tab focus. Focus refetch // just re-fires every mounted query each time the window is refocused. diff --git a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx index 72c16215b..3eb775e95 100644 --- a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingRequestsPage.tsx @@ -48,6 +48,7 @@ import { useBookingList, useBookingListSummary, } from "@/hooks/bookings/useBookings"; +import { ContractReferenceLink } from "@/components/bookings/ContractReferenceLink"; import { api } from "@/services/api"; import type { BookingListFilter } from "@/services/bookings.service"; import type { BookingListRow } from "@/types/booking"; @@ -308,7 +309,17 @@ export default function BookingRequestsPage() { return (
{ref ? ( - {ref} + // Fall back to plain text when the id is missing — the reference is + // still worth showing, it just has nowhere to link to. + (row.original.contractId ? ( + + ) : ( + {ref} + )) ) : ( )} diff --git a/apps/edr-freight-web/backoffice/src/types/booking.ts b/apps/edr-freight-web/backoffice/src/types/booking.ts index ec31e11fa..4b5b5257b 100644 --- a/apps/edr-freight-web/backoffice/src/types/booking.ts +++ b/apps/edr-freight-web/backoffice/src/types/booking.ts @@ -231,6 +231,8 @@ export interface BookingListRow { id: string; reference: string; contractReference?: string | null; + /** Needed to link the reference to the contract's detail page. */ + contractId?: string | null; customerLabel: string; approvalSteps?: BookingApprovalStep[]; status: BookingStatus; diff --git a/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/BookingRow.tsx b/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/BookingRow.tsx index 007fc7fe9..56226594e 100644 --- a/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/BookingRow.tsx +++ b/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/BookingRow.tsx @@ -10,6 +10,7 @@ import { bookingIsSignable, } from "@/pages/bookings/contract/ContractSignButton"; import { ApproveDeliveryButton } from "@/pages/bookings/delivery/ApproveDeliveryButton"; +import { ContractReferenceLink } from "@/pages/bookings/booking-display"; interface BookingRowProps { booking: any; @@ -73,6 +74,7 @@ export const BookingRow = memo(function BookingRow({ {booking.reference} + {commodity} · {origin} → {dest} diff --git a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/ClearanceCard.tsx b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/ClearanceCard.tsx index dcc455ada..a8cc43e14 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/ClearanceCard.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/ClearanceCard.tsx @@ -13,7 +13,6 @@ import type { Freight } from "@edr/types"; import { BookingActionModal } from "@/pages/bookings/clearance/BookingActionModal"; import { getBookingNextAction } from "@/pages/bookings/clearance/bookingNextAction"; -import { BookingClearanceWorkflowBanner } from "@/pages/bookings/BookingClearanceWorkflowBanner"; import { CardTitle, SectionCard } from "./layout"; @@ -65,8 +64,9 @@ export function ClearanceCard({ booking }: { booking: Freight.IBooking }) { return ( - - + {/* The "Clearance progress" stepper moved into the unified journey + wizard at the top of the page — this card keeps only the actions. */} + Clearance documents {action && (