implement update train details feature: add DTO, service method, and UI modal for editing train name and run numbers

This commit is contained in:
Marshal
2026-07-15 20:14:39 +00:00
parent d7d9db9c3a
commit fc44eee25e
44 changed files with 970 additions and 14 deletions

View File

@@ -141,6 +141,7 @@ const RATE_TRIGGERS = [
{ label: "Cancellation", value: "CANCELLATION" },
{ label: "Demurrage", value: "DEMURRAGE" },
{ label: "Shipping line extra fee (PIL)", value: "PIL_EXTRA_FEE" },
{ label: "Customs clearance service fee (prepaid)", value: "CUSTOMS_CLEARANCE" },
];
const unitOption = (value: string) => ({ label: value.replace(/_/g, " "), value });
@@ -162,6 +163,9 @@ const allowedRateUnits = (appliesTo: string, trigger: string): string[] => {
return ["PER_CONTAINER", "PER_TON"];
case "CANCELLATION":
return ["FLAT", "PER_INVOICE"];
case "CUSTOMS_CLEARANCE":
// Flat per clearance (ONE_TIME) / per shipment request (GENERAL).
return ["FLAT"];
case "CONSOLIDATION":
case "SHIPPING_LINE":
case "PIL_EXTRA_FEE":

View File

@@ -1,6 +1,7 @@
import type { ColumnDef } from "@edr/ui-common";
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";
import {
ActionIcon,
Badge,
Box,
Button,
@@ -15,6 +16,7 @@ import { useDebouncedValue } from "@mantine/hooks";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import {
Hammer,
Pencil,
Ruler,
Search,
Train as TrainIcon,
@@ -27,6 +29,7 @@ import { useNavigate } from "react-router-dom";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
import BuildTrainModal from "@/components/trainBuilder/BuildTrainModal";
import EditTrainDetailsModal from "@/components/trainBuilder/EditTrainDetailsModal";
import {
directionColor,
directionRowStyle,
@@ -52,6 +55,7 @@ export default function TrainBuilderListPage() {
const [statusFilter, setStatusFilter] = useState<"ALL" | BuiltTrainStatus>("ALL");
const [yardFilter, setYardFilter] = useState("ALL");
const [buildOpen, setBuildOpen] = useState(false);
const [editTarget, setEditTarget] = useState<BuiltTrainSummary | null>(null);
const resetPage = useCallback(() => {
setPagination((prev) =>
@@ -239,6 +243,26 @@ export default function TrainBuilderListPage() {
</Badge>
),
},
{
id: "actions",
header: "",
meta: { headerClassName, cellClassName },
cell: ({ row }) => (
<ActionIcon
variant="subtle"
color="gray"
aria-label={`Edit train ${row.original.code}`}
title="Edit name & train numbers"
onClick={(e) => {
// Row click navigates to the detail page — keep the edit local.
e.stopPropagation();
setEditTarget(row.original);
}}
>
<Pencil size={15} />
</ActionIcon>
),
},
];
}, []);
@@ -363,6 +387,8 @@ export default function TrainBuilderListPage() {
onClose={() => setBuildOpen(false)}
onBuilt={(composition) => navigate(`/dashboard/train-builder/${composition.id}`)}
/>
<EditTrainDetailsModal train={editTarget} onClose={() => setEditTarget(null)} />
</PageContainer>
);
}