# UI-аудит портала Лидерра — раунд 2: находки + план фиксов

> ✅ **СТАТУС 22.06.2026:** все отмеченные ниже `✅`-фиксы подтверждены **НА ПРОДЕ** (сверка развёрнутого фронта liderra.ru): F-ICONS, F-VALIDATION-LANG, F-K1, F2, F-EMAIL, F-DEALS-1 + минорные. **F-NEWPROJECT-1** — ✅ исправлено в коде по TDD 22.06.2026 (клиентская валидация названия/источника, ⏳ ещё не на проде). Минор «зелёный тост после отмены отчёта» — ✅ тоже исправлен в коде по TDD 22.06.2026 (`ReportsView.onCancel` сбрасывает `submitSuccess`; ⏳ не на проде). Открытых пунктов не осталось.

**Дата:** 21.06.2026. **Метод:** сквозной интерактивный обход через Playwright (протыкивание форм/диалогов/комбинаций), root-cause каждой находки по коду. **Кодовая фраза стены:** «роутер-наставник».

Предыдущий проход: `2026-06-21-ui-audit-findings-and-next-session.md` (Канбан/Настройки/Отчёты/Импорт/Помощь не были пройдены — закрыто этим раундом).

---

## Пройдено и протыкано глазами (Playwright, вход admin@demo.local)

Канбан (drawer/комментарий/смена статуса) · Настройки ×5 вкладок (Профиль/Реквизиты/Безопасность/API/Уведомления) · Отчёты (create/cancel/retry/destroy) · Импорт (upload/polling/dry-run) · Помощь (валидация+submit) · Проекты (диалог создания 3 типа + Вся-РФ-guard + bulk регионы/дни/лимит) · Сделки · Админка (Тенанты/Биллинг/Тарифная сетка/Инциденты/Система/Обращения ПДн + 404).

---

## 🔴 Реальные баги (root-cause найден)

### F-ICONS (HIGH, систематический) — «?» вместо иконок ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/plugins/vuetify.ts:224-236, проверка 22.06.2026)
**Корень:** `resources/js/plugins/vuetify.ts:247` — `const Icon = lucideMap[String(props.icon)] || HelpCircle;`. Любая mdi-иконка НЕ из `lucideMap` рендерится как HelpCircle («?»).
**13 незамапленных иконок** (рендерятся «?»): `mdi-earth` (bulk Регионы), `mdi-target` (bulk Лимит), `mdi-database-import-outline` (Импорт), `mdi-file-delimited-outline`/`mdi-file-excel-outline`/`mdi-file-document-outline` (Отчёты/Сделки экспорт), `mdi-lifebuoy` (Помощь/Реквизиты-вкладка), `mdi-account-cancel`, `mdi-cash-edit`, `mdi-cash-refund`, `mdi-delete-forever`, `mdi-format-list-checks`, `mdi-information-outline` (админка/действия).
**Фикс:** добавить 13 mdi→Lucide маппингов в `lucideMap`. Видно на bulk-баре, импорте, отчётах, реквизитах, помощи, админке — чинит всё разом.

### F-VALIDATION-LANG (HIGH, прод) — сырой ключ «validation.required» ✅ ИСПРАВЛЕНО (подтверждено по коду app/lang/ru/validation.php, проверка 22.06.2026)
**Корень:** `config/app.php` `APP_LOCALE` default `en`, но `.env` `APP_LOCALE=ru`; директории `lang/` НЕТ → Laravel при locale=ru без `lang/ru/validation.php` отдаёт сырой ключ. Auth-формы имеют кастомные `messages()` (ОК), остальные (профиль, **создание проекта**) — нет.
**Где видно:** Профиль (баннер «validation.required»), Новый проект (домен+название → inline «validation.required» ×2).
**Фикс:** добавить `lang/ru/validation.php` (+ `attributes`). Чинит ВСЕ неавторизованные формы.

### F-K1 (HIGH) — комментарий в активности с префиксом «text:» ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/composables/dealsApiMapper.ts:48-50, проверка 22.06.2026)
**Корень:** `resources/js/composables/dealsApiMapper.ts:44-48` — нет ветки `deal.commented`, срабатывает generic-fallback `Object.entries(context).map(k:v)` → бэкенд шлёт `{text:"…"}` → «text: …».
**Фикс:** добавить ветку `else if (api.event === 'deal.commented')` → `detail = String(context.text ?? context.comment ?? '')`.

### F2 (MED) — карточки Канбана «0 ₽» ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/components/kanban/KanbanCard.vue:32, проверка 22.06.2026)
**Корень:** `dealsApiMapper.ts:74` `cost: 0` захардкожен; `KanbanCard.vue:32` биндит `deal.cost` (всегда 0→«0 ₽»). drawer честно «—» (`costKopecks`). List-эндпоинт `cost_kopecks` не отдаёт.
**Фикс (фронт):** KanbanCard рендерить `costKopecks != null ? formatCost : '—'` как drawer. (Реальная цена на листинге = backend-доработка эндпоинта — отдельно.)

### F-EMAIL (MED) — support@liderra.app → liderra.ru ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/views/errors/ErrorView.vue:70,91, проверка 22.06.2026)
**Корень (4 места):** `components/errors/ErrorMeta.vue:56`, `views/errors/ErrorView.vue:70` (+ `:91` `status.liderra.app`), `views/HelpView.vue:9`.
**Решение владельца:** `support@liderra.ru`. ⚠️ `status.liderra.app` (стр.91) — отдельный сабдомен, уточнить (вероятно `status.liderra.ru`).

### F-DEALS-1 (минор) — «Реестр лидов от crm.bp» ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/views/DealsView.vue:305, проверка 22.06.2026)
**Корень:** `views/DealsView.vue:304` «crm.bp» (Импорт/админка — «crm.bp-gr.ru»). Фикс: → «crm.bp-gr.ru».

### F-NEWPROJECT-1 (минор) — домен/название без клиент-валидации ✅ ИСПРАВЛЕНО в коде по TDD 22.06.2026 (в `NewProjectDialog.vue` `submit()` добавлена клиентская валидация: название обязательно, источник обязателен — домен/номер/отправители по типу сигнала; ошибка показывается сразу, без обращения к серверу. Тесты `NewProjectDialog.spec.ts` +2 зелёных, полный фронт-сьют без новых падений. ⏳ ещё не на проде — новый локальный код)
Только серверная валидация (→ сырой ключ). Желательно добавить клиентское required (как у Реквизитов).

---

## 🟠 Требует решения / крупная работа

### F-SEC (HIGH, владелец выбрал «достроить бэкенд»)
Вкладка Безопасность — заглушки:
- `ChangePasswordCard.vue` — захардкоженная дата «12.04.2026 (26 дней назад)» + кнопка «Сменить пароль» БЕЗ обработчика.
- `SessionsTable.vue` — 3 захардкоженных фейк-сессии + кнопка «Завершить» БЕЗ обработчика.
**План:** GET/DELETE `/api/account/sessions` + POST `/api/account/change-password` + диалог old/new/confirm. Бэкенд+фронт+тесты — отдельный батч.

---

## 🟡 Минор (косметика)
- Профиль: ошибка валидации баннером сверху, не inline (Реквизиты делают inline правильно) — желательно унифицировать.
- US-формат даты `mm/dd/yyyy` в нативных `<input type=date>` (Отчёты «Период», Сделки «Диапазон поставки») — нужен кастомный date-picker или принять.
- Отчёты: зелёный тост «Отчёт поставлен в очередь.» висит после отмены (не сбрасывается). ✅ ИСПРАВЛЕНО в коде по TDD 22.06.2026 (`ReportsView.onCancel` сбрасывает `submitSuccess`; тест `ReportsView.spec.ts` «отмена задачи сбрасывает зелёный»; ⏳ не на проде).
- Уведомления: «users.notification_preferences в БД» — имя таблицы на экране пользователя.
- Дашборд: «Активные проекты 3 / 0» (скрывать «/ 0» при лимите 0); «хватит на 0 дней».
- BalanceCapacityIndicator: «1000.00₽» без разделителя тысяч (`:37`). ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/components/billing/BalanceCapacityIndicator.vue:36, проверка 22.06.2026)
- API/Webhook: eye-toggle без aria-label (`ApiTab.vue:192,278`); нет тоста после регенерации ключа. ✅ ИСПРАВЛЕНО (aria-label eye-toggle — подтверждено по коду app/resources/js/views/settings/ApiTab.vue:199, проверка 22.06.2026)
- Реквизиты: телефон без клиент-валидации формата.
- Канбан: смена статуса без тоста-подтверждения (есть пространственный фидбек — переезд карточки); пустой «—» в футере колонки.
- **Админка:** F-Admin-1 литерал «ИНН» под тенантами без значения; F-Admin-2 Тариф «—» (Биллинг) vs «Trial» (Тенанты); F-Admin-3 Тарифная сетка «с 1970-01-01» (epoch-дата); F-Admin-4 цена «500.00 ₽» (точка-десятич + .00); F-Admin-5 Инциденты пустой = белая полоса вместо «Инцидентов нет» ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/views/admin/AdminIncidentsView.vue:199, проверка 22.06.2026); F-Admin-6 «Retention activity_log (hole #2)» dev-жаргон в описании; native `confirm()/alert()` в AdminSupplierIntegrationView/AdminPdSubjectRequestsView ✅ ИСПРАВЛЕНО (window.confirm→диалог; подтверждено по коду AdminSupplierIntegrationView.vue:309-319 + AdminPdSubjectRequestsView.vue:430-477, проверка 22.06.2026).

  > Примечание: F-Admin-3 «Тарифная сетка с 1970-01-01 (epoch-дата)» ✅ ИСПРАВЛЕНО (подтверждено по коду app/resources/js/views/admin/AdminPricingTiersView.vue:164-166, проверка 22.06.2026).

---

## ✅ Работает корректно
Реквизиты (inline-валидация + DaData «Найти по ИНН») · API-ключ (реальная регенерация + диалог-подтверждение) · Уведомления (dirty-tracking, disabled save) · Отчёты (полный CRUD + подтверждения + aria-labels) · Импорт (русские статусы, polling) · Помощь (валидация+submit) · Новый проект (Вся-РФ-guard, табы 3 типа) · bulk-панель проектов · русская локаль Vuetify (таблицы/пагинация во всём приложении и админке).

---

## План фиксов (порядок)
1. **Батч 1 (фронт, безопасный, 1 build/deploy):** F-ICONS (13 маппингов) + F-EMAIL + F-K1 + F2 + F-DEALS-1.
2. **Батч 2:** F-VALIDATION-LANG (`lang/ru/validation.php`).
3. **Батч 3 (крупный):** F-SEC бэкенд (сессии + смена пароля).
4. Минор — добор по согласованию.

Деплой каждого батча на прод через бастион (`npm run build` с sitekey → `tar -cz build | ssh liderra-prod 'sudo tar -xz -C …'`) под owner-escape, верификация Playwright'ом.
