// ============================================================================ // One pickup, many drops. // // A customer-app booking is ONE pickup carrying N destinations — never N // bookings. `GET /admin/bookings` reports how many each row has // (`destinationcount`, `totalpackagecount`) without shipping the destination // array, which is fetched only when a row is opened. // // Every helper here has to survive three shapes of row, because all three // reach the Orders table at once: // // 1. The console running AHEAD of the backend that adds these fields, where // `destinationcount` is undefined. Nothing may change for that row. // 2. An ordinary single-drop booking, which is most of them. // 3. A console-created booking, which has no bookingdestinations rows at all // and reports 0 — distinct from 1, and rendered the same as case 1. // ============================================================================ export const plural = (count, word) => `${count} ${word}${count === 1 ? '' : 's'}`; /** * How many drops one pickup carries, or 0 when the row cannot say. * * `Number(undefined) || 0` collapses the absent-field case to 0, which is what * keeps a console deployed before the backend rendering exactly as it does * today. */ export const dropCountOf = (row) => Number(row?.destinationcount) || 0; /** * Whether this pickup created more than one shipment. * * The single gate for every multi-drop behaviour on the Orders page: the * summary line, and — more importantly — the refusal to render the booking's * own `consignmentstatus` as the row's status. Deliberately `> 1`, never * `>= 1`: "1 destination · 1 package" on every B2C row is noise on the common * case, and a single-drop booking's consignment status IS the booking's. */ export const isMultiDrop = (row) => dropCountOf(row) > 1; /** * The collapsed row's summary — "3 destinations · 4 packages". * * Only meaningful when `isMultiDrop(row)`; callers gate on that. */ export const dropSummary = (row) => { const drops = dropCountOf(row); /* Packages fall back to the destination count rather than to zero. Every destination carries at least one package, so "3 destinations · 0 packages" describes a booking the data cannot actually produce — and would be the reading if the count arrived without the sum. */ const packages = Number(row?.totalpackagecount) || drops; return `${plural(drops, 'destination')} · ${plural(packages, 'package')}`; };