feat(04-01): wire BrowserRouter + BottomTabBar + empty Lists surface

- App.tsx: BrowserRouter with /calendar, /lists, /lists/:listId routes; / redirects to /calendar
- BottomTabBar.tsx: fixed-bottom 56px tab bar with Calendar + Lists NavLinks, active accent
- AppNav.tsx: add Calendar/Lists NavLinks to desktop sidebar (≥768px)
- ListsIndex.tsx: full-height surface with isLoading/isError/empty state branches; "+ New List" FAB placeholder
- ListDetail.tsx: placeholder stub for /lists/:listId (Plan 04-04 fills in)
- listsStore.ts: Zustand UI-only store (activeTab, createListSheetOpen)
- listsClient.ts: fetchLists + List/ListItem types (initial; Plans 04-02/03 expand)
- Fix Wave-0 RED stubs: add vitest imports so stubs execute (todo) not error on import
- Fix CalendarShell.test.tsx: wrap renderWithClient in MemoryRouter (AppNav uses NavLink)
This commit is contained in:
Lucas Berger
2026-06-09 12:03:52 -04:00
parent 2f25b15949
commit c0088edf44
10 changed files with 563 additions and 3 deletions
+34 -1
View File
@@ -1,5 +1,38 @@
/**
* App — BrowserRouter shell with react-router declarative routing.
*
* Routes:
* / → redirect to /calendar
* /calendar → CalendarShell
* /lists → ListsIndex
* /lists/:listId → ListDetail (placeholder for Plan 04-04)
*
* BottomTabBar is rendered as a sibling of <Routes> so it persists across route
* changes. On desktop (≥768px) AppNav sidebar handles navigation — BottomTabBar
* is only visible on phone via CSS, but we render it in the tree at all sizes so
* the tab state remains consistent.
*
* navigateFallback ('/index.html') in vite.config.ts covers SPA deep-links to
* /lists/* — the SW denylist only excludes /callback, /api/, and /health, so
* /lists/* is served from cache correctly.
*/
import { BrowserRouter, Routes, Route, Navigate } from 'react-router'
import { CalendarShell } from './components/CalendarShell.js'
import { ListsIndex } from './routes/ListsIndex.js'
import { ListDetail } from './routes/ListDetail.js'
import { BottomTabBar } from './components/BottomTabBar.js'
export default function App() {
return <CalendarShell />
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Navigate to="/calendar" replace />} />
<Route path="/calendar" element={<CalendarShell />} />
<Route path="/lists" element={<ListsIndex />} />
<Route path="/lists/:listId" element={<ListDetail />} />
</Routes>
<BottomTabBar />
</BrowserRouter>
)
}