# TimeToLeave — Implementation Checklist > **Source:** [REWRITE_PLAN.md](./REWRITE_PLAN.md) > **Total:** 4 phases, 14 steps, ~5 hours estimated effort --- ## Phase 1 — Unblock Runtime (~45 min) Fix bugs that crash the app or lose user data. | Step | ✅ Implemented | ✔️ Reviewed | Notes | |------|:--------------:|:-----------:|-------| | **Step 1: Fix SSR Crash in `useBikeRoute`** (~10 min) | [x] | [x] | Relative URL fetch replaces `window.location.href` — SSR-safe. `isMounted` guard intact. | | **Step 2: Wire Calendar Events into `EventsStore`** (~15 min) | [x] | [x] | `CalendarPanel.tsx` merges via `useEffect` when calendar events arrive. `mergeEvents()` converts `CalendarEvent` (string `eventTime`) → `Event` (Date `eventTime`). Bonus: localStorage persistence with rehydration. | | **Step 3: Add Input Validation to `/api/hafas`** (~20 min) | [x] | [x] | Validates `svcReqL` array shape, method allowlist (TripSearch/LocMatch), caps `numF` at 10. Extra type guard on `svcReq.meth` (`typeof svcReq.meth !== 'string'`) exceeds spec. | --- ## Phase 2 — Deduplicate Code (~2 hours) Eliminate duplicated logic so each integration has one source of truth. - [ ] **Step 4: Consolidate HAFAS Journey Parsing** (~40 min) - Move `parseHafasJourneys` from `useJourneys.ts` into `hafas-client.ts` and export it; import from `useJourneys.ts` (Option A — minimal risk) - Files: `src/lib/hafas-client.ts`, `src/hooks/useJourneys.ts` - [ ] **Step 5: Wire API Routes to Use Library Clients** (~30 min) - Replace raw `fetch()` in `api/geocode/route.ts` with `GeocodingClient`, and in `api/bike-route/route.ts` with `BikeRoutingClient` (module-level singleton, proper error handling) - Files: `src/app/api/geocode/route.ts`, `src/app/api/bike-route/route.ts` - [ ] **Step 6: Remove Dead Code** (~5 min) - Delete `src/lib/live-status-utils.ts` entirely; remove its export from `src/lib/index.ts` - File: `src/lib/live-status-utils.ts`, `src/lib/index.ts` - [ ] **Step 7: Create Missing Test Setup File** (~10 min) - Create `src/test/setup.ts` with `import "@testing-library/jest-dom/vitest"` so jsdom matchers are registered globally - File: `src/test/setup.ts` --- ## Phase 3 — Performance & UX (~1.5 hours) - [ ] **Step 8: Add Debounce to Lookup Hooks** (~25 min) - Wrap fetch in a 400 ms `setTimeout` with `AbortController` cleanup in `useGeocode.ts` and `useDestinationStation.ts` to prevent per-keystroke API calls - Files: `src/hooks/useGeocode.ts`, `src/hooks/useDestinationStation.ts` - [ ] **Step 9: Pre-Group Calendar Events by Date** (~20 min) - Build a `Map` keyed by `YYYY-MM-DD` via `useMemo` in `CalendarView.tsx`; replace per-cell `filter()` with O(1) map lookup - File: `src/app/calendar/CalendarView.tsx` - [ ] **Step 10: Add Dark Mode Toggle** (~20 min) - Create `useTheme.ts` hook (persist to `localStorage`, respect `prefers-color-scheme`); add sun/moon toggle button to `Header.tsx` - Files: `src/hooks/useTheme.ts` (new), `src/app/layout/Header.tsx` - [ ] **Step 11: Fix Bike Route Steps** (~5 min) - Add `steps: "true"` to the query params in `BikeRoutingClient.getBikeRoute()` so OSRM returns turn-by-turn steps - File: `src/lib/bike-routing-client.ts` --- ## Phase 4 — Monitoring & Testing (~1 hour) - [ ] **Step 12: Add Correlation IDs to API Errors** (~15 min) - Generate a short UUID (`randomUUID().slice(0, 8)`) in each API route's catch block; log it server-side and include it in the JSON error response - Files: all `src/app/api/*/route.ts` - [ ] **Step 13: Add Hook Tests** (~30 min) - Create `useJourneys.test.ts` and `useBikeRoute.test.ts` — mock `global.fetch`, test state transitions (loading → success, loading → error) - Files: `src/hooks/__tests__/useJourneys.test.ts`, `src/hooks/__tests__/useBikeRoute.test.ts` - [ ] **Step 14: Add Component Tests** (~15 min) - Create `EventCard.test.tsx` and `CalendarView.test.tsx` — render with mock data, verify key elements are in the document - Files: `src/app/event/__tests__/EventCard.test.tsx`, `src/app/calendar/__tests__/CalendarView.test.tsx` --- ## Summary | Phase | Steps | Est. Time | |-------|-------|-----------| | 1 — Unblock Runtime | 1–3 | ~45 min | | 2 — Deduplicate Code | 4–7 | ~2 hours | | 3 — Performance & UX | 8–11 | ~1.5 hours | | 4 — Monitoring & Testing | 12–14 | ~1 hour | | **Total** | **14** | **~5 hours** |