# 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<PopularRequest[]>`
- `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
