mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 23:35:42 +00:00
Merge pull request #734 from Tria-plc/freight_feature/usermanagement
fix u=issue
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
Textarea,
|
||||
ThemeIcon,
|
||||
Title,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import {
|
||||
AlertCircle,
|
||||
@@ -269,6 +270,19 @@ function NewShipmentBookingForm({
|
||||
mode: "onChange",
|
||||
});
|
||||
|
||||
// 20ft containers ride two per wagon, so an odd total leaves one unpaired and
|
||||
// the booking can never be planned. The server's shipment validation reports
|
||||
// it too, but only once the price modal opens — block it inline instead, the
|
||||
// same way the direct-booking wizard does (new-booking-form `calcWagons`).
|
||||
const watchedContainers = form.watch("containers");
|
||||
const ft20Total =
|
||||
contract.freightType === "CONTAINER"
|
||||
? (watchedContainers ?? [])
|
||||
.filter((l) => l.containerSize === "20ft")
|
||||
.reduce((sum, l) => sum + Number(l.quantity || 0), 0)
|
||||
: 0;
|
||||
const hasOdd20ft = ft20Total % 2 === 1;
|
||||
|
||||
const submitMutation = useMutation({
|
||||
mutationFn: (dto: Freight.CreateBookingUnderContractDto) =>
|
||||
completeBookingId
|
||||
@@ -367,6 +381,8 @@ function NewShipmentBookingForm({
|
||||
// run it for every freight type; container contracts additionally get
|
||||
// overweight warnings + 20ft pairing hard-blocks surfaced in the modal.
|
||||
const handleReview = form.handleSubmit((values) => {
|
||||
// An unpaired 20ft can never be planned onto a wagon — don't even price it.
|
||||
if (hasOdd20ft) return;
|
||||
setPendingValues(values);
|
||||
validateMutation.reset();
|
||||
validateMutation.mutate(buildDto(values));
|
||||
@@ -483,15 +499,26 @@ function NewShipmentBookingForm({
|
||||
}}
|
||||
>
|
||||
<Group justify="flex-end" className="mx-auto max-w-4xl">
|
||||
<Button
|
||||
type="button"
|
||||
color="edr-green"
|
||||
radius="md"
|
||||
leftSection={<Receipt size={16} />}
|
||||
onClick={handleReview}
|
||||
<Tooltip
|
||||
label={`Book an even number of 20ft containers — ${ft20Total} is odd and would leave one unpaired.`}
|
||||
withArrow
|
||||
disabled={!hasOdd20ft}
|
||||
>
|
||||
Review price & book
|
||||
</Button>
|
||||
{/* Mantine tooltips get no pointer events from a disabled button,
|
||||
so the wrapper carries the hover target. */}
|
||||
<Box>
|
||||
<Button
|
||||
type="button"
|
||||
color="edr-green"
|
||||
radius="md"
|
||||
leftSection={<Receipt size={16} />}
|
||||
onClick={handleReview}
|
||||
disabled={hasOdd20ft}
|
||||
>
|
||||
Review price & book
|
||||
</Button>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Box>
|
||||
</form>
|
||||
@@ -1265,6 +1292,28 @@ function CargoStep({
|
||||
This contract has no container sizes in scope.
|
||||
</Text>
|
||||
)}
|
||||
{(() => {
|
||||
const ft20 = lines
|
||||
.filter((l) => l.containerSize === "20ft")
|
||||
.reduce((sum, l) => sum + Number(l.quantity || 0), 0);
|
||||
if (ft20 % 2 !== 1) return null;
|
||||
return (
|
||||
<Alert
|
||||
color="red"
|
||||
variant="light"
|
||||
radius="md"
|
||||
icon={<AlertCircle size={16} />}
|
||||
title={`Odd number of 20ft containers (${ft20})`}
|
||||
>
|
||||
<Text fz={13}>
|
||||
20ft containers travel two per wagon, so they must be booked in
|
||||
even numbers. Please add one more 20ft container or remove one
|
||||
(e.g. book {ft20 + 1} or {ft20 - 1} instead of {ft20}) — the
|
||||
booking cannot be submitted with an unpaired 20ft container.
|
||||
</Text>
|
||||
</Alert>
|
||||
);
|
||||
})()}
|
||||
</Stack>
|
||||
</StepCard>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
Button,
|
||||
Group,
|
||||
@@ -13,7 +14,7 @@ import {
|
||||
Textarea,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { ArrowLeft, CalendarDays, Send } from "lucide-react";
|
||||
import { AlertCircle, ArrowLeft, CalendarDays, Send } from "lucide-react";
|
||||
import toast from "react-hot-toast";
|
||||
import type { Freight } from "@edr/types";
|
||||
import { DatePickerInput } from "@mantine/dates";
|
||||
@@ -98,7 +99,14 @@ export default function NewShipmentRequestPage() {
|
||||
contract.cargoScope?.[0];
|
||||
const isPerItem = bulkScope?.cargoType?.unitOfMeasure === "PER_ITEM";
|
||||
|
||||
// 20ft containers ride two per wagon, so an odd total can never be planned —
|
||||
// and GL's create-booking form blocks it too, so an odd request would only
|
||||
// dead-end there. Same even-number rule the booking forms apply.
|
||||
const ft20Requested = isContainer ? Number(qtyBySize["20ft"]) || 0 : 0;
|
||||
const hasOdd20ft = ft20Requested % 2 === 1;
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (hasOdd20ft) return;
|
||||
const dto: Freight.CreateBookingRequestDto = {
|
||||
contractRouteId: route?.id,
|
||||
scheduledDate: hasCustoms ? undefined : scheduledDate || undefined,
|
||||
@@ -202,6 +210,23 @@ export default function NewShipmentRequestPage() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{hasOdd20ft ? (
|
||||
<Alert
|
||||
color="red"
|
||||
variant="light"
|
||||
radius="md"
|
||||
icon={<AlertCircle size={16} />}
|
||||
title={`Odd number of 20ft containers (${ft20Requested})`}
|
||||
>
|
||||
<Text fz={13}>
|
||||
20ft containers travel two per wagon, so they must be requested
|
||||
in even numbers. Please add one more 20ft container or remove
|
||||
one (e.g. request {ft20Requested + 1} or {ft20Requested - 1}{" "}
|
||||
instead of {ft20Requested}).
|
||||
</Text>
|
||||
</Alert>
|
||||
) : null}
|
||||
|
||||
{capacity?.length ? (
|
||||
<Text size="xs" c="dimmed">
|
||||
Remaining capacity is shown on the contract — GL will validate your request.
|
||||
@@ -220,6 +245,7 @@ export default function NewShipmentRequestPage() {
|
||||
leftSection={<Send size={16} />}
|
||||
loading={submit.isPending}
|
||||
onClick={handleSubmit}
|
||||
disabled={hasOdd20ft}
|
||||
>
|
||||
Submit shipment request
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user