galikon/DEV_GUIDE.md

337 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Пошаговая инструкция по разработке Галикона
## Этап 0. Подготовка окружения (1 день)
1. Установи Node.js 20 LTS
2. Установи PostgreSQL 16
3. Установи Redis 7
4. Создай проект:
- Фронтенд: `npx create-react-app galikon-frontend --template typescript`
- Бэкенд: `mkdir galikon-backend && cd galikon-backend && npm init -y && npm i express cors bcrypt jsonwebtoken pg redis socket.io multer`
5. Настрой ESLint + Prettier
6. Создай репозиторий на GitHub/GitLab, запушь
---
## Этап 1. Авторизация и пользователи (неделя 1-2)
### Шаг 1.1 — База данных
Создай миграцию users:
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
login VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(200) NOT NULL,
sport VARCHAR(100),
role VARCHAR(20) DEFAULT 'athlete',
birth_date DATE,
age INTEGER,
country VARCHAR(100),
city VARCHAR(100),
club VARCHAR(200),
coach VARCHAR(200),
rank VARCHAR(100),
goal TEXT,
phone VARCHAR(30),
email VARCHAR(200),
avatar_url TEXT,
photo_url TEXT,
child_name VARCHAR(200),
stars INTEGER DEFAULT 0,
quiz_score INTEGER DEFAULT 0,
games_won INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
```
### Шаг 1.2 — Регистрация (POST /api/auth/register)
- Прими JSON: login, password, name, sport, role, birth_date, country, city, club, coach, rank, goal, phone, email
- Проверь: login уникален, phone в формате +7..., email содержит @
- Захешируй пароль bcrypt (12 раундов)
- Вычисли возраст из birth_date
- Сохрани в базу
- Верни объект пользователя + accessToken + refreshToken
### Шаг 1.3 — Вход (POST /api/auth/login)
- Прими login + password
- Найди пользователя по логину
- Сравни пароль через bcrypt.compare()
- Сгенерируй JWT accessToken (15 мин) и refreshToken (30 дней)
- Реализуй rate limiting: 5 попыток → блок 1 мин (храни в Redis)
### Шаг 1.4 — Middleware авторизации
- Проверяй заголовок Authorization: Bearer <token>
- Декодируй JWT, доставай userId
- Клади пользователя в req.user
- Если токен просрочен → 401
### Шаг 1.5 — Обновление токена (POST /api/auth/refresh)
- Прими refreshToken
- Проверь в Redis (не отозван ли)
- Сгенерируй новую пару токенов
### Шаг 1.6 — Экран регистрации (фронтенд)
- 8 компонентов-шагов (Step1Name, Step2Login, Step3Sport, Step4Role, Step5Birth, Step6Location, Step7Club, Step8Contacts)
- Компонент StepIndicator (точки 1-8)
- Валидация на каждом шаге
- На шаге 2: индикатор силы пароля (слабый/средний/сильный)
- На шаге 4: выбор роли кнопками, поле «Имя ребёнка» для родителя
- На шаге 5: календарь даты + авто-возраст + аватарки эмодзи + загрузка фото
- На шаге 6: выбрать страну → загрузить города (API /api/locations/cities?country=...)
- На шаге 8: телефон + email с валидацией
---
## Этап 2. Профиль и дневник (неделя 3-4)
### Шаг 2.1 — Таблицы БД
```sql
CREATE TABLE achievements (
id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id),
title VARCHAR(300), date DATE, description TEXT
);
CREATE TABLE diary_entries (
id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id),
date DATE NOT NULL, type VARCHAR(50), km DECIMAL(5,1),
best_time VARCHAR(20), feel INTEGER CHECK(feel BETWEEN 1 AND 5),
note TEXT, created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE events (
id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id),
title VARCHAR(300), date DATE NOT NULL, location VARCHAR(300)
);
```
### Шаг 2.2 — API профиля
- GET /api/profile — вернуть текущего пользователя
- PUT /api/profile — обновить поля (name, sport, club, coach, goal, phone, email)
- POST /api/achievements — добавить достижение
- GET /api/achievements — список достижений
### Шаг 2.3 — API дневника
- GET /api/diary?limit=20&offset=0 — список записей
- POST /api/diary — новая запись (валидация: date обязательно)
- DELETE /api/diary/:id — удалить запись
- GET /api/diary/stats — агрегация: всего записей, суммарный км, среднее feel
### Шаг 2.4 — API календаря
- GET /api/events — все события
- POST /api/events — новое событие (title + date обязательно)
- DELETE /api/events/:id — удалить
### Шаг 2.5 — Система значков (геймификация)
- Бэкенд: эндпоинт GET /api/badges — вычисляет значки на основе данных пользователя
- Логика: 1+ запись в дневнике = 🏊, 10+ = 📖, 30+ = 🔥, есть достижения = 🏆 и т.д.
- Фронтенд: компонент BadgeGrid — сетка значков (полученные — цветные, нет — серые)
### Шаг 2.6 — Компоненты фронтенда
- ProfilePage: аватар, ФИО, спорт, клуб, тренер, значки, достижения
- DiaryPage: форма записи + список (с бесконечным скроллом)
- CalendarPage: форма добавления + предстоящие/прошедшие события
- Кнопка «PDF-отчёт» → GET /api/report/pdf (генерирует PDF на сервере через puppeteer)
---
## Этап 3. Чаты и WebSocket (неделя 5-6)
### Шаг 3.1 — Таблицы БД
```sql
CREATE TABLE chats (id SERIAL PRIMARY KEY, type VARCHAR(20), name VARCHAR(200));
CREATE TABLE chat_members (chat_id INTEGER REFERENCES chats(id), user_id INTEGER REFERENCES users(id));
CREATE TABLE messages (
id SERIAL PRIMARY KEY, chat_id INTEGER REFERENCES chats(id),
from_user_id INTEGER REFERENCES users(id), text TEXT NOT NULL,
read BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT NOW()
);
```
### Шаг 3.2 — WebSocket сервер
- Установи socket.io на сервер
- При подключении: аутентифицируй через JWT (передавай в handshake)
- Присоединяй пользователя к его комнатам (socket.join(`user:${userId}`))
- События:
- `chat:message` — отправить сообщение в чат
- `chat:read` — отметить прочитанным
- `chat:typing` — печатает...
### Шаг 3.3 — REST API чатов
- GET /api/chats — список чатов пользователя
- POST /api/chats — создать чат (прямой или групповой)
- GET /api/chats/:id/messages?limit=50 — сообщения чата
- POST /api/chats/:id/messages — отправить (дублирует WebSocket для надёжности)
### Шаг 3.4 — Фронтенд чата
- ChatList: список чатов с фильтром по роли (Все/Спортсмены/Тренеры/Родители)
- ChatView: сообщения + поле ввода + автоскролл вниз
- Счётчик непрочитанных (useEffect + WebSocket)
### Шаг 3.5 — Игры в чате
- TicTacToe: компонент с сеткой 3×3, ходы через WebSocket
- GuessNumber: компонент с полем ввода, попытки, подсказки «больше/меньше»
- Reaction: компонент с кругом, меняющим цвет (красный→зелёный), замер времени
- SportQuiz: 8 вопросов, варианты ответов, подсчёт очков
- При победе → POST /api/games/win — начислить звёзды
---
## Этап 4. Рейтинг и голосование (неделя 7)
### Шаг 4.1 — Таблица голосов
```sql
CREATE TABLE votes (
voter_id INTEGER REFERENCES users(id),
target_id INTEGER REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW(),
PRIMARY KEY(voter_id, target_id)
);
```
### Шаг 4.2 — API рейтинга
- POST /api/vote/:userId — проголосовать (один голос на пользователя)
- GET /api/ranking?limit=10 — топ спортсменов по звёздам
- Звёзды = голоса + бонусы за игры (автоматически)
### Шаг 4.3 — Фронтенд
- Компонент RankingList: топ-10, золото/серебро/бронза
- Кнопка «Проголосовать» у каждого пользователя
---
## Этап 5. Кабинет тренера и родителя (неделя 8)
### Шаг 5.1 — Кабинет тренера
- API: GET /api/coach/students — найти всех пользователей, где поле coach совпадает с именем тренера
- Для каждого ученика: аватар, ФИО, спорт, разряд, цель, суммарный км, последние 5 тренировок
- Фронтенд: компонент StudentsPage с карточками учеников
### Шаг 5.2 — Кабинет родителя
- API: POST /api/parent/link — привязать ребёнка по логину (проверка: ребёнок существует, роль athlete)
- API: GET /api/parent/child — получить профиль и статистику ребёнка
- Фронтенд: ChildPage — форма привязки + профиль ребёнка + кнопка «Отвязать»
---
## Этап 6. Инструменты (неделя 9)
### Шаг 6.1 — Нормативы
- Статический JSON с таблицей разрядов
- Компонент NormsTable — отображение таблицы
### Шаг 6.2 — Сравнение с чемпионами
- Статические данные Дрессела (14-18 лет)
- Компонент ChampionCompare: ввод времени + возраста → сравнение
### Шаг 6.3 — Анализ видео
- Компонент VideoAnalyzer: загрузка видео + плеер + кнопки покадровой перемотки
- Используй HTML5 video API: video.currentTime += 0.033
### Шаг 6.4 — Витамины и здоровье
- Таблицы: vitamin_log (user_id, date, vitamin_type, taken), sleep_log (user_id, date, hours, pulse), test_results (user_id, test_type, value, date)
- API: GET/POST для каждого лога
- Чек-лист витаминов на сегодня
- Лог сна и пульса с графиком за 7 дней
### Шаг 6.5 — Видеоуроки
- Статический список поисковых запросов YouTube (12 тем)
---
## Этап 7. Аналитика и дашборды (неделя 10)
### Шаг 7.1 — Бэкенд для аналитики
- GET /api/analytics/progress — вернуть массив {date, time} для графика прогресса
- GET /api/analytics/heatmap — годовая тепловая карта [{date, km}]
- GET /api/analytics/kpi — ключевые показатели
- GET /api/analytics/compare — сравнение со средним по возрасту
- GET /api/analytics/export/csv — CSV-файл всех тренировок
- GET /api/analytics/export/dashboard — PDF-отчёт
### Шаг 7.2 — Фронтенд дашборда
- Установи Chart.js: `npm i chart.js react-chartjs-2`
- Компонент ProgressChart: линейный график время/дата + линия цели
- Компонент RadarChart: радарная диаграмма навыков
- Компонент HeatmapCalendar: календарь активности (как на GitHub)
- Компонент KPICards: счётчики (тренировки, км, время, сон)
- Компонент TrainingPie: круговая диаграмма типов тренировок
### Шаг 7.3 — Дашборд тренера
- Компонент CoachDashboard: таблица учеников + групповой график
- Цветовое кодирование строк (зелёный — лидер, красный — отстающий)
- Алерты при отсутствии тренировок 3+ дня
### Шаг 7.4 — Дашборд родителя
- Компонент ParentDashboard: упрощённый график ребёнка + счётчики
---
## Этап 8. Админ-панель (неделя 10)
### Шаг 8.1
- Middleware adminAuth — проверка роли admin
- GET /api/admin/users — список всех пользователей
- DELETE /api/admin/users/:id — удалить
- POST /api/admin/users/:id/reset-password — сброс пароля
### Шаг 8.2
- Компонент AdminPanel: таблица пользователей с кнопками удалить/сбросить
---
## Этап 9. PWA (неделя 11)
### Шаг 9.1
- Создай manifest.json в public/
- Иконки: 192×192 и 512×512 PNG
- Service worker (workbox-webpack-plugin)
- Офлайн-режим: кэширование статики
- Настрой `"display": "standalone"`
### Шаг 9.2
- Мета-теги для iOS (apple-mobile-web-app-capable и т.д.)
- Splash screen для iOS
---
## Этап 10. Тестирование и деплой (неделя 11-12)
### Шаг 10.1 — Тесты
- Unit-тесты: Jest для компонентов и API-хендлеров
- E2E: Playwright для критических сценариев (регистрация, вход, дневник, чат)
### Шаг 10.2 — Деплой
- Собрать фронтенд: `npm run build`
- Настроить Docker:
- Dockerfile для бэкенда (Node.js)
- Dockerfile для фронтенда (Nginx)
- docker-compose.yml (frontend + backend + PostgreSQL + Redis)
- Развернуть на VPS (Hetzner, DigitalOcean) или AWS
### Шаг 10.3 — Мониторинг
- Логирование: Winston + Sentry
- Мониторинг ошибок: Sentry
- Uptime: UptimeRobot
---
## Итоговый чек-лист
- [ ] Регистрация (8 шагов) с валидацией
- [ ] Вход с JWT + refresh токеном
- [ ] Профиль: значки, достижения, PDF-отчёт
- [ ] Дневник тренировок с историей
- [ ] Календарь соревнований
- [ ] Чаты (WebSocket) + 4 игры
- [ ] Рейтинг с голосованием
- [ ] Кабинет тренера (ученики и их прогресс)
- [ ] Кабинет родителя (привязка ребёнка)
- [ ] Нормативы, сравнение с чемпионами, анализ видео
- [ ] Витамины, сон, анализы
- [ ] Видеоуроки (12 тем)
- [ ] Дашборд: графики, тепловая карта, KPI
- [ ] Админ-панель
- [ ] PWA (установка на телефон)
- [ ] Тесты + деплой