diff --git a/CHANGELOG.md b/CHANGELOG.md index d8d18f7..a637830 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,34 @@ #### Added -- Управление паролем и сессиями: проверка текущего пароля, список активных сессий, отзыв выбранной или всех остальных сессий. - Фильтрация стартов по статусу, периоду и дистанции; backfill и обновление автоматически получаемых обложек. +### [1.5.3] — 2026-07-12 + +#### Fixed + +- Миграции базы данных автоматически выполняются перед запуском backend-контейнера. + +### [1.5.2] — 2026-07-12 + +#### Added + +- Настраиваемое имя публичного профиля и раздельная видимость будущих и завершённых стартов. +- Публичные результаты финиша с учётом настроек видимости владельца. + +### [1.5.1] — 2026-07-12 + +#### Added + +- Публичные страницы пользователей и API опубликованного календаря стартов. + +### [1.5.0] — 2026-07-12 + +#### Added + +- Проверка и смена текущего пароля. +- Список активных сессий, отзыв выбранной сессии или всех остальных сессий. + ### [1.4.2] — 2026-07-12 #### Changed @@ -87,7 +112,7 @@ #### Fixed -- Завершённые старты отображаются от самых свежих к более старым. +- По умолчанию завершённые старты отображаются от самых свежих к более старым; явно выбранная сортировка применяется без переопределения. ### [0.10.1] — 2026-08-13 @@ -107,17 +132,48 @@ - В конфигурацию TypeScript для Vite добавлены DOM-типы. -### [0.9.3] — 2026-07-14 +### [0.9.3] — 2026-07-13 -#### Added +#### Changed -- Экран «Аккаунт»: подтверждённый email, смена пароля и управление другими активными сессиями. -- На дашборде появились фильтруемые «Последние старты» с пагинацией и переходом в старт, ссылки из карточек рекордов и интерактивный график прогресса. -- Поиск, фильтры, сортировка и экспорт истории; график прогресса переведён на AG Charts. +- Фильтры календаря сворачиваются и показывают число активных условий; hero-блок дашборда стал компактнее. + +### [0.9.1] — 2026-07-13 #### Fixed -- Упрощён обзор календаря стартов и зарегистрированы модули AG Charts. +- Зарегистрированы необходимые модули AG Charts для корректного отображения графика. + +### [0.9.0] — 2026-07-13 + +#### Added + +- Поиск, фильтры и сортировка истории стартов с синхронизацией параметров в URL. +- Экспорт выбранных стартов в CSV и iCalendar. +- Интерактивный график прогресса на AG Charts. +- Фильтрация стартов по статусу, диапазону дат и дистанции. + +### [0.8.2] — 2026-07-12 + +#### Added + +- Имена публичных профилей и отдельные настройки видимости будущих и завершённых стартов. +- Отображение опубликованных результатов на публичной странице. + +### [0.8.1] — 2026-07-12 + +#### Added + +- Публичная страница пользователя с опубликованным календарём стартов. +- Управление видимостью публичного профиля в аккаунте. + +### [0.8.0] — 2026-07-12 + +#### Added + +- Экран «Аккаунт»: подтверждённый email, смена пароля и управление активными сессиями. +- Фильтруемые «Последние старты» с пагинацией и переходом в старт на дашборде. +- Ссылки из карточек рекордов и интерактивный график прогресса. ### [0.7.1] — 2026-07-12 @@ -171,6 +227,25 @@ - Редизайн дашборда и визуального представления стартов. +### [0.4.3] — 2026-04-13 + +#### Fixed + +- В календаре скрыты всплывающие карточки для дней без стартов. + +### [0.4.2] — 2026-04-13 + +#### Fixed + +- Анимация наведения применяется ко всей строке старта, а не только к внутренней ссылке. + +### [0.4.1] — 2026-04-13 + +#### Fixed + +- Старт автоматически получает статус «Пробежал» при вводе корректного времени финиша. +- Исправлены переходы с дашборда и поведение списка и календаря стартов. + ### [0.4.0] — 2026-04-13 #### Added diff --git a/frontend/src/pages/RacesPage.tsx b/frontend/src/pages/RacesPage.tsx index 33fed31..3e1158a 100644 --- a/frontend/src/pages/RacesPage.tsx +++ b/frontend/src/pages/RacesPage.tsx @@ -37,6 +37,7 @@ const VIEW_STORAGE_KEY = "races-view-mode"; type ViewMode = "list" | "calendar"; type RaceListTab = "upcoming" | "completed"; type RaceSort = "dateAsc" | "dateDesc" | "titleAsc" | "distanceAsc"; +type RaceSortOption = RaceSort | ""; function yearSelectOptions(races: Race[], selectedYear = ""): number[] { const current = new Date().getFullYear(); @@ -146,7 +147,7 @@ export function RacesPage(): JSX.Element { const [distanceMin, setDistanceMin] = useState(() => searchParams.get("distanceMin") ?? ""); const [distanceMax, setDistanceMax] = useState(() => searchParams.get("distanceMax") ?? ""); const [searchQuery, setSearchQuery] = useState(() => searchParams.get("q") ?? ""); - const [sortOrder, setSortOrder] = useState(() => (searchParams.get("sort") as RaceSort | null) ?? "dateAsc"); + const [sortOrder, setSortOrder] = useState(() => (searchParams.get("sort") as RaceSort | null) ?? ""); const [viewMode, setViewMode] = useState(() => searchParams.get("view") === "calendar" ? "calendar" : readInitialViewMode()); const [activeListTab, setActiveListTab] = useState("upcoming"); const [isAdvancedFiltersOpen, setIsAdvancedFiltersOpen] = useState(() => @@ -263,7 +264,7 @@ export function RacesPage(): JSX.Element { if (distanceMin) next.set("distanceMin", distanceMin); if (distanceMax) next.set("distanceMax", distanceMax); if (searchQuery) next.set("q", searchQuery); - if (sortOrder !== "dateAsc") next.set("sort", sortOrder); + if (sortOrder) next.set("sort", sortOrder); setSearchParams(next, { replace: true }); }, [dateFrom, dateTo, distanceMax, distanceMin, monthFilter, searchQuery, setSearchParams, sortOrder, statusFilter, viewMode, yearFilter]); @@ -281,9 +282,11 @@ export function RacesPage(): JSX.Element { const { upcoming, completed } = useMemo( () => ({ upcoming: filteredRaces.filter((race) => race.status !== "completed"), - completed: sortByDateDesc(filteredRaces.filter((race) => race.status === "completed")), + completed: sortOrder + ? filteredRaces.filter((race) => race.status === "completed") + : sortByDateDesc(filteredRaces.filter((race) => race.status === "completed")), }), - [filteredRaces], + [filteredRaces, sortOrder], ); const statusMessage = useMemo(() => { if (errorMessage && !isLoading) { @@ -309,7 +312,7 @@ export function RacesPage(): JSX.Element { dateTo, distanceMin, distanceMax, - sortOrder !== "dateAsc" ? sortOrder : "", + sortOrder, ].filter(Boolean).length; if (errorMessage && races.length === 0 && !isLoading) { @@ -478,7 +481,8 @@ export function RacesPage(): JSX.Element {