7abfddd607
Implement 400ms debounce with AbortController in useGeocode and useDestinationStation to prevent excessive API calls. Add dark mode toggle via new useTheme hook, persisting preference to localStorage and applying to document root. Pre-group calendar events by date using a Map in CalendarView to replace O(n) filter operations with O(1) lookups.
69 lines
3.8 KiB
Markdown
69 lines
3.8 KiB
Markdown
# 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] | | 400ms setTimeout + AbortController in `useGeocode.ts` and `useDestinationStation.ts`. AbortError silently ignored. |
|
||
| **Step 9: Pre-Group Calendar Events by Date** (~20 min) | [x] | | `useMemo` builds `Map<string, Event[]>` keyed by `YYYY-MM-DD`. Per-cell `filter()` replaced with O(1) map lookup. |
|
||
| **Step 10: Add Dark Mode Toggle** (~20 min) | [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] | | `steps: "true"` already present in `BikeRoutingClient.getBikeRoute()` query params. |
|
||
|
||
---
|
||
|
||
## 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** |
|