# Phase 6: Deep entity pages

**Status:** ✅ Done (sub-commits: bd30200 + final remove-overlay commit)
**Parent plan:** [PLAN.md](./PLAN.md)
**Domain:** frontend

## Objective

Заменить выезжающую `.user-panel` overlay на полноценную страницу с URL `#users/123`. Аналогично для session: `#sessions/456` = full detail page. Это самая комплексная фаза — она ломает совместимость с старым overlay UI (удаляет код), потому идёт ПОСЛЕ всех остальных.

## Tasks

- [x] **User detail page** (`frontend/js/admin/sections/user-detail.js`):
  - Реагирует на route `#users/:id`
  - Layout:
    - **Header**: avatar, name, role badge, email, action buttons (ban/edit/perms/delete), back-link to `#users`
    - **Tabs** (sub-nav в странице):
      - Overview — статистика (тестов, средний %, регистрация, посл вход)
      - Sessions — таблица последних 20 сессий с pagination
      - Classes — список классов где он состоит
      - Audit — журнал действий (если есть audit log с user_id)
    - **Graphs** (опционально, можно отдельным таб'ом):
      - Простой SVG-чарт: успеваемость по неделям
      - Mini-bar chart: avg % по предметам
- [x] **Session detail page** (`frontend/js/admin/sections/session-detail.js`):
  - Реагирует на route `#sessions/:id`
  - Layout: header (user, subject, score, дата) + список вопросов/ответов (правильно/нет, текст), back-link
- [x] **Router updates** (`frontend/js/admin/router.js` если ещё не поддерживает): router из Phase 1 уже парсит params — обновлять не пришлось
- [x] **Admin.js dispatch**: добавлена `DEEP_ROUTES` map + `activateDeepPane()` + `activate(route, params)`
- [x] **Удалить overlay-код:**
  - [x] В `frontend/admin.html` удалён `<div class="user-panel" id="user-panel">` блок + `.user-panel*` CSS
  - [x] В `sections/users.js` удалены `openUserPanel`, `closeUserPanel`, `reloadUserPanel`
  - [x] В `sections/users.js` onclick переключён на `AdminRouter.navigate('#users/${u.id}')`
- [x] **Replace** в Phase 5 quick action "Sessions": `quickOpenUserSessions(uid)` → `AdminRouter.navigate('#users/' + uid + '/sessions')`
  - Парсить sub-tab из route (выполнено через `params[1]` в `activate()`)
  - Открывать user-detail page с активным Sessions tab
- [x] **Глоссарий routes после фазы:**
  - `#overview` — dashboard (Phase 3)
  - `#users` — list
  - `#users/123` — user detail (overview tab default)
  - `#users/123/sessions` — user detail with sessions sub-tab
  - `#sessions` — list
  - `#sessions/456` — session detail
  - … остальные без params — как было

## Files to Modify/Create

- `frontend/js/admin/sections/user-detail.js` — новый, ~400-600L
- `frontend/js/admin/sections/session-detail.js` — новый, ~200-300L
- `frontend/admin.html` — удалить `.user-panel` overlay, добавить `<div id="tab-user-detail">` и `<div id="tab-session-detail">`, добавить `<script>` теги
- `frontend/js/admin/sections/users.js` — удалить overlay-функции (~100-150L удаления)
- `frontend/js/admin/router.js` — улучшения parsing для sub-routes (если нужно)
- `frontend/js/admin/admin.js` — dispatch logic для routes с params

## Acceptance Criteria

- Click на user row → URL становится `#users/123`, открывается deep page
- F5 на `#users/123` восстанавливает страницу
- Back navigation → возврат на `#users` list
- Header содержит все action-кнопки (ban, edit, perms, delete)
- Sub-tabs (overview, sessions, classes, audit) переключаются, URL обновляется
- Старая `.user-panel` overlay полностью удалена из HTML и JS
- Click на session id (в любом контексте) → `#sessions/456` → detail page
- Нет console errors
- Графики (если делаются) рендерятся корректно

## Notes

### Backward compat

После Phase 6 старые ссылки/onclick типа `openUserPanel(...)` УЖЕ НЕ работают. Это intentional — мы их удалили. Но `onclick="AdminRouter.navigate('#users/N')"` работает везде.

Если есть external links на админку user-panel — они продолжат работать как `#users/N` через router.

### Графики

Можно использовать chart.js (CDN ~50KB), но проще — inline SVG bar/line chart на нескольких десятках строк. У нас уже есть `.perf-bar` для процентов — можно расширить.

Не обязательно делать графики в этой фазе — можно сделать MVP без них и добавить чартами позже. В acceptance criteria графики помечены опционально.

### Audit log

Если в БД есть таблица `audit_log` с `user_id` — sub-tab Audit показывает её. Если нет — sub-tab скрывается или показывает empty state "Audit logging не активирован".

### Session detail

Сейчас session detail открывается через `adminGetSessionDetail` → возвращает массив answers. Используем тот же endpoint, рендерим в полноценную страницу вместо modal.

### Удаление overlay-кода (опасный шаг)

Делать в КОНЦЕ фазы, после того как deep page работает. Сначала добавить deep page, протестировать, потом удалить overlay. Можно даже сделать отдельным коммитом ("remove overlay").

### Что НЕ делать

- Не делать realtime updates (Phase 7+)
- Не делать collaborative cursors
- Не оптимизировать графики до production-grade (chart.js or similar OK)

## Review Checklist

- [ ] Deep pages работают: F5, back/forward
- [ ] Sub-tabs URL-обновляемы
- [ ] Old overlay code fully removed
- [ ] No regressions: ban/edit/delete user работают из deep page
- [ ] Mobile-friendly: tabs scrollable, layout не ломается
- [ ] Build passes
- [ ] **Final smoke test:** пройти полный сценарий — открыть админку, найти пользователя через Cmd+K, перейти на deep page, выдать монеты, посмотреть сессии, забанить, разбанить, вернуться в overview

## Handoff to Next Phase

Это финальная фаза. Что реализовано в этой фазе:

### Done

- Deep page `#users/:id` с sub-tabs (overview/sessions/classes/audit) и URL-sync sub-routing
- Deep page `#sessions/:id` с полным разбором ответов
- F5 / browser-back / закладки работают на любом deep-URL
- Overlay `.user-panel` полностью удалён (HTML + CSS + JS)
- Sessions row-click переключён с inline drawer на deep page navigation (`gotoSession(id)`)
- Audit sub-tab фильтрует system-wide audit-log по uid client-side
- Inline SVG bar chart для per-subject avg % на Overview sub-tab (no chart.js dep)
- Cmd+K palette user-pick (Phase 4) теперь открывает deep page (ранее был fallback на `#users`)
- 2 sub-commit разбивка для безопасности: `bd30200` (add deep pages, overlay still works) → finale (remove overlay)

### Post-merge follow-ups (NOT блокирующие для merge)

1. **Classes sub-tab — placeholder.** Нет backend endpoint `GET /admin/users/:id/classes`. Текущий UI показывает empty-state со ссылкой на `/classes`. После merge добавить endpoint (выбрать из `class_members` по `user_id`).
2. **Audit sub-tab — client-side filter.** Фильтрация делается на 500 строк из общего лога — для бóльших инсталляций нужен `GET /admin/audit-log?user_id=N` (server-side). Сейчас работает корректно для типичной нагрузки LearnSpace (<10k записей).
3. **Charts — single bar chart only.** План включал опциональные графики "успеваемость по неделям" — оставил на post-merge. Использовать тот же inline SVG паттерн (`.ud-bars` + `.ud-bar-fill`).
4. **Mobile.** Header кнопки сжимаются на ≤640px (см. CSS `.ud-header` block в user-detail.js), но при большом количестве действий могут перекрыть. Можно добавить overflow menu (`<details>`) post-merge если жалобы.
5. **`.user-panel` CSS не полностью удалён** — оставлен только `.btn-close` (используется ещё где-то?). Если нет — можно удалить тоже.
6. **`window.activeUid` — глобальное состояние.** Сейчас и user-detail.js, и users.js пишут/читают `window.activeUid`. Это работает, но в идеале нужно перенести user-only modals (eu-modal, up-modal) в user-detail.js целиком. Не критично, но улучшит изоляцию.

### Final smoke checklist (для final-reviewer)

- [ ] Открыть `/admin#overview` — dashboard
- [ ] Cmd+K → найти юзера → пик из списка → открыть deep page
- [ ] На deep page переключить sub-tabs (URL обновляется)
- [ ] F5 на `#users/N/sessions` → page восстановлен
- [ ] Browser back → возврат на `#users` list
- [ ] Header action: Изменить → modal → save → header обновлён
- [ ] Header action: Бан → toast → header обновлён (метка "Разблокировать")
- [ ] Click on session row in Sessions sub-tab → `#sessions/M` (deep session page)
- [ ] Session page: Delete → toast → navigate back to `#sessions` list
- [ ] No console errors
