Covers data model types, datetime utilities, dictionary hook, and flight display components for the online board feature.
3.8 KiB
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) IFlightLegwith stations, times, status (ClientApp/src/typings/flight/flight-leg.ts)IFlightLegStationwithIAirportInfo(ClientApp/src/typings/flight/flight-station.ts)ITimesSetwith dayChange, local, utc, tzOffset (ClientApp/src/typings/times.ts)FlightRequestTypeenum mapping from AngularRequestMode(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-- fromDurationPipelogicformatTime(date: string | Date): string-- "HH:mm" formatformatDate(date: string | Date, locale?: string): string-- localized date stringisDayChange(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:
DictionariesServicefetches fromnetworkService.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 typessrc/ui/index.ts-- re-export from./flights
Exit criteria
pnpm typecheckgreenpnpm lintgreenpnpm testgreen 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