Files
Learn_System/plans/admin-redesign/phase-2-split-sections.md
T
Maxim Dolgolyov 76e376ee04 chore(plan): admin-redesign 6-phase plan
PLAN.md + 6 subplans + CONTEXT.md

Strategy: Incremental | Mode: Automated | Execution: Orchestrator

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 21:47:55 +03:00

152 lines
8.4 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.
# Phase 2: Split admin.html → per-section modules
**Status:** ⬜ Not Started
**Parent plan:** [PLAN.md](./PLAN.md)
**Domain:** frontend
## Objective
Разделить монолит `admin.js` (3500L) на per-section модули в `frontend/js/admin/sections/*.js`. После фазы `admin.js` становится оркестратором (~500-800L): он только подключает router, инициализирует общие виджеты (notif, sidebar) и делегирует загрузку section-данных в соответствующий модуль.
## Tasks
- [ ] Создать `frontend/js/admin/sections/` директорию
- [ ] Определить единый паттерн модуля:
```js
// js/admin/sections/<name>.js
(function () {
'use strict';
let inited = false;
const ctx = { user: null, isAdmin: false }; // прокидываем из admin.js
async function load() { /* существующий loadX код */ }
window.AdminSections = window.AdminSections || {};
window.AdminSections.<name> = {
init: async (sharedCtx) => {
Object.assign(ctx, sharedCtx);
if (inited) return; inited = true; await load();
},
reload: load,
};
})();
```
- [ ] Извлечь 13 секций (в порядке риска — от меньшего к большему):
- [ ] `stats.js` — `loadStats` + связанные функции (small, ~50L)
- [ ] `sublog.js` — submission log (medium)
- [ ] `sims.js`, `games.js`, `tpl.js` — admin-only (small каждая)
- [ ] `subjects.js` — настройка доступных тестов
- [ ] `permissions.js`
- [ ] `shop.js` — items + purchases + award coins
- [ ] `gam.js` — gamification stats + award xp
- [ ] `assignments.js`
- [ ] `tests.js`
- [ ] `questions.js` — самая большая, ~800L (включая Q-modal)
- [ ] `users.js` — users-table + pagination + user-panel (overlay остаётся!)
- [ ] `sessions.js` — sessions-table + session detail
- [ ] Модифицировать `admin.js`:
- Удалить функции, перенесённые в sections
- Заменить inline вызовы (`loadUsers()` → `AdminSections.users.init(ctx)`)
- Добавить генератор route→section маппинга:
```js
const ROUTE_TO_SECTION = {
stats: 'stats', users: 'users', sessions: 'sessions',
questions: 'questions', tests: 'tests', assignments: 'assignments',
subjects: 'subjects', permissions: 'permissions',
shop: 'shop', gam: 'gam', tpl: 'tpl', sims: 'sims', games: 'games', sublog: 'sublog',
};
AdminRouter.on('change', ({ route }) => {
const sec = ROUTE_TO_SECTION[route];
if (sec && AdminSections[sec]) AdminSections[sec].init(sharedCtx);
});
```
- [ ] Все 13 `<script>` тегов добавить в `admin.html` (после router.js, перед admin.js)
- [ ] Глобальные функции, которые используются из onclick HTML, остаются доступными через `window.X`:
- `changeRole`, `openUserPanel`, `goAddQuestion`, `confirmDeleteUser`, etc.
- Каждый section module экспортирует свои onclick-handler'ы через `window.X = X` или через делегацию из admin.js
- [ ] Удалить per-tab `*Inited` флаги из admin.js — они переехали внутрь section modules
## Files to Modify/Create
- `frontend/js/admin/sections/stats.js` — новый
- `frontend/js/admin/sections/users.js` — новый, ~400-500L
- `frontend/js/admin/sections/sessions.js` — новый
- `frontend/js/admin/sections/questions.js` — новый, ~800L
- `frontend/js/admin/sections/tests.js` — новый
- `frontend/js/admin/sections/assignments.js` — новый
- `frontend/js/admin/sections/subjects.js` — новый
- `frontend/js/admin/sections/permissions.js` — новый
- `frontend/js/admin/sections/shop.js` — новый
- `frontend/js/admin/sections/gam.js` — новый
- `frontend/js/admin/sections/tpl.js` — новый
- `frontend/js/admin/sections/sims.js` — новый
- `frontend/js/admin/sections/games.js` — новый
- `frontend/js/admin/sections/sublog.js` — новый
- `frontend/js/admin/admin.js` — сильно ужать (с 3500L до ~500-800L)
- `frontend/admin.html` — добавить 13 `<script>` тегов
## Acceptance Criteria
- `admin.js` ≤ 800L (от 3500L)
- Каждый section-файл ≤ 900L (questions.js самый большой)
- Все 13 табов работают идентично текущему поведению (no regressions)
- Cross-tab handlers (`goAddQuestion`, `confirmDelete*`) работают
- Lazy-load работает: при первом открытии tab делается fetch, при повторном — нет
- F5 на любом `#X` корректно ленево-грузит секцию (через router из Phase 1)
- Browser back/forward работают
- Никаких console errors в Devtools
## Notes
### Стратегия извлечения
Один section за раз, мелкими безопасными шагами:
1. Скопировать функции `loadX, openXModal, deleteX, ...` в новый файл sections/<name>.js, обернуть в IIFE
2. Экспортировать через `window.AdminSections.X`
3. Подключить `<script>` в admin.html
4. В admin.js заменить вызовы (`loadX()` → `AdminSections.X.init(ctx)`)
5. Удалить дубликаты в admin.js
6. Тест: открыть tab — работает?
7. Перейти к следующей секции
### Что НЕ переезжает в sections
- `LS.initPage()` + auth check — остаётся в admin.js
- `switchTab` (helper) — остаётся
- `pctClass`, `fmtDate`, `fmtTime` — общие утилиты, остаются (или переезжают в `admin/_shared.js`)
- Sidebar / notif init — остаётся
- Router setup — остаётся
### Глобальные функции из onclick
Сейчас многие функции вызываются из HTML onclick (`onclick="openUserPanel(...)"`). Чтобы не переписывать HTML на этой фазе, в каждом section module экспортируем нужные функции через `window.X = X` внутри IIFE. Phase 5/6 могут заменить onclick на event delegation, но Phase 2 этого не делает (incremental).
### Тестирование каждой секции
После каждой выделенной секции:
- Открыть `/admin` → переключиться на этот tab → данные загрузились
- Все кнопки/модалки секции работают
- Cross-tab navigation (если есть) работает
- F5 на `#<route>` корректно открывает tab
Если регрессия — откатить эту итерацию, разобраться, починить.
### Совет implementer'у
Если фаза становится огромной — можно сделать несколько коммитов внутри phase branch. Это inscope. Не нужно делать один гигантский коммит на 14 файлов.
## Review Checklist
- [ ] Все 13 секций имеют одинаковую структуру (init/reload)
- [ ] admin.js ≤ 800L, в нём нет дублирования с sections
- [ ] Все window.X экспорты есть для onclick handlers
- [ ] Lazy-init работает (профилировка: при открытии tab → fetch, при повторе → нет)
- [ ] F5 на каждом из 13 routes восстанавливает секцию
- [ ] Build passes: server starts, no errors
## Handoff to Next Phase
<!-- Implementer должен зафиксировать:
- Структуру window.AdminSections.X.init/reload (точное API)
- Какие функции стали глобальными через window.X (список)
- Как Phase 3 (dashboard) должна добавиться: новый sections/overview.js + new route в ROUTE_TO_SECTION
- Где живут shared утилиты (pctClass, fmtDate, esc) — admin.js или вынесены в _shared.js -->