import { useEffect, useMemo, useState } from "react"; import { Link, useParams } from "react-router-dom"; import type { Race } from "../api"; import { ApiError, getRaces } from "../api"; import { formatDistance, formatRaceDate, getRaceStatusClassName, getRaceStatusLabel, sortByDateAsc } from "../lib"; function getErrorMessage(error: unknown): string { if (error instanceof ApiError) { return error.message; } return "Не удалось загрузить старты."; } export function RaceDayPage(): JSX.Element { const { ymd } = useParams<{ ymd: string }>(); const [races, setRaces] = useState([]); const [isLoading, setIsLoading] = useState(true); const [errorMessage, setErrorMessage] = useState(null); const validYmd = ymd && /^\d{4}-\d{2}-\d{2}$/.test(ymd) ? ymd : null; const year = validYmd ? parseInt(validYmd.slice(0, 4), 10) : NaN; useEffect(() => { if (!validYmd || Number.isNaN(year)) { setIsLoading(false); setRaces([]); return; } const ac = new AbortController(); let mounted = true; async function load(): Promise { setIsLoading(true); try { const items = await getRaces({ year }, { signal: ac.signal }); if (!mounted || ac.signal.aborted) { return; } const forDay = items.filter((r) => r.date.slice(0, 10) === validYmd); setRaces(sortByDateAsc(forDay)); setErrorMessage(null); } catch (e) { if (ac.signal.aborted || !mounted) { return; } setErrorMessage(getErrorMessage(e)); setRaces([]); } finally { if (mounted && !ac.signal.aborted) { setIsLoading(false); } } } void load(); return () => { mounted = false; ac.abort(); }; }, [validYmd, year]); const heading = useMemo(() => { if (!validYmd) { return "Дата не указана"; } return formatRaceDate(validYmd); }, [validYmd]); if (!validYmd) { return (

Некорректная дата

Вернуться к календарю стартов

); } return (

← Календарь стартов

{heading}

{errorMessage ? (

{errorMessage}

) : null} {isLoading ? (

Загружаем…

) : null} {!isLoading && !errorMessage && races.length === 0 ? (

На эту дату стартов нет.

) : null} {!isLoading && races.length > 0 ? (
    {races.map((race) => (
  • {race.title} {formatDistance(race.distanceKm)} ·{" "} {getRaceStatusLabel(race.status, race.date)}
  • ))}
) : null}
Добавить
); }