Implement clearance-first booking flow and completion process for customs contracts

This commit is contained in:
Marshal
2026-07-10 18:56:39 +00:00
parent b50075dc83
commit 9ed473c309
18 changed files with 369 additions and 39 deletions

View File

@@ -1,10 +1,11 @@
import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import { useParams } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";
import {
Alert,
Badge,
Box,
Button,
Grid,
Group,
Loader,
@@ -21,6 +22,7 @@ import {
CheckCircle2,
Clock,
PackageCheck,
PackagePlus,
ShieldCheck,
} from "lucide-react";
import type { Freight } from "@edr/types";
@@ -38,10 +40,14 @@ import { useBookingMilestones } from "@/hooks/contracts/useContracts";
import { bookingsService } from "@/services/bookings.service";
import { downloadBookingFile } from "@/services/files.service";
import { useBookingDetail } from "@/hooks/bookings/useBookings";
import { useAuth } from "@/auth/useAuth";
import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions";
export default function DocumentClearanceDetailPage() {
const params = useParams<{ id?: string; bookingId?: string }>();
const id = params.id ?? params.bookingId;
const navigate = useNavigate();
const { user } = useAuth();
const { view, viewer } = useFileViewer();
const { data: booking } = useBookingDetail(id);
@@ -76,6 +82,15 @@ export default function DocumentClearanceDetailPage() {
booking?.contractKind === "GENERAL" &&
Boolean(clearance?.phase);
// Bare initiated instance whose clearance is done: GL completes the booking
// (container numbers, VGM, shipment day) via the completion form.
const canCompleteBooking =
booking?.status === "CLEARANCE_READY" &&
Boolean(booking?.contractId) &&
Boolean(booking?.customsClearingEnabled) &&
!(Number(booking?.totalAmount ?? 0) > 0) &&
hasPermission(user, FREIGHT_PERMS.contracts.createBooking);
const docsPhaseComplete =
clearance?.milestones?.some(
(m) => m.milestoneCode === "DOCUMENTS_APPROVED" && m.status === "COMPLETED",
@@ -146,6 +161,22 @@ export default function DocumentClearanceDetailPage() {
</Badge>
)
}
action={
canCompleteBooking ? (
<Button
color="edr-green"
radius="md"
leftSection={<PackagePlus size={16} />}
onClick={() =>
navigate(
`/dashboard/contracts/${booking!.contractId}/bookings/${id}/complete`,
)
}
>
Complete booking
</Button>
) : undefined
}
/>
<ClearanceHero booking={booking} clearance={clearance} stats={stats} />

View File

@@ -402,7 +402,7 @@ export default function ShipmentRequestsPage() {
<Stack gap="lg">
<PageHeader
title="Shipment Requests"
subtitle="Customer requests to ship under general customs contracts. Accept one to create the booking and start its clearance."
subtitle="Customer requests to ship under general customs contracts. Each request starts its booking's clearance immediately — complete the booking from the clearance page once it is ready."
meta={
<Badge
variant="light"