diff --git a/src/api/doormile/queries.js b/src/api/doormile/queries.js index 497142d..e40f6df 100644 --- a/src/api/doormile/queries.js +++ b/src/api/doormile/queries.js @@ -212,25 +212,70 @@ const haversineKm = (lat1, lon1, lat2, lon2) => { // page's own optional-chaining render whatever fields actually come back. // Falls back to the miler record itself (which may carry a last-known // position) if the logs call fails or returns nothing. -// Despite the parameter name (kept for caller compatibility), this must be -// a milerprofileid — /admin/milers/:id/* routes 404 on a plain userid -// (confirmed live). -export const getRiderPeriodicLogs = async (userid) => { - if (!userid) return null; +// Handles both milerprofileid and userid inputs by resolving via getMilers(). +export const getRiderPeriodicLogs = async (id) => { + if (!id) return null; + + let profileId = id; + let milerObj = null; + + // Resolve milerprofileid if a userid or generic id was passed try { - const logs = await getMilerLogs(userid, undefined, undefined, 1); + const milers = await getMilers(); + const found = (milers || []).find( + (m) => + String(m.milerprofileid) === String(id) || + String(m.userid) === String(id) || + String(m.milerid) === String(id) || + String(m.id) === String(id) + ); + if (found) { + profileId = found.milerprofileid || found.id || id; + milerObj = found; + } + } catch (e) { + logger.debug('getRiderPeriodicLogs: milers lookup fallback', e); + } + + // 1. Fetch the latest log via /admin/milers/:profileId/logs?limit=1 + try { + const logs = await getMilerLogs(profileId, undefined, undefined, 1); const latest = Array.isArray(logs) ? logs[0] : logs; - if (latest) return latest; - } catch { - // Falls through to the getMiler() fallback below — this is polled every - // 15s by the live map, so a toast here would spam the operator on every - // failed tick. Only surface an error if the fallback also fails. - } - try { - return (await getMiler(userid)) || null; + if (latest && typeof latest === 'object' && Object.keys(latest).length > 0) { + return { + ...milerObj, + ...latest, + userid: latest.userid ?? milerObj?.userid ?? id, + username: + (latest.username && latest.username.trim()) || + milerObj?.displayname || + milerObj?.name || + (latest.userid ? `Rider #${latest.userid}` : `Rider #${id}`) + }; + } } catch (err) { - return null; + logger.debug(`getRiderPeriodicLogs: getMilerLogs failed for profileId ${profileId}`, err); } + + // 2. Fallback to /admin/milers/:profileId if no logs or logs call failed + try { + const miler = milerObj || (await getMiler(profileId)); + if (miler) { + return { + ...miler, + userid: miler.userid ?? id, + username: miler.displayname || miler.name || miler.authname || `Rider #${miler.userid ?? id}`, + latitude: miler.currentlatitude ?? miler.latitude, + longitude: miler.currentlongitude ?? miler.longitude, + status: miler.availabilitystatus ?? miler.status ?? 'offline', + logdate: miler.lastpingat ?? miler.updatedat ?? miler.createdat + }; + } + } catch (err) { + logger.debug(`getRiderPeriodicLogs: getMiler fallback failed for profileId ${profileId}`, err); + } + + return null; }; // ==============================|| fetchAppLocations (zone/location picker) ||============================== // @@ -478,10 +523,10 @@ export const resolveMilerForOrder = (order, lookup) => { const matchedVia = lookup.byUserId.has(String(riderUserId)) ? 'userid' : lookup.byProfileId.has(String(riderUserId)) - ? 'milerprofileid' - : lookup.byName.has(normMilerName(riderName)) - ? 'name' - : null; + ? 'milerprofileid' + : lookup.byName.has(normMilerName(riderName)) + ? 'name' + : null; const rider = lookup.byUserId.get(String(riderUserId)) ?? lookup.byProfileId.get(String(riderUserId)) ?? lookup.byName.get(normMilerName(riderName)); return rider?.milerprofileid ? { rider, matchedVia } : null; diff --git a/src/pages/doormile/dispatch/Dispatch.jsx b/src/pages/doormile/dispatch/Dispatch.jsx index f8e474b..726e14c 100644 --- a/src/pages/doormile/dispatch/Dispatch.jsx +++ b/src/pages/doormile/dispatch/Dispatch.jsx @@ -1113,7 +1113,9 @@ const Dispatch = ({ // changing riderInfoUserid itself, which is compared against elsewhere // in this file for sidebar row highlighting in userid-space. queryFn: () => { - const match = liveRiderLocations.find((r) => String(r.userid) === String(riderInfoUserid)); + const match = + liveRiderLocations.find((r) => String(r.userid) === String(riderInfoUserid) || String(r.milerprofileid) === String(riderInfoUserid)) || + (ridersList || []).find((r) => String(r.userid) === String(riderInfoUserid) || String(r.milerprofileid) === String(riderInfoUserid)); return getRiderPeriodicLogs(match?.milerprofileid ?? riderInfoUserid); }, enabled: viewMode === 'rider-info' && riderInfoUserid != null, @@ -1534,8 +1536,8 @@ const Dispatch = ({ const dateStr = r.assigntime ? parseDoormileTimestamp(r.assigntime).format('YYYY-MM-DD') : r.deliverydate - ? parseDoormileTimestamp(r.deliverydate).format('YYYY-MM-DD') - : 'unknown'; + ? parseDoormileTimestamp(r.deliverydate).format('YYYY-MM-DD') + : 'unknown'; if (selectedDate && dateStr !== selectedDate) return; const batch = getRowBatch(r, selectedTimeField, BATCHES); @@ -1872,8 +1874,8 @@ const Dispatch = ({ () => isAllActiveView ? liveRiderLocations - .filter((r) => r.status !== 'offline' && r.status !== 'blocked' && activeOrderRiderIdSet.has(String(r.id))) - .map((r) => [r.lat, r.lon]) + .filter((r) => r.status !== 'offline' && r.status !== 'blocked' && activeOrderRiderIdSet.has(String(r.id))) + .map((r) => [r.lat, r.lon]) : [], [isAllActiveView, liveRiderLocations, activeOrderRiderIdSet] ); @@ -2437,8 +2439,8 @@ const Dispatch = ({ lp && Number.isFinite(lp.lat) && Number.isFinite(lp.lon) ? [lp.lat, lp.lon] : hasValidPickup(activeOrder) - ? [toNum(pickupLat(activeOrder)), toNum(pickupLon(activeOrder))] - : null; + ? [toNum(pickupLat(activeOrder)), toNum(pickupLon(activeOrder))] + : null; const dLat = toNum(activeOrder.droplat || activeOrder.deliverylat); const dLon = toNum(activeOrder.droplon || activeOrder.deliverylong); if (start && Number.isFinite(dLat) && Number.isFinite(dLon)) { @@ -2579,19 +2581,19 @@ const Dispatch = ({ const stepSegs = roadPath ? splitPolylineByDrops(roadPath, dropCoords) : (() => { - const hasPickup = aerialPath.length > dropCoords.length; - const out = []; - for (let i = 0; i < dropCoords.length; i++) { - const a = hasPickup ? i : i - 1; - const b = hasPickup ? i + 1 : i; - if (a < 0 || a >= aerialPath.length || b >= aerialPath.length) { - out.push([]); - } else { - out.push([aerialPath[a], aerialPath[b]]); - } + const hasPickup = aerialPath.length > dropCoords.length; + const out = []; + for (let i = 0; i < dropCoords.length; i++) { + const a = hasPickup ? i : i - 1; + const b = hasPickup ? i + 1 : i; + if (a < 0 || a >= aerialPath.length || b >= aerialPath.length) { + out.push([]); + } else { + out.push([aerialPath[a], aerialPath[b]]); } - return out; - })(); + } + return out; + })(); // Map each path index → step index by accumulating segment lengths // (segments share endpoints so we use length-1 per segment). const pathIdxToStepIdx = []; @@ -3055,42 +3057,37 @@ const Dispatch = ({ const flagSvg = o.orderstatus ? ` - - ${ - isDelivered - ? '' - : '' - } + + ${isDelivered + ? '' + : '' + } ` : ''; const icon = showNumbers ? (() => { - const seq = compareSeq || o.step || ordersToRender.indexOf(o) + 1; - const sz = 32; - return L.divIcon({ - className: '', - iconSize: [sz, sz], - iconAnchor: [sz / 2, sz / 2], - popupAnchor: [0, -28], - html: `
${ - seq > 0 ? seq : '' - }${flagSvg}
` - }); - })() - : L.divIcon({ + const seq = compareSeq || o.step || ordersToRender.indexOf(o) + 1; + const sz = 32; + return L.divIcon({ className: '', - iconSize: [24, 30], - iconAnchor: [2, 30], - popupAnchor: [10, -25], // Lift popup above the flag, not just the larger 32px marker - html: `
${flagSvg}
` + iconSize: [sz, sz], + iconAnchor: [sz / 2, sz / 2], + popupAnchor: [0, -28], + html: `
${seq > 0 ? seq : '' + }${flagSvg}
` }); + })() + : L.divIcon({ + className: '', + iconSize: [24, 30], + iconAnchor: [2, 30], + popupAnchor: [10, -25], // Lift popup above the flag, not just the larger 32px marker + html: `
${flagSvg}
` + }); return (
{b.label}
{b.range && (
{b.range}
@@ -3481,13 +3475,12 @@ const Dispatch = ({
0 - ? 'bg-amber-100 text-amber-800' - : 'bg-slate-100 text-slate-500' - }`} + ? 'bg-amber-100 text-amber-800' + : 'bg-slate-100 text-slate-500' + }`} > {count} {count === 1 ? 'order' : 'orders'} @@ -4075,9 +4068,8 @@ const Dispatch = ({ ) : (