Commit Graph

4 Commits

Author SHA1 Message Date
c0mrade
7f68e2cd5e fix(theme): readable text on any operator palette + admin consistency pass
Контраст-аудит (WCAG-обход всех текстовых узлов, 4 палитры × юзер+админ
страницы) показал системные провалы читаемости: вторичный текст 1.5-2.5
на светлой/кастомных темах, статусные цвета 1.3-1.6, белый текст на
светлых акцентах 1.9.

Корневые фиксы:
- useThemeColors: контраст-кламп производных серых токенов — dark-400/
  champagne-600 (вторичный текст) держат >=5.0 к поверхности, dark-500/
  champagne-500 (подсказки) >=3.8; палитры с достаточным контрастом
  рендерятся байт-в-байт как раньше
- --color-on-accent/-success/-warning/-error: чёрный или белый текст
  по фактической яркости цвета оператора; text-white на accent-заливках
  заменён на text-on-accent (135 мест + variant примитива Button +
  .btn-primary)
- .light: статусные текстовые оттенки *-300/400 ремапятся на тёмные
  *-700 (жёлтая «Админка» 1.26 -> 3.8+, зелёные суммы 1.4 -> 3.4+,
  бейджи состояний)

Замер после: операторская тёмная палитра — 0 нарушений (всё >=4.5),
худшие точки остальных подняты с 1.26-1.6 до 3.2+.

Консистентность:
- заголовки админ-страниц приведены к text-xl font-bold text-dark-100
  (были 18/20/24/30px и 600/700 вперемешку)
- «Создать FAQ»: warning-500/80+белый -> warning-500+text-on-warning
- formatTraffic: единицы из i18n (убран микс «GB»/«ГБ» на одном экране)
- categoryCanvas -> categoryCANVAS в локалях (битый ключ на настройках)
- «Управление сквадами» -> «Управление локациями» (юзерский экран)
- мин-макс сумм на выборе метода: dark-600 -> dark-400
- неактивные пункты нижнего нава: dark-500 -> dark-400
2026-06-11 15:49:17 +03:00
c0mrade
b5088c70a1 refactor(cabinet): migrate inline SVG icons to the central react-icons set
Audit-driven sweep: replaced 168 hand-written inline <svg> icons across 77
files with the central Phosphor (react-icons/pi) components from
@/components/icons, preserving each icon's size classes and colour (dynamic
stroke colours via the parent's currentColor, RefreshIcon's spinning state,
conditional rotate-180 chevrons).

Verified: tsc + vite build + eslint clean; an adversarial diff review of all
changed files found the replacements correct (70 files clean, 0 blockers).
Remaining inline <svg> dropped from 262 to ~95 — the survivors are legitimate
non-icons (brand/provider logos, loading spinners & framer-motion animations,
charts/sparklines, background decoration) plus a few ambiguous glyphs.
2026-05-31 23:37:12 +03:00
c0mrade
251c862922 adapt(admin): mobile touch-target floor on shared .btn + ticket chat
Audit P2: admin pages prioritise density but cabinet also runs in the
Telegram Mini App on phones. Small button targets (~24-32px) work for
mouse precision but fail mobile thumbs. Apply targeted bumps that keep
desktop density unchanged.

src/styles/globals.css
  • .btn — add min-h-[44px] on mobile, sm:min-h-0 on desktop.
    Cascades to every .btn-primary / .btn-secondary / .btn-ghost /
    .btn-danger consumer (76 + 48 + N usages app-wide). One change,
    everywhere.
  • .btn-icon — same logic (min-h/min-w 44px mobile). Drops the
    duplicate definition that appeared further down the file.

components/admin/userDetail/TicketsTab.tsx — mobile-critical chat
  • Back button h-8 w-8 → h-10 w-10 sm:h-8 sm:w-8 (40px / 32px).
    Adds aria-label since it had none.
  • Status pills px-2.5 py-1 → +min-h-[36px] py-1.5 sm:min-h-0
    sm:py-1 (36px / 26px). Mis-tap penalty on mobile is high (it
    flips ticket status).
  • Reply send button — add min-h/min-w 44px mobile + aria-label.

Why not blanket bump py-1.5 → py-2.5 across all 40+ admin pages:
visual density patterns were iteratively designed and a global sweep
would regress them. Per-page review can target specific buttons that
deserve mobile touch floor without breaking density elsewhere.

icon-only buttons not using .btn-icon (raw <button><svg/></button>)
left as-is — they're typically in compact toolbars where visual
density is the point. Per-page review under /impeccable adapt
target=<page> if mobile flow analysis flags one.
2026-05-26 20:53:40 +03:00
c0mrade
fab2a504d3 refactor(admin-user-detail): extract Tickets tab (list + chat view)
Pulls the tickets tab into components/admin/userDetail/TicketsTab.tsx:
  - ticketsQuery (list)
  - selectedTicketId / selectedTicket state + detail loader
  - reply form state (replyText, replySending)
  - status-change action handler + actionLoading
  - auto-scroll messagesEndRef
  - JSX is split into ChatView + TicketsList + EmptyState helpers
    inside the new file (file stays under 400 lines despite the
    split-view UI)

Parent now passes only userId + formatDate. Imports for adminApi,
MessageMediaGrid, linkifyText, AdminTicket / AdminTicketDetail types
all drop from AdminUserDetail.tsx — tickets are the only consumers.

Net to AdminUserDetail.tsx: down to 2395 lines (-295). Same DOM,
same event handlers, same queryKey ['admin-user-tickets', userId].
2026-05-26 18:00:02 +03:00