mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 05:58:18 +00:00
feat: full wagon cancel, leg board, wagon dates
feat(freight): editable train leg times, SL invoice payer
This commit is contained in:
@@ -34,6 +34,7 @@ import {
|
||||
Navigation,
|
||||
Package,
|
||||
PackageCheck,
|
||||
Grid3x3,
|
||||
Route as RouteIcon,
|
||||
Ruler,
|
||||
Send,
|
||||
@@ -41,6 +42,7 @@ import {
|
||||
Weight,
|
||||
Workflow as WorkflowIcon,
|
||||
} from "lucide-react";
|
||||
import { DateTimePicker } from "@mantine/dates";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
|
||||
@@ -57,6 +59,7 @@ import { ContainerPlacementGrid } from "@/components/trainScheduling/ContainerPl
|
||||
import { FleetAvailabilitySummary } from "@/components/trainScheduling/FleetAvailabilitySummary";
|
||||
import { IntercityRideAlongPanel } from "@/components/trainScheduling/IntercityRideAlongPanel";
|
||||
import { LegCapacityPanel } from "@/components/trainScheduling/LegCapacityPanel";
|
||||
import { LegLoadBoardPanel } from "@/components/trainScheduling/LegLoadBoardPanel";
|
||||
import { LoadEmptyContainersModal } from "@/components/trainScheduling/LoadEmptyContainersModal";
|
||||
import MergeScheduleTrainModal from "@/components/trainScheduling/MergeScheduleTrainModal";
|
||||
import ScheduleHistoryPanel from "@/components/trainScheduling/ScheduleHistoryPanel";
|
||||
@@ -125,6 +128,13 @@ export default function TrainScheduleV2DetailPage() {
|
||||
const [gatepassFileUrl, setGatepassFileUrl] = useState("");
|
||||
const [gatepassNotes, setGatepassNotes] = useState("");
|
||||
const [dispatchConfirmOpen, setDispatchConfirmOpen] = useState(false);
|
||||
// Actual departure — staff often dispatch on paper first and record it later,
|
||||
// so the time is picked (defaults to now when the dialog opens).
|
||||
const [dispatchAt, setDispatchAt] = useState<Date | null>(null);
|
||||
const openDispatchConfirm = () => {
|
||||
setDispatchAt(new Date());
|
||||
setDispatchConfirmOpen(true);
|
||||
};
|
||||
const [switchTarget, setSwitchTarget] = useState<EligibleContainerBooking | null>(null);
|
||||
const [visualization3DOpen, setVisualization3DOpen] = useState(false);
|
||||
const [loadEmptiesOpen, setLoadEmptiesOpen] = useState(false);
|
||||
@@ -477,7 +487,10 @@ export default function TrainScheduleV2DetailPage() {
|
||||
const runDispatch = async () => {
|
||||
setDispatchConfirmOpen(false);
|
||||
try {
|
||||
await dispatch.mutateAsync(scheduleId);
|
||||
await dispatch.mutateAsync({
|
||||
id: scheduleId,
|
||||
payload: dispatchAt ? { actualDepartureAt: dispatchAt.toISOString() } : {},
|
||||
});
|
||||
await openMarshallingDocument({
|
||||
title: "Train dispatched",
|
||||
successDescription: "Marshalling document generated for the dispatched train.",
|
||||
@@ -873,7 +886,7 @@ export default function TrainScheduleV2DetailPage() {
|
||||
radius="md"
|
||||
leftSection={<Send size={18} />}
|
||||
loading={dispatch.isPending}
|
||||
onClick={() => setDispatchConfirmOpen(true)}
|
||||
onClick={openDispatchConfirm}
|
||||
>
|
||||
Dispatch train
|
||||
</Button>
|
||||
@@ -1271,6 +1284,9 @@ export default function TrainScheduleV2DetailPage() {
|
||||
<Tabs.Tab value="legs" leftSection={<RouteIcon size={16} />}>
|
||||
Leg capacity
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value="leg-board" leftSection={<Grid3x3 size={16} />}>
|
||||
Leg board
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value="history" leftSection={<HistoryIcon size={16} />}>
|
||||
History
|
||||
</Tabs.Tab>
|
||||
@@ -1359,6 +1375,13 @@ export default function TrainScheduleV2DetailPage() {
|
||||
<LegCapacityPanel schedule={schedule} />
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="leg-board">
|
||||
<LegLoadBoardPanel
|
||||
schedule={schedule}
|
||||
onChanged={() => void detailQuery.refetch()}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
|
||||
<Tabs.Panel value="history">
|
||||
{scheduleId ? <ScheduleHistoryPanel scheduleId={scheduleId} /> : null}
|
||||
</Tabs.Panel>
|
||||
@@ -1444,6 +1467,17 @@ export default function TrainScheduleV2DetailPage() {
|
||||
undone.
|
||||
</Text>
|
||||
|
||||
<DateTimePicker
|
||||
label="Actual departure"
|
||||
description="When the train left — defaults to now; a past time is fine."
|
||||
value={dispatchAt}
|
||||
onChange={(v) => setDispatchAt(v ? new Date(v) : null)}
|
||||
maxDate={new Date()}
|
||||
valueFormat="DD MMM YYYY HH:mm"
|
||||
clearable={false}
|
||||
radius="md"
|
||||
/>
|
||||
|
||||
{hasDispatchWarnings ? (
|
||||
<Alert
|
||||
color="orange"
|
||||
|
||||
Reference in New Issue
Block a user