Wrap ScheduleDetailsPage in PageLayout + frame

The schedule-details view rendered bare content on the blue background
with no PageLayout, no PageTabs, no breadcrumbs, no white card — so
the flight-number heading, leg list and skeletons were invisible
against the page background. Wrap the component in PageLayout with
the schedule tab + breadcrumb + 'Информация о рейсе: SU 6805' title,
and put each branch inside a <section class='frame'> (error,
not-found, empty, success) so it sits on the same white card as the
board pages.

Also fix the same React key warning the board page had: the leg map
used leg.index as the key, which is undefined for Direct flights.
Fall back to the array index.
This commit is contained in:
2026-04-18 13:11:28 +03:00
parent 77821c3893
commit 96235d5534
@@ -13,6 +13,8 @@ import { useTranslation } from "@/i18n/provider.js";
import { FlightCard } from "@/ui/flights/FlightCard.js";
import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
import { SeoHead } from "@/ui/seo/SeoHead.js";
import { PageLayout } from "@/ui/layout/PageLayout.js";
import { PageTabs } from "@/ui/layout/PageTabs.js";
import { JsonLdRenderer } from "@/shared/seo/json-ld.js";
import { useScheduleDetails } from "../hooks/useScheduleDetails.js";
import { buildScheduleDetailsSeo } from "../seo.js";
@@ -69,23 +71,55 @@ export const ScheduleDetailsPage: FC<ScheduleDetailsPageProps> = ({
const { flights, loading, error } = useScheduleDetails(detailsParams);
const pageTabs = <PageTabs viewType="schedule" />;
const scheduleHref = `/${locale}/schedule`;
const title = flightIds[0]
? `${t("BOARD.FLIGHT-INFO")}: ${flightIds[0].carrier} ${flightIds[0].flightNumber}`
: t("SCHEDULE.TITLE");
if (loading) {
return <FlightListSkeleton count={flightIds.length} />;
return (
<PageLayout
headerLeft={pageTabs}
title={<h1 className="text--white page-title">{title}</h1>}
breadcrumbs={[{ label: t("SCHEDULE.TITLE"), url: scheduleHref }]}
>
<section className="frame">
<FlightListSkeleton count={flightIds.length} />
</section>
</PageLayout>
);
}
if (error) {
return (
<div className="schedule-details schedule-details--error" data-testid="schedule-details-error">
<p>{t("BOARD.LOAD-FAILED")}</p>
</div>
<PageLayout
headerLeft={pageTabs}
title={<h1 className="text--white page-title">{title}</h1>}
breadcrumbs={[{ label: t("SCHEDULE.TITLE"), url: scheduleHref }]}
>
<section className="frame">
<div className="schedule-details schedule-details--error" data-testid="schedule-details-error">
<p>{t("BOARD.LOAD-FAILED")}</p>
</div>
</section>
</PageLayout>
);
}
if (flights.length === 0) {
return (
<div className="schedule-details schedule-details--not-found" data-testid="schedule-details-not-found">
<p>{t("BOARD.FLIGHT-NOT-FOUND")}</p>
</div>
<PageLayout
headerLeft={pageTabs}
title={<h1 className="text--white page-title">{title}</h1>}
breadcrumbs={[{ label: t("SCHEDULE.TITLE"), url: scheduleHref }]}
>
<section className="frame">
<div className="schedule-details schedule-details--not-found" data-testid="schedule-details-not-found">
<p>{t("BOARD.FLIGHT-NOT-FOUND")}</p>
</div>
</section>
</PageLayout>
);
}
@@ -93,47 +127,54 @@ export const ScheduleDetailsPage: FC<ScheduleDetailsPageProps> = ({
const seoProps = buildScheduleDetailsSeo(t, flights, locale, canonicalOrigin, flightIds);
return (
<div className="schedule-details" data-testid="schedule-details">
<PageLayout
headerLeft={pageTabs}
title={<h1 className="text--white page-title">{title}</h1>}
breadcrumbs={[{ label: t("SCHEDULE.TITLE"), url: scheduleHref }]}
>
<SeoHead {...seoProps} />
<section className="frame">
<div className="schedule-details" data-testid="schedule-details">
{flights.map((flight) => {
const jsonLd = buildScheduleFlightJsonLd(flight);
const legs = getLegs(flight);
const flightNumber = `${flight.flightId.carrier} ${flight.flightId.flightNumber}`;
{flights.map((flight) => {
const jsonLd = buildScheduleFlightJsonLd(flight);
const legs = getLegs(flight);
const flightNumber = `${flight.flightId.carrier} ${flight.flightId.flightNumber}`;
return (
<div key={flight.id} className="schedule-details__flight" data-testid={`flight-${flight.id}`}>
<JsonLdRenderer data={jsonLd} />
return (
<div key={flight.id} className="schedule-details__flight" data-testid={`flight-${flight.id}`}>
<JsonLdRenderer data={jsonLd} />
<div className="schedule-details__header">
<h2 className="schedule-details__flight-number">{flightNumber}</h2>
<span className="schedule-details__status">{flight.status}</span>
</div>
<FlightCard flight={flight} />
{legs.map((leg) => (
<div key={leg.index} className="schedule-details__leg" data-testid={`leg-${leg.index}`}>
<div className="schedule-details__leg-route">
<span>{leg.departure.scheduled.airportCode}</span>
<span>&rarr;</span>
<span>{leg.arrival.scheduled.airportCode}</span>
<div className="schedule-details__header">
<h2 className="schedule-details__flight-number">{flightNumber}</h2>
<span className="schedule-details__status">{flight.status}</span>
</div>
<div className="schedule-details__leg-times">
<span>{leg.departure.times.scheduledDeparture.localTime}</span>
<span> - </span>
<span>{leg.arrival.times.scheduledArrival.localTime}</span>
</div>
{leg.equipment.name && (
<div className="schedule-details__aircraft">
{leg.equipment.name}
<FlightCard flight={flight} />
{legs.map((leg, i) => (
<div key={`leg-${leg.index ?? i}`} className="schedule-details__leg" data-testid={`leg-${leg.index ?? i}`}>
<div className="schedule-details__leg-route">
<span>{leg.departure.scheduled.airportCode}</span>
<span>&rarr;</span>
<span>{leg.arrival.scheduled.airportCode}</span>
</div>
<div className="schedule-details__leg-times">
<span>{leg.departure.times.scheduledDeparture.localTime}</span>
<span> - </span>
<span>{leg.arrival.times.scheduledArrival.localTime}</span>
</div>
{leg.equipment.name && (
<div className="schedule-details__aircraft">
{leg.equipment.name}
</div>
)}
</div>
)}
))}
</div>
))}
</div>
);
})}
</div>
);
})}
</div>
</section>
</PageLayout>
);
};