From fc03c08278dee79114edc642c2bfe36e6ef3fdb4 Mon Sep 17 00:00:00 2001 From: gnezim Date: Wed, 15 Apr 2026 07:52:23 +0300 Subject: [PATCH] Add Phase 2A UI adapter implementation plan Covers data model types, datetime utilities, dictionary hook, and flight display components for the online board feature. --- .../plans/2026-04-15-phase-2a-ui-adapter.md | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-15-phase-2a-ui-adapter.md diff --git a/docs/superpowers/plans/2026-04-15-phase-2a-ui-adapter.md b/docs/superpowers/plans/2026-04-15-phase-2a-ui-adapter.md new file mode 100644 index 00000000..fc59595e --- /dev/null +++ b/docs/superpowers/plans/2026-04-15-phase-2a-ui-adapter.md @@ -0,0 +1,112 @@ +# Phase 2A -- UI Adapter Layer + +> Sub-plan of Phase 2 (Online Board). Implements the flight-display component library at `src/ui/flights/` and supporting utilities. + +**Depends on:** Phase 1 (foundation complete). +**Consumed by:** 2C (API hooks use types), 2E (pages compose components). + +--- + +## Tasks + +### Task 1: Data model types (`src/features/online-board/types.ts`) + +Port the key Angular interfaces to minimal React-friendly TypeScript types. Source analysis: + +- Angular `ISimpleFlight` = `IDirectFlight | IMultiLegFlight` (`ClientApp/src/typings/flight/flight.ts`) +- `IFlightLeg` with stations, times, status (`ClientApp/src/typings/flight/flight-leg.ts`) +- `IFlightLegStation` with `IAirportInfo` (`ClientApp/src/typings/flight/flight-station.ts`) +- `ITimesSet` with dayChange, local, utc, tzOffset (`ClientApp/src/typings/times.ts`) +- `FlightRequestType` enum mapping from Angular `RequestMode` (`ClientApp/src/typings/enums.ts`) +- `IParsedFlightId` (`ClientApp/src/typings/flight/flight-id.ts`) +- `IBoardResponse`, `IDaysResponse` (`ClientApp/src/typings/responses.ts`) + +Flatten into idiomatic TS -- no class hierarchies, no Angular deps. + +**Test:** Type-level tests (compile-time satisfaction checks) in `src/features/online-board/types.test.ts`. + +### Task 2: Datetime utility functions (`src/shared/utils/datetime/`) + +Pure functions ported from Angular pipes: + +- `formatDuration(minutes: number): string` -- from `DurationPipe` logic +- `formatTime(date: string | Date): string` -- "HH:mm" format +- `formatDate(date: string | Date, locale?: string): string` -- localized date string +- `isDayChange(scheduledDate: string | Date, actualDate: string | Date): number` -- day offset + +**Test:** `src/shared/utils/datetime/datetime.test.ts` -- TDD, write tests first. + +### Task 3: Airport/city dictionary hook (`src/shared/hooks/useDictionaries.ts`) + +- `useCityName(code: string): string` -- returns city name for IATA code +- Phase 2 stub: returns the code itself (passthrough) with TODO for real API +- Angular source: `DictionariesService` fetches from `networkService.getDictionary('cities')` -- API endpoint TBD from customer + +**Test:** `src/shared/hooks/useDictionaries.test.ts` -- verify passthrough behavior. + +### Task 4: `StationDisplay.tsx` component + +Renders airport IATA code + city name. Uses `useCityName` hook. + +Props: `{ airportCode: string; airportName?: string; cityName?: string }`. + +No test (UI component -- visual testing in 2G). + +### Task 5: `TimeGroup.tsx` component + +Displays scheduled + actual times with day-change indicator. + +Props: `{ scheduled: string; actual?: string; dayChange?: number; label?: string }`. + +Uses `formatTime` utility. + +### Task 6: `FlightStatus.tsx` component + +Status badge with semantic styling. + +Props: `{ status: FlightStatus }`. + +Maps status to display label + CSS class. + +### Task 7: `DurationDisplay.tsx` component + +Flight duration display. + +Props: `{ minutes: number }`. + +Uses `formatDuration` utility. + +### Task 8: `FlightCard.tsx` component + +Composes Station + TimeGroup + Status + Duration into a flight row. + +Props: `{ flight: ISimpleFlight }`. + +### Task 9: `FlightListSkeleton.tsx` component + +Loading placeholder for flight list. Renders N placeholder rows with CSS animation. + +Props: `{ count?: number }`. + +### Task 10: `FlightList.tsx` component + +List of FlightCards with loading state. + +Props: `{ flights: ISimpleFlight[]; loading?: boolean }`. + +Uses `FlightListSkeleton` when loading. + +### Task 11: Update barrel exports + +- `src/ui/flights/index.ts` -- export all components and types +- `src/ui/index.ts` -- re-export from `./flights` + +--- + +## Exit criteria + +- `pnpm typecheck` green +- `pnpm lint` green +- `pnpm test` green with datetime utility tests + type satisfaction tests + dictionary hook test passing +- No Angular dependencies in any new file +- All components are pure functional React components with typed props