mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 23:28:11 +00:00
feat: implement wagon transfer management modals and page
- Add TransferFulfillModal for fulfilling wagon transfer requests. - Create TransferRequestFormModal for filing new wagon transfer requests. - Introduce TransferCloseShortModal for closing requests that cannot be fully fulfilled. - Develop WagonTransfersPage to manage and display wagon transfer requests. - Implement utility functions for handling wagon transfer request data and UI components. - Enhance UI with Mantine components for better user experience.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Draw order for a schedule's consist.
|
||||
*
|
||||
* A slot's stored `sequenceNo` is its place in the wagon PLAN, not its place in
|
||||
* the train. The train's real coupling order lives on the physical wagons
|
||||
* (`wagons.sequence_number`), which the caller passes in already ordered — ASC
|
||||
* normally, DESC for a `reverseWagonOrder` schedule.
|
||||
*
|
||||
* Ordering by the physical wagon is what keeps the drawing honest:
|
||||
* - moving a load between wagons repaints WHICH wagon is loaded and never
|
||||
* shuffles the train, because each slot is drawn wherever its wagon sits;
|
||||
* - a train-builder reorder lands on the next read, allocations included,
|
||||
* since the order is derived on every read instead of copied at pin time.
|
||||
*
|
||||
* Slots with no physical wagon (not pinned yet, or a schedule that isn't tied
|
||||
* to a built train) have no place in the consist — they keep slot order, last.
|
||||
*/
|
||||
export interface ConsistOrderable {
|
||||
sequenceNo: number;
|
||||
physicalWagonId?: string | null;
|
||||
}
|
||||
|
||||
export interface ConsistOrderOptions {
|
||||
/**
|
||||
* Every wagon coupled to the built train, in real coupling order (already
|
||||
* reversed by the caller for a `reverseWagonOrder` schedule). Empty for a
|
||||
* frozen schedule or one with no built train — the consist then keeps slot
|
||||
* order.
|
||||
*/
|
||||
physicalWagonIdsInOrder: string[];
|
||||
reverseWagonOrder?: boolean;
|
||||
}
|
||||
|
||||
export const orderConsistWagons = <T extends ConsistOrderable>(
|
||||
wagons: T[],
|
||||
{ physicalWagonIdsInOrder, reverseWagonOrder }: ConsistOrderOptions,
|
||||
): (T & { position: number })[] => {
|
||||
const physicalOrder = new Map(physicalWagonIdsInOrder.map((id, index) => [id, index]));
|
||||
const bySlotSequence = (a: T, b: T) =>
|
||||
reverseWagonOrder ? b.sequenceNo - a.sequenceNo : a.sequenceNo - b.sequenceNo;
|
||||
|
||||
const ordered = physicalOrder.size
|
||||
? [...wagons].sort((a, b) => {
|
||||
const ai = a.physicalWagonId ? physicalOrder.get(a.physicalWagonId) : undefined;
|
||||
const bi = b.physicalWagonId ? physicalOrder.get(b.physicalWagonId) : undefined;
|
||||
if (ai == null && bi == null) return bySlotSequence(a, b);
|
||||
if (ai == null) return 1;
|
||||
if (bi == null) return -1;
|
||||
return ai - bi;
|
||||
})
|
||||
: [...wagons].sort(bySlotSequence);
|
||||
|
||||
return ordered.map((wagon, index) => ({ ...wagon, position: index + 1 }));
|
||||
};
|
||||
Reference in New Issue
Block a user