plan/react-rewrite #1
@@ -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
|
||||
Reference in New Issue
Block a user