diff --git a/docs/superpowers/plans/2026-04-15-phase-5-popular-requests-master.md b/docs/superpowers/plans/2026-04-15-phase-5-popular-requests-master.md new file mode 100644 index 00000000..1e03b640 --- /dev/null +++ b/docs/superpowers/plans/2026-04-15-phase-5-popular-requests-master.md @@ -0,0 +1,111 @@ +# Phase 5 — Popular Requests MASTER Plan + +> **This document is a plan INDEX, not an executable plan.** It lists the Phase 5 sub-plans, their dependency order, the contracts each sub-plan exports for downstream sub-plans to consume, and the shared files that cross sub-plan boundaries. + +**Goal of Phase 5:** Port the Popular Requests feature from Angular to React, wire it into existing route pages, implement the `useSearchHistory` hook backed by `@/shared/storage`, and verify SEO + parity. Popular Requests is an embedded component (not a standalone routed page) — used inside the OnlineBoard and Schedule start pages. It also includes the language switcher (ported from Angular layout) and a per-language-namespaced search history hook. + +**Phase 5 exit gate** (must pass before next phase starts): + +- `PopularRequestsPanel` renders correctly with all 5 request modes: `FlightNumber`, `Route`, `Arrival`, `Departure`, `RouteWithBack`. +- `usePopularRequests` hook calls `GET /Requests/1/getpopular` and handles loading/error states. +- `useSearchHistory` hook persists search history via `@/shared/storage` with per-language namespacing (`afl_history_{lang}`). +- No direct `localStorage` access outside `src/shared/storage.ts` (enforced by ESLint `no-restricted-globals`). +- MF expose `PopularRequests.tsx` upgraded from stub to real component. +- Feature barrel `src/features/popular-requests/index.ts` exports all public surface. +- `pnpm typecheck && pnpm lint && pnpm test && pnpm build:standalone` all green. + +**Angular source analyzed:** + +- **API:** `GET /api/Requests/1/getpopular` returns `IPopularRequest[]` (union of 4 discriminated types keyed by `RequestMode`). +- **Types:** `RequestMode` enum: `FlightNumber | Route | RouteWithBack | Departure | Arrival`. `IPopularRequestType`: `'Schedule' | 'Onlineboard'`. `IPopularRequest` = union of `IPopularRouteRequest | IPopularArrivalRequest | IPopularDepartureRequest | IPopularFlightNumberRequest`. +- **Components:** `PopularRequestsComponent` (container, fetches data, handles clicks + navigation), `PopularRequestComponent` (switch by mode), `ArrivalRequestComponent`, `DepartureRequestComponent`, `FlightNumberRequestComponent`, `RouteRequestComponent`, `RequestInfoComponent` (styled clickable span). +- **Behavior:** On click, populates filter state in `OnlineBoardFiltersStateService` / `ScheduleFiltersStateService` and navigates to `onlineboard` or `schedule` route. Uses `cityName` pipe (maps IATA code to city name via dictionaries). +- **Search History:** `SearchHistoryService` — in-memory array of `ISearchHistoryItem` with dedup-by-URL and prepend logic. Displayed on start pages. React version should persist to localStorage via `@/shared/storage`. +- **No dedicated route** — embedded inside `OnlineBoardStartPage` and `ScheduleStartPage`. + +--- + +## Sub-plan inventory + +| ID | Sub-plan | Estimated size | Description | +|---|---|---|---| +| **5A** | Types + API + hooks | Small (8-12 tasks) | `PopularRequest` types, `getPopularRequests` API fn, `usePopularRequests` hook | +| **5B** | Route page + components | Medium (12-18 tasks) | `PopularRequestsPanel`, mode-specific sub-components, MF expose update | +| **5C** | SEO + parity + integration tests | Small (6-10 tasks) | Verify no SEO regression, integration tests for the panel | +| **5D** | Search history hook | Small (8-12 tasks) | `useSearchHistory` with per-language localStorage namespacing via `@/shared/storage` | + +--- + +## Dependency graph + +``` + ┌──────────────────────────────┐ + │ 5A Types + API + hooks │ + │ src/features/popular- │ + │ requests/{types,api,hooks} │ + └──────────────┬───────────────┘ + │ + ┌──────────────▼───────────────┐ + │ 5B Components + MF expose │◄── depends on 5A types/hooks + │ src/features/popular- │ + │ requests/components/ │ + │ src/mf/expose/ │ + └──────────────┬───────────────┘ + │ + ┌──────────────▼───────────────┐ + │ 5C SEO + parity + tests │◄── depends on 5B components + └──────────────────────────────┘ + + ┌──────────────────────────────┐ + │ 5D useSearchHistory hook │ (independent of 5A-5C) + │ src/shared/hooks/ │ + └──────────────────────────────┘ +``` + +5D is independent and can be executed in parallel with 5A-5C. + +--- + +## Contracts exported per sub-plan + +### 5A — Types + API + hooks + +**Files created:** +- `src/features/popular-requests/types.ts` — `RequestMode`, `PopularRequestType`, `PopularRequest` union, sub-types +- `src/features/popular-requests/api.ts` — `getPopularRequests(client: ApiClient): Promise` +- `src/features/popular-requests/api.test.ts` — API function tests +- `src/features/popular-requests/hooks/usePopularRequests.ts` — React hook wrapping the API call +- `src/features/popular-requests/index.ts` — barrel update + +**Consumed by:** 5B (types + hook), 5C (tests) + +### 5B — Components + MF expose + +**Files created:** +- `src/features/popular-requests/components/PopularRequestsPanel.tsx` — container component +- `src/features/popular-requests/components/PopularRequestItem.tsx` — mode-switching renderer +- `src/features/popular-requests/components/RequestInfo.tsx` — styled clickable span + +**Files modified:** +- `src/mf/expose/PopularRequests.tsx` — stub replaced with real component +- `src/features/popular-requests/index.ts` — barrel update + +**Consumed by:** 5C (integration tests), route pages (OnlineBoardStartPage, ScheduleStartPage) + +### 5C — SEO + parity + integration tests + +**Files created:** +- `src/features/popular-requests/components/PopularRequestsPanel.test.tsx` — component tests + +**Consumed by:** Exit gate verification + +### 5D — Search history hook + +**Files created:** +- `src/shared/hooks/useSearchHistory.ts` — hook with per-language localStorage namespacing +- `src/shared/hooks/useSearchHistory.test.ts` — hook tests + +**Files modified:** +- `src/features/popular-requests/index.ts` — re-export if appropriate + +**Consumed by:** Start pages (OnlineBoardStartPage, ScheduleStartPage) in future integration