diff --git a/docs/superpowers/specs/2026-04-16-popular-requests-prefill-design.md b/docs/superpowers/specs/2026-04-16-popular-requests-prefill-design.md new file mode 100644 index 00000000..6072079b --- /dev/null +++ b/docs/superpowers/specs/2026-04-16-popular-requests-prefill-design.md @@ -0,0 +1,95 @@ +# Popular Requests Form Pre-fill + +## Goal + +When a user clicks a popular request on the OnlineBoard or Schedule start pages, navigate to the same start page with query params that pre-fill the search form — matching the Angular app's behavior. + +## Current State (Bug) + +Both `OnlineBoardStartPage` and `ScheduleStartPage` have empty `handlePopularRequestClick` callbacks. Clicking a popular request does nothing. + +Angular's behavior: sets filter state in a service before navigating to the start page. The destination filter reads from the service on init and pre-fills the form. + +## Design + +Use query params instead of a state service (aligns with React's URL-driven architecture). + +### Flow + +1. User clicks popular request +2. `handlePopularRequestClick` reads the `PopularRequest` object +3. Builds a URL with query params for the current start page +4. Navigates via `useNavigate()` +5. Start page reads query params on mount via `useSearchParams()` +6. Passes values as initial props to the filter component +7. User sees pre-filled form, modifies if needed, clicks "Search" + +### Query Param Patterns + +**OnlineBoard** (`/ru/onlineboard?...`): + +| Mode | Params | +|------|--------| +| FlightNumber | `tab=flight&carrier=SU&flight=0654` | +| Departure | `tab=route&departure=LED` | +| Arrival | `tab=route&arrival=VKO` | +| Route | `tab=route&departure=LED&arrival=KRR` | + +**Schedule** (`/ru/schedule?...`): + +| Mode | Params | +|------|--------| +| Route | `departure=LED&arrival=KRR` | +| RouteWithBack | `departure=LED&arrival=KRR&return=true` | + +### Files to Change + +1. **`src/features/online-board/components/OnlineBoardStartPage.tsx`** + - Implement `handlePopularRequestClick`: build query param URL, navigate + - Read `useSearchParams()` on mount + - Pass parsed values as initial props to `OnlineBoardFilter` + +2. **`src/features/online-board/components/OnlineBoardFilter.tsx`** + - No changes needed — already accepts `initialDeparture`, `initialArrival`, `initialDate`, `initialTab`, `initialFlightNumber` props + +3. **`src/features/schedule/components/ScheduleStartPage.tsx`** + - Implement `handlePopularRequestClick`: build query param URL, navigate + - Read `useSearchParams()` on mount + - Use parsed values as initial state for `departureAirport`, `arrivalAirport`, `withReturn` + +### What OnlineBoardFilter Already Supports + +```typescript +interface OnlineBoardFilterProps { + initialDeparture?: string; + initialArrival?: string; + initialDate?: string; // yyyyMMdd + initialTab?: "flight" | "route"; + initialFlightNumber?: string; +} +``` + +These props feed directly into `useState` initializers. No changes needed. + +### ScheduleStartPage Form State Changes + +Current (no initial support): +```typescript +const [departureAirport, setDepartureAirport] = useState(""); +const [arrivalAirport, setArrivalAirport] = useState(""); +const [withReturn, setWithReturn] = useState(false); +``` + +After (reads from query params): +```typescript +const [searchParams] = useSearchParams(); +const [departureAirport, setDepartureAirport] = useState(searchParams.get("departure") ?? ""); +const [arrivalAirport, setArrivalAirport] = useState(searchParams.get("arrival") ?? ""); +const [withReturn, setWithReturn] = useState(searchParams.get("return") === "true"); +``` + +### Edge Cases + +- If query params are empty (normal navigation to start page): form initializes with defaults (empty strings, today's date) — no change from current behavior +- If user clicks a popular request while the form already has values: navigating with query params replaces the page, form re-initializes with new values +- Date is always today (matching Angular behavior which uses `new Date()`)