Commit Graph

7 Commits

Author SHA1 Message Date
Maxim Dolgolyov 0b0c113181 feat(shop): каталог товаров карточками по типам с реальным превью
Таблица заменена на сетку карточек, сгруппированных по типам
(Рамки/Титулы/Фоны/Эффекты) с заголовками и счётчиками. Каждая
карточка показывает настоящий вид товара:
- frame  → кольцо аватара по data.css
- background → .bg-preview.bg-<slug> (тот же CSS, что у клиента)
- title  → текст титула в его цвете (data.text/color)
- effect → анимация pulse / иконка-фоллбэк
Фильтр по типу, поиск и счётчик сохранены; неактивные товары
притушены; удаление компактной иконкой.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:24:33 +03:00
Maxim Dolgolyov 1b78f675f8 feat(shop): компактный UX вкладки Магазин — статы-строка, фильтр, поиск
- 4 крупные карточки статистики → компактная строка stat-пиллов
- тулбар: фильтр по типу + поиск по названию + счётчик (N из M)
- таблица: иконка-чип по типу + название с описанием в одной ячейке,
  цветные бейджи типов, колонка ID убрана (id ушёл в подпись)
- состояния «Нет товаров» / «Ничего не найдено»

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:14:55 +03:00
Maxim Dolgolyov e37432d812 feat(shop): добавление/редактирование товара в модальном окне
Инлайн-панель формы внизу страницы заменена на модалку через LS.modal:
- shopAdminCreateItem/EditItem открывают окно openItemModal (create/edit)
- валидация: обязательное название + проверка JSON в поле «Данные»
- блокировка кнопки на время сохранения, ошибки через m.setError
- удалены инлайн-форма из admin.html и неактуальные
  shopAdminSaveItem/shopAdminCancelForm/showShopForm + стейт

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:09:52 +03:00
Maxim Dolgolyov 34c7886a41 refactor(shop): убрать дублирующее «Начислить монеты» из вкладки Магазин
Начисление монет осталось в «Пользователях» (быстрое действие quickAwardCoins)
и во вкладке «Геймификация». Из магазина удалены: HTML-блок «Начислить монеты»,
функции shopSearchUser/shopPickUser/shopAdminAwardCoins, их window-экспорты и
неиспользуемые стейт-переменные. Эндпоинт /shop/admin/award-coins не тронут —
им пользуется quickAwardCoins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:05:14 +03:00
Maxim Dolgolyov 78a870ab70 fix(shop): форма товара скроллится в видимую область + тип «Фон» вместо мёртвого «Тема»
- shopAdminCreateItem/EditItem открывали форму под таблицей на 51 строку —
  вне экрана, выглядело как «кнопки не работают». Добавлен showShopForm():
  scrollIntoView + фокус в поле названия.
- В выпадающем списке типов «Тема» (theme) не поддерживается бэкендом
  (валидация POST: frame/title/effect/background) → создание падало с 400.
  Заменён на рабочий «Фон» (background); добавлена подпись в typeLabels.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:02:05 +03:00
Maxim Dolgolyov bf70c3d7d7 fix(admin-redesign): security — stored XSS via user name in onclick
Security review caught: per-row hover actions (users.js) and async

user picker (shop.js, gam.js) interpolated user-controlled name into

JS string literals inside onclick. LS.esc() escapes & < > " but

NOT backslash; the .replace(/'/g, '\'') fallback was broken.

Attack: any authenticated user could set their name to

  a\'); alert(1); //

via PATCH /api/auth/profile (stripTags doesn't strip \) — admin

viewing the users/shop/gam picker would execute arbitrary JS.

Fix: switch from JS-string interpolation to data-uid/data-name

attributes, read via dataset in handler. esc() correctly escapes

for HTML-attribute context; dataset returns the raw string with

zero parse re-entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 00:30:34 +03:00
Maxim Dolgolyov 92030b462c feat(admin): phase 2 — split admin.js into 13 section modules
Replace ~3500L admin.js monolith with thin orchestrator (~700L) +

14 IIFE-wrapped per-section modules under /js/admin/sections/.

Section modules expose AdminSections.<name>.init/reload (lazy init via

switchTab/router) and re-expose onclick handlers via window.X for

backward compat. Shared helpers (MODES/DIFFS, fmtDate, pctClass,

renderMath, qTypeBadge, pagination) live in /js/admin/_shared.js

exposed on window.AdminCtx.

switchTab now dispatches to AdminSections via ROUTE_TO_SECTION map;

non-extracted system tabs (topics/audit/errors/health/classroom/avatars)

remain inline in admin.js. user-panel overlay markup untouched — Phase 6

will remove it.
2026-05-16 22:50:14 +03:00