# 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 | ✅ Implemented | ✔️ Reviewed | Notes | |------|:------:|:------:|-------| | **Step 4: Consolidate HAFAS Journey Parsing** (~40 min) | [x] | [x] | parseHafasJourneys moved to hafas-client.ts, exported, imported by useJourneys.ts. Option A followed. | | **Step 5: Wire API Routes to Use Library Clients** (~30 min) | [x] | [x] | Both routes use module-level singleton clients. Param validation, error handling, and try/catch intact. | | **Step 6: Remove Dead Code** (~5 min) | [x] | [x] | live-status-utils.ts deleted, export removed from index.ts. No remaining references. | | **Step 7: Create Missing Test Setup File** (~10 min) | [x] | [x] | src/test/setup.ts created with jest-dom vitest import. Referenced correctly in vitest.config.ts. | --- ## Phase 3 — Performance & UX (~1.5 hours) | Step | ✅ Implemented | ✔️ Reviewed | Notes | |------|:------:|:------:|-------| | **Step 8: Add Debounce to Lookup Hooks** (~25 min) | [x] | [x] | 400ms setTimeout + AbortController in `useGeocode.ts` and `useDestinationStation.ts`. AbortError silently ignored. | | **Step 9: Pre-Group Calendar Events by Date** (~20 min) | [x] | [x] | `useMemo` builds `Map` keyed by `YYYY-MM-DD`. Per-cell `filter()` replaced with O(1) map lookup. | | **Step 10: Add Dark Mode Toggle** (~20 min) | [x] | [x] | `useTheme.ts` created (localStorage + prefers-color-scheme). Sun/moon toggle button added to `Header.tsx`. | | **Step 11: Fix Bike Route Steps** (~5 min) | [x] | [x] | `steps: "true"` already present in `BikeRoutingClient.getBikeRoute()` query params. | --- ## Phase 4 — Monitoring & Testing (~1 hour) | Step | ✅ Implemented | ✔️ Reviewed | Notes | |------|:------:|:------:|-------| | **Step 12: Add Correlation IDs to API Errors** (~15 min) | [x] | [x] | `randomUUID().slice(0, 8)` in catch blocks of `bike-route`, `geocode`, `hafas`, `calendar`, `calendar/parse`. Logged server-side, returned in JSON. Existing API tests updated to assert `correlationId`. | | **Step 13: Add Hook Tests** (~30 min) | [x] | [x] | `useJourneys.test.ts` (4 tests: no-op when missing IDs, success, HTTP error, fetch throw). `useBikeRoute.test.ts` (4 tests: no-op when missing coords, success, HTTP error, fetch throw). | | **Step 14: Add Component Tests** (~15 min) | [x] | [x] | `EventCard.test.tsx` (renders title + destination, hooks mocked). `CalendarView.test.tsx` (3 tests: month header, event on correct day, overflow indicator). | --- ## 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** |