diff --git a/src/features/schedule/components/ScheduleSearchPage.tsx b/src/features/schedule/components/ScheduleSearchPage.tsx index 97a637c9..bae46aeb 100644 --- a/src/features/schedule/components/ScheduleSearchPage.tsx +++ b/src/features/schedule/components/ScheduleSearchPage.tsx @@ -65,12 +65,50 @@ function formatApiDate(yyyymmdd: string): string { } /** - * Extract simple flights from the mixed IFlight[] response for rendering. + * Convert the mixed IFlight[] response into a flat ISimpleFlight[] for + * rendering. Connecting flights are folded into a synthetic MultiLeg + * shape so the existing FlightCard can render them with combined leg + * numbers, both airline logos, and the total flying time — matching + * Angular's `schedule-list-flight-header` for connecting flights. */ -function extractSimpleFlights(flights: Array<{ routeType: string }>): ISimpleFlight[] { - return flights.filter( - (f): f is ISimpleFlight => f.routeType === "Direct" || f.routeType === "MultiLeg", - ); +function extractSimpleFlights( + flights: Array<{ routeType: string }>, +): ISimpleFlight[] { + const out: ISimpleFlight[] = []; + for (const f of flights) { + if (f.routeType === "Direct" || f.routeType === "MultiLeg") { + out.push(f as unknown as ISimpleFlight); + continue; + } + if (f.routeType === "Connecting") { + const conn = f as unknown as { + flights: ISimpleFlight[]; + flyingTime: string; + status: import("@/features/online-board/types.js").FlightStatus; + }; + const first = conn.flights[0]; + if (!first) continue; + const allLegs: import("@/features/online-board/types.js").IFlightLeg[] = []; + for (const child of conn.flights) { + if (child.routeType === "Direct") allLegs.push(child.leg); + else allLegs.push(...child.legs); + } + const synthetic = { + routeType: "MultiLeg", + flightId: first.flightId, + flyingTime: conn.flyingTime, + operatingBy: first.operatingBy, + id: conn.flights.map((c) => c.id).join("+"), + status: conn.status, + legs: allLegs, + // Carry through the original child flight numbers so the header + // can display 'SU 6188, SU 6233'. + _childFlightIds: conn.flights.map((c) => c.flightId), + } as unknown as ISimpleFlight; + out.push(synthetic); + } + } + return out; } export const ScheduleSearchPage: FC = ({ params }) => { @@ -214,9 +252,6 @@ export const ScheduleSearchPage: FC = ({ params }) => {
-

- {t("SCHEDULE.OUTBOUND")}: {outbound.departure} → {outbound.arrival} -

= ({ const depTimes = depStation.times; const arrTimes = arrStation.times; - const flightNumber = `${flight.flightId.carrier} ${flight.flightId.flightNumber}`; + // Connecting flights get folded into a synthetic MultiLeg shape with + // an extra `_childFlightIds` array so we can render `SU 6188, SU 6233` + // — Angular's `schedule-list-flight-header` does the same via + // `flightNumber` pipe over `getFlights()`. + const childFlightIds = (flight as ISimpleFlight & { + _childFlightIds?: { carrier: string; flightNumber: string; suffix?: string }[]; + })._childFlightIds; + const flightNumber = childFlightIds && childFlightIds.length > 1 + ? childFlightIds + .map((id) => `${id.carrier} ${id.flightNumber}${id.suffix ?? ""}`) + .join(", ") + : `${flight.flightId.carrier} ${flight.flightId.flightNumber}`; const carrier = operatingCarrier(flight.operatingBy) ?? flight.flightId.carrier; const isMultiLeg = flight.routeType === "MultiLeg"; const aircraftName = @@ -104,6 +141,10 @@ export const FlightCard: FC = ({ departureLeg.equipment?.aircraft?.scheduled?.title ?? null; + // Total duration shown in the middle column on schedule rows. Prefer + // the flight-level flyingTime; fall back to the primary leg. + const flightDuration = flight.flyingTime || departureLeg.flyingTime || ""; + const [expanded, setExpanded] = useState(Boolean(initialExpanded)); const rowClickable = expandable || Boolean(onClick); const toggleExpanded = (): void => { @@ -180,6 +221,11 @@ export const FlightCard: FC = ({ key={`${operatingCarrier(leg.operatingBy) ?? carrier}-${i}`} carrier={operatingCarrier(leg.operatingBy) ?? carrier} locale={language} + // Collapsed multi-leg schedule rows show two small + // round airline badges side-by-side — matches + // Angular's `operator-logo-and-model` with + // `round="!expanded || !direct"`. + round={direction === "schedule" && !expanded} /> )) : } @@ -206,9 +252,18 @@ export const FlightCard: FC = ({ />
-
- -
+ {direction === "schedule" ? ( +
+
+ ) : ( +
+ +
+ )}
= ({ />
- {direction === "schedule" ? ( -
- e.stopPropagation()} - > - {t("SHARED.BUY-TICKET") || "Купить"} - - e.stopPropagation()} - > - {t("SHARED.DETAILS")} - -
- ) : expandable && ( + {(expandable || direction === "schedule") && (