mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 05:30:55 +00:00
Merge pull request #1430 from Tria-plc/freight_feature/usermanagement
feat: simplify dispatch logic by removing manual loading checks and u…
This commit is contained in:
@@ -135,14 +135,8 @@ export default function TrainScheduleV2DetailPage() {
|
||||
// Actual departure — staff often dispatch on paper first and record it later,
|
||||
// so the time is picked (defaults to now when the dialog opens).
|
||||
const [dispatchAt, setDispatchAt] = useState<Date | null>(null);
|
||||
// Loading is manual: dispatch decides the fate of every unloaded origin
|
||||
// boarder — checked = loaded and departs, unchecked = left behind (wagon
|
||||
// freed, booking back to the pool). Default unchecked; government bookings
|
||||
// cannot be removed from a train so they are forced on.
|
||||
const [dispatchLoadedIds, setDispatchLoadedIds] = useState<Set<string>>(new Set());
|
||||
const openDispatchConfirm = () => {
|
||||
setDispatchAt(new Date());
|
||||
setDispatchLoadedIds(new Set());
|
||||
setDispatchConfirmOpen(true);
|
||||
};
|
||||
const [switchTarget, setSwitchTarget] = useState<EligibleContainerBooking | null>(null);
|
||||
@@ -473,9 +467,8 @@ export default function TrainScheduleV2DetailPage() {
|
||||
// per yard from the track page's log-pass flow. Everything below is advisory.
|
||||
const hasDispatchWarnings =
|
||||
unassignedCount > 0 || unloadedCount > 0 || intercityNotLoadedCount > 0;
|
||||
// Unloaded boarders at the TRAIN's origin — the dispatch dialog's manual
|
||||
// load/leave list. Mirrors the API's unloadedOriginBoarderIds predicate
|
||||
// (plus government, which is shown but forced-loaded).
|
||||
// Unloaded boarders at the TRAIN's origin — all sent as loaded on dispatch.
|
||||
// Mirrors the API's unloadedOriginBoarderIds predicate (plus government).
|
||||
const originYardId = schedule.originStation?.id;
|
||||
const pendingOriginBoarders = dispatchBookings.filter(
|
||||
(b) =>
|
||||
@@ -489,12 +482,9 @@ export default function TrainScheduleV2DetailPage() {
|
||||
// Shipping-line bookings ride from accept on the credit ledger.
|
||||
(Boolean(b.shippingLineCompanyId) && b.status === "FULLY_EXECUTED")),
|
||||
);
|
||||
const dispatchLeftCount = pendingOriginBoarders.filter(
|
||||
(b) => !b.isGovernment && !dispatchLoadedIds.has(b.id),
|
||||
).length;
|
||||
// Origin loading time window: dispatch (which marks the ticked boarders
|
||||
// loaded) is server-rejected until "Start loading" was clicked for the
|
||||
// origin yard, so the button mirrors that gate.
|
||||
// Origin loading time window: dispatch (which marks the boarders loaded)
|
||||
// is server-rejected until "Start loading" was clicked for the origin
|
||||
// yard, so the button mirrors that gate.
|
||||
const originLoadingLog = originYardId
|
||||
? schedule.stationWorkLogs?.[originYardId]?.loading
|
||||
: undefined;
|
||||
@@ -557,9 +547,9 @@ export default function TrainScheduleV2DetailPage() {
|
||||
id: scheduleId,
|
||||
payload: {
|
||||
...(dispatchAt ? { actualDepartureAt: dispatchAt.toISOString() } : {}),
|
||||
loadedBookingIds: pendingOriginBoarders
|
||||
.filter((b) => b.isGovernment || dispatchLoadedIds.has(b.id))
|
||||
.map((b) => b.id),
|
||||
// No per-booking ticking in the dispatch dialog: every pending origin
|
||||
// boarder rides — none are left behind at dispatch time.
|
||||
loadedBookingIds: pendingOriginBoarders.map((b) => b.id),
|
||||
},
|
||||
});
|
||||
await openMarshallingDocument({
|
||||
@@ -1590,56 +1580,6 @@ export default function TrainScheduleV2DetailPage() {
|
||||
radius="md"
|
||||
/>
|
||||
|
||||
{pendingOriginBoarders.length > 0 ? (
|
||||
<Stack gap={6}>
|
||||
<Text size="sm" fw={700}>
|
||||
Cargo boarding at {schedule.originStation?.label ?? "the origin yard"} —
|
||||
tick what was loaded
|
||||
</Text>
|
||||
{originYardId ? (
|
||||
<StationWorkControls
|
||||
scheduleId={scheduleId}
|
||||
yardId={originYardId}
|
||||
phase="loading"
|
||||
log={originLoadingLog}
|
||||
/>
|
||||
) : null}
|
||||
<Text size="xs" c="dimmed">
|
||||
Unticked bookings are left behind: removed from this train, their
|
||||
wagons freed, and the booking returned to the pool for a later
|
||||
schedule. The customer is notified.
|
||||
</Text>
|
||||
<Stack gap={6} mah={220} style={{ overflowY: "auto" }}>
|
||||
{pendingOriginBoarders.map((b) => (
|
||||
<Checkbox
|
||||
key={b.id}
|
||||
size="sm"
|
||||
checked={b.isGovernment || dispatchLoadedIds.has(b.id)}
|
||||
disabled={b.isGovernment}
|
||||
onChange={(e) => {
|
||||
const next = new Set(dispatchLoadedIds);
|
||||
if (e.currentTarget.checked) next.add(b.id);
|
||||
else next.delete(b.id);
|
||||
setDispatchLoadedIds(next);
|
||||
}}
|
||||
label={
|
||||
<Text size="sm" span>
|
||||
{b.reference ?? b.id.slice(0, 8)} — {b.customer ?? "Unknown customer"}
|
||||
{b.isGovernment ? " (government — always rides)" : ""}
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
{dispatchLeftCount > 0 ? (
|
||||
<Text size="xs" c="orange.7" fw={600}>
|
||||
{dispatchLeftCount} booking{dispatchLeftCount === 1 ? "" : "s"} will
|
||||
be left behind and returned to the booking pool.
|
||||
</Text>
|
||||
) : null}
|
||||
</Stack>
|
||||
) : null}
|
||||
|
||||
{hasDispatchWarnings ? (
|
||||
<Alert
|
||||
color="orange"
|
||||
|
||||
Reference in New Issue
Block a user