diff --git a/src/features/online-board/components/OnlineBoardDetailsPage.test.tsx b/src/features/online-board/components/OnlineBoardDetailsPage.test.tsx index 5faba627..ebf3157d 100644 --- a/src/features/online-board/components/OnlineBoardDetailsPage.test.tsx +++ b/src/features/online-board/components/OnlineBoardDetailsPage.test.tsx @@ -9,7 +9,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen } from "@testing-library/react"; import { OnlineBoardDetailsPage } from "./OnlineBoardDetailsPage.js"; -import type { IParsedFlightId, IDirectFlight } from "../types.js"; +import type { IParsedFlightId, IDirectFlight, IMultiLegFlight, IFlightLeg } from "../types.js"; const mockFlightId: IParsedFlightId = { carrier: "SU", @@ -75,8 +75,8 @@ const mockFlight: IDirectFlight = { // Mutable state for test control let mockState = { - flight: mockFlight as IDirectFlight | null, - allFlights: [mockFlight] as IDirectFlight[], + flight: mockFlight as IDirectFlight | IMultiLegFlight | null, + allFlights: [mockFlight] as (IDirectFlight | IMultiLegFlight)[], daysOfFlight: ["20250115"] as string[], loading: false, error: null as Error | null, @@ -273,6 +273,70 @@ describe("OnlineBoardDetailsPage", () => { }); }); + describe("multi-leg timeline integration", () => { + function makeLeg(index: number, overrides: Partial = {}): IFlightLeg { + return { + ...mockFlight.leg, + index, + ...overrides, + } as IFlightLeg; + } + + it("does not render FullRouteTimeline for Direct flights", () => { + render( + , + ); + expect(screen.queryByTestId("full-route-timeline")).toBeNull(); + expect(screen.queryByTestId("transfer-bar")).toBeNull(); + }); + + it("renders FullRouteTimeline for MultiLeg flights", () => { + const multiLeg: IMultiLegFlight = { + id: "SU100-20250115", + flightId: { carrier: "SU", flightNumber: "100", suffix: "", date: "20250115" }, + routeType: "MultiLeg", + status: "Scheduled", + flyingTime: "12:00", + operatingBy: {}, + legs: [makeLeg(0), makeLeg(1)], + }; + mockState = { + flight: multiLeg, + allFlights: [multiLeg], + daysOfFlight: ["20250115"], + loading: false, + error: null, + }; + render( + , + ); + expect(screen.getByTestId("full-route-timeline")).toBeTruthy(); + }); + + it("interleaves one TransferBar between two legs", () => { + const multiLeg: IMultiLegFlight = { + id: "SU100-20250115", + flightId: { carrier: "SU", flightNumber: "100", suffix: "", date: "20250115" }, + routeType: "MultiLeg", + status: "Scheduled", + flyingTime: "12:00", + operatingBy: {}, + legs: [makeLeg(0), makeLeg(1)], + }; + mockState = { + flight: multiLeg, + allFlights: [multiLeg], + daysOfFlight: ["20250115"], + loading: false, + error: null, + }; + render( + , + ); + expect(screen.getAllByTestId("transfer-bar")).toHaveLength(1); + }); + }); + describe("flight schedule integration", () => { it("renders FlightSchedule when firstLeg.daysOfWeek is present", () => { const flightWithDaysOfWeek = { diff --git a/src/features/online-board/components/OnlineBoardDetailsPage.tsx b/src/features/online-board/components/OnlineBoardDetailsPage.tsx index 306e2210..8bb4e991 100644 --- a/src/features/online-board/components/OnlineBoardDetailsPage.tsx +++ b/src/features/online-board/components/OnlineBoardDetailsPage.tsx @@ -7,7 +7,7 @@ * @module */ -import { useCallback, type FC } from "react"; +import { Fragment, useCallback, type FC } from "react"; import { useNavigate } from "@modern-js/runtime/router"; import { useTranslation } from "@/i18n/provider.js"; import "./OnlineBoardDetailsPage.scss"; @@ -28,6 +28,8 @@ import { DayTabs } from "./DayTabs/index.js"; import { BoardDetailsHeader } from "./BoardDetailsHeader/index.js"; import { DetailsBackButton } from "./DetailsBackButton/index.js"; import { FlightSchedule } from "./FlightSchedule/index.js"; +import { FullRouteTimeline } from "./FullRouteTimeline/index.js"; +import { TransferBar } from "./TransferBar/index.js"; import type { IParsedFlightId, IFlightLeg } from "../types.js"; export interface OnlineBoardDetailsPageProps { @@ -41,12 +43,20 @@ export interface OnlineBoardDetailsPageProps { /** * Render all legs of a flight with departure/arrival station details. + * For multi-leg flights, interleaves a TransferBar between consecutive legs. */ -function FlightLegs({ legs }: { legs: IFlightLeg[] }): JSX.Element { +function FlightLegs({ + legs, + viewType, +}: { + legs: IFlightLeg[]; + viewType: "Onlineboard" | "Schedule"; +}): JSX.Element { return (
- {legs.map((leg) => ( -
+ {legs.map((leg, i) => ( + +
Leg {leg.index + 1} {leg.status} @@ -124,6 +134,10 @@ function FlightLegs({ legs }: { legs: IFlightLeg[] }): JSX.Element { )}
+ {i < legs.length - 1 && ( + + )} + ))}
); @@ -278,6 +292,10 @@ export const OnlineBoardDetailsPage: FC = ({ + {displayFlight.routeType === "MultiLeg" && ( + + )} + {/* Summary card */} @@ -292,7 +310,7 @@ export const OnlineBoardDetailsPage: FC = ({ )} {/* Detailed leg information */} - + {/* Flying time */}