Commit graph

2 commits

Author SHA1 Message Date
bot-backend
d9e675e7ae feat(tradein/support): on-site chat window instead of Telegram redirect
Клиент теперь общается с поддержкой прямо на странице /v2 — SupportButton
открывает панель чата (SupportChatPanel) вместо перехода на t.me. Под капотом
сообщения по-прежнему зеркалятся в тот же Telegram-топик (backend contract:
feat/tradein-web-chat-backend, /api/v1/trade-in/support/*), оператор отвечает
как раньше, клиент этого не видит.

- useSupportChat.ts (src/lib): TanStack Query polling — сообщения только пока
  панель открыта (5-10с), unread-бейдж только пока закрыта (20с); pause на
  неактивной вкладке — встроенное поведение refetchInterval
  (refetchIntervalInBackground по умолчанию false), без ручной
  visibilitychange-логики.
- SupportChatContext.tsx: общее open/close состояние поверх React Context —
  TopNav («Помощь») и SupportButton не являются родителем/потомком друг
  друга, оба открывают ОДНО и то же окно.
- SupportChatPanel.tsx: лента + композер (Enter отправляет, Shift+Enter —
  перенос, лимит 4000 символов со счётчиком), честные состояния (loading /
  error+retry / empty-welcome / 429 / 503 — тексты уже человекочитаемы на
  бэкенде), focus-trap + Esc (мирроринг LocationDrawer), plain-text рендер
  сообщений оператора (untrusted input, без dangerouslySetInnerHTML).
  Telegram-ссылка остаётся маленьким запасным вариантом внутри окна — у
  веб-чата нет push, поэтому это осознанный fallback, не удаление.
- z-index 45 для панели: выше кнопки (25) и LocationDrawer (40/41), ниже
  TopNav (50) и UserMenu (200) — не ворует клики у верхней навигации.
2026-07-26 23:14:24 +03:00
bot-backend
7fd40f6ea5 feat(tradein/ui): вход в поддержку с сайта — плавающая кнопка + живая «Помощь»
All checks were successful
CI / changes (pull_request) Successful in 11s
CI Trade-In / changes (pull_request) Successful in 12s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m15s
Support-мост (#2526) уже работает на проде, но попасть в бота с сайта было
неоткуда — клиент о нём просто не узнавал.

Два входа, оба ведут в @MERAsupport_bot:
- SupportButton — плавающая кнопка в правом нижнем углу, на всех экранах /v2
- «Помощь» в меню TopNav — была задизейблена с «скоро появится», теперь живая

Закрывает перекос пошире: LeadForm монтируется только при hasEstimate
(v2/page.tsx:1064), т.е. до расчёта оценки у клиента не было НИ ОДНОГО способа
связаться. Единственная другая ссылка на связь во всём UI — NoAccessScreen.tsx:84,
и та лишь на экране «доступ закончился».

Решения:
- Это внешняя ссылка, а не чат-виджет: бот живёт в Telegram, поэтому ни API,
  ни состояния, ни сокетов не нужно.
- URL — module-константа, не NEXT_PUBLIC_*: env инлайнятся на build-time, так что
  переменная не дала бы гибкости рантайма, только лишний build-arg. Источник
  правды один — SUPPORT_BOT_URL в SupportButton.tsx, TopNav импортирует его.
- Монтаж в v2/layout, не в глобальный app/layout: последний накрывает ещё админку
  /scrapers/** и /sale-share — другой продукт без бренда МЕРА.
- createPortal в document.body: /v2 рисует HUD внутри артборда 1536×1024 с
  transform: scale(), а position:fixed внутри трансформированного предка
  позиционируется относительно него, а не вьюпорта — без портала кнопку унесло бы
  вместе с HUD.
- z-index 25 — осознанно НИЖЕ всех оверлеев v2 (SectionOverlay 29/30,
  LocationDrawer 40/41, TopNav 50, UserMenu 200): при открытой модалке кнопка
  должна уходить под неё, а не воровать клики и таб-порядок.
- Стиль только через tokens.ts (файл прямо запрещает хардкодить hex);
  готового <Button> в проекте нет, следуем инлайн-паттерну LeadForm.

Профиль/Настройки в том же меню остаются задизейбленными — страниц под них нет.

A11y: aria-label, тач-таргет 44px, focus-visible ring, инлайновый SVG с aria-hidden.

Проверка: tsc --noEmit чисто, lint чисто (3 warning'а pre-existing, не в этих
файлах), npm run build успешно (/v2 49.4 kB, все 15 страниц prerender).
Визуальная проверка — на проде после деплоя: локально RouteGuard без бекенда
возвращает null (RouteGuard.tsx:46) и рендер не доходит до кнопки.
2026-07-16 22:09:26 +03:00