import { JSX } from "react"; // --- TYPES --- interface TfLStatusReason { statusSeverityDescription: string; reason?: string; } interface TfLLineStatus { id: string; name: string; lineStatuses: TfLStatusReason[]; } interface OpenMeteoWeather { current: { temperature_2m: number; weather_code: number; }; current_units: { temperature_2m: string; }; } // --- FETCH FUNCTIONS --- async function getTfLTransitStatus(): Promise { // Public endpoint - No API key needed const res = await fetch( "https://api.tfl.gov.uk/line/mode/tube,elizabeth-line,dlr/status", { next: { revalidate: 300 }, // Cache for 5 minutes }, ); if (!res.ok) throw new Error("Failed to fetch TfL line statuses"); return res.json(); } async function getLondonWeather(): Promise { // Public endpoint - No API key needed const res = await fetch( "https://api.open-meteo.com/v1/forecast?latitude=51.5074&longitude=-0.1278¤t=temperature_2m,weather_code", { next: { revalidate: 300 } }, ); if (!res.ok) throw new Error("Failed to fetch London weather"); return res.json(); } // Helper: Badge color depending on TfL status function getStatusBadge(statusText: string): string { if (statusText === "Good Service") return "badge-success"; if (statusText.includes("Minor") || statusText.includes("Part")) return "badge-warning"; return "badge-error"; } // --- SERVER COMPONENT --- export default async function TrafficAndWeatherPage(): Promise { // PARALLEL FETCHING: Triggers both external network calls simultaneously const [transitData, weatherData] = await Promise.all([ getTfLTransitStatus(), getLondonWeather(), ]); return (
{/* Header */}

London Transit & Weather

Fetched in parallel on the server via{" "} Promise.all()

{/* Quick Weather Stat Card */}
London Temp
{weatherData.current.temperature_2m} {weatherData.current_units.temperature_2m}
{/* TfL Tube & Rail Status Grid */}

🚇 Real-Time Transit Status (TfL Live)

{transitData.map((line) => { const currentStatus = line.lineStatuses[0]; const statusDesc = currentStatus?.statusSeverityDescription || "Unknown"; const disruptionDetail = currentStatus?.reason; return (

{line.name}

{statusDesc}
{disruptionDetail && (

{disruptionDetail}

)}
); })}
); }