updates
This commit is contained in:
@@ -15,6 +15,7 @@ import { OpenToast } from 'components/nearle_components/OpenToast';
|
|||||||
const ActiveSection = ({
|
const ActiveSection = ({
|
||||||
visibleRiders,
|
visibleRiders,
|
||||||
riders,
|
riders,
|
||||||
|
resetKey,
|
||||||
focusedStop,
|
focusedStop,
|
||||||
handleRiderFocus,
|
handleRiderFocus,
|
||||||
setFocusedStop,
|
setFocusedStop,
|
||||||
@@ -35,6 +36,14 @@ const ActiveSection = ({
|
|||||||
|
|
||||||
// Toast notifications: detect status transitions across renders
|
// Toast notifications: detect status transitions across renders
|
||||||
const prevStatusMapRef = useRef(null);
|
const prevStatusMapRef = useRef(null);
|
||||||
|
// Tracks which batch/date/location the baseline above belongs to. When it
|
||||||
|
// changes (e.g. operator switches Morning Batch → Afternoon Batch) the
|
||||||
|
// whole order set is replaced wholesale — that is a view switch, not a
|
||||||
|
// stream of real status transitions, so we must reseed the baseline
|
||||||
|
// silently instead of diffing against the old batch's orders (which would
|
||||||
|
// otherwise treat every order in the new batch as "brand-new and already
|
||||||
|
// active" and re-fire the delivering/reached toasts for all of them).
|
||||||
|
const prevResetKeyRef = useRef(resetKey);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentMap = {};
|
const currentMap = {};
|
||||||
@@ -48,8 +57,9 @@ const ActiveSection = ({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const viewSwitched = prevResetKeyRef.current !== resetKey;
|
||||||
const prev = prevStatusMapRef.current;
|
const prev = prevStatusMapRef.current;
|
||||||
if (prev !== null) {
|
if (prev !== null && !viewSwitched) {
|
||||||
Object.entries(currentMap).forEach(([oid, cur]) => {
|
Object.entries(currentMap).forEach(([oid, cur]) => {
|
||||||
const old = prev[oid];
|
const old = prev[oid];
|
||||||
if (!old) {
|
if (!old) {
|
||||||
@@ -71,7 +81,8 @@ const ActiveSection = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
prevStatusMapRef.current = currentMap;
|
prevStatusMapRef.current = currentMap;
|
||||||
}, [visibleRiders]);
|
prevResetKeyRef.current = resetKey;
|
||||||
|
}, [visibleRiders, resetKey]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1606,9 +1606,10 @@ const Dispatch = ({
|
|||||||
: riders,
|
: riders,
|
||||||
[isAllActiveView, riders, activeOrderRiderIdSet]
|
[isAllActiveView, riders, activeOrderRiderIdSet]
|
||||||
);
|
);
|
||||||
// Active section sidebar riders — built from the FULL day's unfiltered rows
|
// Active section sidebar riders — built from the currently selected batch's
|
||||||
// (liveRows, all batches, no GPS-status gate). Uses a sticky cache so cards
|
// rows (filteredLiveRows), so switching to e.g. "Afternoon Batch" doesn't
|
||||||
// only disappear when the API returns an explicit terminal status (delivered /
|
// keep showing morning-batch orders. Uses a sticky cache so cards only
|
||||||
|
// disappear when the API returns an explicit terminal status (delivered /
|
||||||
// cancelled / skipped). Temporary row omissions during the 15-second poll
|
// cancelled / skipped). Temporary row omissions during the 15-second poll
|
||||||
// cycle (single-page refetch, brief API inconsistency) no longer cause cards
|
// cycle (single-page refetch, brief API inconsistency) no longer cause cards
|
||||||
// to flash away and reappear.
|
// to flash away and reappear.
|
||||||
@@ -1620,7 +1621,7 @@ const Dispatch = ({
|
|||||||
|
|
||||||
const TERMINAL = new Set(['delivered', 'cancelled', 'skipped', 'complete', 'completed']);
|
const TERMINAL = new Set(['delivered', 'cancelled', 'skipped', 'complete', 'completed']);
|
||||||
|
|
||||||
liveRows.forEach((o) => {
|
filteredLiveRows.forEach((o) => {
|
||||||
const id = String(o.orderid);
|
const id = String(o.orderid);
|
||||||
const s = String(o.orderstatus || '').toLowerCase();
|
const s = String(o.orderstatus || '').toLowerCase();
|
||||||
if (s === 'active') {
|
if (s === 'active') {
|
||||||
@@ -1653,7 +1654,7 @@ const Dispatch = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Object.values(byRider);
|
return Object.values(byRider);
|
||||||
}, [isAllActiveView, liveRows, riders]);
|
}, [isAllActiveView, filteredLiveRows, riders]);
|
||||||
// Live GPS coordinates of exactly the riders this view shows (active + has an
|
// Live GPS coordinates of exactly the riders this view shows (active + has an
|
||||||
// order), fed to MapController's auto-fit so the map frames what's rendered.
|
// order), fed to MapController's auto-fit so the map frames what's rendered.
|
||||||
const allViewLivePoints = useMemo(
|
const allViewLivePoints = useMemo(
|
||||||
@@ -1666,11 +1667,13 @@ const Dispatch = ({
|
|||||||
[isAllActiveView, liveRiderLocations, activeOrderRiderIdSet]
|
[isAllActiveView, liveRiderLocations, activeOrderRiderIdSet]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clear the sticky Active-view cache when the operator switches date or hub —
|
// Clear the sticky Active-view cache when the operator switches date, hub, or
|
||||||
// otherwise cards from a previously viewed day/location could linger.
|
// batch — otherwise cards from a previously viewed day/location/batch (e.g.
|
||||||
|
// Morning Batch orders still marked "active") could linger after switching
|
||||||
|
// to Afternoon Batch.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
stickyActiveRef.current = {};
|
stickyActiveRef.current = {};
|
||||||
}, [selectedDate, selectedAppLocationId]);
|
}, [selectedDate, selectedAppLocationId, selectedBatch, selectedTimeField]);
|
||||||
|
|
||||||
// Per-rider canvas renderer for the actual (right) map in Compare mode.
|
// Per-rider canvas renderer for the actual (right) map in Compare mode.
|
||||||
// Single setter used by every interactive site in the UI. In uncontrolled mode it
|
// Single setter used by every interactive site in the UI. In uncontrolled mode it
|
||||||
@@ -1752,14 +1755,15 @@ const Dispatch = ({
|
|||||||
}
|
}
|
||||||
// "All Active Routes": the header must reflect exactly what the list/map
|
// "All Active Routes": the header must reflect exactly what the list/map
|
||||||
// shows — the in-progress orders and the riders working them — NOT the whole
|
// shows — the in-progress orders and the riders working them — NOT the whole
|
||||||
// day's totals. We count only active deliveries (and `visibleRiders`, which
|
// day's totals. Derived from `activeViewRiders` (the same sticky-cached data
|
||||||
// is already gated to active-order riders) so the tiles can't disagree with
|
// the sidebar list below renders) instead of the GPS-status-gated
|
||||||
// the list/map below.
|
// allViewOrders/visibleRiders, which could disagree with the list and read
|
||||||
|
// 0 even while riders/orders are visible below.
|
||||||
if (isAllActiveView) {
|
if (isAllActiveView) {
|
||||||
const activeOrders = allViewOrders.filter((o) => String(o?.orderstatus || '').toLowerCase() === 'active');
|
const activeOrders = activeViewRiders.flatMap((r) => r.orders);
|
||||||
return {
|
return {
|
||||||
orders: activeOrders.length,
|
orders: activeOrders.length,
|
||||||
riders: visibleRiders.length,
|
riders: activeViewRiders.length,
|
||||||
km: activeOrders.reduce((s, o) => s + parseFloat(o.actualkms || o.kms || 0), 0),
|
km: activeOrders.reduce((s, o) => s + parseFloat(o.actualkms || o.kms || 0), 0),
|
||||||
profit: activeOrders.reduce((s, o) => s + parseFloat(o.profit || 0), 0),
|
profit: activeOrders.reduce((s, o) => s + parseFloat(o.profit || 0), 0),
|
||||||
label: 'Active Fleet'
|
label: 'Active Fleet'
|
||||||
@@ -1772,7 +1776,7 @@ const Dispatch = ({
|
|||||||
profit: stats.totalProfit,
|
profit: stats.totalProfit,
|
||||||
label: 'Total Fleet'
|
label: 'Total Fleet'
|
||||||
};
|
};
|
||||||
}, [focusedRider, focusedKitchen, isAllActiveView, allViewOrders, visibleRiders, stats]);
|
}, [focusedRider, focusedKitchen, isAllActiveView, activeViewRiders, stats]);
|
||||||
|
|
||||||
// Count of in-progress deliveries shown in the Active view list. Derives from
|
// Count of in-progress deliveries shown in the Active view list. Derives from
|
||||||
// the sticky cache (via activeViewRiders) so header and card list always agree.
|
// the sticky cache (via activeViewRiders) so header and card list always agree.
|
||||||
@@ -4605,6 +4609,7 @@ const Dispatch = ({
|
|||||||
<ActiveSection
|
<ActiveSection
|
||||||
visibleRiders={activeViewRiders}
|
visibleRiders={activeViewRiders}
|
||||||
riders={riders}
|
riders={riders}
|
||||||
|
resetKey={`${selectedDate}|${selectedAppLocationId}|${selectedBatch}`}
|
||||||
focusedStop={focusedStop}
|
focusedStop={focusedStop}
|
||||||
handleRiderFocus={handleRiderFocus}
|
handleRiderFocus={handleRiderFocus}
|
||||||
setFocusedStop={setFocusedStop}
|
setFocusedStop={setFocusedStop}
|
||||||
|
|||||||
Reference in New Issue
Block a user