remove reopen delay minutes from global rules and update related types

- Removed the  field from  and related components.
- Updated  to reflect the removal of the reopen delay input field.
- Modified  to include new train number fields:  and .
- Added  interface to manage active schedules with trade direction.
- Introduced  interface to track wagon shortages in bookings.
- Updated  logic to ensure consistent UI state representation.
- Created migrations to drop the  column and add  and  columns to the  table.
- Added tests for the new booking window display logic and wagon planning functionality.
This commit is contained in:
Marshal
2026-07-15 09:13:02 +00:00
parent 9be7f356f0
commit 11771e5f92
39 changed files with 1731 additions and 269 deletions

View File

@@ -32,7 +32,11 @@ import AvailableWagonsPanel from "@/components/trainBuilder/AvailableWagonsPanel
import ChangeLocomotivesModal from "@/components/trainBuilder/ChangeLocomotivesModal";
import ChangeYardModal from "@/components/trainBuilder/ChangeYardModal";
import ConsistWagonList from "@/components/trainBuilder/ConsistWagonList";
import { trainStatusColor, trainStatusLabel } from "@/components/trainBuilder/trainStatus";
import {
directionColor,
trainStatusColor,
trainStatusLabel,
} from "@/components/trainBuilder/trainStatus";
import { TrainCompositionDiagram } from "@/components/trainScheduling/TrainCompositionDiagram";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { api } from "@/services/api";
@@ -128,9 +132,17 @@ export default function TrainBuilderDetailPage() {
}
backTo="/dashboard/train-builder"
meta={
<Badge color={trainStatusColor(composition.status)} variant="light">
{trainStatusLabel(composition.status)}
</Badge>
<Group gap="xs">
<Badge color={trainStatusColor(composition.status)} variant="light">
{trainStatusLabel(composition.status)}
</Badge>
<Badge color="blue" variant="light" ff="monospace">
IMP {composition.importTrainNumber ?? "—"}
</Badge>
<Badge color="orange" variant="light" ff="monospace">
EXP {composition.exportTrainNumber ?? "—"}
</Badge>
</Group>
}
action={
<Menu position="bottom-end" withinPortal shadow="md" width={220}>
@@ -289,6 +301,16 @@ export default function TrainBuilderDetailPage() {
<Text size="sm" ff="monospace" fw={600}>
{schedule.reference ?? schedule.id.slice(0, 8)}
</Text>
{schedule.trainNumber ? (
<Text size="sm" ff="monospace" fw={700}>
{schedule.trainNumber}
</Text>
) : null}
{schedule.direction ? (
<Badge size="sm" variant="light" color={directionColor(schedule.direction)}>
{schedule.direction}
</Badge>
) : null}
<Badge size="sm" variant="light">
{schedule.status}
</Badge>

View File

@@ -27,7 +27,12 @@ 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 { trainStatusColor, trainStatusLabel } from "@/components/trainBuilder/trainStatus";
import {
directionColor,
directionRowStyle,
trainStatusColor,
trainStatusLabel,
} from "@/components/trainBuilder/trainStatus";
import { api } from "@/services/api";
import type {
BuiltTrainListFilters,
@@ -146,6 +151,32 @@ export default function TrainBuilderListPage() {
</Group>
),
},
{
id: "numbers",
header: "Train No.",
meta: { headerClassName, cellClassName },
cell: ({ row }) => {
const active = row.original.activeSchedule;
return (
<Stack gap={2}>
{active?.trainNumber ? (
<Group gap={6} wrap="nowrap">
<Text size="sm" fw={700} ff="monospace" lh={1.2}>
{active.trainNumber}
</Text>
<Badge size="xs" variant="light" color={directionColor(active.direction)}>
{active.direction ?? "—"}
</Badge>
</Group>
) : null}
<Text size="xs" c="dimmed" ff="monospace" lh={1.2}>
IMP {row.original.importTrainNumber ?? "—"} · EXP{" "}
{row.original.exportTrainNumber ?? "—"}
</Text>
</Stack>
);
},
},
{
id: "yard",
header: "Yard",
@@ -293,6 +324,7 @@ export default function TrainBuilderListPage() {
data={trains}
status={tableStatus}
onRowClick={(train) => navigate(`/dashboard/train-builder/${train.id}`)}
rowStyle={(train) => directionRowStyle(train.activeSchedule?.direction)}
error={
trainsQuery.isError
? {