From e66bf2638b33683877583fc1125aa699b6191aaf Mon Sep 17 00:00:00 2001 From: Shawn Date: Wed, 27 May 2026 19:08:58 -0400 Subject: [PATCH] fix: route planner fetch calls now use api() wrapper with auth token Root cause: rpLoadTechs() and all other route planner API calls used raw fetch() instead of the api() wrapper, so no Authorization header was attached. Auth middleware returned 401, technician list never loaded, users saw 'Select at least one technician'. Fixed by replacing all 6 fetch('/api/...') calls in the route planner with api('/api/...') and removing redundant .json() parsing (api() returns parsed data directly). Tested in browser: technician checkboxes populate, Load Today's Route returns 3 optimized stops with 12.5km route, map renders correctly, search tab queries return Disney WO results via auth. Closes: #issue-to-be-created --- static/index.html | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/static/index.html b/static/index.html index 7079c82..c891294 100644 --- a/static/index.html +++ b/static/index.html @@ -5177,8 +5177,7 @@ async function rpLoadTechs() { const savedTechs = JSON.parse(localStorage.getItem('rpTechs') || '[]'); try { - const r = await fetch('/api/workorders/technicians'); - const data = await r.json(); + const data = await api('/api/workorders/technicians'); const container = document.getElementById('rpTechCheckboxes'); // Keep the "All" checkbox, remove existing tech checkboxes container.querySelectorAll('label:not(:first-child)').forEach(el => el.remove()); @@ -5270,8 +5269,7 @@ if (q.length < 2) { container.innerHTML = ''; return; } container.innerHTML = '
Searching...
'; try { - const r = await fetch('/api/workorders/search?q=' + encodeURIComponent(q) + '&limit=30'); - const data = await r.json(); + const data = await api('/api/workorders/search?q=' + encodeURIComponent(q) + '&limit=30'); if (!data.results || data.results.length === 0) { container.innerHTML = '
No results
'; return; @@ -5330,8 +5328,7 @@ rpShowLoading('Loading today\u2019s work orders...'); try { const params = techs.map(t => 'tech=' + encodeURIComponent(t)).join('&'); - const r = await fetch('/api/workorders/today?' + params); - const data = await r.json(); + const data = await api('/api/workorders/today?' + params); if (!data.workorders || data.workorders.length === 0) { rpHideLoading(); return alert('No work orders found for today'); @@ -5368,12 +5365,11 @@ let woDetails = preloaded || null; if (!woDetails) { try { - const r = await fetch('/api/workorders/lookup', { + const data = await api('/api/workorders/lookup', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ids: woIds }), }); - const data = await r.json(); woDetails = data.found || []; } catch (e) { rpHideLoading(); @@ -5388,12 +5384,11 @@ }; try { - const r = await fetch('/api/route/optimize', { + const data = await api('/api/route/optimize', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); - const data = await r.json(); rpHideLoading(); rpDisplayRoute(data, woDetails); } catch (e) { @@ -5514,8 +5509,7 @@ overlay.style.display = ''; modal.style.display = ''; try { - const r = await fetch('/api/workorders/' + encodeURIComponent(woName) + '/asset'); - const data = await r.json(); + const data = await api('/api/workorders/' + encodeURIComponent(woName) + '/asset'); const d = data.details || {}; let html = '
' + esc(data.asset_name || woName) + '
'; const sections = {};