mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 14:38:12 +00:00
leg-aware capacity and wagon sharing
This commit is contained in:
@@ -26,6 +26,8 @@ type DragState = { sourceWagonId: string } | null;
|
||||
interface InteractiveTrainConsistProps {
|
||||
wagons: Wagon[];
|
||||
locomotive: Locomotive | null | undefined;
|
||||
/** Full locomotive set (built trains, ≥2). Takes precedence over `locomotive`. */
|
||||
locomotives?: NonNullable<TrainScheduleDetail["trainSet"]>["locomotives"] | null;
|
||||
/** Resolve the customer/company name for a booking id (joined from schedule bookings). */
|
||||
getCompany: (bookingId: string | undefined) => string | null;
|
||||
selectedWagonId: string | null;
|
||||
@@ -557,6 +559,7 @@ function WagonCar({
|
||||
export const InteractiveTrainConsist = ({
|
||||
wagons,
|
||||
locomotive,
|
||||
locomotives,
|
||||
getCompany,
|
||||
selectedWagonId,
|
||||
onSelectWagon,
|
||||
@@ -565,6 +568,7 @@ export const InteractiveTrainConsist = ({
|
||||
onMoveLoad,
|
||||
}: InteractiveTrainConsistProps) => {
|
||||
const [drag, setDrag] = useState<DragState>(null);
|
||||
const locos = locomotives?.length ? locomotives : locomotive ? [locomotive] : [];
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
@@ -589,7 +593,12 @@ export const InteractiveTrainConsist = ({
|
||||
) : null}
|
||||
|
||||
<Group gap={0} wrap="nowrap" align="flex-start" style={{ minWidth: "min-content" }}>
|
||||
{locomotive ? <LocomotiveCar locomotive={locomotive} /> : null}
|
||||
{locos.map((loco, i) => (
|
||||
<Group key={loco.code ?? i} gap={0} wrap="nowrap" align="flex-start">
|
||||
{i > 0 ? <Coupler /> : null}
|
||||
<LocomotiveCar locomotive={loco} />
|
||||
</Group>
|
||||
))}
|
||||
{wagons.length === 0 ? (
|
||||
<Text size="sm" c="dimmed" pl="md" pt="lg">
|
||||
No wagons assigned
|
||||
@@ -599,7 +608,7 @@ export const InteractiveTrainConsist = ({
|
||||
const bookingId = wagon.allocations?.[0]?.bookingId;
|
||||
return (
|
||||
<Group key={wagon.id} gap={0} wrap="nowrap" align="flex-start">
|
||||
{i > 0 || locomotive ? <Coupler /> : null}
|
||||
{i > 0 || locos.length ? <Coupler /> : null}
|
||||
<WagonCar
|
||||
wagon={wagon}
|
||||
company={getCompany(bookingId)}
|
||||
|
||||
@@ -135,13 +135,27 @@ export const TrainConsistView = ({
|
||||
const weightUsed = cargoUsed + tareUsed;
|
||||
const lengthUsed = wagons.reduce((sum, w) => sum + (w.lengthMeters ?? 0), 0);
|
||||
|
||||
// Weakest locomotive caps the set — same rule the allocation engine applies.
|
||||
const locos = trainSet?.locomotives?.length
|
||||
? trainSet.locomotives
|
||||
: trainSet?.locomotive
|
||||
? [trainSet.locomotive]
|
||||
: [];
|
||||
const weightMax = locos.length
|
||||
? Math.min(...locos.map((l) => l.maxPullWeightTons))
|
||||
: null;
|
||||
const lengthCaps = locos
|
||||
.map((l) => l.maxTrainLengthMeters)
|
||||
.filter((v): v is number => v != null);
|
||||
const lengthMax = lengthCaps.length ? Math.min(...lengthCaps) : null;
|
||||
|
||||
return (
|
||||
<Stack gap="md" style={{ width: "100%" }}>
|
||||
<TrainStatsBar
|
||||
weightUsed={weightUsed}
|
||||
weightMax={trainSet?.locomotive?.maxPullWeightTons ?? null}
|
||||
weightMax={weightMax}
|
||||
lengthUsed={lengthUsed}
|
||||
lengthMax={trainSet?.locomotive?.maxTrainLengthMeters ?? null}
|
||||
lengthMax={lengthMax}
|
||||
wagonCount={loadedCount}
|
||||
wagonMax={maxWagons}
|
||||
/>
|
||||
@@ -202,6 +216,7 @@ export const TrainConsistView = ({
|
||||
<InteractiveTrainConsist
|
||||
wagons={wagons}
|
||||
locomotive={trainSet?.locomotive}
|
||||
locomotives={trainSet?.locomotives}
|
||||
getCompany={(bookingId) => (bookingId ? companyByBooking.get(bookingId) ?? null : null)}
|
||||
selectedWagonId={selectedWagonId}
|
||||
onSelectWagon={(w) => setSelectedWagonId((prev) => (prev === w.id ? null : w.id))}
|
||||
|
||||
Reference in New Issue
Block a user