Maxim Dolgolyov
d1d20c4c86
polish(admin-dash): avatar pills, skeleton loader, mobile breakpoints, palette kept
...
- Avatar circles in top/worst-5 tables: initials from name, hsl color from hash of name
- Structural skeleton on first load: 4 shimmer card boxes + 5 row placeholders (replaces
LS.state.loading spinner for better layout-anchored feedback)
- @media ≤640px: 2-column main grid, hero card reverts to normal size, quick-grid 2-col
- Palette: existing per-card colors (violet/cyan/green/amber) already form a good muted
hue family with vivid pink/amber for alert cards — kept as is to avoid regression
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-17 15:07:18 +03:00
Maxim Dolgolyov
124236db58
feat(admin-dash): P1 — sparklines, content inventory, subject distribution, worst-5 sessions
...
- 7d sparkline per 3 main metric cards (inline SVG polyline, renderSparkline helper)
- "Контент проекта" row: questions/tests/courses/classes totals (compact .ov-inv-grid)
- Per-subject stacked bar (24h) with hue-cycle colors and legend below
- "Худшие 5 сегодня" mirrors top-5 table; both side-by-side ≥1100px via .ov-results-grid
- renderSessionRows() shared helper for top/worst table rows
Backend: 5 new prepared statements (worstSessions24h, sparkUsers7d, sparkSessions7d,
sparkActiveUsers7d, inventory, sessionsBySubject24h)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-17 15:05:57 +03:00
Maxim Dolgolyov
64112e56ed
feat(admin-dash): P0 — honest zeros, refresh+timestamp, hero hierarchy, stuck-sessions alert
...
- fmtNum: 0 no longer renders as "—" (muted "0" via .ov-zero instead)
- backend: classesTotal (renamed from activeClasses — was already full count, label fixed)
- backend: abandonedSessions24h (was failedSessions24h status!=completed; now only status=abandoned)
- backend: stuckSessions[] — in_progress > 1h with user/subject join, limit 5
- header: timestamp + manual refresh button (.ov-header flex layout), updates every 30s via interval
- newSessions24h card promoted to hero (2.6rem value, 52px icon, 2fr column ≥720px)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-17 15:03:30 +03:00
Maxim Dolgolyov
41acbdd0d0
feat(admin): phase 3 — dashboard #overview landing
...
GET /api/admin/overview returns 24h digest (~0.08ms/call).
- adminController.getOverview: 7 prepared statements (users 24h, sessions 24h, active users, classes count, failed sessions, banned this week, top-5 sessions)
- new section frontend/js/admin/sections/overview.js (~205L): bento-grid cards, alerts (only when >0), top-5 table, quick-links
- nav-item + tab-pane reordered: #overview is now default; #stats remains routable
Auth: admin-only (inside requireRole('admin') block, sibling of /stats).
Backward compat: all 13 existing routes unchanged.
Known follow-ups (post-merge polish):
- activeClasses counts all (label could be 'Всего классов')
- failedSessions24h includes in_progress (could tighten to abandoned only)
- topSessions24h drops NULL-score completed rows
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-16 23:26:59 +03:00