Files
WhatIDo/todo.md
T
2026-09-19 13:06:21 +03:00

79 lines
6.1 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.
# TODO: профиль ученика + ZIP-архив
## Задача
1. На `/students.html` у каждого ученика — кнопка **«Профиль»**, которая одним нажатием
отдаёт ZIP-архив со всеми данными ученика (фото, работы/файлы, записи журнала).
2. Сгенерированная страница `index.html` внутри архива должна быть оформлена
**полностью по дизайну `student-profile.html`** (тёмная/светлая тема, токены,
топбар, hero, статистика, образование, опыт, навыки, проекты, уроки, «о себе», футер).
3. Если в БД нет данных для заполнения блоков этой страницы — страница не должна
ломаться или показывать выдуманные данные: блоки рендерятся из того, что есть,
пустые разделы получают аккуратный empty-state, а **данные можно добавить позже**
(без правок кода).
## План работ
- [x] Разведка: `server.js` (экспорт `/api/export/student`, `createZipWriter`,
`renderStudentReport`), `public/students.html` + `public/js/students.js`,
`db/init.sql` + `db/migration.sql`, дизайн-макет `student-profile.html`.
- [x] `todo.md` (этот файл).
- [x] БД: у ученика появляются поля для будущего заполнения профиля —
`students.profile JSONB` и `students.photo_path` (`db/init.sql`, `db/migration.sql`).
- [x] Бэкап/восстановление: новые поля сохраняются и восстанавливаются
(`normalizeRestoreData`, `INSERT INTO students`).
- [x] API: `GET/PUT /api/students/:id/profile` (requireAuth + проверка филиала,
валидация структуры профиля, аудит `student.profile.update`).
- [x] Новый модуль `student-report.js`: ZIP-writer (перенесён из `server.js`) +
`renderStudentReport()` — страница профиля ученика по дизайну
`student-profile.html` (самодостаточный HTML+CSS+JS, Lucide через CDN с
fallback-заглушками, лайтбокс, ленты, тема, печать, анимации).
- [x] `server.js`: вызов рендера через модуль, убрать старый рендер из `server.js`,
расширить выборки экспорта (модули, статус ИИ, филиал, `students.profile`).
- [x] `public/students.html` + `public/js/students.js`: кнопка **«Профиль»**
(прямая выгрузка ZIP) и кнопка **«Данные»** (модальное окно заполнения данных
профиля: роль, статус, город, наставник, о себе, цитата, теги, контакты,
достижения, навыки, опыт, прогресс по модулям).
- [x] Архив: `index.html` + `photos/` + `files/` + `data.json` (метаданные профиля).
- [x] Проверка: `node --check`, генерация тестового ZIP и разбор `zipfile`
(структура + наличие разделов профиля в `index.html`).
## Решения и допущения
- «index.html» из задачи — это `index.html` внутри ZIP-архива (страница профиля
ученика). Именно он теперь оформлен по `student-profile.html`. Публичный
`public/index.html` (форма отправки записи) не переделывался: это отдельная
страница, и в задаче про неё данных нет.
- Кнопка называется «Профиль» (в задаче опечатка «Профаил»), подпись в подсказке:
«Скачать профиль ученика (ZIP: фото и работы)».
- Дизайн-макет использует Lucide-иконки через CDN; в архиве оставлен тот же подход,
потому что он полностью офлайн-деградирует (класс `no-icons`), как и в макете.
- Данные, которых нет в БД (опыт, навыки, контакты, достижения, прогресс по модулям,
фото), рендерятся из полей `students.profile`; пока их нет — показывается
empty-state с подсказкой, а заполнить их можно в админке («Данные» у ученика).
- В `renderStudentReport` добавлен раздел «Фотографии» (лента в стиле макета) —
без него фото из архива негде было бы посмотреть; ленты и лайтбокс — в стиле
`student-profile.html`.
## Как применить на существующей базе
```bash
docker compose exec -T db psql -U app -d whereldo \
-c "ALTER TABLE students ADD COLUMN IF NOT EXISTS photo_path VARCHAR(255);" \
-c "ALTER TABLE students ADD COLUMN IF NOT EXISTS profile JSONB;"
docker compose up -d --build app
```
(`db/migration.sql` уже содержит эти же ALTER-команды; на чистой базе `init.sql`
создаёт поля сразу.)
## Как проверить
```bash
# 1. Админка → «Ученики»: у каждого ученика кнопки «Профиль» и «Данные»
# 2. «Данные» → заполнить роль/био/навыки/контакты/достижения/опыт → Сохранить
# 3. «Профиль» → скачивается profile_<имя>_<дата>.zip:
# index.html (страница профиля по student-profile.html), photos/, files/, data.json
```