76e376ee04
PLAN.md + 6 subplans + CONTEXT.md Strategy: Incremental | Mode: Automated | Execution: Orchestrator Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
113 lines
6.3 KiB
Markdown
113 lines
6.3 KiB
Markdown
# Phase 3: Dashboard #overview
|
||
|
||
**Status:** ⬜ Not Started
|
||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||
**Domain:** fullstack
|
||
**Parallelizable with:** Phase 4, Phase 5
|
||
|
||
## Objective
|
||
|
||
Сделать `#overview` дефолтным route'ом admin-панели — landing-страница "что требует внимания". Заменяет нынешние обезличенные stat-cards (totalUsers, totalTests, ...) на actionable digest за последние 24-48 часов.
|
||
|
||
## Tasks
|
||
|
||
- [ ] Backend: новый endpoint `GET /api/admin/overview`:
|
||
```js
|
||
{
|
||
newUsers24h: number, // регистрации за 24ч
|
||
newSessions24h: number, // запущенных тестов
|
||
bannedThisWeek: [{ id, name, banned_at }],
|
||
failedSessions24h: number, // тесты со статусом не completed
|
||
topSessions24h: [{ id, user_name, subject, score, total, finished_at }], // топ-5 за 24ч
|
||
activeUsers24h: number, // unique last_login за 24ч
|
||
pendingMigrations: number, // если возможно проверить
|
||
recentErrors: [{ id, type, message, created_at }] // если есть audit log с типом 'error'
|
||
}
|
||
```
|
||
- Контроллер: `backend/src/controllers/adminController.js` → новая функция `getOverview`
|
||
- Route: добавить в `backend/src/routes/admin.js`
|
||
- Auth: admin или teacher (как остальные admin/* — RBAC same)
|
||
- Performance: один запрос для каждого поля, простые COUNT/SELECT, без JOIN'ов где возможно
|
||
- [ ] Frontend: новый section `frontend/js/admin/sections/overview.js`:
|
||
- Использует структуру из Phase 2
|
||
- Загружает `/api/admin/overview`
|
||
- Рендерит карточки в `<div id="tab-overview">` секции:
|
||
- **Активность 24ч** — registr, sessions, active users (число + спарклайн если есть данные)
|
||
- **Требует внимания** — banned this week (если >0), failed sessions (если >5%), pending migrations
|
||
- **Топ-сессии** — таблица top-5 за день с click→drilldown
|
||
- **Quick links** — "Все пользователи", "Все сессии", "Создать тест" (deep-link в соответствующие routes)
|
||
- LS.skeleton при загрузке, LS.state.error на fail
|
||
- [ ] HTML: добавить `<div class="tab-pane" id="tab-overview">` в admin.html (перед остальными tab-pane)
|
||
- [ ] Nav: добавить admin-nav-item для `overview` (icon: layout-dashboard / activity)
|
||
- [ ] Регистрация в ROUTE_TO_SECTION (из Phase 2): `overview: 'overview'`
|
||
- [ ] Сделать `#overview` дефолтным route'ом в router (из Phase 1) — если пустой hash, navigate to `#overview` вместо `#stats`
|
||
- [ ] Старый `#stats` остаётся как доступный route (legacy backend stats), но не дефолтный
|
||
|
||
## Files to Modify/Create
|
||
|
||
- `backend/src/controllers/adminController.js` — добавить `getOverview` функцию (~60-90L)
|
||
- `backend/src/routes/admin.js` — добавить `router.get('/overview', requireAdmin, getOverview)`
|
||
- `frontend/js/admin/sections/overview.js` — новый, ~250-350L
|
||
- `frontend/admin.html` — добавить `<div id="tab-overview">` + nav-item + `<script>` тег
|
||
- `frontend/js/admin/admin.js` — изменить default route на `#overview` (если ещё не сделано через router.js config)
|
||
|
||
## Acceptance Criteria
|
||
|
||
- `/admin` (без hash) → редирект на `#overview`
|
||
- `#overview` показывает реальные данные (новые регистрации видны если кто-то зарегистрировался)
|
||
- Карточки кликабельные (click → deep-link в users / sessions с фильтром)
|
||
- При отсутствии данных (свежая БД) — empty states, не crash
|
||
- Endpoint выполняется <100ms на тестовой БД
|
||
- F5 на `#overview` работает
|
||
- Auth: только teacher/admin (как остальные /admin/*)
|
||
|
||
## Notes
|
||
|
||
### Что считать "требует внимания"
|
||
|
||
Делаем простые threshold'ы для MVP:
|
||
- `bannedThisWeek` > 0 — показать жёлтую карточку с именами
|
||
- `failedSessions24h` > 0 — показать список (failed = status != 'completed')
|
||
- `pendingMigrations` > 0 — показать красную (но это редкий случай — миграции применяются на старте)
|
||
|
||
Можно потом расширить до "новых жалоб", "переполненных классов", и т.д. — это уже после merge.
|
||
|
||
### Дизайн карточек
|
||
|
||
Bento-grid из 4-6 карточек:
|
||
```
|
||
+---------+---------+
|
||
| 24ч | Внимание|
|
||
| метрики | ! |
|
||
+---------+---------+
|
||
| Топ сессии |
|
||
| (table) |
|
||
+---------+---------+
|
||
| Quick links |
|
||
+-------------------+
|
||
```
|
||
|
||
Использовать существующие стили `.stat-card`, `.section-title` из admin.html — не изобретать.
|
||
|
||
### Что НЕ делать в этой фазе
|
||
|
||
- Не делать реалтайм WebSocket-обновления (это уже Phase 7+)
|
||
- Не делать графики/чарты (пока числа + sparkline опционально)
|
||
- Не делать персонализацию (например "ваши классы")
|
||
|
||
## Review Checklist
|
||
|
||
- [ ] Endpoint работает и возвращает корректную форму ответа
|
||
- [ ] Frontend handles empty state gracefully
|
||
- [ ] Click на quick-link корректно навигирует через AdminRouter
|
||
- [ ] Нет hardcoded date math (использовать SQL `datetime('now', '-24 hours')`)
|
||
- [ ] Roles correct (admin/teacher only, не у students)
|
||
- [ ] No SQL injection — параметры через `?` placeholders
|
||
- [ ] Build passes
|
||
|
||
## Handoff to Next Phase
|
||
|
||
<!-- Implementer: записать, какой shape у overview-ответа,
|
||
какие route переходы внедрены, какие deep-links открыты для Phase 6
|
||
(например, `#users?filter=banned` или `#sessions?status=failed`). -->
|