fix: mobile routing renders Dashboard instead of correct page (#162) #163

Closed
opened 2026-02-13 22:22:03 +00:00 by egullickson · 2 comments
Owner

Relates to #162

Severity: Critical

Problem

Direct URL navigation on mobile (e.g. typing /garage/fuel-logs or /garage/maintenance in the address bar, or refreshing the page) renders the Dashboard instead of the correct page. Only bottom-nav button taps correctly navigate. This means bookmarked links and shared URLs break on mobile.

Acceptance Criteria

  • Direct URL navigation on mobile renders the correct page (not Dashboard)
  • Page refresh on mobile preserves the current route
  • Bookmarked and shared URLs work correctly on mobile
  • Bottom-nav navigation continues to work
  • Desktop routing unaffected
  • Tested on mobile (320px, 768px) and desktop (1920px)
Relates to #162 ## Severity: Critical ## Problem Direct URL navigation on mobile (e.g. typing `/garage/fuel-logs` or `/garage/maintenance` in the address bar, or refreshing the page) renders the Dashboard instead of the correct page. Only bottom-nav button taps correctly navigate. This means bookmarked links and shared URLs break on mobile. ## Acceptance Criteria - Direct URL navigation on mobile renders the correct page (not Dashboard) - Page refresh on mobile preserves the current route - Bookmarked and shared URLs work correctly on mobile - Bottom-nav navigation continues to work - Desktop routing unaffected - Tested on mobile (320px, 768px) and desktop (1920px)
egullickson added the
status
backlog
type
chore
labels 2026-02-13 22:22:21 +00:00
egullickson added this to the Sprint 2026-02-02 milestone 2026-02-13 22:22:30 +00:00
Author
Owner

Implementation Plan (from #162 -- Milestone 2)

Phase: 1 (Foundation) | Priority: Critical | Depends on: None | Blocks: None

Context

Mobile navigation uses Zustand state-based nav (activeScreen in the navigation store), NOT React Router. When a user navigates directly to a URL like /garage/maintenance, the browser path is ignored and the Dashboard screen renders instead. URLs and Zustand screen state are never synchronized.

Implementation

1. Create route-to-screen mapping in frontend/src/core/store/navigation.ts:

const routeToScreen: Record<string, MobileScreen> = {
  '/garage/dashboard': 'Dashboard',
  '/garage/vehicles': 'Vehicles',
  '/garage/fuel-logs': 'Log Fuel',
  '/garage/maintenance': 'Maintenance',
  '/garage/documents': 'Documents',
  '/garage/stations': 'Stations',
  '/garage/settings': 'Settings',
};

2. In frontend/src/App.tsx, add useEffect for URL-to-screen sync on mount:

  • Read window.location.pathname
  • Map to MobileScreen value using the mapping above
  • Call navigateToScreen() from Zustand store
  • URL takes precedence on initial load

3. Sync screen changes back to browser URL:

  • When activeScreen changes in Zustand, call window.history.replaceState() to update the browser URL
  • This enables bookmark support and URL sharing

4. Prevent stale localStorage override:

  • Remove activeScreen from Zustand partialize persist config to avoid stale localStorage overriding URLs on reload

Files

  • frontend/src/App.tsx
  • frontend/src/core/store/navigation.ts

Commit Convention

fix: sync mobile routing with browser URL for direct navigation (refs #163)

Test Criteria

  • Direct URL navigation on mobile (e.g., /garage/maintenance) renders the correct page
  • Page refresh preserves the current route
  • Back/forward browser buttons work correctly
  • Tapping nav items in bottom bar and hamburger menu updates the URL
  • Desktop routing is unaffected
  • Verify on mobile (320px, 768px) and desktop (1920px) viewports

Risk Notes

  • Highest complexity milestone. Zustand/URL sync must not break existing navigation flows.
  • Test all navigation paths: bottom nav, hamburger menu, quick actions, breadcrumbs.

Branch

Work on branch issue-162-ux-design-audit-cleanup (shared with all #162 sub-issues)

## Implementation Plan (from #162 -- Milestone 2) **Phase**: 1 (Foundation) | **Priority**: Critical | **Depends on**: None | **Blocks**: None ### Context Mobile navigation uses Zustand state-based nav (`activeScreen` in the navigation store), NOT React Router. When a user navigates directly to a URL like `/garage/maintenance`, the browser path is ignored and the Dashboard screen renders instead. URLs and Zustand screen state are never synchronized. ### Implementation **1. Create route-to-screen mapping in `frontend/src/core/store/navigation.ts`:** ```typescript const routeToScreen: Record<string, MobileScreen> = { '/garage/dashboard': 'Dashboard', '/garage/vehicles': 'Vehicles', '/garage/fuel-logs': 'Log Fuel', '/garage/maintenance': 'Maintenance', '/garage/documents': 'Documents', '/garage/stations': 'Stations', '/garage/settings': 'Settings', }; ``` **2. In `frontend/src/App.tsx`, add `useEffect` for URL-to-screen sync on mount:** - Read `window.location.pathname` - Map to `MobileScreen` value using the mapping above - Call `navigateToScreen()` from Zustand store - URL takes precedence on initial load **3. Sync screen changes back to browser URL:** - When `activeScreen` changes in Zustand, call `window.history.replaceState()` to update the browser URL - This enables bookmark support and URL sharing **4. Prevent stale localStorage override:** - Remove `activeScreen` from Zustand `partialize` persist config to avoid stale localStorage overriding URLs on reload ### Files - `frontend/src/App.tsx` - `frontend/src/core/store/navigation.ts` ### Commit Convention ``` fix: sync mobile routing with browser URL for direct navigation (refs #163) ``` ### Test Criteria - Direct URL navigation on mobile (e.g., `/garage/maintenance`) renders the correct page - Page refresh preserves the current route - Back/forward browser buttons work correctly - Tapping nav items in bottom bar and hamburger menu updates the URL - Desktop routing is unaffected - Verify on mobile (320px, 768px) and desktop (1920px) viewports ### Risk Notes - **Highest complexity milestone**. Zustand/URL sync must not break existing navigation flows. - Test all navigation paths: bottom nav, hamburger menu, quick actions, breadcrumbs. ### Branch Work on branch `issue-162-ux-design-audit-cleanup` (shared with all #162 sub-issues)
egullickson added
status
in-progress
and removed
status
backlog
labels 2026-02-14 01:33:54 +00:00
Author
Owner

Milestone: Mobile URL-to-Screen Sync

Phase: Execution | Agent: Developer | Status: PASS

Changes Made

1. Route-to-screen mapping (navigation.ts)

  • Added routeToScreen mapping: 16 URL paths to MobileScreen values (including /garage, /garage/dashboard, all feature and admin routes)
  • Added screenToRoute reverse mapping: MobileScreen values to canonical URL paths
  • Removed activeScreen from partialize persist config to prevent stale localStorage from overriding URL on reload

2. URL sync effects (App.tsx)

  • Added mount-time useEffect: reads window.location.pathname, maps via routeToScreen, calls navigateToScreen() so direct URLs render the correct screen
  • Added activeScreen watcher useEffect: calls window.history.replaceState() to keep browser URL in sync when Zustand state changes (enables bookmarks and URL sharing)

3. Store barrel export (store/index.ts)

  • Exported routeToScreen and screenToRoute for use in App.tsx

Files Modified

  • frontend/src/core/store/navigation.ts - route mappings + persist fix
  • frontend/src/App.tsx - URL sync effects
  • frontend/src/core/store/index.ts - exports

Verification

  • Type-check: PASS (0 errors)
  • Lint: PASS (0 errors, 226 pre-existing warnings)
  • Tests: 147 passed, 8 failed (all pre-existing failures unrelated to this change)

Commit

0e8c607 - fix: sync mobile routing with browser URL for direct navigation (refs #163)

Verdict: PASS | Next: Browser testing on mobile (320px, 768px) and desktop (1920px) viewports

## Milestone: Mobile URL-to-Screen Sync **Phase**: Execution | **Agent**: Developer | **Status**: PASS ### Changes Made **1. Route-to-screen mapping (`navigation.ts`)** - Added `routeToScreen` mapping: 16 URL paths to `MobileScreen` values (including `/garage`, `/garage/dashboard`, all feature and admin routes) - Added `screenToRoute` reverse mapping: `MobileScreen` values to canonical URL paths - Removed `activeScreen` from `partialize` persist config to prevent stale localStorage from overriding URL on reload **2. URL sync effects (`App.tsx`)** - Added mount-time `useEffect`: reads `window.location.pathname`, maps via `routeToScreen`, calls `navigateToScreen()` so direct URLs render the correct screen - Added `activeScreen` watcher `useEffect`: calls `window.history.replaceState()` to keep browser URL in sync when Zustand state changes (enables bookmarks and URL sharing) **3. Store barrel export (`store/index.ts`)** - Exported `routeToScreen` and `screenToRoute` for use in App.tsx ### Files Modified - `frontend/src/core/store/navigation.ts` - route mappings + persist fix - `frontend/src/App.tsx` - URL sync effects - `frontend/src/core/store/index.ts` - exports ### Verification - Type-check: PASS (0 errors) - Lint: PASS (0 errors, 226 pre-existing warnings) - Tests: 147 passed, 8 failed (all pre-existing failures unrelated to this change) ### Commit `0e8c607` - `fix: sync mobile routing with browser URL for direct navigation (refs #163)` *Verdict*: PASS | *Next*: Browser testing on mobile (320px, 768px) and desktop (1920px) viewports
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#163