mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 19:30:57 +00:00
add hard capacity ceiling to weight limit rules
This commit is contained in:
@@ -444,6 +444,7 @@ export default function GlCreateBookingForm() {
|
||||
|
||||
const displayTotal = serverTotal ?? priceTotal;
|
||||
const pairingErrors = validation?.pairingErrors ?? [];
|
||||
const capacityErrors = validation?.capacityErrors ?? [];
|
||||
const overweightLines = validation?.overweightLines ?? [];
|
||||
|
||||
const openPriceModal = () => {
|
||||
@@ -459,6 +460,8 @@ export default function GlCreateBookingForm() {
|
||||
if (!contract || !windowOpen) return;
|
||||
// Never book past unresolved 20ft pairing hard-blocks.
|
||||
if (pairingErrors.length > 0) return;
|
||||
// A line above the container type's max capacity can never book.
|
||||
if (capacityErrors.length > 0) return;
|
||||
const payload = buildPayload();
|
||||
if (!payload) return;
|
||||
|
||||
@@ -938,6 +941,28 @@ export default function GlCreateBookingForm() {
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{capacityErrors.length > 0 && (
|
||||
<Alert
|
||||
color="red"
|
||||
variant="light"
|
||||
radius="md"
|
||||
icon={<AlertCircle size={16} />}
|
||||
title="Cannot create booking — over maximum capacity"
|
||||
>
|
||||
<Stack gap={6}>
|
||||
{capacityErrors.map((msg, i) => (
|
||||
<Text key={i} fz="sm" c="red.8">
|
||||
{msg}
|
||||
</Text>
|
||||
))}
|
||||
<Text fz="xs" c="red.7" mt={2}>
|
||||
Reduce the cargo weight or split it across more containers
|
||||
to book this shipment.
|
||||
</Text>
|
||||
</Stack>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{overweightLines.length > 0 && (
|
||||
<Alert
|
||||
color="yellow"
|
||||
@@ -1023,7 +1048,9 @@ export default function GlCreateBookingForm() {
|
||||
leftSection={<CheckCircle2 size={16} />}
|
||||
loading={mutations.createBooking.isPending}
|
||||
disabled={
|
||||
validateShipmentMutation.isPending || pairingErrors.length > 0
|
||||
validateShipmentMutation.isPending ||
|
||||
pairingErrors.length > 0 ||
|
||||
capacityErrors.length > 0
|
||||
}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { isAxiosError } from "axios";
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
@@ -47,6 +48,18 @@ interface ScheduleWorkspacePanelProps {
|
||||
|
||||
const GREEN = "var(--mantine-color-edr-green-6)";
|
||||
|
||||
/** Pull the API's violation detail out of an error (e.g. "No CW3 wagon available…"). */
|
||||
function apiErrorMessage(error: unknown, fallback: string): string {
|
||||
if (isAxiosError(error)) {
|
||||
const data = error.response?.data as Record<string, unknown> | undefined;
|
||||
const violations = data?.violations;
|
||||
if (Array.isArray(violations) && violations.length) return violations.join(", ");
|
||||
if (typeof data?.message === "string") return data.message;
|
||||
if (Array.isArray(data?.message)) return (data.message as string[]).join(", ");
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deadline + label for the window phase this schedule is currently in.
|
||||
* Phases run: window open (windowClosesAt) → document review (docReviewEndsAt)
|
||||
@@ -198,8 +211,12 @@ export function ScheduleWorkspacePanel({
|
||||
onChanged();
|
||||
void poolQuery.refetch();
|
||||
})
|
||||
.catch(() =>
|
||||
toast({ title: "Could not add booking", variant: "destructive" }),
|
||||
.catch((error) =>
|
||||
toast({
|
||||
title: "Could not add booking",
|
||||
description: apiErrorMessage(error, "Validation failed — check capacity and status."),
|
||||
variant: "destructive",
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -211,8 +228,12 @@ export function ScheduleWorkspacePanel({
|
||||
onChanged();
|
||||
void poolQuery.refetch();
|
||||
})
|
||||
.catch(() =>
|
||||
toast({ title: "Could not remove booking", variant: "destructive" }),
|
||||
.catch((error) =>
|
||||
toast({
|
||||
title: "Could not remove booking",
|
||||
description: apiErrorMessage(error, "Please try again."),
|
||||
variant: "destructive",
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -226,8 +247,12 @@ export function ScheduleWorkspacePanel({
|
||||
onChanged();
|
||||
void poolQuery.refetch();
|
||||
})
|
||||
.catch(() =>
|
||||
toast({ title: "Could not reassign booking", variant: "destructive" }),
|
||||
.catch((error) =>
|
||||
toast({
|
||||
title: "Could not reassign booking",
|
||||
description: apiErrorMessage(error, "Target train may be closed or full."),
|
||||
variant: "destructive",
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user