import { Suspense } from "react"; import { notFound } from "next/navigation"; import { AiAnalysisCard } from "@/components/ai-analysis-card"; import { RouteMapSection } from "@/components/route-map-section"; import { StatCard } from "@/components/stat-card"; import { formatDate, formatDistance, formatDuration, formatPace } from "@/lib/format"; import { fetchActivityRoutePoints, getAuthorizedClient } from "@/lib/garmin/client"; import { getLatestAnalysisForTarget } from "@/lib/models/analysis"; import { getRunningActivity, setRunningActivityRoutePoints, type RunningActivity } from "@/lib/models/running"; export const dynamic = "force-dynamic"; async function RouteMapFetcher({ activity }: { activity: RunningActivity }) { let routePoints = activity.routePoints; if (!routePoints && activity.hasRoute) { try { const client = await getAuthorizedClient(); const points = await fetchActivityRoutePoints(client, activity.garminActivityId); if (points) { await setRunningActivityRoutePoints(activity.garminActivityId, points); routePoints = points; } } catch { // GPS fetch failed silently } } return (
{routePoints && routePoints.length > 0 ? ( ) : (
Brak danych GPS
)}
); } function MapSkeleton() { return (
); } export default async function RunningActivityPage({ params, }: { params: Promise<{ id: string }>; }) { const { id } = await params; const activity = await getRunningActivity(id); if (!activity) { notFound(); } const analysis = await getLatestAnalysisForTarget("running", activity._id); return (

{activity.name}

{formatDate(activity.startTime)}

{/* Map: cols 1–2, rows 1–3 — streamed in after page skeleton */} }> {/* Col 3, rows 1–3: key pace stats */} {/* Row 4: HR, calories, cadence — always shown */} {/* Row 5+: optional advanced stats, auto-flow */} {activity.maxHr ? : null} {activity.elevationGainM ? : null} {activity.vo2Max ? : null} {activity.avgGroundContactTimeMs ? ( ) : null} {activity.avgVerticalOscillationCm ? ( ) : null} {activity.avgVerticalRatioPct ? ( ) : null} {activity.avgStrideLengthCm ? ( ) : null} {activity.avgGroundContactBalanceLeftPct ? ( ) : null} {activity.avgPowerW ? : null} {activity.maxPowerW ? : null} {activity.avgRespirationRate ? ( ) : null} {activity.aerobicTrainingEffect ? ( ) : null} {activity.anaerobicTrainingEffect ? ( ) : null}
); }