mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 02:58:11 +00:00
Merge pull request #616 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
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!),
|
||||
@@ -174,18 +198,17 @@ export default function GlCreateBookingForm() {
|
||||
);
|
||||
|
||||
// Next future window across all routes, used for the "next window" notice —
|
||||
// the train dispatching soonest among those not yet open, matching the
|
||||
// departure-date ordering of the window cards.
|
||||
// the next moment booking OPENS (chronological), which may belong to a
|
||||
// later-departing train. Departure-first ordering here named the soonest
|
||||
// train's later opening as "next" while another lane opened earlier.
|
||||
const nextWindow = useMemo(() => {
|
||||
const now = Date.now();
|
||||
return (bookingWindows ?? [])
|
||||
.filter((w) => w.windowOpensAt && new Date(w.windowOpensAt).getTime() > now)
|
||||
.sort((a, b) => {
|
||||
const da = a.departureDate ? new Date(a.departureDate).getTime() : Infinity;
|
||||
const db = b.departureDate ? new Date(b.departureDate).getTime() : Infinity;
|
||||
if (da !== db) return da - db;
|
||||
return new Date(a.windowOpensAt!).getTime() - new Date(b.windowOpensAt!).getTime();
|
||||
})[0];
|
||||
.sort(
|
||||
(a, b) =>
|
||||
new Date(a.windowOpensAt!).getTime() - new Date(b.windowOpensAt!).getTime(),
|
||||
)[0];
|
||||
}, [bookingWindows]);
|
||||
|
||||
const [scheduledDate, setScheduledDate] = useState("");
|
||||
@@ -636,6 +659,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 +720,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 +1298,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 +1454,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 +1465,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 +1476,7 @@ export default function GlCreateBookingForm() {
|
||||
}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Confirm & book
|
||||
{completeBookingId ? "Confirm & complete" : "Confirm & book"}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
|
||||
Reference in New Issue
Block a user