Some checks failed
CI / build-and-test (pull_request) Has been cancelled
- Add PLAN.md and sync backend docs, .env.example, API doc (404 details) - Document mock DB and PORT/API_PORT in docs/backend.md; README monorepo + frontend/.env.example - Migration 002: finish_place column, status registered; mapper and mock DB updated - Frontend: registered status, finishPlace, calendar year/month filters, pace sparkline - Extract createApp for tests; supertest + tsx; GitHub Actions CI Made-with: Cursor
62 lines
4.2 KiB
Markdown
62 lines
4.2 KiB
Markdown
# Calendar Run — план продукта
|
||
|
||
Монорепозиторий: **backend** (Express + PostgreSQL) и **frontend** (React + Vite). Цель — календарь стартов с метриками бегуна: планирование, результаты, PR и сравнение.
|
||
|
||
## Вне объёма (намеренно)
|
||
|
||
- Авторизация, мультипользовательность, личные кабинеты.
|
||
- Парсинг сайтов организаторов и автозагрузка результатов.
|
||
- Отдача статики SPA с того же процесса, что и API (фронт — отдельный Vite/build).
|
||
|
||
## Модель данных `Race` (API — camelCase)
|
||
|
||
| Поле | Тип | Описание |
|
||
|------|-----|----------|
|
||
| `id` | string | Стабильный ключ, например `{YYYY-MM-DD}-{slug}` |
|
||
| `date` | string | `YYYY-MM-DD` |
|
||
| `title` | string | Название |
|
||
| `distanceKm` | number | Дистанция, км |
|
||
| `status` | `planned` \| `registered` \| `completed` \| null | Жизненный цикл старта |
|
||
| `officialUrl` | string \| null | Сайт организатора |
|
||
| `startTime` | string \| null | Время старта (строка, напр. `09:30`) |
|
||
| `clusterSchedule` | string \| null | Расписание кластеров |
|
||
| `bibPickup` | string \| null | Выдача номеров |
|
||
| `bibNumber` | string \| null | Стартовый номер |
|
||
| `finishTime` | string \| null | Результат `H:MM:SS` или `MM:SS` |
|
||
| `finishPlace` | string \| null | Место на финише (текст: «3», «3/120» и т.п.) |
|
||
| `notes` | string \| null | Заметки |
|
||
| `createdAt` | string | ISO, read-only |
|
||
| `updatedAt` | string \| null | ISO, read-only |
|
||
|
||
PostgreSQL: `snake_case` столбцы, маппинг в [`backend/src/mappers/race.ts`](backend/src/mappers/race.ts).
|
||
|
||
## HTTP API (минимум)
|
||
|
||
- `GET /health` — liveness без БД.
|
||
- `GET /ready` — readiness (подключение к БД; в режиме mock считается доступной — только для dev/CI).
|
||
- `GET /races` — список; query: `year`, `month` (целые; `month` 1–12).
|
||
- `GET /races/:id`, `POST /races`, `PATCH /races/:id`, `DELETE /races/:id`.
|
||
|
||
Ошибки: JSON, единый стиль (`validation_error`, `not_found`, `conflict`, `database_unavailable`). Подробности — [`docs/backend-api-for-frontend.md`](docs/backend-api-for-frontend.md).
|
||
|
||
## Seed
|
||
|
||
- Файл [`import/races_2026_calendar.csv`](import/races_2026_calendar.csv).
|
||
- Стабильный `id`, upsert по `id`. Повторный запуск безопасен.
|
||
|
||
## Режим без PostgreSQL (dev/CI)
|
||
|
||
Переменная `CALENDAR_RUN_MOCK_DB=1` (или `true`): HTTP-обработчики используют заглушку пула **без** реальной БД. **Не использовать** для `npm run db:migrate` и `npm run seed` — нужен настоящий Postgres и `DB_*`.
|
||
|
||
## Frontend (SPA)
|
||
|
||
- Маршруты: дашборд (`/`), список стартов (`/races`), карточка (`/races/:id`).
|
||
- Дашборд: ближайший старт, последний результат, PR, сезон, PR по ключевым дистанциям, сравнение завершённых стартов, при необходимости — лёгкая визуализация прогресса.
|
||
- Список: будущие / прошедшие; фильтрация по году и месяцу через API.
|
||
- Стили: BEM и дизайн-токены; ориентир по духу — [`agent-frontend-ui-instructions.md`](agent-frontend-ui-instructions.md).
|
||
|
||
## Критерии готовности текущей итерации
|
||
|
||
- Документация согласована с кодом: [`README.md`](README.md), [`docs/backend.md`](docs/backend.md), [`docs/backend-api-for-frontend.md`](docs/backend-api-for-frontend.md).
|
||
- Миграции и seed воспроизводимы; контракт API покрыт smoke-тестами в CI при необходимости с mock-БД.
|