Пошаговая инструкция для разработчиков
This commit is contained in:
parent
9ff5334fd4
commit
d96b06e580
336
DEV_GUIDE.md
Normal file
336
DEV_GUIDE.md
Normal file
@ -0,0 +1,336 @@
|
||||
# Пошаговая инструкция по разработке Галикона
|
||||
|
||||
## Этап 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 (установка на телефон)
|
||||
- [ ] Тесты + деплой
|
||||
Loading…
Reference in New Issue
Block a user