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.
3.8 KiB
3.8 KiB
TimeToLeave — Implementation Checklist
Source: 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
- Generate a short UUID (
-
Step 13: Add Hook Tests (~30 min)
- Create
useJourneys.test.tsanduseBikeRoute.test.ts— mockglobal.fetch, test state transitions (loading → success, loading → error) - Files:
src/hooks/__tests__/useJourneys.test.ts,src/hooks/__tests__/useBikeRoute.test.ts
- Create
-
Step 14: Add Component Tests (~15 min)
- Create
EventCard.test.tsxandCalendarView.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
- Create
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 |