Merge pull request #616 from Tria-plc/freight_feature/usermanagement

Freight feature/usermanagement
This commit is contained in:
marshal
2026-07-11 09:42:56 +03:00
committed by GitHub
57 changed files with 2711 additions and 345 deletions

View File

@@ -1,7 +1,14 @@
import { Button, Group, type ButtonProps } from "@mantine/core";
import {
Button,
Group,
Modal,
Text,
ThemeIcon,
type ButtonProps,
} from "@mantine/core";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import type { LucideIcon } from "lucide-react";
import type { ReactNode } from "react";
import { useState, type ReactNode } from "react";
import toast from "react-hot-toast";
import { useNavigate } from "react-router-dom";
@@ -57,7 +64,9 @@ export function ContractCustomerAction({
}
if (action.type === "pay") {
return <PayNowButton booking={action.booking} label={action.label} size={size} />;
return (
<PayNowButton booking={action.booking} label={action.label} size={size} />
);
}
if (action.type === "initiate") {
@@ -118,6 +127,7 @@ export function InitiateBookingButton({
}) {
const navigate = useNavigate();
const queryClient = useQueryClient();
const [confirmOpen, setConfirmOpen] = useState(false);
const mutation = useMutation({
mutationFn: () =>
@@ -137,6 +147,7 @@ export function InitiateBookingButton({
toast.success(
"Booking initiated — upload your clearance documents to start the review.",
);
setConfirmOpen(false);
navigate(`/bookings/${booking.id}`);
},
onError: (e: Error) =>
@@ -144,37 +155,87 @@ export function InitiateBookingButton({
});
return (
<Button
size={size}
radius="md"
h={listStyle ? 34 : undefined}
variant="filled"
color="edr-green"
fullWidth={fullWidth}
leftSection={<Icon size={15} />}
loading={mutation.isPending}
onClick={(e) => {
e.stopPropagation();
mutation.mutate();
}}
styles={
listStyle
? {
root: {
fontWeight: 600,
fontSize: 13,
paddingInline: 14,
whiteSpace: "nowrap" as const,
boxShadow: "0 1px 2px rgba(14,163,113,0.25)",
},
}
: undefined
}
fw={listStyle ? undefined : 700}
fz={listStyle ? undefined : 13}
>
{label}
</Button>
<>
<Modal
opened={confirmOpen}
onClose={() => {
if (!mutation.isPending) setConfirmOpen(false);
}}
centered
radius="lg"
size="md"
closeOnClickOutside={!mutation.isPending}
closeOnEscape={!mutation.isPending}
withCloseButton={!mutation.isPending}
title={
<Group gap={10} wrap="nowrap">
<ThemeIcon variant="light" color="edr-green" radius="md" size={34}>
<Icon size={18} />
</ThemeIcon>
<Text fw={700}>Initiate a new booking?</Text>
</Group>
}
>
<Text size="sm" c="dimmed">
This creates a new shipment booking under contract{" "}
<Text span fw={700} c="#10202F">
{contract.reference}
</Text>
. You&apos;ll upload the clearance documents next, and the shipment
quantity is drawn down from your contract&apos;s reserved capacity.
</Text>
<Group justify="flex-end" gap="sm" mt="lg">
<Button
variant="default"
radius="md"
onClick={() => setConfirmOpen(false)}
disabled={mutation.isPending}
>
Cancel
</Button>
<Button
color="edr-green"
radius="md"
leftSection={<Icon size={16} />}
loading={mutation.isPending}
onClick={() => mutation.mutate()}
>
Yes, initiate booking
</Button>
</Group>
</Modal>
<Button
size={size}
radius="md"
h={listStyle ? 34 : undefined}
variant="filled"
color="edr-green"
fullWidth={fullWidth}
leftSection={<Icon size={15} />}
loading={mutation.isPending}
onClick={(e) => {
e.stopPropagation();
setConfirmOpen(true);
}}
styles={
listStyle
? {
root: {
fontWeight: 600,
fontSize: 13,
paddingInline: 14,
whiteSpace: "nowrap" as const,
boxShadow: "0 1px 2px rgba(14,163,113,0.25)",
},
}
: undefined
}
fw={listStyle ? undefined : 700}
fz={listStyle ? undefined : 13}
>
{label}
</Button>
</>
);
}
@@ -191,7 +252,12 @@ export function ContractCustomerActionCell({
return (
<Group gap={8} wrap="nowrap" justify="flex-end">
{docButton}
<ContractCustomerAction contract={contract} bookings={bookings} size="sm" listStyle />
<ContractCustomerAction
contract={contract}
bookings={bookings}
size="sm"
listStyle
/>
</Group>
);
}