mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Merge pull request #1415 from Tria-plc/freight_feature/usermanagement
feat: implement MANUAL_ONLY status for bookings and update related logic
This commit is contained in:
@@ -35,6 +35,8 @@ export function SchedulingStatusBadge({ status }: { status?: string | null }) {
|
||||
ELIGIBLE: "blue",
|
||||
SCHEDULED: "indigo",
|
||||
DISPATCHED: "edr-green",
|
||||
WAITING_FOR_WAGON: "yellow",
|
||||
MANUAL_ONLY: "orange",
|
||||
};
|
||||
return (
|
||||
<Badge variant="light" color={colors[status] ?? "gray"} size="sm">
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Card,
|
||||
Group,
|
||||
Modal,
|
||||
Radio,
|
||||
SegmentedControl,
|
||||
Select,
|
||||
SimpleGrid,
|
||||
@@ -23,10 +24,13 @@ import {
|
||||
Container,
|
||||
Eye,
|
||||
FileText,
|
||||
Flag,
|
||||
Globe,
|
||||
Lock,
|
||||
Pencil,
|
||||
Plus,
|
||||
Trash2,
|
||||
type LucideIcon,
|
||||
} from "lucide-react";
|
||||
|
||||
import { useAuth } from "@/auth/useAuth";
|
||||
@@ -109,6 +113,39 @@ function directionOf(template: ContractTemplate): string {
|
||||
: template.code.split("_")[0];
|
||||
}
|
||||
|
||||
/** The three customs options offered in the create-template modal. */
|
||||
const CUSTOMS_OPTIONS: Array<{
|
||||
value: string;
|
||||
label: string;
|
||||
description: string;
|
||||
color: string;
|
||||
icon: LucideIcon;
|
||||
}> = [
|
||||
{
|
||||
value: "true",
|
||||
label: "With customs clearing",
|
||||
description:
|
||||
"The Service Provider clears customs in both Djibouti and Ethiopia on the client's behalf.",
|
||||
color: "teal",
|
||||
icon: Globe,
|
||||
},
|
||||
{
|
||||
value: "ethiopian",
|
||||
label: "Ethiopian customs only",
|
||||
description:
|
||||
"The Service Provider clears the Ethiopian side only — Djibouti clearing stays with the client. Used for service types marked “Ethiopian customs only”.",
|
||||
color: "indigo",
|
||||
icon: Flag,
|
||||
},
|
||||
{
|
||||
value: "false",
|
||||
label: "Without customs clearing",
|
||||
description: "Transport only — the client handles its own declarations.",
|
||||
color: "gray",
|
||||
icon: FileText,
|
||||
},
|
||||
];
|
||||
|
||||
function formatUpdated(value: string): string {
|
||||
return new Date(value).toLocaleDateString("en-GB", {
|
||||
day: "numeric",
|
||||
@@ -281,8 +318,25 @@ function CreateTemplateModal({
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal opened={opened} onClose={close} title="New bulk contract template" centered>
|
||||
<Stack gap="md">
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={close}
|
||||
size={640}
|
||||
radius="lg"
|
||||
padding="xl"
|
||||
centered
|
||||
title={
|
||||
<div>
|
||||
<Text fw={600} size="lg">
|
||||
New bulk contract template
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" mt={2}>
|
||||
One template per trade direction, customs option and commodity
|
||||
</Text>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Stack gap="lg">
|
||||
<div>
|
||||
<Text size="sm" fw={500} mb={6}>
|
||||
Trade direction
|
||||
@@ -299,36 +353,6 @@ function CreateTemplateModal({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{intercity ? (
|
||||
<Text size="xs" c="dimmed">
|
||||
Intercity contracts are domestic and cross no border, so they have
|
||||
no customs clearing variant — one template per cargo type.
|
||||
</Text>
|
||||
) : (
|
||||
<div>
|
||||
<Text size="sm" fw={500} mb={6}>
|
||||
Customs clearing
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
fullWidth
|
||||
value={withCustoms}
|
||||
onChange={setWithCustoms}
|
||||
data={[
|
||||
{ value: "true", label: "With customs clearing" },
|
||||
{ value: "ethiopian", label: "Ethiopian customs only" },
|
||||
{ value: "false", label: "Without customs clearing" },
|
||||
]}
|
||||
/>
|
||||
{withCustoms === "ethiopian" && (
|
||||
<Text size="xs" c="dimmed" mt={6}>
|
||||
Used for service types marked “Ethiopian customs only”: the
|
||||
Service Provider clears the Ethiopian side, Djibouti clearing
|
||||
stays with the client.
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Select
|
||||
label="Bulk cargo type"
|
||||
description="Only cargo types with “has contract template” enabled are listed"
|
||||
@@ -340,6 +364,62 @@ function CreateTemplateModal({
|
||||
nothingFoundMessage="No cargo type allows contract templates yet — enable the flag on the cargo type first"
|
||||
/>
|
||||
|
||||
{intercity ? (
|
||||
<Text size="xs" c="dimmed">
|
||||
Intercity contracts are domestic and cross no border, so they have
|
||||
no customs clearing variant — one template per cargo type.
|
||||
</Text>
|
||||
) : (
|
||||
<Radio.Group
|
||||
value={withCustoms}
|
||||
onChange={setWithCustoms}
|
||||
label="Customs clearing"
|
||||
styles={{ label: { fontWeight: 500, marginBottom: 6 } }}
|
||||
>
|
||||
<Stack gap="xs">
|
||||
{CUSTOMS_OPTIONS.map((option) => {
|
||||
const checked = withCustoms === option.value;
|
||||
return (
|
||||
<Radio.Card
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
radius="md"
|
||||
p="sm"
|
||||
style={{
|
||||
borderColor: checked
|
||||
? `var(--mantine-color-${option.color}-6)`
|
||||
: undefined,
|
||||
backgroundColor: checked
|
||||
? `var(--mantine-color-${option.color}-light)`
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
<Group wrap="nowrap" align="flex-start" gap="sm">
|
||||
<Radio.Indicator mt={2} color={option.color} />
|
||||
<ThemeIcon
|
||||
size={34}
|
||||
radius="md"
|
||||
variant="light"
|
||||
color={option.color}
|
||||
>
|
||||
<option.icon size={17} strokeWidth={1.75} />
|
||||
</ThemeIcon>
|
||||
<div>
|
||||
<Text size="sm" fw={500}>
|
||||
{option.label}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed" lh={1.45}>
|
||||
{option.description}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Radio.Card>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Radio.Group>
|
||||
)}
|
||||
|
||||
<Group justify="flex-end" gap="sm">
|
||||
<Button variant="default" onClick={close}>
|
||||
Cancel
|
||||
|
||||
@@ -8,7 +8,9 @@ export type SchedulingStatus =
|
||||
| "ELIGIBLE"
|
||||
| "SCHEDULED"
|
||||
| "DISPATCHED"
|
||||
| "WAITING_FOR_WAGON";
|
||||
| "WAITING_FOR_WAGON"
|
||||
/** Removed from a train by staff — auto-allocation skips it; manual assign only. */
|
||||
| "MANUAL_ONLY";
|
||||
|
||||
export type TrainScheduleStatus =
|
||||
| "DRAFT"
|
||||
|
||||
Reference in New Issue
Block a user