--- name: Frontend implementation plan overview: Собрать минималистичный frontend для календаря забегов по UI-инструкции, строго в рамках текущего API-контракта, с отдельной внешней задачей на недостающие backend-поля для completed-забегов. 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 полем place и последующую интеграцию во frontend status: pending isProject: false --- # План frontend части Calendar Run ## Исходные опоры - UI и UX принципы берём строго из [d:\vaka.pro\calendar_run\agent-frontend-ui-instructions.md](d:/vaka.pro/calendar_run/agent-frontend-ui-instructions.md): минимализм, воздух, акцент на данных, спокойная палитра, быстрые сценарии. - Продуктовые ограничения и структура экранов сверяем с [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-забегов поле `место` обязательно по UX, но в API отсутствует: выделяем отдельную задачу другому агенту на расширение backend (`place`) и считаем это внешней зависимостью. ## Архитектура 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`, `notes`. - `place` — вывод включается после backend-расширения. - PR блок: - Дистанции: 5K, 10K, 21.1, 42.2 (согласно UI-инструкции). - Расчёт по completed-забегам с валидным `finishTime`. - Сравнение стартов (ключевая фича): - Таблица/карточки по годам с `time`, `pace`, `place`. - До появления `place` в API — graceful-degradation: колонка в состоянии «нет данных». ## UX и визуальные требования - Визуальная система: светлый фон, белые карточки, один акцентный цвет, без кислотных сочетаний. - Иерархия типографики: H1/H2/body/caption, крупные числовые метрики. - Минимум визуального шума, 2–3 клика на частые действия. - Консистентные состояния загрузки/ошибок/пустых данных. - A11y-базис: фокус-стили, клавиатурная навигация, контраст, корректная разметка интерактивных элементов. ## Отдельная зависимая задача (другой агент) - Создать отдельную backend-задачу: добавить поле `place` в модель `Race` (миграция + API + документация контракта). - После доставки backend-изменения: обновить frontend-типы, формы и блок сравнения, заменить placeholder на реальное значение. ## Порядок реализации 1. Подготовить каркас frontend и дизайн-токены (BEM + CSS variables). 2. Реализовать API-клиент и типы данных с обработкой ошибок. 3. Собрать Dashboard и календарные списки (будущие/прошедшие). 4. Реализовать карточку старта с вычислением `pace` на клиенте. 5. Реализовать PR и блок сравнения стартов с fallback для `place`. 6. Добавить состояния пустых данных/ошибок/загрузки и а11y-полировку. 7. Подготовить handoff-note с зависимостью на backend-задачу (`place`) и интеграционным чеклистом. ## Definition of Done для frontend - Все ключевые экраны из UI-инструкции доступны и консистентны визуально. - API-интеграция работает по текущему контракту без локальных обходов хранилища. - `pace` считается корректно для completed-забегов. - `registered` не ломает модель: визуально интерпретируется в рамках `planned`. - Для `place` есть явная внешняя задача и безопасный fallback в UI.