import { useEffect, useMemo, useState } from "react"; import { Link, useParams } from "react-router-dom"; import { ApiError, getRaceById } from "../api"; import { formatDistance, formatRaceDate, getPaceLabel, getRaceStatusLabel } from "../lib"; import type { Race } from "../api"; function getErrorMessage(error: unknown): string { if (error instanceof ApiError) { return error.message; } return "Не удалось загрузить карточку старта."; } export function RaceDetailsPage(): JSX.Element { const { raceId } = useParams<{ raceId: string }>(); const [race, setRace] = useState(null); const [isLoading, setIsLoading] = useState(true); const [errorMessage, setErrorMessage] = useState(null); useEffect(() => { let isMounted = true; async function loadRace(): Promise { if (!raceId) { setErrorMessage("Не найден идентификатор старта."); setIsLoading(false); return; } try { const item = await getRaceById(raceId); if (!isMounted) { return; } setRace(item); setErrorMessage(null); } catch (error) { if (!isMounted) { return; } setErrorMessage(getErrorMessage(error)); } finally { if (isMounted) { setIsLoading(false); } } } void loadRace(); return () => { isMounted = false; }; }, [raceId]); const paceLabel = useMemo(() => { if (!race || race.status !== "completed") { return null; } return getPaceLabel(race.finishTime, race.distanceKm); }, [race]); if (isLoading) { return (

Карточка старта

Загружаем данные старта...

); } if (errorMessage || !race) { return (

Карточка старта

{errorMessage ?? "Старт не найден."}

Вернуться к списку стартов
); } const isCompleted = race.status === "completed"; return (

{race.title}

{formatRaceDate(race.date)} · {formatDistance(race.distanceKm)}

{getRaceStatusLabel(race.status)}

Основная информация

Дата
{formatRaceDate(race.date)}
Дистанция
{formatDistance(race.distanceKm)}
Статус
{getRaceStatusLabel(race.status)}

Completed-метрики

{isCompleted ? (
Время
{race.finishTime ?? "время не указано"}
Темп
{paceLabel ?? "не удалось вычислить"}
Стартовый номер
{race.bibNumber ?? "не указан"}
) : (

Метрики появятся после завершения старта и ввода результата.

)}

Заметки

{race.notes?.trim() ? race.notes : "Заметок пока нет."}

Назад к календарю стартов
); }