- Add missing assetCountBar div with count bar styling
- Add missing clearFiltersBtn with show/hide logic
- Add .search-highlight CSS for matching term highlighting
- Add .ai-location CSS for location context in asset items
- Add loading spinner overlay during search debounce
- Fix filter pills to use JS string escaping (not HTML escaping)
- Add 'make' filter parameter to API query
- Include 'make' in filter detection for count bar
The switchTab function had an early return after closeNavigate() that
skipped the actual tab panel switching (slide animation, active class
management). closeNavigate() only cleans up navigation state (map, data,
UI elements) — it does NOT switch panels. This caused the Navigate
panel to remain visible permanently after the first visit, overlapping
with any subsequent tab content.
Removed the early return so the normal tab switching logic runs after
closeNavigate() cleanup.
- Fixed switchTab recursion bug when leaving tabNavigate (set currentTab early + return)
- Fixed closeNavigate to not call switchTab (caller handles tab transition)
- Added renderNavPage call in switchTab lifecycle for tabNavigate
- Added empty state with asset search on Navigate page
- Added route-finding: search assets, navigate from search results
- Added driving/walking mode toggle with OSRM route display
- Added ETA display for driving mode
- Fixed route polyline to use OSRM road geometry when available
- Added switchNavMode function for mode switching
- Improved directions label (Walking vs Driving)
- Fix Active Technicians: query users WHERE role='technician' instead of counting from visit data
- Interactive bar charts: hover tooltips show label+count, click drills down to filtered asset list
- Quick action icons: coin for Assets, Sites, Check-in replaces CSV export buttons
- No visit data: suggestion card with 'Add a Check-in' button
- No manufacturer data: hide section entirely when empty
- 30-second TTL cache on both backend (/api/stats) and frontend (loadDashboard)
- Add dashboard cache module with time-based invalidation
- New tabNavigate panel with its own map, route info, walking directions, Google Maps link
- Added to bottom nav bar (🧭 Nav) and drawer nav (🧭 Navigate)
- navigateToAsset() now switches to tabNavigate instead of cluttering the map tab
- Back button returns to previous tab
- Auto-cleanup navMap when leaving the tab
The F2 auto-populate address block was accidentally inserted inside
the payload={} object literal, causing a JS syntax error that
broke the entire script and prevented the login screen from showing.
F1: Scan existing asset → auto check-in (handleBarcode now autoCheckins)
F2: Auto-generate address from GPS reverse geocode (Nominatim, all 3 modes)
F3: Larger camera viewport (3:4 aspect ratio, full-width)
F4: Building # already syncs to Address/Trailer field (existing)
F5: Parking location GPS button already exists (fillGpsParking)
F6: Navigation tool with route line on map (existing navigateToAsset)
Backend: Added GET /api/geocode endpoint for reverse geocoding
ZXing.BrowserMultiFormatReader.listVideoInputDevices is an instance
method, not a static method. Call codeReader.listVideoInputDevices()
after creating the reader. Also wrap in try/catch with null fallback
so decodeFromVideoDevice picks the default camera if enumeration fails.
- OCR: Extract only last 5 digits from Connect ID (XXXXX-XXXXXX → last 5)
- Barcode: Switch to decodeFromVideoDevice with 1D-only format hints
(Code 128/39/EAN/UPC/ITF/Codabar), TRY_HARDER, 50ms scan interval
- Auto check-in: New assets auto-checkin with GPS on creation via
all three entry modes (barcode, OCR, manual)
- Tests: Updated e2e tests for login wait and API flow