mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 18:55:42 +00:00
Merge pull request #966 from Tria-plc/freight_feature/usermanagement
add dispute functionality for contract duty and implement collection…
This commit is contained in:
@@ -20,17 +20,15 @@ import { useDebouncedValue } from "@mantine/hooks";
|
|||||||
import { isAxiosError } from "axios";
|
import { isAxiosError } from "axios";
|
||||||
import {
|
import {
|
||||||
ArrowRight,
|
ArrowRight,
|
||||||
// Ban, — used only by the commented-out "Cancel schedule" row action
|
Ban,
|
||||||
CalendarClock,
|
CalendarClock,
|
||||||
Clock,
|
Clock,
|
||||||
Eye,
|
Eye,
|
||||||
Lock,
|
|
||||||
MoreHorizontal,
|
MoreHorizontal,
|
||||||
Navigation,
|
Navigation,
|
||||||
Pencil,
|
Pencil,
|
||||||
Play,
|
Play,
|
||||||
Send,
|
Send,
|
||||||
Unlock,
|
|
||||||
Train,
|
Train,
|
||||||
Weight,
|
Weight,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
@@ -125,12 +123,10 @@ export default function TrainScheduleV2ListPage() {
|
|||||||
const [sortDir, setSortDir] = useState<"desc" | "asc">("desc");
|
const [sortDir, setSortDir] = useState<"desc" | "asc">("desc");
|
||||||
const [createOpen, setCreateOpen] = useState(false);
|
const [createOpen, setCreateOpen] = useState(false);
|
||||||
const [windowSettingsId, setWindowSettingsId] = useState<string | null>(null);
|
const [windowSettingsId, setWindowSettingsId] = useState<string | null>(null);
|
||||||
// Dispatching a train and closing its booking window are both irreversible
|
// Dispatch is irreversible from this screen, so it goes through an explicit
|
||||||
// from this screen, so each goes through an explicit confirmation.
|
// confirmation.
|
||||||
const [dispatchTarget, setDispatchTarget] =
|
const [dispatchTarget, setDispatchTarget] =
|
||||||
useState<TrainScheduleListItem | null>(null);
|
useState<TrainScheduleListItem | null>(null);
|
||||||
const [windowTarget, setWindowTarget] =
|
|
||||||
useState<TrainScheduleListItem | null>(null);
|
|
||||||
const [editDateSchedule, setEditDateSchedule] =
|
const [editDateSchedule, setEditDateSchedule] =
|
||||||
useState<TrainScheduleListItem | null>(null);
|
useState<TrainScheduleListItem | null>(null);
|
||||||
const [routeId, setRouteId] = useState("");
|
const [routeId, setRouteId] = useState("");
|
||||||
@@ -213,10 +209,7 @@ export default function TrainScheduleV2ListPage() {
|
|||||||
const dispatchSchedule = useMutation(
|
const dispatchSchedule = useMutation(
|
||||||
api.trainScheduling.dispatchSchedule.mutationOptions(),
|
api.trainScheduling.dispatchSchedule.mutationOptions(),
|
||||||
);
|
);
|
||||||
const setWindow = useMutation(
|
const cancel = useMutation(api.trainScheduling.cancelSchedule.mutationOptions());
|
||||||
api.trainScheduling.setBookingWindow.mutationOptions(),
|
|
||||||
);
|
|
||||||
// const cancel = useMutation(api.trainScheduling.cancelSchedule.mutationOptions());
|
|
||||||
|
|
||||||
// Intercity (same-country / DOMESTIC) routes cannot be scheduled yet — the
|
// Intercity (same-country / DOMESTIC) routes cannot be scheduled yet — the
|
||||||
// API rejects them, so keep them out of the picker entirely.
|
// API rejects them, so keep them out of the picker entirely.
|
||||||
@@ -484,27 +477,6 @@ export default function TrainScheduleV2ListPage() {
|
|||||||
Booking window settings
|
Booking window settings
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
) : null}
|
) : null}
|
||||||
{/* Stop / resume taking bookings on this departure without
|
|
||||||
opening it. FULL is a capacity state the engine owns, so
|
|
||||||
only an explicitly OPEN/CLOSED window is toggled here. */}
|
|
||||||
{canUpdate &&
|
|
||||||
["DRAFT", "SCHEDULED"].includes(schedule.status) &&
|
|
||||||
schedule.bookingWindowStatus !== "FULL" ? (
|
|
||||||
<Menu.Item
|
|
||||||
leftSection={
|
|
||||||
schedule.bookingWindowStatus === "CLOSED" ? (
|
|
||||||
<Unlock size={15} />
|
|
||||||
) : (
|
|
||||||
<Lock size={15} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onClick={() => setWindowTarget(schedule)}
|
|
||||||
>
|
|
||||||
{schedule.bookingWindowStatus === "CLOSED"
|
|
||||||
? "Open booking window"
|
|
||||||
: "Close booking window"}
|
|
||||||
</Menu.Item>
|
|
||||||
) : null}
|
|
||||||
{/* Start the run. Same transition as the detail page's
|
{/* Start the run. Same transition as the detail page's
|
||||||
Dispatch button — that page also shows unassigned-wagon
|
Dispatch button — that page also shows unassigned-wagon
|
||||||
and not-loaded warnings, so it stays the fuller surface. */}
|
and not-loaded warnings, so it stays the fuller surface. */}
|
||||||
@@ -516,9 +488,6 @@ export default function TrainScheduleV2ListPage() {
|
|||||||
Start (dispatch) train
|
Start (dispatch) train
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
) : null}
|
) : null}
|
||||||
{/* Cancel schedule — hidden for now (frontend only; the
|
|
||||||
cancelSchedule mutation is untouched). Restore by
|
|
||||||
uncommenting.
|
|
||||||
{["DRAFT", "SCHEDULED"].includes(schedule.status) ? (
|
{["DRAFT", "SCHEDULED"].includes(schedule.status) ? (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
color="red"
|
color="red"
|
||||||
@@ -542,7 +511,6 @@ export default function TrainScheduleV2ListPage() {
|
|||||||
Cancel schedule
|
Cancel schedule
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
) : null}
|
) : null}
|
||||||
*/}
|
|
||||||
</Menu.Dropdown>
|
</Menu.Dropdown>
|
||||||
</Menu>
|
</Menu>
|
||||||
</Group>
|
</Group>
|
||||||
@@ -902,74 +870,6 @@ export default function TrainScheduleV2ListPage() {
|
|||||||
onSaved={() => void schedulesQuery.refetch()}
|
onSaved={() => void schedulesQuery.refetch()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Modal
|
|
||||||
opened={windowTarget != null}
|
|
||||||
onClose={() => setWindowTarget(null)}
|
|
||||||
title={
|
|
||||||
windowTarget?.bookingWindowStatus === "CLOSED"
|
|
||||||
? "Open booking window?"
|
|
||||||
: "Close booking window?"
|
|
||||||
}
|
|
||||||
centered
|
|
||||||
radius="md"
|
|
||||||
>
|
|
||||||
<Stack gap="md">
|
|
||||||
<Text size="sm" c="dimmed">
|
|
||||||
{windowTarget?.bookingWindowStatus === "CLOSED" ? (
|
|
||||||
<>
|
|
||||||
Customers will be able to book onto{" "}
|
|
||||||
<Text span fw={600} c="dark">
|
|
||||||
{windowTarget?.trainNumber ?? windowTarget?.reference ?? "this departure"}
|
|
||||||
</Text>{" "}
|
|
||||||
again, up to its remaining capacity.
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
No further bookings will be accepted onto{" "}
|
|
||||||
<Text span fw={600} c="dark">
|
|
||||||
{windowTarget?.trainNumber ?? windowTarget?.reference ?? "this departure"}
|
|
||||||
</Text>
|
|
||||||
. Bookings already aboard are unaffected, and you can reopen the
|
|
||||||
window from this menu.
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
<Group justify="flex-end" gap="sm">
|
|
||||||
<Button variant="default" onClick={() => setWindowTarget(null)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={windowTarget?.bookingWindowStatus === "CLOSED" ? "edr-green" : "orange"}
|
|
||||||
loading={setWindow.isPending}
|
|
||||||
onClick={async () => {
|
|
||||||
if (!windowTarget) return;
|
|
||||||
const next =
|
|
||||||
windowTarget.bookingWindowStatus === "CLOSED" ? "OPEN" : "CLOSED";
|
|
||||||
try {
|
|
||||||
await setWindow.mutateAsync({ id: windowTarget.id, status: next });
|
|
||||||
toast({
|
|
||||||
title:
|
|
||||||
next === "OPEN" ? "Booking window opened" : "Booking window closed",
|
|
||||||
});
|
|
||||||
setWindowTarget(null);
|
|
||||||
void schedulesQuery.refetch();
|
|
||||||
} catch (err) {
|
|
||||||
toast({
|
|
||||||
title: "Could not update the booking window",
|
|
||||||
description: parseError(err, "Update failed"),
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{windowTarget?.bookingWindowStatus === "CLOSED"
|
|
||||||
? "Open window"
|
|
||||||
: "Close window"}
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
opened={dispatchTarget != null}
|
opened={dispatchTarget != null}
|
||||||
onClose={() => setDispatchTarget(null)}
|
onClose={() => setDispatchTarget(null)}
|
||||||
|
|||||||
@@ -203,8 +203,6 @@ export interface TrainScheduleListItem {
|
|||||||
totalLengthMeters: number;
|
totalLengthMeters: number;
|
||||||
bookingsCount: number;
|
bookingsCount: number;
|
||||||
status: TrainScheduleStatus | string;
|
status: TrainScheduleStatus | string;
|
||||||
/** Whether the departure is still taking bookings (orthogonal to `status`). */
|
|
||||||
bookingWindowStatus?: "OPEN" | "FULL" | "CLOSED" | string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TrainScheduleSortField =
|
export type TrainScheduleSortField =
|
||||||
|
|||||||
Reference in New Issue
Block a user