diff --git a/src/pages/nearle/deliveries/deliveries.js b/src/pages/nearle/deliveries/deliveries.js index 4d218a9..837e853 100644 --- a/src/pages/nearle/deliveries/deliveries.js +++ b/src/pages/nearle/deliveries/deliveries.js @@ -148,21 +148,6 @@ const BATCH_OPTIONS = [ })) ]; -// Auto-pick the batch matching the operator's LOCAL wall-clock hour so the -// page lands them on the slot they're most likely curious about. Falls back -// to 'all' when the current hour lies in a configured gap (8–9 AM, 12 PM–4 -// PM, after 7 PM). Local time, not UTC, to match the dispatch page's -// bucketing — both pages must agree on which batch a given row belongs to. -const detectInitialBatchId = () => { - const now = dayjs(); - const h = now.hour() + now.minute() / 60; - for (const b of BATCH_OPTIONS) { - if (b.id === 'all') continue; - if (h >= b.startHour && h < b.endHour) return b.id; - } - return 'all'; -}; - // Bucket by `orderdate` only — the booking's `createdat`, i.e. when the order // came in. Must stay identical to the dispatch page's bucket field // (Dispatch.js's `BATCH_TIME_FIELD = 'created'`, whose `keys` is @@ -270,8 +255,27 @@ const Deliveries = () => { const [dialogopen, setDialogopen] = useState(false); const [locaName, setLocoName] = useState('All'); const [appId, setAppId] = useState(0); - const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD')); - const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD')); + // Unscoped by default ('' is the same "no bound" sentinel the date-range + // picker's own Clear button already sets — see inRange in api.js, and the + // `startdate && enddate ? … : 'Select date range'` header label below, + // both of which already treat '' as "no filter applied"). + // + // Defaulting this to TODAY (as it did before) meant the Pending/Accepted/ + // Arrived/Picked/Active tabs — which represent an outstanding-work QUEUE, + // not a day's log — only showed a booking whose `orderdate` (creation day, + // deliberately NOT `assigntime`; see fetchDeliveries in api.js for why) + // fell on today. Assign a rider to a booking that was created yesterday + // or last week and it's still correctly "Pending" work, but it vanished + // from the operator's board until they manually cleared the date filter — + // reported as "I just assigned it and it's not showing." Same "state vs + // flow" distinction the Doormile AI assistant already draws (see + // assistant/CLAUDE.md §3): "how many orders are assigned" is answered + // unscoped because it describes the queue right now, not a period. + // Delivered/Cancelled stay meaningful to scope by date — an operator + // still explicitly narrows the range for those via the picker, same as + // before. + const [startdate, setStartdate] = useState(''); + const [enddate, setEnddate] = useState(''); const [tabstatus, setTabstatus] = useState('Pending'); const [open, setOpen] = useState(false); const [kms, setKms] = useState(''); @@ -350,10 +354,16 @@ const Deliveries = () => { const [tenantid, setTenantid] = useState(0); const [locationid, setLocationid] = useState(0); const [riderid, setRiderid] = useState(0); - // Selected batch id — drives the client-side row filter. Defaults to the - // batch matching the current UTC hour (the operator is most likely curious - // about "now"); never `null` since there's no longer an "All" option. - const [selectedBatch, setSelectedBatch] = useState(detectInitialBatchId); + // Selected batch id — drives the client-side row filter. A Morning/ + // Afternoon/Evening slot is a slice of ONE day, so `detectInitialBatchId` + // (jump to whichever slot matches the operator's current wall-clock hour) + // only means something once the date range above is scoped to a single + // day. Now that startdate/enddate default to unscoped (see that state's + // comment), defaulting the batch too would silently hide almost + // everything: a booking created three days ago at 11am has no relationship + // to "the slot matching right now" on a different day. Defaults to 'all' + // and is left for the operator to narrow, same as the date range. + const [selectedBatch, setSelectedBatch] = useState('all'); // showAction/showSelect only depend on tabstatus, computed here (rather than // just before the return, where they used to live) so the TanStack Table @@ -561,6 +571,20 @@ const Deliveries = () => { // whenever the operator switches batches. Search keyword is intentionally // dropped from this key so the chip counts reflect the batch totals rather // than the search-filtered subset. + // + // pagesize 1000 — the documented server cap (express-console-api.md, + // "Conventions": default 500, cap 1000), not the 200 this used to request. + // GET /admin/bookings has no documented sort order, and `inRange` below + // filters to today's window client-side only AFTER every page lands — so a + // booking created and assigned moments ago is only guaranteed visible once + // the page containing it has been fetched. At 200/page against a tenant + // with any real history, a freshly assigned order could sit several + // sequential round-trips deep and simply not have arrived yet when the + // operator checks the Pending tab, reading as "the order isn't there" when + // it's really "not fetched yet." 1000/page cuts that to a fifth of the + // round-trips and, for any tenant whose lifetime booking count is under + // 1000 (true for most while this platform is young), collapses the whole + // drain to a single request — no ordering assumption needed at all. const { data: countSourceData, fetchNextPage: countFetchNext, @@ -569,7 +593,7 @@ const Deliveries = () => { isLoading: countSourceIsLoading, refetch: countSourceRefetch } = useInfiniteQuery({ - queryKey: ['fetchdeliveries-batchcounts', appId, userid, 'all', startdate, enddate, 200, '', tenantid, locationid, riderid], + queryKey: ['fetchdeliveries-batchcounts', appId, userid, 'all', startdate, enddate, 1000, '', tenantid, locationid, riderid], queryFn: fetchDeliveries, getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined });