- {r.orders.reduce((s, o) => s + parseFloat(o.actualkms || o.kms || 0), 0).toFixed(1)} km
- {estMeters !== null && (
-
- {formatMeters(estMeters)} to drop
-
+ {isGpsOnly ? (
+
+ LIVE
+
+ ) : (
+
+ {delivered}/{total}
+
)}
-
- {r.orders.slice(0, 15).map(o => S{o.step})}
-
+ {!isGpsOnly && (
+ <>
+
+
+ {r.orders.reduce((s, o) => s + parseFloat(o.actualkms || o.kms || 0), 0).toFixed(1)} km
+ {estMeters !== null && (
+
+ {formatMeters(estMeters)} to drop
+
+ )}
+
+
+ {r.orders.slice(0, 15).map(o => S{o.step})}
+
+ >
+ )}
);
};
@@ -2298,6 +2539,11 @@ const Dispatch = ({
{o.rider_name || o.ridername || 'Unassigned'}
+ {(o.deliverycustomer || o.customername) && (
+
+ {o.deliverycustomer || o.customername}
+
+ )}
{o.deliveryid != null && (
Delivery #{o.deliveryid}
)}
@@ -2412,7 +2658,9 @@ const Dispatch = ({
// duplicate, slightly-offset pins that clutter the view.
if (compareOpen && focusedRider && compareViewMode === 'actual') return null;
- let ordersToRender = allOrders;
+ // In "All Active Routes" view the base set is restricted to active riders'
+ // orders (allViewOrders); a focus selection still overrides as usual.
+ let ordersToRender = allViewOrders;
if (focusedZone) ordersToRender = focusedZone.orders;
if (focusedKitchen) ordersToRender = focusedKitchen.orders;
if (focusedRider) ordersToRender = focusedRider.orders;
@@ -2531,7 +2779,9 @@ const Dispatch = ({
const routes = [];
const zoneRiderIds = focusedZone ? new Set(focusedZone.riders.map((zr) => String(zr.rider_id))) : null;
if (hidePlanned) return routes;
- riders.forEach(r => {
+ // visibleRiders === riders in every view except "All Active Routes", where
+ // it's pre-filtered to riders whose live GPS is currently active.
+ visibleRiders.forEach(r => {
const isActive = activeRiders.has(r.id);
if (focusedRider && focusedRider.id !== r.id) return;
if (focusedKitchen && !focusedKitchen.riders.has(r.id)) return;
@@ -3025,7 +3275,7 @@ const Dispatch = ({
onClick={() => { logger.info('View mode changed: By Zone'); setViewMode('zones'); handleRiderFocus(null); setFocusedKitchen(null); setFocusedZone(null); }}
> By Zone
-
+
@@ -4140,7 +4458,7 @@ const Dispatch = ({
{compareOpen && }
-
+
{kitchens
.filter(k => Number.isFinite(k.lat) && Number.isFinite(k.lon))
.filter(k => !focusedRider || k.riders.has(focusedRider.id))
@@ -4173,14 +4491,23 @@ const Dispatch = ({
{/* Live rider GPS markers from /partners/getriderlogs/. Mirrors the
Reports → Riders Logs map: green pin when the rider's last log
row is `active`, red otherwise, with the rider's username as a
- label. Scoped to riders who actually have orders in the
- currently selected slot — `riders` is derived from
- filteredLiveRows so it already reflects the slot filter. A
- rider with zero orders in the current slot is hidden, even if
- getriderlogs still returns their GPS row. When a specific
- rider is focused, only that one is shown. */}
+ label.
+
+ "All Active Routes" view: show EVERY active rider's live GPS —
+ including riders with no orders in the current slot (those get a
+ bike marker only, no route). Riders with an active delivery also
+ get their route drawn by renderRoutes(). Other views stay scoped
+ to riders who actually have orders in the slot (`riders` is
+ derived from filteredLiveRows so it already reflects the slot
+ filter); a rider with zero orders is hidden there even if
+ getriderlogs still returns their GPS row. When a specific rider
+ is focused, only that one is shown. */}
{liveRiderLocations
- .filter((r) => riders.some((rd) => String(rd.id) === String(r.id)))
+ .filter((r) =>
+ isAllActiveView
+ ? r.status === 'active'
+ : riders.some((rd) => String(rd.id) === String(r.id))
+ )
.filter((r) => !focusedRider || String(focusedRider.id) === String(r.id))
.map((r) => {
const isActive = r.status === 'active';
@@ -4204,39 +4531,82 @@ const Dispatch = ({
const nextDropArea = nextOrder
? (nextOrder.deliverysuburb || extractArea(nextOrder.deliveryaddress))
: null;
- const liveIcon = L.divIcon({
- className: '',
- iconSize: [140, 56],
- iconAnchor: [12, 41],
- popupAnchor: [58, -40],
- html: `