import { Badge, Group, Pagination, Paper, Stack, Text, ThemeIcon, Timeline, } from "@mantine/core"; import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; import { ArrowLeftRight, History, MapPin, Minus, PackageCheck, PackageMinus, PackageOpen, Plus, User, } from "lucide-react"; import { api } from "@/services/api"; import type { ScheduleHistoryEntry } from "@/services/trainBuilder.service"; const ACTION_META: Record< ScheduleHistoryEntry["action"], { label: string; color: string; icon: typeof Plus } > = { ADD: { label: "Wagon coupled", color: "edr-green", icon: Plus }, REMOVE: { label: "Wagon trimmed", color: "red", icon: Minus }, SWITCH: { label: "Wagon switched", color: "blue", icon: ArrowLeftRight }, BOOKING_REMOVED: { label: "Booking removed", color: "orange", icon: PackageMinus }, BOOKING_LOADED: { label: "Booking loaded", color: "edr-green", icon: PackageCheck }, BOOKING_UNLOADED: { label: "Booking unloaded", color: "blue", icon: PackageOpen }, }; /** * "History" tab: every change made to the train after it was scheduled — * wagons coupled/trimmed/switched (with the stop where it happened) and * bookings removed from the composition — newest first. */ export default function ScheduleHistoryPanel({ scheduleId }: { scheduleId: string }) { const [page, setPage] = useState(1); const historyQuery = useQuery( api.trainScheduling.scheduleHistory.queryOptions({ input: { scheduleId, page, pageSize: 20 }, enabled: Boolean(scheduleId), // Keep the previous page on screen while the next one loads. placeholderData: (prev) => prev, }), ); const entries = historyQuery.data?.items ?? []; const totalPages = Math.max(1, historyQuery.data?.meta.totalPages ?? 1); const total = historyQuery.data?.meta.total ?? 0; return ( Change history Wagons coupled, trimmed or switched, bookings loaded/unloaded per yard, and bookings removed — after this train was scheduled, newest first. {historyQuery.isLoading ? ( Loading history… ) : entries.length === 0 ? ( No changes recorded yet — the consist and composition are as scheduled. ) : ( {entries.map((entry) => { const meta = ACTION_META[entry.action] ?? ACTION_META.ADD; const Icon = meta.icon; return ( } color={meta.color} title={ {meta.label} {entry.subject ? ( {entry.subject} ) : null} } > {new Date(entry.occurredAt).toLocaleString()} {entry.yardLabel ? ( at {entry.yardLabel} ) : null} {entry.actor ? ( {entry.actor} ) : null} {entry.note ? ( {entry.note} ) : null} ); })} )} {totalPages > 1 ? ( {total} change(s) ) : null} ); }