feat(auth): UserMenu — личный кабинет top-right (PR D) #590

Merged
Light1YT merged 1 commit from feat/user-menu into main 2026-05-26 10:48:57 +00:00

1 commit

Author SHA1 Message Date
358824c284 feat(auth): UserMenu — avatar + dropdown + basic_auth logout
Личный кабинет в правом верхнем углу top-bar (gendsgn.ru + /trade-in/).

Компонент:
- Avatar 32×32 (первая буква username в круге, `var(--accent-soft)` фон,
  `var(--accent)` text)
- Dropdown по клику: username, role badge («Админ» / «Пилот»),
  кнопка «Выйти» (text-only, `var(--danger)`)
- Закрытие по Escape, click-outside; focus возвращается на avatar
- `aria-label="Личный кабинет"`, `role="menu"`, `role="menuitem"`

Logout flow (basic_auth quirk):
1. Fetch `/api/v1/me` (через `API_BASE_URL` чтобы single source of truth
   с `apiFetchWithStatus`) с явно invalid Basic creds `logout:logout`
   → 401 от Caddy → браузер очищает cached basic_auth для origin
2. `window.location.href = "/"` — hard reload, новый basic_auth prompt

Integration:
- Main `frontend/`: `<UserMenu />` в `<TopNav rightSlot>`. Pricing CTA
  (`PilotRequestModal` trigger) на странице остался — не дублировался
  в TopNav.
- Tradein `frontend/`: `<UserMenu />` в конце `.top-nav` в `Topbar.tsx`
  (после tabs). MIRROR с inline LogOut SVG (нет lucide-react dep) +
  `API_BASE_URL` import для logout fetch (consistency с rest of tradein).

Manual smoke план (post-deploy):
- Safari incognito → admintest → авitar «A» + role «Админ»
- Click «Выйти» → basic_auth prompt появляется снова
- Same в Chrome / Firefox (cross-browser logout reliability см. PR review)

Code-reviewer LGTM (1 critical fixed inline — tradein logout fetch
теперь использует `API_BASE_URL` вместо `process.env.NEXT_PUBLIC_BASE_PATH`).
2026-05-26 15:48:26 +05:00