mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 07:45:45 +00:00
feat: add hazardous goods declaration feature
- Introduced HazardDeclarationPanel component to display dangerous goods declaration details. - Updated URL constants to include CLEARANCE_PROCEED endpoint for re-requesting operations. - Enhanced permissions to include hazardous approval roles for contract approvals. - Integrated HazardDeclarationPanel into ContractRequestDetailPage and ContractClearanceDetailPage. - Added proceedToOperation method in bookings service for handling operation re-requests. - Updated contract forms and schemas to include hazard class and UN number fields. - Implemented validation for hazardous contracts in the contract creation flow. - Added expiry notice functionality for contracts nearing validity end. - Created tests for expiry notice calculations and labels. - Updated UI components to reflect hazardous cargo information and validation errors.
This commit is contained in:
@@ -35,6 +35,7 @@ import {
|
||||
isDjiboutiGl,
|
||||
} from "@/lib/permissions";
|
||||
|
||||
import { BookingChangesRequestedAlert } from "@/components/contracts/BookingChangesRequestedAlert";
|
||||
import { ClearanceOpsTabs } from "@/components/contracts/ClearanceOpsTabs";
|
||||
import { PageContainer } from "@/components/page/PageContainer";
|
||||
import { PageHeader } from "@/components/page/PageHeader";
|
||||
@@ -137,10 +138,15 @@ export default function ContractClearanceDetailPage() {
|
||||
// The GL-created booking expired unpaid — the slot is free again and GL
|
||||
// rebooks on the customer's behalf (customs bookings are never self-booked).
|
||||
const bookingExpired = clearance?.linkedBookingStatus === "EXPIRED";
|
||||
const canRebook =
|
||||
bookingExpired &&
|
||||
// Operations sent the GL-created booking back. GL owns customs bookings, so
|
||||
// the note and the resubmit belong here, not in the customer's portal.
|
||||
const bookingNeedsChanges =
|
||||
clearance?.linkedBookingStatus === "OPERATION_CHANGES_REQUESTED";
|
||||
const isGlBookingOwner =
|
||||
hasPermission(user, FREIGHT_PERMS.contracts.createBooking) &&
|
||||
!isDjiboutiGl(user);
|
||||
const canResubmitBooking = bookingNeedsChanges && isGlBookingOwner;
|
||||
const canRebook = bookingExpired && isGlBookingOwner;
|
||||
const rebookHref = linkedBookingId
|
||||
? `${bookingHref}?copyFrom=${linkedBookingId}`
|
||||
: bookingHref;
|
||||
@@ -294,6 +300,19 @@ export default function ContractClearanceDetailPage() {
|
||||
) : null}
|
||||
</Stack>
|
||||
</Alert>
|
||||
) : bookingNeedsChanges && linkedBookingId ? (
|
||||
<BookingChangesRequestedAlert
|
||||
bookingId={linkedBookingId}
|
||||
reference={clearance.linkedBookingReference}
|
||||
note={clearance.linkedBookingReviewNote}
|
||||
scheduledDate={clearance.linkedBookingScheduledDate}
|
||||
canResubmit={canResubmitBooking}
|
||||
onResubmitted={() => {
|
||||
void refetch();
|
||||
void refetchContract();
|
||||
refetchBookingMilestonesIfLinked();
|
||||
}}
|
||||
/>
|
||||
) : bookingAlreadyCreated ? (
|
||||
<Alert
|
||||
color="blue"
|
||||
|
||||
@@ -135,9 +135,10 @@ function toClearanceRow(contract: Freight.IContract): ClearanceRow {
|
||||
return {
|
||||
id: contract.id,
|
||||
reference: contract.reference,
|
||||
// The queue joins the company relation — show its name, never the raw uuid.
|
||||
customerLabel: contract.isGovernment
|
||||
? (contract.governmentInstitution ?? "Government")
|
||||
: (contract.companyId ?? "—"),
|
||||
: (contract.company?.name ?? "—"),
|
||||
tradeDirection: contract.tradeDirection ?? "—",
|
||||
freightType: contract.freightType ?? "—",
|
||||
originLabel: yardLabel(first?.originYard),
|
||||
|
||||
@@ -50,6 +50,7 @@ import { ContractStatusBadge } from "@/components/contracts/ContractStatusBadge"
|
||||
import { ContractWorkflowStepper } from "@/components/contracts/ContractWorkflowStepper";
|
||||
import { ContractActionsToolbar } from "@/components/contracts/ContractActionsToolbar";
|
||||
import { ContractApprovalStepsCard } from "@/components/contracts/ContractApprovalStepsCard";
|
||||
import { HazardDeclarationPanel } from "@/components/contracts/HazardDeclarationPanel";
|
||||
import { ClearanceWorkflowFilesPanel } from "@/components/contracts/ClearanceWorkflowFilesPanel";
|
||||
import { ContractRevisionTimeline } from "@/components/contracts/ContractRevisionTimeline";
|
||||
import {
|
||||
@@ -587,6 +588,11 @@ export default function ContractRequestDetailPage() {
|
||||
</Badge>
|
||||
) : null}
|
||||
</Group>
|
||||
{contract.isHazardous ? (
|
||||
<Box mb="md">
|
||||
<HazardDeclarationPanel contract={contract} />
|
||||
</Box>
|
||||
) : null}
|
||||
{(contract.cargoScope ?? []).length === 0 ? (
|
||||
<Text size="sm" c="dimmed">
|
||||
No cargo scope lines.
|
||||
|
||||
Reference in New Issue
Block a user