From 2de1c2e7beea059413cd4c093b09cd0d33f681b7 Mon Sep 17 00:00:00 2001 From: Marshal Date: Sun, 28 Jun 2026 15:25:22 +0000 Subject: [PATCH] feat: enhance contract detail page with document grouping and clearance modal - Added functionality to group contract documents into categories: Contract, Profile, and Clearance. - Implemented a modal for uploading and managing clearance documents. - Created a new ActionNeededSection component to display pending customer actions. - Introduced deriveActionItems function to generate actionable items based on contract and booking statuses. - Developed ContractClearancePanel for handling clearance document uploads and reviews. - Added support for ad-hoc document uploads in the clearance panel. --- .../contracts/contract-clearance.service.ts | 10 +- .../src/pages/MyPortalPage/MyPortalPage.tsx | 7 + .../portal/src/pages/MyPortalPage/actions.ts | 96 ++++ .../components/ActionNeededSection.tsx | 205 +++++++++ .../pages/MyPortalPage/components/index.ts | 1 + .../pages/contracts/ContractClearanceFlow.tsx | 430 +----------------- .../contracts/ContractClearancePanel.tsx | 423 +++++++++++++++++ .../pages/contracts/ContractDetailPage.tsx | 243 +++++++--- 8 files changed, 921 insertions(+), 494 deletions(-) create mode 100644 apps/edr-freight-web/portal/src/pages/MyPortalPage/actions.ts create mode 100644 apps/edr-freight-web/portal/src/pages/MyPortalPage/components/ActionNeededSection.tsx create mode 100644 apps/edr-freight-web/portal/src/pages/contracts/ContractClearancePanel.tsx diff --git a/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts b/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts index a16ccc5c9..cb047b572 100644 --- a/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts +++ b/apps/edr-freight-api/src/modules/contracts/contract-clearance.service.ts @@ -294,7 +294,15 @@ export class ContractClearanceService { note?: string, ): Promise { const contract = await this.contractsService.findById(contractId); - if (contract.status !== 'CLEARANCE_UNDER_REVIEW') { + // Reviewing is allowed both while the batch is UNDER_REVIEW and after it has + // dropped back to AWAITING_CLEARANCE_DOCUMENTS — querying one document flips + // the contract to "awaiting" (the customer must re-upload), but the reviewer + // may still be working through the rest of the batch. Restricting to + // UNDER_REVIEW only would 409 every review after the first query. + if ( + contract.status !== 'CLEARANCE_UNDER_REVIEW' && + contract.status !== 'AWAITING_CLEARANCE_DOCUMENTS' + ) { throw new ConflictException( `Cannot review clearance documents on status "${contract.status}".`, ); diff --git a/apps/edr-freight-web/portal/src/pages/MyPortalPage/MyPortalPage.tsx b/apps/edr-freight-web/portal/src/pages/MyPortalPage/MyPortalPage.tsx index a07bd8492..ce69be041 100644 --- a/apps/edr-freight-web/portal/src/pages/MyPortalPage/MyPortalPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/MyPortalPage/MyPortalPage.tsx @@ -5,6 +5,7 @@ import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { PROFILE_TYPE_LABELS } from "@/constants/profileMode"; import { + ActionNeededSection, FreightVolumeSection, HelloSection, InvoicesSection, @@ -13,6 +14,7 @@ import { ShipmentsSection, StatsSection, } from "./components"; +import { deriveActionItems } from "./actions"; import { useMyPortalData } from "./hooks"; export default function MyPortalPage() { @@ -25,6 +27,7 @@ export default function MyPortalPage() { bookingsQuery, dashboardQuery, contractsQuery, + allContracts, recentContracts, activeContractsCount, allBookings, @@ -45,6 +48,8 @@ export default function MyPortalPage() { label: `${PROFILE_TYPE_LABELS[p.type] ?? p.type} · ${p.reference}`, })); + const actionItems = deriveActionItems(allContracts, allBookings); + const handleBookingClick = (id: string) => { navigate(`/bookings/${id}`); }; @@ -53,6 +58,8 @@ export default function MyPortalPage() { + + {serviceOptions.length > 1 && (