From ffd7bac0ac18497f47d0bee9bcf34649c93ba908 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Sat, 16 May 2026 19:48:31 +0300 Subject: [PATCH] =?UTF-8?q?ux(admin):=20sticky=20table=20headers=20+=20col?= =?UTF-8?q?lapsible=20nav=20+=20=D1=83=D0=BD=D0=B8=D1=84=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BB=D0=B5=D0=B9=D0=B1=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3 победы из аудита админ-панели за один заход: 1) STICKY TABLE HEADERS admin.html:142 — добавлен position:sticky; top:0; z-index:5; на Заголовки колонок теперь остаются видны при scroll длинных таблиц (Users, Sessions, Shop, Gam — 100+ строк). Background фон поменян на opaque #E5EAF7 чтобы строки скроллились чисто за header'ом. Стоимость: 1 CSS-правило. Эффект: пользователи не теряют контекст столбцов при просмотре длинного списка. 2) COLLAPSIBLE NAV GROUPS admin.html:875+ — 4 группы (Аналитика, Контент, Пользователи, Система) вместо плоского списка 21 кнопки с просто визуальными сепараторами. Каждая группа сворачивается кликом по заголовку. Состояние per-группа в localStorage (ls_adm_g_). Группа «Система» (только админ) теперь объединяет shop, gam, sims, games, audit, errors, health — раньше они шли вперемешку с teacher-видимыми табами (sublog, topics, broadcast). Переместил sublog/broadcast в группу «Пользователи», topics в «Контент» — логичнее по смыслу. Паттерн один-в-один как у sidebar.js (где мы это сделали ранее). 3) УНИФИКАЦИЯ ЛЕЙБЛОВ Правило: «+ Добавить» для атомов (вопрос, тема, опция, товар), «+ Создать» для составных объектов (тест, задание, курс). Изменения: - admin.html:1431 — «Создать» → «Добавить» (форма темы — атом) - admin.html:1195 — «Новый товар» → «Добавить товар» - admin.js:415 — q-modal title «Новый вопрос» → «Добавить вопрос» - admin.js:2239 — shop-form-title «Новый товар» → «Добавить товар» Теперь кнопка в toolbar и заголовок модалки/формы согласованы. Остались крупные пункты из аудита (на отдельный заход): - Q-modal wizard (split на 2 шага) — 🔴 высокий приоритет - Pagination в больших таблицах — 🟡 - Standardized error/loading states — 🔵 --- frontend/admin.html | 190 ++++++++++++++++++++++--------------- frontend/js/admin/admin.js | 23 ++++- 2 files changed, 135 insertions(+), 78 deletions(-) diff --git a/frontend/admin.html b/frontend/admin.html index 8c38483..dc35bff 100644 --- a/frontend/admin.html +++ b/frontend/admin.html @@ -139,7 +139,8 @@ /* tables */ .table-wrap { background: var(--surface); backdrop-filter: var(--blur); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; margin-bottom: 48px; box-shadow: var(--shadow); } table { width: 100%; border-collapse: collapse; } - th { padding: 14px 20px; text-align: left; font-size: 0.82rem; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; border-bottom: 1px solid var(--border); background: rgba(238,242,255,0.5); } + /* Sticky header: stays visible while body scrolls (in .sb-content). Background opaque (not transparent) so rows scroll cleanly behind. */ + th { padding: 14px 20px; text-align: left; font-size: 0.82rem; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; border-bottom: 1px solid var(--border); background: #E5EAF7; position: sticky; top: 0; z-index: 5; } td { padding: 15px 20px; font-size: 0.94rem; border-bottom: 1px solid var(--border); vertical-align: middle; } tr:last-child td { border-bottom: none; } tr.clickable { cursor: pointer; transition: background var(--tr); } @@ -196,6 +197,22 @@ } .admin-nav-label:first-child { margin-top: 0; } .admin-nav-sep { height: 1px; background: var(--border); margin: 8px 6px; } + /* Collapsible nav groups */ + .admin-nav-group { margin-bottom: 6px; } + .admin-nav-ghdr { + width: 100%; padding: 6px 10px 4px; border: none; background: none; + display: flex; align-items: center; justify-content: space-between; + font-family: 'Manrope', system-ui, sans-serif; + font-size: 0.68rem; font-weight: 800; letter-spacing: 0.08em; + color: var(--text-3); text-transform: uppercase; + cursor: pointer; transition: color .12s, opacity .12s; opacity: .72; + } + .admin-nav-ghdr:hover { color: var(--violet); opacity: 1; } + .admin-nav-ghdr .adm-chev { width: 12px; height: 12px; transition: transform .18s; } + .admin-nav-group.collapsed .adm-chev { transform: rotate(-90deg); } + .admin-nav-body { display: flex; flex-direction: column; max-height: 1500px; overflow: hidden; transition: max-height .25s ease, opacity .18s; opacity: 1; } + .admin-nav-group.collapsed .admin-nav-body { max-height: 0; opacity: 0; pointer-events: none; } + .admin-nav-group .admin-nav-item { padding-left: 10px; } .admin-nav-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px; border: none; @@ -874,80 +891,105 @@
@@ -1192,7 +1234,7 @@