The reverted code had two bugs in the tab switching logic:
1. closeNavigate() called switchTab() -> infinite recursion since
switchTab() calls closeNavigate() when leaving tabNavigate
2. currentTab was updated AFTER closeNavigate(), so the recursive
call hit the same condition over and over
Fix: move currentTab assignment before cleanup, use a wasNavigating
flag to track the old tab state, and make closeNavigate() only reset
nav UI (caller handles tab transition).
- Remove duplicate FAB HTML element (was two #fabAdd buttons)
- Remove duplicate FAB CSS block (keep single definition with pulse class)
- Add .fab:hover to remaining FAB CSS block
- Convert all fab.style.display usage to hidden-fab CSS class for smooth transitions
- Add direction-aware tab transitions: forward slides from right, reverse (back) slides from left
- Fix FAB pulse persistence: restart animation on click instead of removing permanently
- Move FAB init code after FAB HTML element so hidden-fab applies on initial load
- Remove redundant style.display FAB visibility in switchTab (now handled by updateFabVisibility)
Tab transition animations already existed (slide+fade with cubic-bezier easing).
Button press/hover scale effects and .btn-pressed haptic class already existed.
Success toast slide-up already existed via translateY transition.
Consistent easing curve (cubic-bezier 0.4,0,0.2,1) already applied across transitions.
prefers-reduced-motion already respected (animation-duration: 0.01ms at line 1696).
- Improved geolocation error messages (maps error codes to friendly text: Location blocked, GPS unavailable, GPS timed out)
- Added location data to list_assets API (location_latitude, longitude, address, building_name, building_number, name) via LEFT JOIN
- Map pins now use location coordinates as direct fallback when asset lacks own lat/lng
- GeocodeAndPin now falls back to location address fields when asset address is empty
- All 96 map-related tests pass (66 API + 30 frontend)
- Added GPS-aware empty state with location needed/gps off messaging
- Added GPS warning banner with 'enable location access' link in Navigate tab
- Show user's current location pin + accuracy circle on map when GPS available
- Enhanced destination search: GPS-aware filtering, badges for nav status
- Back button navigates to previous tab (or Map tab as fallback)
- Added navBackToPrevious() function with proper switchTab recursion avoidance
- Added CSS: .gps-warning, .gps-enable-link, .nav-route-info, .nav-route-item
- navigateToAsset() now goes to Nav tab even without GPS to show warning UI
- Improved search results: shows GPS on/off badge, disables non-navigable assets
- All navigation and smoke tests pass (5/5)
- Add GPS warning banner with enable-location link when GPS unavailable
- Refactor route info cards from inline styles to CSS classes
- Update empty state messaging based on GPS availability
- Show user location marker with accuracy circle on nav map when GPS available
- Hide map container when no GPS (show only empty state + search)
- Handle both [lat, lng] array and {lat, lng} object formats in geofence rendering
- All empty states verified: consistent icon + heading + description + CTA pattern
- Onboarding welcome overlay with localStorage flag
- 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