feat(train): enhance train history and scheduling features

- Added a reason field to train history entries for detach/maintenance actions.
- Updated TrainHistoryPanel to display the reason for wagon detachments.
- Introduced per-wagon load/unload functionality in ScheduleWorkspacePanel with a modal for managing individual wagons.
- Implemented API endpoints for loading and unloading specific wagons, including the ability to cancel remaining wagons with a reason.
- Refactored detach request handling in TrainBuilderDetailPage to streamline the process and remove the approval flow, requiring a reason for detachments.
- Updated types and services to support new wagon loading/unloading features and booking wagon retrieval.
This commit is contained in:
Marshal
2026-08-28 07:33:28 +00:00
parent 8b8870e85e
commit ba56974e32
26 changed files with 1435 additions and 583 deletions

View File

@@ -1,6 +1,15 @@
import { Badge, Group, Pagination, Paper, Stack, Text, ThemeIcon, Timeline } from "@mantine/core";
import { useQuery } from "@tanstack/react-query";
import { ArrowLeftRight, History, MapPin, Minus, Plus, TrainFront, User } from "lucide-react";
import {
ArrowLeftRight,
History,
MapPin,
MessageSquare,
Minus,
Plus,
TrainFront,
User,
} from "lucide-react";
import { useState } from "react";
import { api } from "@/services/api";
@@ -49,7 +58,8 @@ export default function TrainHistoryPanel({ trainId }: { trainId: string }) {
</Text>
<Text size="sm" c="dimmed">
Who attached, detached or switched which wagon on this train from
the builder and from its trips newest first.
the builder and from its trips newest first, with the reason
given for detaching off a scheduled run.
</Text>
</Stack>
</Group>
@@ -120,6 +130,17 @@ export default function TrainHistoryPanel({ trainId }: { trainId: string }) {
</Group>
) : null}
</Group>
{entry.reason ? (
<Group gap={4} wrap="nowrap" align="flex-start" mt={4}>
<MessageSquare
size={12}
style={{ flexShrink: 0, marginTop: 3 }}
/>
<Text size="xs" c="dimmed" style={{ fontStyle: "italic" }}>
{entry.reason}
</Text>
</Group>
) : null}
</Timeline.Item>
);
})}