Replace wagon/locomotive readiness with yard tracking, assign unassigned bookings from origin-yard fleet, standardize rates on USD with CBE ETB conversion, and update fleet/scheduling UI

This commit is contained in:
marshal
2026-06-14 01:32:39 +03:00
parent b73bf2154e
commit 87b0ce6339
45 changed files with 1249 additions and 520 deletions

View File

@@ -90,7 +90,7 @@ export default function TrainScheduleTrackPage() {
onSuccess: () => {
toast({
title: isFinal
? "Train arrived — assets freed, readiness flipped"
? "Train arrived — assets freed, moved to destination yard"
: "Checkpoint logged",
});
},

View File

@@ -785,11 +785,11 @@ export default function TrainScheduleV2DetailPage() {
label="Locomotive"
value={schedule.trainSet?.locomotive?.code ?? "—"}
hint={
schedule.trainSet?.locomotive?.readiness === "EXPORT_READY"
? "Export-ready"
: schedule.trainSet?.locomotive?.readiness === "IMPORT_READY"
? "Import-ready"
: undefined
schedule.trainSet?.locomotive?.currentYardId
? schedule.trainSet.locomotive.currentYardId === schedule.originStation?.id
? `At ${schedule.originStation?.label ?? schedule.originStation?.code ?? "origin yard"}`
: "Not at schedule origin yard"
: "No current yard set"
}
accent="#F2A516"
graph="area"

View File

@@ -89,15 +89,13 @@ export default function TrainScheduleV2ListPage() {
const selectedRoute = activeRoutes.find((r) => r.id === routeId);
const locomotiveReadinessHint = useMemo(() => {
const locomotiveYardHint = useMemo(() => {
if (!selectedRoute) return "Select a route first";
const origin = selectedRoute.originYard?.country?.trim();
const dest = selectedRoute.destinationYard?.country?.trim();
if (origin === "Djibouti") return "Import corridor — import-ready locomotives only";
if (dest === "Djibouti" && origin !== "Djibouti") {
return "Export corridor — export-ready locomotives only";
}
return "Domestic corridor — any readiness";
const originLabel =
selectedRoute.originYard?.label ??
selectedRoute.originYard?.code ??
"the route origin yard";
return `Only locomotives currently at ${originLabel} are shown`;
}, [selectedRoute]);
useEffect(() => {
@@ -525,7 +523,7 @@ export default function TrainScheduleV2ListPage() {
/>
{routeId ? (
<Text size="xs" c="dimmed">
{locomotiveReadinessHint}
{locomotiveYardHint}
</Text>
) : null}
<TextInput
@@ -542,9 +540,7 @@ export default function TrainScheduleV2ListPage() {
placeholder={routeId ? "Select locomotive" : "Select a route first"}
data={(locomotivesQuery.data ?? []).map((l) => ({
value: l.id,
label: `${l.code}${l.name ? `${l.name}` : ""} · ${
l.readiness === "EXPORT_READY" ? "Export-ready" : "Import-ready"
}`,
label: `${l.code}${l.name ? `${l.name}` : ""}`,
}))}
value={locomotiveId || null}
onChange={(v) => setLocomotiveId(v ?? "")}