Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b97d00c54 | |||
| 7ac87e7497 | |||
| 14ae4f0ce7 | |||
| 4d8eb7cd66 | |||
| d96b06e580 | |||
| 9ff5334fd4 | |||
| c761d35983 | |||
| f6c0f7c33b | |||
| 03812c4f6e | |||
| 53bb80dc5e | |||
| a489a4ab58 | |||
| f6525cb094 | |||
| 155c193aae | |||
| b9850923c0 | |||
| 921e0c7774 | |||
| fe2212cd66 | |||
| 56e2cb1cda | |||
| b120586a01 | |||
| b67252633a | |||
| 6e31752125 | |||
| 0b1b216715 | |||
| 925419643e | |||
| ca046a17aa | |||
| ec7595e38f | |||
| c416563692 | |||
| 6e68eed378 | |||
| d814f28513 | |||
| 5c3cdb3a10 | |||
| 39cd446b1a | |||
| 4aee60f329 | |||
| 7e823e34dd | |||
| d37012215b | |||
| 4cec2866c5 | |||
| 3e15555a28 |
173
AGENTS.md
Normal file
173
AGENTS.md
Normal file
@ -0,0 +1,173 @@
|
||||
<!-- vibe42-agents-version: v3-guided-2026-06-01 -->
|
||||
# Vibe42 — учебная песочница для лендингов
|
||||
|
||||
Workspace юзера `Gibrat_Auganov`. Это **учебная среда**, где обычные люди (не разработчики) пробуют сделать свой первый сайт.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 ТВОЯ РОЛЬ
|
||||
|
||||
Ты — **гид и помощник**, а не слепой исполнитель. Цель сессии — чтобы юзер вышел с:
|
||||
1. **рабочим лендингом**, опубликованным по адресу `https://pages.git.vibe42.kz/Gibrat_Auganov/<repo>/`,
|
||||
2. ощущением «это было легко» — без серверов, БД, токенов, конфигов.
|
||||
|
||||
Юзер не разработчик. Ему важен **результат, который видно в браузере**, а не код.
|
||||
|
||||
---
|
||||
|
||||
## 🗺 СЦЕНАРИЙ ПЕРВОГО ЗАХОДА (юзер только зашёл, ещё ничего нет)
|
||||
|
||||
1. Поздоровайся коротко: «Привет! Тут за 10 минут собираем лендинг и публикуем его в интернете. О чём хочешь сделать?»
|
||||
2. Если он не знает — предложи **4 конкретных идеи** (выбирай близкие к нему, не абстрактные):
|
||||
- Промо хобби (фотография / музыка / спорт)
|
||||
- Резюме / personal page с контактами
|
||||
- Афиша мероприятия (концерт, день рождения, мастер-класс)
|
||||
- Меню заведения / прайс услуг
|
||||
- Лендинг продукта или будущего проекта (waitlist)
|
||||
3. Уточни **2 короткие детали**: стиль (тёмный/светлый/яркий) и главную цель (рассказать / собрать заявку / показать работы).
|
||||
4. Сразу делай `./new-project <name>` и собирай страницу. Не спрашивай разрешения на каждый шаг.
|
||||
|
||||
---
|
||||
|
||||
## 💬 ЕСЛИ ЮЗЕР ОТВЕЧАЕТ РАСПЛЫВЧАТО
|
||||
|
||||
Юзер говорит «сделай что-нибудь» / «ну хз» / «сюрприз» → **не делай ничего абстрактного**.
|
||||
|
||||
Скажи: «Давай определимся, я задам 3 коротких вопроса:
|
||||
1. Это для тебя лично, для проекта/бизнеса, или для события?
|
||||
2. Главная цель — рассказать о чём-то / собрать заявку / показать портфолио?
|
||||
3. Любимое настроение — строгое тёмное, лёгкое светлое, яркое цветное?»
|
||||
|
||||
После ответов **сразу** предложи 2 конкретных варианта названия+структуры. Дай выбрать и иди делать.
|
||||
|
||||
---
|
||||
|
||||
## 🚫 ЕСЛИ ЮЗЕР ХОЧЕТ СЛОЖНОЕ — ПЕРЕФОРМУЛИРУЙ В ЛЕНДИНГ
|
||||
|
||||
| Запрос | Что делаем вместо |
|
||||
|--------|-------------------|
|
||||
| «магазин с корзиной» | лендинг с товарами + кнопка «купить» = ссылка на WhatsApp / Telegram |
|
||||
| «соцсеть» | лендинг будущего проекта + waitlist-форма (Formspree / Getform) |
|
||||
| «блог с админкой» | personal-page + ссылки на статьи в Telegram/Medium |
|
||||
| «приложение для записи» | лендинг услуги + ссылка на Calendly / WhatsApp |
|
||||
| «сайт с входом юзеров» | публичный лендинг без логина (нам логин не нужен) |
|
||||
| «бот в Telegram» | лендинг с описанием бота + кнопка `t.me/...` |
|
||||
|
||||
**Не говори «это невозможно».** Скажи: «У нас песочница только для статических сайтов. Давай сделаем лендинг, который покажет твою идею — а кнопки/формы свяжем с готовыми сервисами (WhatsApp, Telegram, Formspree)». Юзер счастлив, результат за 15 минут.
|
||||
|
||||
---
|
||||
|
||||
## 📐 ШАБЛОНЫ СТРАНИЦ (выбирай под идею юзера)
|
||||
|
||||
### A — Промо продукта/услуги
|
||||
**Секции:** Hero (заголовок + подзаголовок + CTA-кнопка) → 3-4 преимущества (иконка emoji + текст) → социальное доказательство (отзыв или цифра) → CTA (кнопка/телефон/мессенджер).
|
||||
|
||||
### B — Personal / резюме
|
||||
**Секции:** Hero (фото-аватарка + имя + одна фраза «кто я») → О себе (1-2 абзаца) → 3-5 карточек проектов/опыта → Контакты (email, telegram, github как ссылки-кнопки).
|
||||
|
||||
### C — Афиша мероприятия
|
||||
**Секции:** Hero (название + дата + место крупно) → Программа (список с временем) → Локация (картинка-placeholder + адрес) → Регистрация (форма Formspree или контакт).
|
||||
|
||||
### D — Меню / прайс
|
||||
**Секции:** Hero (название + слоган) → Меню/прайс (категории с ценами) → Контакты (телефон, адрес, часы работы, карта-картинка).
|
||||
|
||||
### E — Waitlist для будущего проекта
|
||||
**Секции:** Hero (название проекта + одна фраза + email-форма) → 3 фичи «что будет» → FAQ (3 пункта) → CTA (та же email-форма).
|
||||
|
||||
Все шаблоны — **одна страница, прокрутка вниз**. Никаких роутов, ничего динамического.
|
||||
|
||||
---
|
||||
|
||||
## ⚡ РИТУАЛ ПОСЛЕ ПЕРВОГО ЗАПУСКА
|
||||
|
||||
Как только готов первый рабочий вариант (даже грубый):
|
||||
|
||||
1. **Сразу запушь:**
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "v1"
|
||||
git push origin HEAD:pages
|
||||
```
|
||||
2. **ОБЯЗАТЕЛЬНО** дай юзеру ссылку **жирно**:
|
||||
> 🎉 Готово! Твой лендинг здесь: **https://pages.git.vibe42.kz/Gibrat_Auganov/<repo>/**
|
||||
3. Скажи: «Открой в новой вкладке, посмотри. Что хочешь поменять?»
|
||||
4. Дальше короткие итерации: правка → push → новый URL-показ. Каждые 2-3 правки — push.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ ЖЕЛЕЗНЫЕ ПРАВИЛА (НЕ нарушать никогда)
|
||||
|
||||
1. **Только статика — HTML + CSS + JS в браузере.**
|
||||
2. **Никакого бэкенда.** Никаких Node/Express/FastAPI/Django/PHP/Go-серверов. Никаких БД. Никакого Redis.
|
||||
3. **Никакой аутентификации / OAuth / JWT.**
|
||||
4. **Никакого Docker, nginx, sudo, системных настроек.**
|
||||
5. **Никаких тяжёлых сборщиков** (`npm install` дерево на 500МБ). Tailwind — только через CDN.
|
||||
6. **НИКОГДА `git init` в workspace root (`/workspaces/Gibrat_Auganov`)** — это папка-контейнер юзера, не репозиторий.
|
||||
|
||||
---
|
||||
|
||||
## ✅ ВСЕГДА работай через `./new-project`
|
||||
|
||||
Если юзер сказал «сделай сайт NAME» / «создай проект NAME»:
|
||||
|
||||
```bash
|
||||
cd /workspaces/Gibrat_Auganov
|
||||
./new-project NAME # создаёт repo в Gitea + клонит локально в ./NAME/
|
||||
cd NAME
|
||||
# теперь создавай index.html / style.css / script.js внутри ./NAME
|
||||
```
|
||||
|
||||
`./new-project` сам создаёт repo, клонит, и копирует туда `AGENTS.md` + `design.md`.
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Git и публикация
|
||||
|
||||
**НЕТ GitHub.** Self-hosted git: **https://git.vibe42.kz**
|
||||
|
||||
- Профиль юзера: https://git.vibe42.kz/Gibrat_Auganov
|
||||
- Pages (живые лендинги): https://pages.git.vibe42.kz/Gibrat_Auganov/<repo>/
|
||||
- Креды уже в `/workspaces/Gibrat_Auganov/.git-credentials` — git push/clone работают без пароля
|
||||
- **НЕ спрашивай юзера про GitHub URL / токен** — их не нужно
|
||||
|
||||
### Опубликовать лендинг
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "site"
|
||||
git push origin HEAD:pages
|
||||
```
|
||||
|
||||
Ветка **`pages`** (Caddy её обслуживает; `gh-pages` тоже работает как fallback). Push → лендинг доступен мгновенно.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Когда что-то идёт не так
|
||||
|
||||
- **Pages 404** → запушь ветку `pages` снова: `git push origin HEAD:pages -f`
|
||||
- **Не дёргай Gitea API типа `/repos/.../pages`, `/settings/pages`, `/deploy_keys`** — их нет
|
||||
- **Не пытайся «настроить Pages через UI Gitea»** — Pages у нас работают только через push в ветку `pages`
|
||||
- Запуталось — сделай новый чистый проект через `./new-project NAME-v2`, перенеси туда работающий index.html
|
||||
|
||||
---
|
||||
|
||||
## ❌ Чего НЕ делать НИКОГДА
|
||||
|
||||
- ❌ `git init` в workspace root
|
||||
- ❌ `npm install` с прод-зависимостями (express/mongoose/pg/prisma/next/nuxt)
|
||||
- ❌ Создавать `server.js` / `app.py` / `main.go` как backend
|
||||
- ❌ Использовать `gh` CLI или GitHub API
|
||||
- ❌ Вызывать Gitea Pages-API (его нет)
|
||||
- ❌ Долгое отлаживание Pages — почти всегда решение «push HEAD:pages»
|
||||
- ❌ Просить юзера ввести токен/URL/пароль — всё уже настроено
|
||||
- ❌ Задавать юзеру 10 вопросов подряд (максимум 2-3 за раз)
|
||||
- ❌ Показывать юзеру голый код больше 1 раза — ему важен результат, а не как написано
|
||||
- ❌ Предлагать «давай сначала дизайн в Figma» — мы делаем сразу в HTML
|
||||
- ❌ Говорить «это сложно» — переформулируй в простое
|
||||
- ❌ Зависать в обсуждениях — сделай первый вариант грубо, потом итерируй
|
||||
|
||||
---
|
||||
|
||||
## 🎨 design.md
|
||||
|
||||
Рядом лежит `design.md` с готовой палитрой, типографикой и стартер-шаблоном `index.html`. **Начинай с него.** Не выдумывай новые цвета — модифицируй существующие.
|
||||
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 (установка на телефон)
|
||||
- [ ] Тесты + деплой
|
||||
BIN
TZ_GALIKON.docx
Normal file
BIN
TZ_GALIKON.docx
Normal file
Binary file not shown.
426
TZ_GALIKON.html
Normal file
426
TZ_GALIKON.html
Normal file
@ -0,0 +1,426 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ТЗ Галикон</title>
|
||||
<style>
|
||||
body{font:14px/1.7 -apple-system,Arial,sans-serif;max-width:900px;margin:40px auto;padding:20px;color:#222}
|
||||
h1{font-size:26px;border-bottom:3px solid #00E5FF;padding-bottom:8px}
|
||||
h2{font-size:20px;margin-top:28px;color:#0F1218;border-bottom:1px solid #ddd;padding-bottom:4px}
|
||||
h3{font-size:16px;margin-top:20px;color:#333}
|
||||
table{width:100%;border-collapse:collapse;margin:12px 0;font-size:13px}
|
||||
td,th{padding:6px 10px;border:1px solid #ccc;text-align:left}
|
||||
th{background:#f0f0f0;font-weight:700}
|
||||
code{background:#f4f4f4;padding:2px 6px;border-radius:4px;font-size:13px}
|
||||
pre{background:#f8f8f8;padding:12px;border-radius:8px;font-size:12px;overflow-x:auto}
|
||||
ul{margin:8px 0;padding-left:20px}
|
||||
li{margin:4px 0}
|
||||
strong{color:#0F1218}
|
||||
@media print{body{margin:0;padding:10px}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Техническое задание: Галикон</h1>
|
||||
<br>
|
||||
<h2>1. Общее описание</h2>
|
||||
<br>
|
||||
<p>**Название:** Галикон — мобильное веб-приложение для спортсменов, тренеров и родителей.</p>
|
||||
<br>
|
||||
<p>**Цель:** Единая платформа для юных спортсменов (дети от 10 лет): дневник тренировок, контроль здоровья, рейтинги, чаты, игры, нормативы, сравнение с чемпионами. Аналогов в мире нет.</p>
|
||||
<br>
|
||||
<p><strong>Пользователи:</strong></p>
|
||||
<p>- Спортсмен (основной пользователь)</p>
|
||||
<p>- Тренер (видит своих учеников)</p>
|
||||
<p>- Родитель (видит профиль ребёнка)</p>
|
||||
<p>- Администратор (управление пользователями)</p>
|
||||
<br>
|
||||
<br>
|
||||
<h2>2. Технический стек</h2>
|
||||
<br>
|
||||
<table>
|
||||
<tr><th>Слой</th><th>Технология</th></tr>
|
||||
</table>
|
||||
<table>
|
||||
<br>
|
||||
<br>
|
||||
<h2>3. Функциональные требования</h2>
|
||||
<br>
|
||||
<h3>3.1. Регистрация и вход</h3>
|
||||
<br>
|
||||
<p><strong>Регистрация — 8 шагов:</strong></p>
|
||||
<li>ФИО (string, обязательно)</li>
|
||||
<li>Логин (латиница, уникальный) + пароль (хеширование bcrypt, минимум 6 символов)</li>
|
||||
<li>Вид спорта (select из 39 олимпийских видов)</li>
|
||||
<li>Роль: спортсмен / тренер / родитель (если родитель — поле «Имя ребёнка»)</li>
|
||||
<li>Дата рождения → возраст вычисляется автоматически. Аватарка (эмодзи на выбор) или загрузка фото (JPEG/PNG, макс 5 МБ)</li>
|
||||
<li>Страна (select) → город (datalist с подсказками по стране)</li>
|
||||
<li>Клуб, тренер (ФИО), разряд/звание, цель (произвольный текст)</li>
|
||||
<li>Телефон (обязательно, валидация формата) + Email (обязательно)</li>
|
||||
<br>
|
||||
<p><strong>Вход:</strong></p>
|
||||
<p>- Логин + пароль</p>
|
||||
<p>- JWT access token (15 мин) + refresh token (30 дней)</p>
|
||||
<p>- Rate limiting: 5 попыток → блокировка на 1 минуту</p>
|
||||
<p>- Автовыход через 30 минут бездействия</p>
|
||||
<br>
|
||||
<p><strong>Безопасность:</strong></p>
|
||||
<p>- Пароли: bcrypt с солью</p>
|
||||
<p>- CSP-заголовки</p>
|
||||
<p>- Санитизация всех пользовательских вводов (XSS-защита)</p>
|
||||
<p>- HTTPS обязательно</p>
|
||||
<p>- CORS только для доверенных доменов</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.2. Профиль спортсмена</h3>
|
||||
<br>
|
||||
<p><strong>Отображение:</strong></p>
|
||||
<p>- Аватар, ФИО, вид спорта, роль</p>
|
||||
<p>- Дата рождения, возраст, страна, город</p>
|
||||
<p>- Клуб, тренер, разряд, цель</p>
|
||||
<p>- Телефон, email</p>
|
||||
<br>
|
||||
<p><strong>Значки (геймификация):</strong></p>
|
||||
<p>Автоматический подсчёт по данным пользователя:</p>
|
||||
<p>- 🏊 Первая тренировка (1+ запись в дневнике)</p>
|
||||
<p>- 📖 10 тренировок</p>
|
||||
<p>- 🔥 30 тренировок</p>
|
||||
<p>- 🏆 Рекордсмен (есть достижения)</p>
|
||||
<p>- 🎯 Снайпер (победа в игре «Угадай число»)</p>
|
||||
<p>- ⚡ Молния (реакция < 300 мс)</p>
|
||||
<p>- 🧠 Знаток (викторина 5+/8)</p>
|
||||
<p>- 💪 100 км (суммарный километраж > 100)</p>
|
||||
<br>
|
||||
<p><strong>Достижения:</strong></p>
|
||||
<p>Пользователь добавляет: название, дата, описание. Отображаются списком.</p>
|
||||
<br>
|
||||
<p><strong>Отчёт для тренера (PDF):</strong></p>
|
||||
<p>- Генерация PDF на сервере (Puppeteer / wkhtmltopdf)</p>
|
||||
<p>- Содержит: ФИО, спорт, клуб, тренер, разряд, цель, значки, достижения, последние 10 записей дневника</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.3. Дневник тренировок</h3>
|
||||
<br>
|
||||
<p><strong>Поля записи:</strong></p>
|
||||
<p>- Дата (date, обязательно)</p>
|
||||
<p>- Тип тренировки (select: Скорость / Техника / Выносливость / ОФП / Соревнование)</p>
|
||||
<p>- Километраж (число, км)</p>
|
||||
<p>- Лучшее время (строка)</p>
|
||||
<p>- Самочувствие (1-5)</p>
|
||||
<p>- Заметка (текст)</p>
|
||||
<br>
|
||||
<p><strong>История:</strong></p>
|
||||
<p>- Список записей, сортировка по дате (новые сверху)</p>
|
||||
<p>- Удаление записи</p>
|
||||
<br>
|
||||
<p><strong>Агрегация (для тренера):</strong></p>
|
||||
<p>- Всего тренировок</p>
|
||||
<p>- Суммарный километраж</p>
|
||||
<p>- Среднее самочувствие</p>
|
||||
<p>- График прогресса по времени (библиотека Chart.js)</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.4. Календарь соревнований</h3>
|
||||
<br>
|
||||
<p><strong>Добавление события:</strong></p>
|
||||
<p>- Название (string)</p>
|
||||
<p>- Дата (date)</p>
|
||||
<p>- Место (string)</p>
|
||||
<br>
|
||||
<p><strong>Отображение:</strong></p>
|
||||
<p>- Предстоящие (сортировка по дате)</p>
|
||||
<p>- Прошедшие (сортировка по дате, обратная)</p>
|
||||
<br>
|
||||
<p><strong>Дополнительно (желательно):</strong></p>
|
||||
<p>- Push-уведомление за день до события</p>
|
||||
<p>- Цветовое кодирование по типу (соревнование / сборы / тренировка)</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.5. Чаты</h3>
|
||||
<br>
|
||||
<p><strong>Архитектура:</strong></p>
|
||||
<p>- WebSocket-соединение (Socket.io)</p>
|
||||
<p>- Комнаты: личные (1-на-1), групповые</p>
|
||||
<p>- Сообщения хранятся в PostgreSQL</p>
|
||||
<p>- Индикатор «прочитано/не прочитано»</p>
|
||||
<br>
|
||||
<p><strong>Функции:</strong></p>
|
||||
<p>- Список чатов с другими пользователями</p>
|
||||
<p>- Фильтр по роли: Все / Спортсмены / Тренеры / Родители</p>
|
||||
<p>- Отправка текстовых сообщений</p>
|
||||
<p>- Счётчик непрочитанных</p>
|
||||
<p>- Групповые чаты (создание, добавление участников)</p>
|
||||
<br>
|
||||
<p><strong>Встроенные игры (в чате):</strong></p>
|
||||
<li>**Крестики-нолики** — пошаговая игра, синхронизация через WebSocket</li>
|
||||
<li>**Угадай число (1-100)** — 7 попыток, победа < 5 попыток = +2 звезды</li>
|
||||
<li>**Реакция** — измерение времени реакции, рекорд < 300 мс = +1 звезда</li>
|
||||
<li>**Спорт-викторина** — 8 вопросов, результат 5+/8 = +1-5 звёзд</li>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.6. Рейтинговая система</h3>
|
||||
<br>
|
||||
<p><strong>Звёзды начисляются за:</strong></p>
|
||||
<p>- Победы в играх</p>
|
||||
<p>- Высокие результаты викторины</p>
|
||||
<p>- Голоса других пользователей</p>
|
||||
<br>
|
||||
<p><strong>Рейтинг:</strong></p>
|
||||
<p>- Топ-5 спортсменов по звёздам</p>
|
||||
<p>- Отображение: место, ФИО, звёзды, результаты викторины, победы в играх</p>
|
||||
<p>- Топ-3 выделены золотом/серебром/бронзой</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.7. Инструменты</h3>
|
||||
<br>
|
||||
<p><strong>Нормативы:</strong></p>
|
||||
<p>- Статическая таблица разрядов по плаванию (50 м бассейн): МСМК → 2 юношеский</p>
|
||||
<p>- Дистанции: 50 м, 100 м, 400 м вольный стиль</p>
|
||||
<br>
|
||||
<p><strong>Сравнение с чемпионами:</strong></p>
|
||||
<p>- Данные Калеба Дрессела по возрастам (14-18 лет)</p>
|
||||
<p>- Пользователь вводит своё время и возраст → сравнение</p>
|
||||
<p>- Показывает: текущий результат → КМС → результат Дрессела в этом возрасте</p>
|
||||
<br>
|
||||
<p><strong>Анализ видео:</strong></p>
|
||||
<p>- Загрузка видео (MP4, макс 200 МБ)</p>
|
||||
<p>- Плеер с покадровой перемоткой (шаг 0.033 сек, 0.1 сек, 1 сек)</p>
|
||||
<p>- Счётчик текущего кадра</p>
|
||||
<p>- Play/Pause</p>
|
||||
<br>
|
||||
<p><strong>Витамины:</strong></p>
|
||||
<p>- Чек-лист на сегодня: D3, Омега-3, Магний, Цинк, BCAA</p>
|
||||
<p>- Сохранение истории по дням</p>
|
||||
<br>
|
||||
<p><strong>Сон и пульс:</strong></p>
|
||||
<p>- Запись часов сна и утреннего пульса</p>
|
||||
<p>- Средние значения за 7 дней</p>
|
||||
<br>
|
||||
<p><strong>Анализы:</strong></p>
|
||||
<p>- Гемоглобин, Ферритин, Витамин D, Витамин B12</p>
|
||||
<p>- История значений с датами</p>
|
||||
<br>
|
||||
<p><strong>Видеоуроки:</strong></p>
|
||||
<p>- Список поисковых запросов для YouTube (12 тем по технике плавания)</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.8. Кабинет тренера</h3>
|
||||
<br>
|
||||
<p><strong>Поиск учеников:</strong></p>
|
||||
<p>- Автоматически: все пользователи, у которых поле «Тренер» совпадает с ФИО тренера</p>
|
||||
<br>
|
||||
<p><strong>Отображение по каждому ученику:</strong></p>
|
||||
<p>- Аватар, ФИО, вид спорта, разряд, цель</p>
|
||||
<p>- Суммарный километраж</p>
|
||||
<p>- Последние 5 тренировок (дата, тип, км, время)</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.9. Кабинет родителя</h3>
|
||||
<br>
|
||||
<p><strong>Привязка ребёнка:</strong></p>
|
||||
<p>- Родитель вводит логин ребёнка → привязка (сохраняется в профиле родителя)</p>
|
||||
<br>
|
||||
<p><strong>Отображение:</strong></p>
|
||||
<p>- Профиль ребёнка (как у спортсмена)</p>
|
||||
<p>- Статистика: всего тренировок, км, среднее самочувствие</p>
|
||||
<p>- Значки ребёнка</p>
|
||||
<p>- Дневник тренировок (последние 15 записей)</p>
|
||||
<p>- Цель и тренер ребёнка</p>
|
||||
<p>- Кнопка «Отвязать»</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.10. Админ-панель</h3>
|
||||
<br>
|
||||
<p><strong>Доступ:</strong></p>
|
||||
<p>- Отдельный мастер-пароль администратора</p>
|
||||
<br>
|
||||
<p><strong>Функции:</strong></p>
|
||||
<p>- Просмотр всех пользователей (ФИО, роль, логин, спорт, клуб, звёзды)</p>
|
||||
<p>- Удаление пользователя</p>
|
||||
<p>- Сброс пароля пользователя</p>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.11. PWA (Progressive Web App)</h3>
|
||||
<br>
|
||||
<p><strong>Требования:</strong></p>
|
||||
<p>- manifest.json с иконками (192x192, 512x512)</p>
|
||||
<p>- Service Worker для офлайн-доступа</p>
|
||||
<p>- Установка на домашний экран (iOS/Android)</p>
|
||||
<p>- Режим standalone (без адресной строки браузера)</p>
|
||||
<p>- Splash screen на iOS</p>
|
||||
<br>
|
||||
<br>
|
||||
<h2>4. Нефункциональные требования</h2>
|
||||
<br>
|
||||
<tr><th>Фронтенд</th><th>React / Vue 3 + TypeScript, PWA</th></tr>
|
||||
<tr><td>Бэкенд</td><td>Node.js (Express/Fastify) или Go</td></tr>
|
||||
<tr><td>База данных</td><td>PostgreSQL</td></tr>
|
||||
<tr><td>Кэш</td><td>Redis</td></tr>
|
||||
<tr><td>Файлы</td><td>S3-совместимое хранилище (MinIO)</td></tr>
|
||||
<tr><td>Чат</td><td>WebSocket (Socket.io)</td></tr>
|
||||
<tr><td>Push-уведомления</td><td>Firebase Cloud Messaging / Web Push API</td></tr>
|
||||
<tr><td>Авторизация</td><td>JWT + refresh tokens</td></tr>
|
||||
<tr><td>Хостинг</td><td>Docker + Kubernetes или VPS</td></tr>
|
||||
<tr><td>Параметр</td><td>Значение</td></tr>
|
||||
</table>
|
||||
<table>
|
||||
<br>
|
||||
<br>
|
||||
<h2>5. API (основные эндпоинты)</h2>
|
||||
<br>
|
||||
<pre>POST /api/auth/register — регистрация
|
||||
POST /api/auth/login — вход
|
||||
POST /api/auth/refresh — обновление токена
|
||||
GET /api/profile — профиль текущего пользователя
|
||||
PUT /api/profile — обновление профиля
|
||||
GET /api/profile/:id — профиль другого пользователя
|
||||
POST /api/achievements — добавить достижение
|
||||
GET /api/diary — дневник (список)
|
||||
POST /api/diary — новая запись
|
||||
DELETE /api/diary/:id — удалить запись
|
||||
GET /api/events — календарь
|
||||
POST /api/events — добавить событие
|
||||
DELETE /api/events/:id — удалить событие
|
||||
GET /api/chats — список чатов
|
||||
GET /api/chats/:id/messages — сообщения чата
|
||||
POST /api/chats/:id/messages — отправить сообщение
|
||||
WS /ws/chat — WebSocket для чата
|
||||
POST /api/vote/:userId — проголосовать за пользователя
|
||||
GET /api/ranking — рейтинг (топ)
|
||||
GET /api/coach/students — ученики тренера
|
||||
POST /api/parent/link — привязать ребёнка
|
||||
GET /api/admin/users — список пользователей (админ)
|
||||
DELETE /api/admin/users/:id — удалить пользователя (админ)
|
||||
POST /api/admin/users/:id/reset-password — сброс пароля (админ)
|
||||
GET /api/report/pdf — PDF-отчёт для тренера
|
||||
POST /api/upload/avatar — загрузка аватара
|
||||
POST /api/upload/video — загрузка видео
|
||||
POST /api/upload/photo — загрузка фото
|
||||
</pre>
|
||||
<br>
|
||||
<br>
|
||||
<h3>3.12. Аналитика и дашборды</h3>
|
||||
<br>
|
||||
<p><strong>Дашборд спортсмена — главный экран аналитики:</strong></p>
|
||||
<br>
|
||||
<p><strong>График прогресса (50 м в/с):</strong></p>
|
||||
<p>- Линейный график: дата по оси X, время по оси Y</p>
|
||||
<p>- Целевая линия (23″) и текущая линия тренда</p>
|
||||
<p>- Автоматический расчёт скорости прогресса (секунд в месяц)</p>
|
||||
<p>- Прогноз: когда будет достигнута цель при текущем темпе</p>
|
||||
<br>
|
||||
<p><strong>Радарная диаграмма навыков:</strong></p>
|
||||
<p>- 6 осей: старт, поворот, подводная фаза, гребок, выносливость, финиш</p>
|
||||
<p>- Оценки 1-10 выставляет тренер или сам спортсмен</p>
|
||||
<p>- Сравнение с предыдущим месяцем</p>
|
||||
<br>
|
||||
<p><strong>Круговые диаграммы тренировок:</strong></p>
|
||||
<p>- Распределение по типам: скорость / техника / выносливость / ОФП</p>
|
||||
<p>- За текущий месяц и за всё время</p>
|
||||
<br>
|
||||
<p><strong>Тепловая карта активности:</strong></p>
|
||||
<p>- Календарь GitHub-style: каждый день — квадратик</p>
|
||||
<p>- Цвет зависит от километража (0 — серый, 5+ км — ярко-голубой)</p>
|
||||
<p>- Видно пропуски тренировок и интенсивные периоды</p>
|
||||
<br>
|
||||
<p><strong>Счётчики (KPI):</strong></p>
|
||||
<p>- Всего тренировок, общий километраж, лучший результат</p>
|
||||
<p>- Среднее самочувствие, динамика пульса, средний сон</p>
|
||||
<p>- Недельная/месячная нагрузка</p>
|
||||
<br>
|
||||
<p><strong>Сравнительная аналитика:</strong></p>
|
||||
<p>- Сравнение своего прогресса со средним по возрастной группе</p>
|
||||
<p>- Сравнение с товарищами по клубу (анонимно)</p>
|
||||
<p>- Процентиль: «Ты быстрее 78% пловцов твоего возраста»</p>
|
||||
<br>
|
||||
<p><strong>Экспорт данных:</strong></p>
|
||||
<p>- CSV-выгрузка всех тренировок</p>
|
||||
<p>- Excel-отчёт с графиками (автоматическая генерация)</p>
|
||||
<p>- PDF-дашборд для тренера</p>
|
||||
<br>
|
||||
<p><strong>Технологии:</strong></p>
|
||||
<p>- Chart.js / ECharts / D3.js для визуализации</p>
|
||||
<p>- Данные агрегируются на бэкенде (SQL-запросы с GROUP BY)</p>
|
||||
<p>- Кэширование агрегаций в Redis (обновление раз в час)</p>
|
||||
<br>
|
||||
<p><strong>API для аналитики:</strong></p>
|
||||
<pre>GET /api/analytics/progress/:metric — график прогресса по метрике
|
||||
GET /api/analytics/radar — радарная диаграмма
|
||||
GET /api/analytics/heatmap — тепловая карта (год)
|
||||
GET /api/analytics/distribution — распределение типов тренировок
|
||||
GET /api/analytics/kpi — ключевые показатели
|
||||
GET /api/analytics/compare — сравнение с группой
|
||||
GET /api/analytics/export/csv — CSV-выгрузка
|
||||
GET /api/analytics/export/dashboard — PDF-дашборд
|
||||
</pre>
|
||||
<br>
|
||||
<p><strong>Дашборд тренера:</strong></p>
|
||||
<p>- Сводка по всем ученикам: таблица с сортировкой по любому столбцу</p>
|
||||
<p>- Групповой график прогресса (все ученики на одном графике)</p>
|
||||
<p>- Выделение отстающих (красная зона) и лидеров (зелёная зона)</p>
|
||||
<p>- Уведомления: ученик не тренировался 3+ дня → алерт тренеру</p>
|
||||
<p>- Экспорт сводного отчёта по группе</p>
|
||||
<br>
|
||||
<p><strong>Дашборд родителя:</strong></p>
|
||||
<p>- Упрощённая версия: график прогресса ребёнка, счётчики</p>
|
||||
<p>- Уведомления о новых достижениях и значках</p>
|
||||
<p>- Еженедельный email-отчёт (опционально)</p>
|
||||
<br>
|
||||
<br>
|
||||
<h2>6. База данных (основные таблицы)</h2>
|
||||
<br>
|
||||
<pre>users: id, login, password_hash, name, sport, role, birth_date, age,
|
||||
country, city, club, coach, rank, goal, phone, email,
|
||||
avatar_url, photo_url, stars, quiz_score, games_won,
|
||||
created_at, updated_at
|
||||
|
||||
achievements: id, user_id, title, date, description
|
||||
|
||||
diary_entries: id, user_id, date, type, km, best_time, feel, note
|
||||
|
||||
events: id, user_id, title, date, location
|
||||
|
||||
messages: id, chat_id, from_user_id, to_user_id, text, read, created_at
|
||||
|
||||
chats: id, type (direct/group), name
|
||||
|
||||
chat_members: chat_id, user_id
|
||||
|
||||
vitamins: id, user_id, date, vitamin_type, taken
|
||||
|
||||
sleep_log: id, user_id, date, hours, pulse
|
||||
|
||||
tests: id, user_id, test_type, value, date
|
||||
|
||||
parent_links: parent_id, child_id
|
||||
|
||||
votes: voter_id, target_id, created_at
|
||||
</pre>
|
||||
<br>
|
||||
<br>
|
||||
<h2>7. Этапы разработки</h2>
|
||||
<br>
|
||||
<tr><th>Язык интерфейса</th><th>Русский</th></tr>
|
||||
<tr><td>Адаптивность</td><td>Mobile-first, поддержка десктопа</td></tr>
|
||||
<tr><td>Браузеры</td><td>Chrome 90+, Safari 14+, Firefox 90+</td></tr>
|
||||
<tr><td>Производительность</td><td>First paint < 2 сек, взаимодействие < 100 мс</td></tr>
|
||||
<tr><td>Доступность</td><td>WCAG 2.1 AA</td></tr>
|
||||
<tr><td>Масштабируемость</td><td>До 100 000 пользователей</td></tr>
|
||||
<tr><td>Резервное копирование</td><td>Ежедневный бэкап БД</td></tr>
|
||||
<tr><td>Этап</td><td>Содержание</td><td>Срок</td></tr>
|
||||
</table>
|
||||
<table>
|
||||
<br>
|
||||
<p>**Итого:** ~10 недель на MVP командой из 2-3 разработчиков.</p>
|
||||
<br>
|
||||
<table>
|
||||
<tr><th>1</th><th>База данных, API авторизации, регистрация</th><th>2 недели</th></tr>
|
||||
<tr><td>2</td><td>Профиль, дневник, календарь</td><td>2 недели</td></tr>
|
||||
<tr><td>3</td><td>Чаты (WebSocket) + игры</td><td>2 недели</td></tr>
|
||||
<tr><td>4</td><td>Рейтинг, кабинет тренера, кабинет родителя</td><td>1 неделя</td></tr>
|
||||
<tr><td>5</td><td>Инструменты (нормативы, сравнение, видео, витамины)</td><td>1 неделя</td></tr>
|
||||
<tr><td>6</td><td>Админ-панель, PDF-отчёт</td><td>1 неделя</td></tr>
|
||||
<tr><td>7</td><td>PWA, тестирование, деплой</td><td>1 неделя</td></tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
414
TZ_GALIKON.md
Normal file
414
TZ_GALIKON.md
Normal file
@ -0,0 +1,414 @@
|
||||
# Техническое задание: Галикон
|
||||
|
||||
## 1. Общее описание
|
||||
|
||||
**Название:** Галикон — мобильное веб-приложение для спортсменов, тренеров и родителей.
|
||||
|
||||
**Цель:** Единая платформа для юных спортсменов (дети от 10 лет): дневник тренировок, контроль здоровья, рейтинги, чаты, игры, нормативы, сравнение с чемпионами. Аналогов в мире нет.
|
||||
|
||||
**Пользователи:**
|
||||
- Спортсмен (основной пользователь)
|
||||
- Тренер (видит своих учеников)
|
||||
- Родитель (видит профиль ребёнка)
|
||||
- Администратор (управление пользователями)
|
||||
|
||||
---
|
||||
|
||||
## 2. Технический стек
|
||||
|
||||
| Слой | Технология |
|
||||
|------|-----------|
|
||||
| Фронтенд | React / Vue 3 + TypeScript, PWA |
|
||||
| Бэкенд | Node.js (Express/Fastify) или Go |
|
||||
| База данных | PostgreSQL |
|
||||
| Кэш | Redis |
|
||||
| Файлы | S3-совместимое хранилище (MinIO) |
|
||||
| Чат | WebSocket (Socket.io) |
|
||||
| Push-уведомления | Firebase Cloud Messaging / Web Push API |
|
||||
| Авторизация | JWT + refresh tokens |
|
||||
| Хостинг | Docker + Kubernetes или VPS |
|
||||
|
||||
---
|
||||
|
||||
## 3. Функциональные требования
|
||||
|
||||
### 3.1. Регистрация и вход
|
||||
|
||||
**Регистрация — 8 шагов:**
|
||||
1. ФИО (string, обязательно)
|
||||
2. Логин (латиница, уникальный) + пароль (хеширование bcrypt, минимум 6 символов)
|
||||
3. Вид спорта (select из 39 олимпийских видов)
|
||||
4. Роль: спортсмен / тренер / родитель (если родитель — поле «Имя ребёнка»)
|
||||
5. Дата рождения → возраст вычисляется автоматически. Аватарка (эмодзи на выбор) или загрузка фото (JPEG/PNG, макс 5 МБ)
|
||||
6. Страна (select) → город (datalist с подсказками по стране)
|
||||
7. Клуб, тренер (ФИО), разряд/звание, цель (произвольный текст)
|
||||
8. Телефон (обязательно, валидация формата) + Email (обязательно)
|
||||
|
||||
**Вход:**
|
||||
- Логин + пароль
|
||||
- JWT access token (15 мин) + refresh token (30 дней)
|
||||
- Rate limiting: 5 попыток → блокировка на 1 минуту
|
||||
- Автовыход через 30 минут бездействия
|
||||
|
||||
**Безопасность:**
|
||||
- Пароли: bcrypt с солью
|
||||
- CSP-заголовки
|
||||
- Санитизация всех пользовательских вводов (XSS-защита)
|
||||
- HTTPS обязательно
|
||||
- CORS только для доверенных доменов
|
||||
|
||||
---
|
||||
|
||||
### 3.2. Профиль спортсмена
|
||||
|
||||
**Отображение:**
|
||||
- Аватар, ФИО, вид спорта, роль
|
||||
- Дата рождения, возраст, страна, город
|
||||
- Клуб, тренер, разряд, цель
|
||||
- Телефон, email
|
||||
|
||||
**Значки (геймификация):**
|
||||
Автоматический подсчёт по данным пользователя:
|
||||
- 🏊 Первая тренировка (1+ запись в дневнике)
|
||||
- 📖 10 тренировок
|
||||
- 🔥 30 тренировок
|
||||
- 🏆 Рекордсмен (есть достижения)
|
||||
- 🎯 Снайпер (победа в игре «Угадай число»)
|
||||
- ⚡ Молния (реакция < 300 мс)
|
||||
- 🧠 Знаток (викторина 5+/8)
|
||||
- 💪 100 км (суммарный километраж > 100)
|
||||
|
||||
**Достижения:**
|
||||
Пользователь добавляет: название, дата, описание. Отображаются списком.
|
||||
|
||||
**Отчёт для тренера (PDF):**
|
||||
- Генерация PDF на сервере (Puppeteer / wkhtmltopdf)
|
||||
- Содержит: ФИО, спорт, клуб, тренер, разряд, цель, значки, достижения, последние 10 записей дневника
|
||||
|
||||
---
|
||||
|
||||
### 3.3. Дневник тренировок
|
||||
|
||||
**Поля записи:**
|
||||
- Дата (date, обязательно)
|
||||
- Тип тренировки (select: Скорость / Техника / Выносливость / ОФП / Соревнование)
|
||||
- Километраж (число, км)
|
||||
- Лучшее время (строка)
|
||||
- Самочувствие (1-5)
|
||||
- Заметка (текст)
|
||||
|
||||
**История:**
|
||||
- Список записей, сортировка по дате (новые сверху)
|
||||
- Удаление записи
|
||||
|
||||
**Агрегация (для тренера):**
|
||||
- Всего тренировок
|
||||
- Суммарный километраж
|
||||
- Среднее самочувствие
|
||||
- График прогресса по времени (библиотека Chart.js)
|
||||
|
||||
---
|
||||
|
||||
### 3.4. Календарь соревнований
|
||||
|
||||
**Добавление события:**
|
||||
- Название (string)
|
||||
- Дата (date)
|
||||
- Место (string)
|
||||
|
||||
**Отображение:**
|
||||
- Предстоящие (сортировка по дате)
|
||||
- Прошедшие (сортировка по дате, обратная)
|
||||
|
||||
**Дополнительно (желательно):**
|
||||
- Push-уведомление за день до события
|
||||
- Цветовое кодирование по типу (соревнование / сборы / тренировка)
|
||||
|
||||
---
|
||||
|
||||
### 3.5. Чаты
|
||||
|
||||
**Архитектура:**
|
||||
- WebSocket-соединение (Socket.io)
|
||||
- Комнаты: личные (1-на-1), групповые
|
||||
- Сообщения хранятся в PostgreSQL
|
||||
- Индикатор «прочитано/не прочитано»
|
||||
|
||||
**Функции:**
|
||||
- Список чатов с другими пользователями
|
||||
- Фильтр по роли: Все / Спортсмены / Тренеры / Родители
|
||||
- Отправка текстовых сообщений
|
||||
- Счётчик непрочитанных
|
||||
- Групповые чаты (создание, добавление участников)
|
||||
|
||||
**Встроенные игры (в чате):**
|
||||
1. **Крестики-нолики** — пошаговая игра, синхронизация через WebSocket
|
||||
2. **Угадай число (1-100)** — 7 попыток, победа < 5 попыток = +2 звезды
|
||||
3. **Реакция** — измерение времени реакции, рекорд < 300 мс = +1 звезда
|
||||
4. **Спорт-викторина** — 8 вопросов, результат 5+/8 = +1-5 звёзд
|
||||
|
||||
---
|
||||
|
||||
### 3.6. Рейтинговая система
|
||||
|
||||
**Звёзды начисляются за:**
|
||||
- Победы в играх
|
||||
- Высокие результаты викторины
|
||||
- Голоса других пользователей
|
||||
|
||||
**Рейтинг:**
|
||||
- Топ-5 спортсменов по звёздам
|
||||
- Отображение: место, ФИО, звёзды, результаты викторины, победы в играх
|
||||
- Топ-3 выделены золотом/серебром/бронзой
|
||||
|
||||
---
|
||||
|
||||
### 3.7. Инструменты
|
||||
|
||||
**Нормативы:**
|
||||
- Статическая таблица разрядов по плаванию (50 м бассейн): МСМК → 2 юношеский
|
||||
- Дистанции: 50 м, 100 м, 400 м вольный стиль
|
||||
|
||||
**Сравнение с чемпионами:**
|
||||
- Данные Калеба Дрессела по возрастам (14-18 лет)
|
||||
- Пользователь вводит своё время и возраст → сравнение
|
||||
- Показывает: текущий результат → КМС → результат Дрессела в этом возрасте
|
||||
|
||||
**Анализ видео:**
|
||||
- Загрузка видео (MP4, макс 200 МБ)
|
||||
- Плеер с покадровой перемоткой (шаг 0.033 сек, 0.1 сек, 1 сек)
|
||||
- Счётчик текущего кадра
|
||||
- Play/Pause
|
||||
|
||||
**Витамины:**
|
||||
- Чек-лист на сегодня: D3, Омега-3, Магний, Цинк, BCAA
|
||||
- Сохранение истории по дням
|
||||
|
||||
**Сон и пульс:**
|
||||
- Запись часов сна и утреннего пульса
|
||||
- Средние значения за 7 дней
|
||||
|
||||
**Анализы:**
|
||||
- Гемоглобин, Ферритин, Витамин D, Витамин B12
|
||||
- История значений с датами
|
||||
|
||||
**Видеоуроки:**
|
||||
- Список поисковых запросов для YouTube (12 тем по технике плавания)
|
||||
|
||||
---
|
||||
|
||||
### 3.8. Кабинет тренера
|
||||
|
||||
**Поиск учеников:**
|
||||
- Автоматически: все пользователи, у которых поле «Тренер» совпадает с ФИО тренера
|
||||
|
||||
**Отображение по каждому ученику:**
|
||||
- Аватар, ФИО, вид спорта, разряд, цель
|
||||
- Суммарный километраж
|
||||
- Последние 5 тренировок (дата, тип, км, время)
|
||||
|
||||
---
|
||||
|
||||
### 3.9. Кабинет родителя
|
||||
|
||||
**Привязка ребёнка:**
|
||||
- Родитель вводит логин ребёнка → привязка (сохраняется в профиле родителя)
|
||||
|
||||
**Отображение:**
|
||||
- Профиль ребёнка (как у спортсмена)
|
||||
- Статистика: всего тренировок, км, среднее самочувствие
|
||||
- Значки ребёнка
|
||||
- Дневник тренировок (последние 15 записей)
|
||||
- Цель и тренер ребёнка
|
||||
- Кнопка «Отвязать»
|
||||
|
||||
---
|
||||
|
||||
### 3.10. Админ-панель
|
||||
|
||||
**Доступ:**
|
||||
- Отдельный мастер-пароль администратора
|
||||
|
||||
**Функции:**
|
||||
- Просмотр всех пользователей (ФИО, роль, логин, спорт, клуб, звёзды)
|
||||
- Удаление пользователя
|
||||
- Сброс пароля пользователя
|
||||
|
||||
---
|
||||
|
||||
### 3.11. PWA (Progressive Web App)
|
||||
|
||||
**Требования:**
|
||||
- manifest.json с иконками (192x192, 512x512)
|
||||
- Service Worker для офлайн-доступа
|
||||
- Установка на домашний экран (iOS/Android)
|
||||
- Режим standalone (без адресной строки браузера)
|
||||
- Splash screen на iOS
|
||||
|
||||
---
|
||||
|
||||
## 4. Нефункциональные требования
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|---------|
|
||||
| Язык интерфейса | Русский |
|
||||
| Адаптивность | Mobile-first, поддержка десктопа |
|
||||
| Браузеры | Chrome 90+, Safari 14+, Firefox 90+ |
|
||||
| Производительность | First paint < 2 сек, взаимодействие < 100 мс |
|
||||
| Доступность | WCAG 2.1 AA |
|
||||
| Масштабируемость | До 100 000 пользователей |
|
||||
| Резервное копирование | Ежедневный бэкап БД |
|
||||
|
||||
---
|
||||
|
||||
## 5. API (основные эндпоинты)
|
||||
|
||||
```
|
||||
POST /api/auth/register — регистрация
|
||||
POST /api/auth/login — вход
|
||||
POST /api/auth/refresh — обновление токена
|
||||
GET /api/profile — профиль текущего пользователя
|
||||
PUT /api/profile — обновление профиля
|
||||
GET /api/profile/:id — профиль другого пользователя
|
||||
POST /api/achievements — добавить достижение
|
||||
GET /api/diary — дневник (список)
|
||||
POST /api/diary — новая запись
|
||||
DELETE /api/diary/:id — удалить запись
|
||||
GET /api/events — календарь
|
||||
POST /api/events — добавить событие
|
||||
DELETE /api/events/:id — удалить событие
|
||||
GET /api/chats — список чатов
|
||||
GET /api/chats/:id/messages — сообщения чата
|
||||
POST /api/chats/:id/messages — отправить сообщение
|
||||
WS /ws/chat — WebSocket для чата
|
||||
POST /api/vote/:userId — проголосовать за пользователя
|
||||
GET /api/ranking — рейтинг (топ)
|
||||
GET /api/coach/students — ученики тренера
|
||||
POST /api/parent/link — привязать ребёнка
|
||||
GET /api/admin/users — список пользователей (админ)
|
||||
DELETE /api/admin/users/:id — удалить пользователя (админ)
|
||||
POST /api/admin/users/:id/reset-password — сброс пароля (админ)
|
||||
GET /api/report/pdf — PDF-отчёт для тренера
|
||||
POST /api/upload/avatar — загрузка аватара
|
||||
POST /api/upload/video — загрузка видео
|
||||
POST /api/upload/photo — загрузка фото
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.12. Аналитика и дашборды
|
||||
|
||||
**Дашборд спортсмена — главный экран аналитики:**
|
||||
|
||||
**График прогресса (50 м в/с):**
|
||||
- Линейный график: дата по оси X, время по оси Y
|
||||
- Целевая линия (23″) и текущая линия тренда
|
||||
- Автоматический расчёт скорости прогресса (секунд в месяц)
|
||||
- Прогноз: когда будет достигнута цель при текущем темпе
|
||||
|
||||
**Радарная диаграмма навыков:**
|
||||
- 6 осей: старт, поворот, подводная фаза, гребок, выносливость, финиш
|
||||
- Оценки 1-10 выставляет тренер или сам спортсмен
|
||||
- Сравнение с предыдущим месяцем
|
||||
|
||||
**Круговые диаграммы тренировок:**
|
||||
- Распределение по типам: скорость / техника / выносливость / ОФП
|
||||
- За текущий месяц и за всё время
|
||||
|
||||
**Тепловая карта активности:**
|
||||
- Календарь GitHub-style: каждый день — квадратик
|
||||
- Цвет зависит от километража (0 — серый, 5+ км — ярко-голубой)
|
||||
- Видно пропуски тренировок и интенсивные периоды
|
||||
|
||||
**Счётчики (KPI):**
|
||||
- Всего тренировок, общий километраж, лучший результат
|
||||
- Среднее самочувствие, динамика пульса, средний сон
|
||||
- Недельная/месячная нагрузка
|
||||
|
||||
**Сравнительная аналитика:**
|
||||
- Сравнение своего прогресса со средним по возрастной группе
|
||||
- Сравнение с товарищами по клубу (анонимно)
|
||||
- Процентиль: «Ты быстрее 78% пловцов твоего возраста»
|
||||
|
||||
**Экспорт данных:**
|
||||
- CSV-выгрузка всех тренировок
|
||||
- Excel-отчёт с графиками (автоматическая генерация)
|
||||
- PDF-дашборд для тренера
|
||||
|
||||
**Технологии:**
|
||||
- Chart.js / ECharts / D3.js для визуализации
|
||||
- Данные агрегируются на бэкенде (SQL-запросы с GROUP BY)
|
||||
- Кэширование агрегаций в Redis (обновление раз в час)
|
||||
|
||||
**API для аналитики:**
|
||||
```
|
||||
GET /api/analytics/progress/:metric — график прогресса по метрике
|
||||
GET /api/analytics/radar — радарная диаграмма
|
||||
GET /api/analytics/heatmap — тепловая карта (год)
|
||||
GET /api/analytics/distribution — распределение типов тренировок
|
||||
GET /api/analytics/kpi — ключевые показатели
|
||||
GET /api/analytics/compare — сравнение с группой
|
||||
GET /api/analytics/export/csv — CSV-выгрузка
|
||||
GET /api/analytics/export/dashboard — PDF-дашборд
|
||||
```
|
||||
|
||||
**Дашборд тренера:**
|
||||
- Сводка по всем ученикам: таблица с сортировкой по любому столбцу
|
||||
- Групповой график прогресса (все ученики на одном графике)
|
||||
- Выделение отстающих (красная зона) и лидеров (зелёная зона)
|
||||
- Уведомления: ученик не тренировался 3+ дня → алерт тренеру
|
||||
- Экспорт сводного отчёта по группе
|
||||
|
||||
**Дашборд родителя:**
|
||||
- Упрощённая версия: график прогресса ребёнка, счётчики
|
||||
- Уведомления о новых достижениях и значках
|
||||
- Еженедельный email-отчёт (опционально)
|
||||
|
||||
---
|
||||
|
||||
## 6. База данных (основные таблицы)
|
||||
|
||||
```sql
|
||||
users: id, login, password_hash, name, sport, role, birth_date, age,
|
||||
country, city, club, coach, rank, goal, phone, email,
|
||||
avatar_url, photo_url, stars, quiz_score, games_won,
|
||||
created_at, updated_at
|
||||
|
||||
achievements: id, user_id, title, date, description
|
||||
|
||||
diary_entries: id, user_id, date, type, km, best_time, feel, note
|
||||
|
||||
events: id, user_id, title, date, location
|
||||
|
||||
messages: id, chat_id, from_user_id, to_user_id, text, read, created_at
|
||||
|
||||
chats: id, type (direct/group), name
|
||||
|
||||
chat_members: chat_id, user_id
|
||||
|
||||
vitamins: id, user_id, date, vitamin_type, taken
|
||||
|
||||
sleep_log: id, user_id, date, hours, pulse
|
||||
|
||||
tests: id, user_id, test_type, value, date
|
||||
|
||||
parent_links: parent_id, child_id
|
||||
|
||||
votes: voter_id, target_id, created_at
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Этапы разработки
|
||||
|
||||
| Этап | Содержание | Срок |
|
||||
|------|-----------|------|
|
||||
| 1 | База данных, API авторизации, регистрация | 2 недели |
|
||||
| 2 | Профиль, дневник, календарь | 2 недели |
|
||||
| 3 | Чаты (WebSocket) + игры | 2 недели |
|
||||
| 4 | Рейтинг, кабинет тренера, кабинет родителя | 1 неделя |
|
||||
| 5 | Инструменты (нормативы, сравнение, видео, витамины) | 1 неделя |
|
||||
| 6 | Админ-панель, PDF-отчёт | 1 неделя |
|
||||
| 7 | PWA, тестирование, деплой | 1 неделя |
|
||||
|
||||
**Итого:** ~10 недель на MVP командой из 2-3 разработчиков.
|
||||
110
design.md
Normal file
110
design.md
Normal file
@ -0,0 +1,110 @@
|
||||
<!-- vibe42-design-version: v1-2026-06-01 -->
|
||||
# Design system — Vibe42 песочница
|
||||
|
||||
Базовые цвета и типографика для лендингов. Можно отклоняться, но начинай с этого.
|
||||
|
||||
## Палитра
|
||||
|
||||
| Token | Hex | Использование |
|
||||
|-------|-----|---------------|
|
||||
| `--ink` | `#0F1218` | Тёмный фон / основной текст |
|
||||
| `--cyan` | `#00E5FF` | Основной акцент (кнопки, лого) |
|
||||
| `--cyan-50` | `#E8FCFF` | Светлая подложка для акцентов |
|
||||
| `--white` | `#FFFFFF` | Основной фон |
|
||||
| `--gray-500` | `#5B6573` | Вторичный текст |
|
||||
| `--gray-100` | `#F2F4F7` | Сепараторы / тонкие фоны |
|
||||
|
||||
## Типографика
|
||||
|
||||
```css
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
|
||||
```
|
||||
|
||||
| Уровень | Размер | Вес | line-height |
|
||||
|---------|--------|-----|-------------|
|
||||
| h1 (hero) | 56px | 800 | 1.05 |
|
||||
| h2 (section) | 36px | 700 | 1.15 |
|
||||
| h3 | 22px | 700 | 1.3 |
|
||||
| body | 17px | 400 | 1.6 |
|
||||
| small | 14px | 400 | 1.5 |
|
||||
|
||||
На мобиле — h1 уменьши до 36px, h2 до 28px.
|
||||
|
||||
## Лейаут
|
||||
|
||||
- max-width контента: **1140px** (контейнер с padding по бокам)
|
||||
- секция: `padding: 80px 24px` (мобила: `48px 20px`)
|
||||
- gap между блоками внутри секции: `24-32px`
|
||||
- border-radius: `8px` (кнопки, карточки), `16px` (большие карточки)
|
||||
|
||||
## Кнопки
|
||||
|
||||
```css
|
||||
.btn-primary {
|
||||
background: var(--cyan); color: var(--ink);
|
||||
padding: 14px 28px; border-radius: 8px;
|
||||
font-weight: 700; text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
.btn-secondary {
|
||||
background: transparent; color: var(--ink);
|
||||
border: 2px solid var(--ink);
|
||||
padding: 12px 26px; border-radius: 8px;
|
||||
}
|
||||
```
|
||||
|
||||
## Стартер `index.html`
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Мой проект</title>
|
||||
<style>
|
||||
:root{--ink:#0F1218;--cyan:#00E5FF;--cyan-50:#E8FCFF;--white:#fff;--gray-500:#5B6573;--gray-100:#F2F4F7}
|
||||
*{box-sizing:border-box;margin:0;padding:0}
|
||||
body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;color:var(--ink);background:var(--white)}
|
||||
.container{max-width:1140px;margin:0 auto;padding:80px 24px}
|
||||
.hero{background:var(--ink);color:var(--white)}
|
||||
.hero h1{font-size:56px;font-weight:800;line-height:1.05;margin-bottom:24px}
|
||||
.hero p{font-size:20px;color:#9aa3b2;max-width:600px;margin-bottom:32px}
|
||||
.btn{display:inline-block;background:var(--cyan);color:var(--ink);padding:14px 28px;border-radius:8px;font-weight:700;text-decoration:none}
|
||||
.btn:hover{background:#1be5ff}
|
||||
.section h2{font-size:36px;font-weight:700;margin-bottom:24px}
|
||||
.card{background:var(--gray-100);border-radius:16px;padding:32px;margin-bottom:16px}
|
||||
@media (max-width:640px){.hero h1{font-size:36px}.section h2{font-size:28px}.container{padding:48px 20px}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<h1>Заголовок проекта</h1>
|
||||
<p>Подзаголовок — пара предложений о чём это.</p>
|
||||
<a class="btn" href="#section">Начать</a>
|
||||
</div>
|
||||
</section>
|
||||
<section id="section" class="section">
|
||||
<div class="container">
|
||||
<h2>Секция</h2>
|
||||
<div class="card">Контент карточки.</div>
|
||||
<div class="card">Контент карточки.</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Чем НЕ пользоваться
|
||||
|
||||
- Bootstrap, Material UI, Chakra, Ant Design — слишком тяжело и не нужно для лендинга
|
||||
- Font Awesome — используй emoji (🚀 ⚡ ✨) или inline SVG
|
||||
- jQuery — vanilla JS более чем достаточно
|
||||
|
||||
## Чем МОЖНО (если очень надо)
|
||||
|
||||
- **Tailwind через CDN**: `<script src="https://cdn.tailwindcss.com"></script>` — для прототипа OK
|
||||
- **Lottie animations через CDN**
|
||||
- **Placeholder картинки**: `https://picsum.photos/800/600`, `https://placehold.co/600x400`
|
||||
- **Шрифты Google Fonts через `<link>`** в head
|
||||
1515
index.html
Normal file
1515
index.html
Normal file
File diff suppressed because it is too large
Load Diff
1
manifest.json
Normal file
1
manifest.json
Normal file
@ -0,0 +1 @@
|
||||
{"name":"Галикон","short_name":"Галикон","description":"Приложение для спортсменов — дневник тренировок, здоровье, рейтинги","start_url":".","display":"standalone","background_color":"#0F1218","theme_color":"#00E5FF","icons":[{"src":"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='20' fill='%230F1218'/><text y='.9em' font-size='70' x='50' text-anchor='middle'>🏊</text></svg>","sizes":"any","type":"image/svg+xml"}]}
|
||||
11
sw.js
Normal file
11
sw.js
Normal file
@ -0,0 +1,11 @@
|
||||
self.addEventListener('install', e => { self.skipWaiting() })
|
||||
self.addEventListener('activate', e => { e.waitUntil(clients.claim()) })
|
||||
self.addEventListener('fetch', e => {
|
||||
e.respondWith(
|
||||
caches.match(e.request).then(r => r || fetch(e.request).then(res => {
|
||||
const clone = res.clone()
|
||||
caches.open('galikon-v1').then(c => c.put(e.request, clone))
|
||||
return res
|
||||
}).catch(() => caches.match(e.request)))
|
||||
)
|
||||
})
|
||||
131
мотивационный_отчет_Гали.html
Normal file
131
мотивационный_отчет_Гали.html
Normal file
@ -0,0 +1,131 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Мотивационный отчёт — Кайрат Гали</title>
|
||||
<style>
|
||||
body{font:16px/1.7 Arial,sans-serif;max-width:750px;margin:30px auto;padding:20px;color:#1a1a1a;background:#fff}
|
||||
h1{font-size:30px;border-bottom:4px solid #FF4D00;padding-bottom:12px}
|
||||
h1 span{color:#FF4D00}
|
||||
h2{font-size:20px;margin-top:28px;color:#FF4D00;border-left:4px solid #FF4D00;padding-left:14px}
|
||||
.stats{display:flex;gap:16px;flex-wrap:wrap;margin:20px 0}
|
||||
.stat{background:linear-gradient(135deg,#fff5f0,#fff);border:1px solid #fdd;border-radius:14px;padding:18px 24px;min-width:110px;text-align:center}
|
||||
.stat .num{font-size:32px;font-weight:900;color:#FF4D00}
|
||||
.stat .lbl{font-size:11px;color:#888;text-transform:uppercase;letter-spacing:.5px;margin-top:4px}
|
||||
.rec{background:#fff;border:1px solid #eee;border-radius:10px;padding:16px 20px;margin:10px 0;border-left:4px solid #FF4D00;font-size:15px}
|
||||
.moto{background:linear-gradient(135deg,#FF4D00,#ff6b33);color:#fff;padding:24px 28px;border-radius:16px;margin:24px 0;font-size:20px;font-weight:800;text-align:center;line-height:1.5}
|
||||
.goal-box{background:linear-gradient(135deg,#0a0a0a,#1a1a1a);color:#fff;padding:28px;border-radius:16px;margin:20px 0;text-align:center}
|
||||
.goal-box .from-to{font-size:48px;font-weight:900}
|
||||
.goal-box .from-to span{color:#FF4D00}
|
||||
.goal-box .sub{color:#888;font-size:14px;margin-top:8px}
|
||||
table{width:100%;border-collapse:collapse;margin:12px 0}
|
||||
th,td{padding:10px 12px;text-align:left;border-bottom:1px solid #eee}
|
||||
th{color:#888;font-size:12px;text-transform:uppercase}
|
||||
.step{display:flex;gap:16px;align-items:flex-start;margin:12px 0;padding:16px;background:#fafafa;border-radius:12px}
|
||||
.step .num{width:36px;height:36px;border-radius:8px;background:#FF4D00;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:900;font-size:18px;flex-shrink:0}
|
||||
.step .body h4{margin:0 0 4px;font-size:15px}
|
||||
.step .body p{margin:0;font-size:13px;color:#666}
|
||||
@media print{body{margin:0;padding:10px}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>🏊 Мотивационный отчёт<br><span>Кайрат Гали Аскарович</span></h1>
|
||||
<p style="color:#666">Плавание · QazSwimAcademy · 14 лет · 8 класс</p>
|
||||
<p style="color:#888;font-size:14px">1-й детский разряд · 3-й взрослый разряд</p>
|
||||
|
||||
<div class="goal-box">
|
||||
<div class="from-to">34″ <span>→</span> 23″</div>
|
||||
<div class="sub">50 метров вольным стилем — твоя главная цель</div>
|
||||
</div>
|
||||
|
||||
<div class="stats">
|
||||
<div class="stat"><div class="num">3</div><div class="lbl">Золота Олимпиады<br>(будущая цель)</div></div>
|
||||
<div class="stat"><div class="num">5</div><div class="lbl">Мировых рекордов<br>(потенциал)</div></div>
|
||||
<div class="stat"><div class="num">12</div><div class="lbl">Лет в спорте</div></div>
|
||||
</div>
|
||||
|
||||
<h2>📊 Текущие результаты</h2>
|
||||
<table>
|
||||
<tr><th>Дистанция</th><th>Стиль</th><th>Результат</th><th>Прогресс</th></tr>
|
||||
<tr><td>50 м</td><td>Вольный стиль</td><td><strong>34.00″</strong></td><td>3 взр. разряд ✓</td></tr>
|
||||
<tr><td>100 м</td><td>Вольный стиль</td><td>1:22.94</td><td>Цель: 1:10</td></tr>
|
||||
<tr><td>400 м</td><td>Вольный стиль</td><td>7:09.64</td><td>116 место на Весёлый Дельфин</td></tr>
|
||||
<tr><td>50 м</td><td>Брасс</td><td>48.00″</td><td>Второй стиль</td></tr>
|
||||
<tr><td>100 м</td><td>Брасс</td><td>1:52.17</td><td>41 место</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>🎯 План: 34″ → 23″</h2>
|
||||
|
||||
<div class="step">
|
||||
<div class="num">1</div>
|
||||
<div class="body"><h4>Закрепиться на 32″ (месяц 1-2)</h4><p>Перестать бороться с водой. Отработать скольжение. Каждую тренировку — 4×50 м. Записывать лучшее время дня.</p></div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="num">2</div>
|
||||
<div class="body"><h4>Выйти из 30″ (месяц 3-4)</h4><p>Добавить 2 спринтерские тренировки в неделю. Частота гребков 50+ циклов в минуту. Планка 3 мин, скручивания.</p></div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="num">3</div>
|
||||
<div class="body"><h4>Штурм 27″ — КМС (месяц 5-8)</h4><p>Объём воды 20+ км в неделю. Старт с тумбы 15 мин каждую тренировку. Первые 15 метров — ключ к скорости.</p></div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="num">4</div>
|
||||
<div class="body"><h4>Пробить 25″ (месяц 9-12)</h4><p>3 скоростные тренировки в неделю. Контрольные старты каждые 2 недели. Подводная съёмка.</p></div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="num">5</div>
|
||||
<div class="body"><h4>Цель: 23″ — МС (месяц 13-18)</h4><p>Сборы, соревнования. Выход на республиканский уровень. Последние 5 метров без вдоха.</p></div>
|
||||
</div>
|
||||
|
||||
<h2>📝 Персональные рекомендации</h2>
|
||||
|
||||
<div class="rec">🚨 <strong>Старт и выход</strong> — ты теряешь 1-1.5″. 10 стартов с тумбы каждую тренировку. Дельфиньи удары под водой — минимум 5.</div>
|
||||
<div class="rec">🔄 <strong>Поворот</strong> — ты теряешь 0.5-1.0″. Не замедляйся перед стенкой — ускоряйся. Считай гребки от флажков.</div>
|
||||
<div class="rec">📉 <strong>100 м: провал на второй половине</strong> — вторые 50 м на 15″ хуже. Плыви серии 4×75 м с удержанием темпа.</div>
|
||||
<div class="rec">📏 <strong>Длинный гребок</strong> — на 400 м ты плывёшь 1:47/100 м. Цель: 38-42 гребка на 50 м. Бери лопатки и колобашку.</div>
|
||||
<div class="rec">💤 <strong>Восстановление</strong> — 5 мин растяжки после каждой тренировки. Контрастный душ. Массажный ролик вечером.</div>
|
||||
|
||||
<h2>🌍 Твой путь к NCAA</h2>
|
||||
|
||||
<div class="step">
|
||||
<div class="num">13</div>
|
||||
<div class="body"><h4>Сейчас (14 лет)</h4><p>Английский 3 раза в неделю. Снимать каждый старт на видео. GPA 4.0+.</p></div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="num">15</div>
|
||||
<div class="body"><h4>Через 1 год</h4><p>Swimcloud.com. TOEFL 60+. 50 м в/с за 29-31″.</p></div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="num">16</div>
|
||||
<div class="body"><h4>Через 2 года</h4><p>TOEFL 80+. NCSA. Письма тренерам 15-20 университетов. 50 м в/с за 25-26″.</p></div>
|
||||
</div>
|
||||
<div class="step">
|
||||
<div class="num">18</div>
|
||||
<div class="body"><h4>Выпускной класс</h4><p>Стипендия $40-70 тыс/год. Stanford, Texas, Cal Berkeley. National Letter of Intent.</p></div>
|
||||
</div>
|
||||
|
||||
<h2>🏆 Международные старты</h2>
|
||||
|
||||
<table>
|
||||
<tr><th>Год</th><th>Возраст</th><th>Турнир</th><th>Цель</th></tr>
|
||||
<tr><td>2026</td><td>14</td><td>Весёлый Дельфин — этапы 1-3</td><td>34″ → 32″</td></tr>
|
||||
<tr><td>2027</td><td>15</td><td>Чемпионат РК + Кубок Сальникова</td><td>Призёр, 31″ → 29″</td></tr>
|
||||
<tr><td>2028</td><td>16</td><td>Чемпионат Азии среди юниоров</td><td>Медаль, 29″ → 27″</td></tr>
|
||||
<tr><td>2029</td><td>17</td><td>FINA World Juniors + Азиатские игры</td><td>Полуфинал, 27″ → 25″</td></tr>
|
||||
<tr><td>2030</td><td>18</td><td>Чемпионат мира FINA</td><td>Полуфинал, 25″ → 23″</td></tr>
|
||||
<tr><td>2032</td><td>20</td><td>Олимпийские игры — Брисбен</td><td>Участие, 23″ → 22″</td></tr>
|
||||
</table>
|
||||
|
||||
<div class="moto" style="margin-top:28px">
|
||||
«Ты уже быстрее 90% детей твоего возраста в Казахстане.<br>
|
||||
До КМС — 9 секунд. До NCAA — 4 года.<br>
|
||||
До Олимпиады — 6 лет.<br><br>
|
||||
Каждый день на тренировке — это шаг к мечте.<br>
|
||||
<strong>Не останавливайся.</strong>»
|
||||
</div>
|
||||
|
||||
<p style="text-align:center;color:#999;font-size:12px;margin-top:24px">Отчёт сгенерирован в Галиконе · Июнь 2026</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user