Some checks failed
CI / build-and-test (pull_request) Has been cancelled
- Remove PLAN/agent instruction files; single root .env.example for DB + API - Stack compose uses env_file .env; delete stack env example duplicate - Refresh README, backend docs, API doc; trim gitignore/dockerignore Made-with: Cursor
65 lines
5.3 KiB
Markdown
65 lines
5.3 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-БД.
|
||
|