- {o.orderstatus && (() => {
- const s = getStatusStyle(o.orderstatus);
- const isDel = String(o.orderstatus || '').toLowerCase() === 'delivered';
- return (
-
- );
- })()}
+
+
{o.step || idx + 1}
+
-
Order #{o.orderid}
- {/* Show the customer's delivery address rather than the kitchen's
- pickup location (locationname/locationsuburb) — the kitchen is
- already implied by the surrounding trip header. */}
- {(o.deliveryaddress || o.deliverysuburb) && (
-
- {o.deliveryaddress || o.deliverysuburb}
-
- )}
- {o.ordernotes && (
-
{o.ordernotes}
- )}
-
-
{o.actualkms || o.kms || 0} km
- {(() => {
- const p = parseFloat(o.profit || 0);
- const isLoss = p < 0;
- return (
-
- {isLoss ? '-' : ''}₹{Math.abs(p).toFixed(0)}
-
- );
- })()}
- {o.deliverycharge != null && (
-
₹{parseFloat(o.deliverycharge).toFixed(0)} chg
- )}
- {o.ordertype && (
-
{o.ordertype}
- )}
+ {(() => {
+ // Stack the status pill and delivery time vertically on
+ // the right of the header so the operator sees the order
+ // outcome and the wall-clock time it landed at a glance.
+ const actual = formatTimeOnly(o.deliverytime);
+ const expected = formatTimeOnly(o.expecteddeliverytime);
+ if (!o.orderstatus && !actual && !expected) return null;
+ return (
+
+ {o.orderstatus && (
+
+ {statusStyle.label}
+
+ )}
+ {(actual || expected) && (
+
+ {actual || expected}
+
+ )}
+
+ );
+ })()}
+
+
+
+ {o.deliverycustomer || '—'}
+
+
+ {o.pickupcustomer && (
+
+ {o.pickupcustomer}
+ )}
+ {(o.deliveryaddress || o.deliverysuburb) && (
+
+ {o.deliveryaddress || o.deliverysuburb}
+
+ )}
+ {o.ordernotes && (
+
+ {o.ordernotes}
+
+ )}
+
+
+
+ {o.actualkms || o.kms || 0} km
+
+
+ {isLoss ? '-' : ''}₹{Math.abs(profit).toFixed(0)}
+
+ {o.deliverycharge != null && (
+
+ ₹{parseFloat(o.deliverycharge).toFixed(0)} chg
+
+ )}
+ {o.ordertype && (
+
+ {o.ordertype}
+
+ )}
+
+ T{o.trip_number || tNum} · S{o.step || idx + 1}
+
- );
- })()}
);
})}
@@ -1396,167 +1895,98 @@ const Dispatch = ({
- {/* Status breakdown */}
- {Object.keys(focusedZone.statusCounts).length > 0 && focusedZone.totalOrders > 0 && (
-
-
Status Breakdown
-
- {Object.entries(focusedZone.statusCounts).map(([status, count]) => {
- const style = getStatusStyle(status);
- const pct = (count / focusedZone.totalOrders) * 100;
+
+
Orders ({focusedZone.orders.length})
+ {focusedZone.orders.length === 0 ? (
+
No orders in this zone.
+ ) : (
+
+ {focusedZone.orders.map((o, idx) => {
+ const lat = parseFloat(o.droplat || o.deliverylat);
+ const lon = parseFloat(o.droplon || o.deliverylong);
+ const canFocus = Number.isFinite(lat) && Number.isFinite(lon);
+ const isStopActive = focusedStop && focusedStop.orderid === o.orderid;
+ const statusStyle = getStatusStyle(o.orderstatus);
+ const profit = parseFloat(o.profit || 0);
+ const isLoss = profit < 0;
return (
setFocusedStop(isStopActive ? null : { orderid: o.orderid, lat, lon }) : undefined}
>
- {pct > 7 &&
{count} }
+
+
+ {idx + 1}
+
+
+
Order #{o.orderid}
+
+ {o.rider_name || o.ridername || 'Unassigned'}
+
+
+ {o.orderstatus && (
+
+ {statusStyle.label}
+
+ )}
+
+
+
+ {o.deliverycustomer || '—'}
+
+
+ {o.pickupcustomer && (
+
+ {o.pickupcustomer}
+
+ )}
+ {(o.deliveryaddress || o.deliverysuburb) && (
+
+ {o.deliveryaddress || o.deliverysuburb}
+
+ )}
+ {o.ordernotes && (
+
+ {o.ordernotes}
+
+ )}
+
+
+
+ {o.actualkms || o.kms || 0} km
+
+
+ {isLoss ? '-' : ''}₹{Math.abs(profit).toFixed(0)}
+
+ {o.deliverycharge != null && (
+
+ ₹{parseFloat(o.deliverycharge).toFixed(0)} chg
+
+ )}
+ {o.ordertype && (
+
+ {o.ordertype}
+
+ )}
+
+ T{o.trip_number || '-'} · S{o.step || '-'}
+
+
);
})}
-
- {Object.entries(focusedZone.statusCounts).map(([status, count]) => {
- const style = getStatusStyle(status);
- return (
-
-
- {style.label} {count}
-
- );
- })}
-
-
- )}
-
- {/* Areas covered (delivery suburbs) — clicking a chip drills down to that
- suburb's orders in an inline panel below the chip row. */}
- {focusedZone.suburbs.length > 0 && (
-
-
Areas Covered ({focusedZone.suburbs.length})
-
- {focusedZone.suburbs.map((s) => {
- const isActive = selectedSuburb === s.name;
- return (
- setSelectedSuburb(isActive ? null : s.name)}
- title={isActive ? 'Click again to close' : `Show ${s.count} order${s.count === 1 ? '' : 's'} in ${s.name}`}
- >
- {s.name}
- {s.count}
-
- );
- })}
-
-
- {selectedSuburb && (() => {
- // Suburb strings in the source data can have trailing whitespace
- // and inconsistent casing (e.g. "uppilipalayam "). The tally that
- // builds chip names keeps them as-is, so normalize BOTH sides to
- // a trimmed lowercase key when filtering.
- const norm = (v) => String(v || '').trim().toLowerCase();
- const target = norm(selectedSuburb);
- const suburbOrders = focusedZone.orders.filter((o) =>
- norm(o.deliverysuburb || o.locationsuburb) === target
- );
- return (
-
-
-
- {selectedSuburb}
- {suburbOrders.length} {suburbOrders.length === 1 ? 'order' : 'orders'}
-
-
setSelectedSuburb(null)}
- title="Close"
- aria-label="Close suburb panel"
- >×
-
- {suburbOrders.length === 0 ? (
-
No orders in this area.
- ) : (
-
- {suburbOrders.map((o, idx) => {
- const lat = parseFloat(o.droplat || o.deliverylat);
- const lon = parseFloat(o.droplon || o.deliverylong);
- const canFocus = Number.isFinite(lat) && Number.isFinite(lon);
- const isStopActive = focusedStop && focusedStop.orderid === o.orderid;
- const riderColor = getRiderColor(o.rider_id);
- const statusStyle = getStatusStyle(o.orderstatus);
- return (
-
setFocusedStop(isStopActive ? null : { orderid: o.orderid, lat, lon }) : undefined}
- >
-
-
-
- {o.deliverycustomer || '—'}
- {o.orderstatus && (
- {statusStyle.label}
- )}
-
-
Order #{o.orderid} · Rider: {o.rider_name || o.ridername || '—'}
- {(o.deliveryaddress || o.deliverysuburb) && (
-
- {o.deliveryaddress || o.deliverysuburb}
-
- )}
-
-
- );
- })}
-
- )}
-
- );
- })()}
-
- )}
-
- {/* Pickup kitchens */}
- {focusedZone.kitchens.length > 0 && (
-
-
Kitchens ({focusedZone.kitchens.length})
-
- {focusedZone.kitchens.map((k) => (
-
- {k.name}
- {k.count}
-
- ))}
-
-
- )}
-
- {/* Riders */}
-
-
Riders ({focusedZone.activeRidersCount})
- {focusedZone.riders
- .map((zr) => riders.find((rd) => String(rd.id) === String(zr.rider_id)))
- .filter(Boolean)
- .map(renderRiderCard)}
+ )}
+
) : (
@@ -1786,21 +2216,35 @@ const Dispatch = ({
{viewMode === 'kitchens' ? (
- kitchens.slice(0, 10).map(k => (
-
setFocusedKitchen(k)}>
-
-
{k.kitchenName}
-
{k.orders.length}
-
- ))
+ kitchens.slice(0, 10).map(k => {
+ const total = k.orders.length;
+ const delivered = k.orders.filter((o) =>
+ FINAL_STATUSES.has(String(o.orderstatus || '').toLowerCase())
+ ).length;
+ const isDone = total > 0 && delivered >= total;
+ return (
+
setFocusedKitchen(k)} title={`${delivered} delivered of ${total} total`}>
+
+
{k.kitchenName}
+
{delivered}/{total}
+
+ );
+ })
) : (
- riders.slice(0, 10).map(r => (
-
handleRiderFocus(r)}>
-
-
{r.riderName}
-
{r.orders.length}
-
- ))
+ riders.slice(0, 10).map(r => {
+ const total = r.orders.length;
+ const delivered = r.orders.filter((o) =>
+ FINAL_STATUSES.has(String(o.orderstatus || '').toLowerCase())
+ ).length;
+ const isDone = total > 0 && delivered >= total;
+ return (
+
handleRiderFocus(r)} title={`${delivered} delivered of ${total} total`}>
+
+
{r.riderName}
+
{delivered}/{total}
+
+ );
+ })
)}
@@ -1811,6 +2255,8 @@ const Dispatch = ({