diff --git a/apps/edr-freight-web/backoffice/src/components/trainBuilder/BuildTrainModal.tsx b/apps/edr-freight-web/backoffice/src/components/trainBuilder/BuildTrainModal.tsx
index 7f60cabe9..49dd19bcc 100644
--- a/apps/edr-freight-web/backoffice/src/components/trainBuilder/BuildTrainModal.tsx
+++ b/apps/edr-freight-web/backoffice/src/components/trainBuilder/BuildTrainModal.tsx
@@ -16,6 +16,7 @@ import { useEffect, useState } from "react";
import { api } from "@/services/api";
import type { TrainComposition } from "@/services/trainBuilder.service";
import { useToast } from "@/hooks/use-toast";
+import { EXPORT_TRAIN_OPTIONS, importRunFor } from "@/constants/trainRuns";
const parseError = (error: unknown, fallback: string) => {
if (isAxiosError(error)) {
@@ -26,10 +27,6 @@ const parseError = (error: unknown, fallback: string) => {
return fallback;
};
-// Run-number parity carries the trade direction: odd = export, even = import.
-const isOddNumber = (value: string) => /^\d*[13579]$/.test(value.trim());
-const isEvenNumber = (value: string) => /^\d*[02468]$/.test(value.trim());
-
/**
* Step one of the Train Builder: pick the yard it is being assembled in and
* couple at least two locomotives from that yard. The train code is assigned by
@@ -59,6 +56,12 @@ export default function BuildTrainModal({ opened, onClose, onBuilt }: BuildTrain
setLocomotiveIds([]);
}, [yardId]);
+ // The import run is fixed by the export run, so it tracks it rather than
+ // being entered by hand (and clears back to empty when the export is cleared).
+ useEffect(() => {
+ setImportTrainNumber(importRunFor(exportTrainNumber));
+ }, [exportTrainNumber]);
+
useEffect(() => {
if (!opened) {
setExportTrainNumber("");
@@ -78,9 +81,11 @@ export default function BuildTrainModal({ opened, onClose, onBuilt }: BuildTrain
});
return;
}
- if (!isOddNumber(exportTrainNumber) || !isEvenNumber(importTrainNumber)) {
+ // Both numbers come from the fixed run pairs, so parity cannot be wrong —
+ // only "nothing picked" is reachable here.
+ if (!exportTrainNumber || !importTrainNumber) {
toast({
- title: "Enter both run numbers — export must be odd (e.g. 8001), import even (e.g. 8002)",
+ title: "Pick an export train number (e.g. 8001) — the import run follows it",
variant: "destructive",
});
return;
@@ -133,31 +138,24 @@ export default function BuildTrainModal({ opened, onClose, onBuilt }: BuildTrain
maxLength={100}
/>
- setExportTrainNumber(e.currentTarget.value)}
- maxLength={20}
- error={
- exportTrainNumber && !isOddNumber(exportTrainNumber)
- ? "Must be numeric and odd"
- : undefined
- }
+ data={EXPORT_TRAIN_OPTIONS}
+ value={exportTrainNumber || null}
+ onChange={(value) => setExportTrainNumber(value ?? "")}
+ searchable
+ clearable
/>
+ {/* Fixed by the export run — derived, never typed. */}
setImportTrainNumber(e.currentTarget.value)}
- maxLength={20}
- error={
- importTrainNumber && !isEvenNumber(importTrainNumber)
- ? "Must be numeric and even"
- : undefined
- }
+ readOnly
+ variant="filled"
/>