--- name: Frontend implementation plan overview: Собрать минималистичный frontend для календаря забегов по UI-инструкции, строго в рамках текущего API-контракта. todos: - id: frontend-structure content: Подготовить структуру frontend, роутинг, базовые layout-компоненты и дизайн-токены на CSS variables + BEM status: completed - id: api-contract-layer content: Реализовать типизированный API-клиент и слой нормализации/обработки ошибок по контракту backend-api-for-frontend.md status: completed - id: dashboard-and-calendar content: Собрать Dashboard, списки будущих/прошедших стартов и базовые карточки по минималистичному UI-гайду status: completed - id: race-details-and-metrics content: Реализовать экран карточки старта, вычисление темпа на фронте и отображение completed-метрик status: completed - id: pr-and-comparison content: Сделать блок PR и сравнение стартов с fallback для отсутствующего поля place status: completed - id: backend-dependency-task content: "Расширение API полем finishPlace: миграция 002, маппер, DTO, фронтенд-интеграция — выполнено" status: completed isProject: false --- # План frontend части Calendar Run ## Исходные опоры - UI и UX принципы: минимализм, воздух, акцент на данных, спокойная палитра, быстрые сценарии (дизайн-токены в `frontend/src/styles/tokens.css`). - Продуктовые ограничения и структура экранов сверяем с [d:\vaka.pro\calendar_run\PLAN.md](d:/vaka.pro/calendar_run/PLAN.md). - Интеграционный контракт берём из [d:\vaka.pro\calendar_run\docs\backend-api-for-frontend.md](d:/vaka.pro/calendar_run/docs/backend-api-for-frontend.md). - Общий контекст запуска/окружения — [d:\vaka.pro\calendar_run\README.md](d:/vaka.pro/calendar_run/README.md) и [d:\vaka.pro\calendar_run\docs\backend.md](d:/vaka.pro/calendar_run/docs/backend.md). ## Границы версии (V1) - Только frontend + интеграция с текущим API. - Статус `зарегистрирован` трактуется как UI-вариант `planned` (без изменения backend-контракта). - Для completed-забегов обязательно показываем `темп`; считаем на фронте из `finishTime` и `distanceKm`. - Для completed-забегов поле `место` (`finishPlace`) доступно в API (миграция 002, маппер, DTO); фронтенд отображает его в карточке и таблице сравнения. ## Архитектура frontend - Базовая структура: `frontend/src/app`, `frontend/src/pages`, `frontend/src/components`, `frontend/src/api`, `frontend/src/features`, `frontend/src/lib`, `frontend/src/styles`. - Дизайн-система на CSS variables: токены цвета/типографики/отступов/радиусов, единые состояния (`success`, `warning`, `error`). - БЭМ для всех UI-блоков и модификаторов (`block`, `block__element`, `block--modifier`). - Единый слой API-клиента: - `GET /races`, `GET /races/:id`, `POST /races`, `PATCH /races/:id`, `DELETE /races/:id` (если используется UI-сценарием). - Типы `Race`, `RaceStatus`, DTO для POST/PATCH. - Централизованный маппинг ошибок API (`validation_error`, `not_found`, `database_unavailable`, `conflict`) в UX-сообщения. ## Экранная модель и сценарии - Dashboard: - `Ближайший старт`, `Последний результат`, `Личный рекорд`, `Сезон`. - CTA к календарю и добавлению старта. - Календарь стартов: - Переключение `Будущие` / `Прошедшие`. - Карточка старта: `title`, `date`, `distanceKm`, статус-лейбл. - Карточка старта: - Базовые поля + `finishTime`, вычисляемый `pace`, `finishPlace`, `notes`. - PR блок: - Дистанции: 5K, 10K, 21.1, 42.2 (согласно UI-инструкции). - Расчёт по completed-забегам с валидным `finishTime`. - Сравнение стартов (ключевая фича): - Таблица/карточки по годам с `time`, `pace`, `finishPlace`. - Если `finishPlace` не заполнено — graceful-degradation: колонка в состоянии «нет данных». ## UX и визуальные требования - Визуальная система: светлый фон, белые карточки, один акцентный цвет, без кислотных сочетаний. - Иерархия типографики: H1/H2/body/caption, крупные числовые метрики. - Минимум визуального шума, 2–3 клика на частые действия. - Консистентные состояния загрузки/ошибок/пустых данных. - A11y-базис: фокус-стили, клавиатурная навигация, контраст, корректная разметка интерактивных элементов. ## Зависимая задача (выполнена) - Поле `finishPlace` добавлено в модель `Race`: миграция `002_finish_place_and_registered_status.sql`, маппер `race.ts`, DTO, API-документация. - Frontend-типы, карточка и блок сравнения используют `finishPlace`. ## Порядок реализации 1. Подготовить каркас frontend и дизайн-токены (BEM + CSS variables). 2. Реализовать API-клиент и типы данных с обработкой ошибок. 3. Собрать Dashboard и календарные списки (будущие/прошедшие). 4. Реализовать карточку старта с вычислением `pace` на клиенте. 5. Реализовать PR и блок сравнения стартов с fallback для `place`. 6. Добавить состояния пустых данных/ошибок/загрузки и а11y-полировку. ## Definition of Done для frontend - Все ключевые экраны из UI-инструкции доступны и консистентны визуально. - API-интеграция работает по текущему контракту без локальных обходов хранилища. - `pace` считается корректно для completed-забегов. - `registered` не ломает модель: визуально интерпретируется в рамках `planned`. - `finishPlace` интегрирован; при отсутствии значения — безопасный fallback в UI.