Add 6 online board route pages
Start page, flight/departure/arrival/route search pages, and flight details page. Each route is thin: parses URL params, lazy-loads the feature component with Suspense.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Online Board flight details route.
|
||||
*
|
||||
* Parses flight ID from URL, renders detailed flight info.
|
||||
* URL: /{lang}/onlineboard/{carrier}{flightNumber}-{yyyyMMdd}
|
||||
*/
|
||||
|
||||
import { lazy, Suspense } from "react";
|
||||
import { useParams } from "@modern-js/runtime/router";
|
||||
import { parseFlightUrlParams } from "@/features/online-board/url.js";
|
||||
import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
|
||||
|
||||
const OnlineBoardDetailsPage = lazy(() =>
|
||||
import("@/features/online-board/components/OnlineBoardDetailsPage.js").then(
|
||||
(m) => ({ default: m.OnlineBoardDetailsPage }),
|
||||
),
|
||||
);
|
||||
|
||||
export default function FlightDetailsPage(): JSX.Element {
|
||||
const routeParams = useParams<{ params: string }>();
|
||||
const raw = routeParams.params ?? "";
|
||||
const parsed = parseFlightUrlParams(raw);
|
||||
|
||||
if (!parsed) {
|
||||
return (
|
||||
<div data-testid="invalid-params">
|
||||
<p>Invalid flight parameters.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Suspense fallback={<FlightListSkeleton count={1} />}>
|
||||
<OnlineBoardDetailsPage flightId={parsed} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Online Board arrival search route.
|
||||
*
|
||||
* Parses station params from URL, renders shared search page.
|
||||
* URL: /{lang}/onlineboard/arrival/{station}-{yyyyMMdd}[-{timeRange}]
|
||||
*/
|
||||
|
||||
import { lazy, Suspense } from "react";
|
||||
import { useParams } from "@modern-js/runtime/router";
|
||||
import { parseStationUrlParams } from "@/features/online-board/url.js";
|
||||
import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
|
||||
|
||||
const OnlineBoardSearchPage = lazy(() =>
|
||||
import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
|
||||
(m) => ({ default: m.OnlineBoardSearchPage }),
|
||||
),
|
||||
);
|
||||
|
||||
export default function ArrivalSearchPage(): JSX.Element {
|
||||
const routeParams = useParams<{ params: string }>();
|
||||
const raw = routeParams.params ?? "";
|
||||
const parsed = parseStationUrlParams(raw);
|
||||
|
||||
if (!parsed) {
|
||||
return (
|
||||
<div data-testid="invalid-params">
|
||||
<p>Invalid arrival parameters.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const searchParams = {
|
||||
type: "arrival" as const,
|
||||
station: parsed.station,
|
||||
date: parsed.date,
|
||||
...(parsed.timeFrom !== undefined && parsed.timeTo !== undefined
|
||||
? { timeFrom: parsed.timeFrom, timeTo: parsed.timeTo }
|
||||
: {}),
|
||||
};
|
||||
|
||||
return (
|
||||
<Suspense fallback={<FlightListSkeleton />}>
|
||||
<OnlineBoardSearchPage params={searchParams} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Online Board departure search route.
|
||||
*
|
||||
* Parses station params from URL, renders shared search page.
|
||||
* URL: /{lang}/onlineboard/departure/{station}-{yyyyMMdd}[-{timeRange}]
|
||||
*/
|
||||
|
||||
import { lazy, Suspense } from "react";
|
||||
import { useParams } from "@modern-js/runtime/router";
|
||||
import { parseStationUrlParams } from "@/features/online-board/url.js";
|
||||
import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
|
||||
|
||||
const OnlineBoardSearchPage = lazy(() =>
|
||||
import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
|
||||
(m) => ({ default: m.OnlineBoardSearchPage }),
|
||||
),
|
||||
);
|
||||
|
||||
export default function DepartureSearchPage(): JSX.Element {
|
||||
const routeParams = useParams<{ params: string }>();
|
||||
const raw = routeParams.params ?? "";
|
||||
const parsed = parseStationUrlParams(raw);
|
||||
|
||||
if (!parsed) {
|
||||
return (
|
||||
<div data-testid="invalid-params">
|
||||
<p>Invalid departure parameters.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const searchParams = {
|
||||
type: "departure" as const,
|
||||
station: parsed.station,
|
||||
date: parsed.date,
|
||||
...(parsed.timeFrom !== undefined && parsed.timeTo !== undefined
|
||||
? { timeFrom: parsed.timeFrom, timeTo: parsed.timeTo }
|
||||
: {}),
|
||||
};
|
||||
|
||||
return (
|
||||
<Suspense fallback={<FlightListSkeleton />}>
|
||||
<OnlineBoardSearchPage params={searchParams} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Online Board flight number search route.
|
||||
*
|
||||
* Parses flight params from URL, renders shared search page.
|
||||
* URL: /{lang}/onlineboard/flight/{carrier}{flightNumber}-{yyyyMMdd}
|
||||
*/
|
||||
|
||||
import { lazy, Suspense } from "react";
|
||||
import { useParams } from "@modern-js/runtime/router";
|
||||
import { parseFlightUrlParams } from "@/features/online-board/url.js";
|
||||
import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
|
||||
|
||||
const OnlineBoardSearchPage = lazy(() =>
|
||||
import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
|
||||
(m) => ({ default: m.OnlineBoardSearchPage }),
|
||||
),
|
||||
);
|
||||
|
||||
export default function FlightSearchPage(): JSX.Element {
|
||||
const routeParams = useParams<{ params: string }>();
|
||||
const raw = routeParams.params ?? "";
|
||||
const parsed = parseFlightUrlParams(raw);
|
||||
|
||||
if (!parsed) {
|
||||
return (
|
||||
<div data-testid="invalid-params">
|
||||
<p>Invalid flight parameters.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Suspense fallback={<FlightListSkeleton />}>
|
||||
<OnlineBoardSearchPage
|
||||
params={{
|
||||
type: "flight",
|
||||
carrier: parsed.carrier,
|
||||
flightNumber: parsed.flightNumber,
|
||||
suffix: parsed.suffix,
|
||||
date: parsed.date,
|
||||
}}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Online Board start page route.
|
||||
*
|
||||
* Renders the search form landing page. No API calls on load.
|
||||
* URL: /{lang}/onlineboard
|
||||
*/
|
||||
|
||||
import { lazy, Suspense } from "react";
|
||||
|
||||
const OnlineBoardStartPage = lazy(() =>
|
||||
import("@/features/online-board/components/OnlineBoardStartPage.js").then(
|
||||
(m) => ({ default: m.OnlineBoardStartPage }),
|
||||
),
|
||||
);
|
||||
|
||||
export default function OnlineBoardPage(): JSX.Element {
|
||||
return (
|
||||
<Suspense fallback={<div aria-busy="true">Loading...</div>}>
|
||||
<OnlineBoardStartPage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Online Board route search page.
|
||||
*
|
||||
* Parses departure + arrival + date from URL, renders shared search page.
|
||||
* URL: /{lang}/onlineboard/route/{dep}-{arr}-{yyyyMMdd}[-{timeRange}]
|
||||
*/
|
||||
|
||||
import { lazy, Suspense } from "react";
|
||||
import { useParams } from "@modern-js/runtime/router";
|
||||
import { parseRouteUrlParams } from "@/features/online-board/url.js";
|
||||
import { FlightListSkeleton } from "@/ui/flights/FlightListSkeleton.js";
|
||||
|
||||
const OnlineBoardSearchPage = lazy(() =>
|
||||
import("@/features/online-board/components/OnlineBoardSearchPage.js").then(
|
||||
(m) => ({ default: m.OnlineBoardSearchPage }),
|
||||
),
|
||||
);
|
||||
|
||||
export default function RouteSearchPage(): JSX.Element {
|
||||
const routeParams = useParams<{ params: string }>();
|
||||
const raw = routeParams.params ?? "";
|
||||
const parsed = parseRouteUrlParams(raw);
|
||||
|
||||
if (!parsed) {
|
||||
return (
|
||||
<div data-testid="invalid-params">
|
||||
<p>Invalid route parameters.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const searchParams = {
|
||||
type: "route" as const,
|
||||
departure: parsed.departure,
|
||||
arrival: parsed.arrival,
|
||||
date: parsed.date,
|
||||
...(parsed.timeFrom !== undefined && parsed.timeTo !== undefined
|
||||
? { timeFrom: parsed.timeFrom, timeTo: parsed.timeTo }
|
||||
: {}),
|
||||
};
|
||||
|
||||
return (
|
||||
<Suspense fallback={<FlightListSkeleton />}>
|
||||
<OnlineBoardSearchPage params={searchParams} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user