mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 22:18:12 +00:00
Implement clearance-first booking flow and completion process for customs contracts
This commit is contained in:
@@ -145,13 +145,37 @@ function bulkUnitOfMeasure(
|
||||
}
|
||||
|
||||
export default function GlCreateBookingForm() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
// With `bookingId` the form runs in COMPLETION mode: the bare instance
|
||||
// (auto-initiated by the customer's shipment request) already finished its
|
||||
// per-booking customs clearance, and this form supplies the deferred cargo
|
||||
// (container numbers, VGM) + binding shipment day. Same window gate, same
|
||||
// validation and price confirmation — the submit completes the existing
|
||||
// booking instead of creating a new one.
|
||||
const { id, bookingId: completeBookingId } = useParams<{
|
||||
id: string;
|
||||
bookingId?: string;
|
||||
}>();
|
||||
const [searchParams] = useSearchParams();
|
||||
const requestId = searchParams.get("requestId");
|
||||
const requestIdParam = searchParams.get("requestId");
|
||||
const navigate = useNavigate();
|
||||
const { data: contract, isLoading } = useContractDetail(id);
|
||||
const mutations = useContractMutations(id ?? "");
|
||||
|
||||
// Completion mode without an explicit ?requestId=: find the shipment request
|
||||
// that initiated this instance so the quantities still prefill.
|
||||
const { data: contractRequests } = useQuery({
|
||||
queryKey: ["shipment-requests-for-contract", id],
|
||||
queryFn: () => contractsService.listBookingRequests(id!),
|
||||
enabled: Boolean(id) && Boolean(completeBookingId) && !requestIdParam,
|
||||
});
|
||||
const requestId =
|
||||
requestIdParam ??
|
||||
(completeBookingId
|
||||
? (contractRequests?.find(
|
||||
(r) => r.createdBookingId === completeBookingId,
|
||||
)?.id ?? null)
|
||||
: null);
|
||||
|
||||
const { data: bookingRequest } = useQuery({
|
||||
queryKey: ["shipment-request", requestId],
|
||||
queryFn: () => contractsService.getBookingRequest(requestId!),
|
||||
@@ -636,6 +660,18 @@ export default function GlCreateBookingForm() {
|
||||
const payload = buildPayload();
|
||||
if (!payload) return;
|
||||
|
||||
if (completeBookingId) {
|
||||
// Completion mode: cargo + day land on the already-cleared instance —
|
||||
// the request was linked and accepted at submission time.
|
||||
mutations.completeBooking.mutate(
|
||||
{ bookingId: completeBookingId, payload },
|
||||
{
|
||||
onSuccess: () => navigate(`/dashboard/clearance/${completeBookingId}`),
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
mutations.createBooking.mutate(payload, {
|
||||
onSuccess: async (booking) => {
|
||||
if (requestId) {
|
||||
@@ -685,10 +721,12 @@ export default function GlCreateBookingForm() {
|
||||
<Group justify="space-between" align="flex-end" wrap="wrap" gap="md" mb="lg">
|
||||
<Box>
|
||||
<Text fw={800} fz={26} style={{ letterSpacing: "-0.01em" }}>
|
||||
New Shipment Booking
|
||||
{completeBookingId ? "Complete Shipment Booking" : "New Shipment Booking"}
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed" mt={4}>
|
||||
Book a shipment on behalf of the customer for contract {contract.reference}.
|
||||
{completeBookingId
|
||||
? `Clearance is finalized — enter the cargo details and shipment day to complete the booking under contract ${contract.reference}.`
|
||||
: `Book a shipment on behalf of the customer for contract ${contract.reference}.`}
|
||||
</Text>
|
||||
</Box>
|
||||
<Button
|
||||
@@ -1261,7 +1299,11 @@ export default function GlCreateBookingForm() {
|
||||
<Modal
|
||||
opened={priceOpen}
|
||||
onClose={() => {
|
||||
if (!mutations.createBooking.isPending) setPriceOpen(false);
|
||||
if (
|
||||
!mutations.createBooking.isPending &&
|
||||
!mutations.completeBooking.isPending
|
||||
)
|
||||
setPriceOpen(false);
|
||||
}}
|
||||
centered
|
||||
radius="lg"
|
||||
@@ -1413,7 +1455,10 @@ export default function GlCreateBookingForm() {
|
||||
radius="md"
|
||||
leftSection={<X size={16} />}
|
||||
onClick={() => setPriceOpen(false)}
|
||||
disabled={mutations.createBooking.isPending}
|
||||
disabled={
|
||||
mutations.createBooking.isPending ||
|
||||
mutations.completeBooking.isPending
|
||||
}
|
||||
>
|
||||
Reject & edit
|
||||
</Button>
|
||||
@@ -1421,7 +1466,10 @@ export default function GlCreateBookingForm() {
|
||||
color="edr-green"
|
||||
radius="md"
|
||||
leftSection={<CheckCircle2 size={16} />}
|
||||
loading={mutations.createBooking.isPending}
|
||||
loading={
|
||||
mutations.createBooking.isPending ||
|
||||
mutations.completeBooking.isPending
|
||||
}
|
||||
disabled={
|
||||
validateShipmentMutation.isPending ||
|
||||
pairingErrors.length > 0 ||
|
||||
@@ -1429,7 +1477,7 @@ export default function GlCreateBookingForm() {
|
||||
}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Confirm & book
|
||||
{completeBookingId ? "Confirm & complete" : "Confirm & book"}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
|
||||
Reference in New Issue
Block a user