fix frontend

This commit is contained in:
2026-10-03 13:54:57 +07:00
parent 78303b2796
commit a9f91cfea4
@@ -0,0 +1,126 @@
# План приведения фронтенда к стандарту кода
Дата аудита: 2026-10-03
Репозиторий: `evening_detective_frontend`
## Результат проверки
- `npm run type-check` — успешно.
- `npx eslint .` — успешно.
- `npx stylelint 'src/**/*.{css,scss,vue}'` — успешно.
- Проверки запускались без `--fix`, исходный код аудитом не изменён.
- `src/api/generated/**` и `dist/**` в план исправлений не включены.
Автоматические проверки подтверждают синтаксическую и базовую lint-корректность,
но не проверяют все обязательные правила `docs/FRONTEND_CODE_STANDARD.md`.
## Приоритетный план
### 1. Ошибки, загрузка и повторные действия — P0
Цель: ни один API-вызов не должен терять ошибку или оставлять UI в неясном
состоянии.
- Обработать `getPermissions()` в `src/components/HeaderMenu.vue:24` и
`src/components/OfficePage.vue:17`: показать русское сообщение через
`useMessage()` и добавить состояние загрузки/ошибки, если оно влияет на UI.
- Обернуть начальные вызовы `getStory()` и `getAnswers()` в
`src/components/TeamStoryPage.vue:115` в единый flow с отображением ошибки.
- Проверить мутации `src/components/GamePage.vue:287-655` и
`src/components/ScenariosEditorPage.vue:85-529`: для каждого действия оставить
`try/catch/finally`, пользовательское сообщение и блокировку повторной отправки.
- Проверить `src/components/LoginPage.vue:40-76`: во время всех операций формы
кнопки должны быть недоступны, а ошибка должна обрабатываться в том же flow.
- Для каждого экрана явно сохранить состояния loading, empty и error в template.
Готово, когда ручной API-ошибкой можно проверить, что пользователь получает
сообщение, кнопка разблокируется после `finally`, а частично изменённые данные не
перезаписываются фоновым обновлением.
### 2. Доступность интерактивных элементов и изображений — P0
- Заменить кликабельные `div`/`span` или дать им полноценную клавиатурную
семантику в `src/components/HeaderMenu.vue`, `GamePage.vue`,
`PlaceBlock.vue`, `IntroBlock.vue` и `ScenariosPage.vue`.
- Восстановить видимый focus: в частности, не оставлять
`outline: none` в `src/components/GameInputForm.vue:186-189` без равноценной
замены.
- Добавить осмысленные `alt` к изображениям в `src/components/PlaceBlock.vue`
(строки 268, 298, 345, 355, 368, 453, 504), а также проверить остальные
`<img>` через поиск по `src`.
- Для модальных окон в `OfficePage.vue:261` и `UsersPage.vue:114` добавить
`n-card` с `role="dialog"` и `aria-modal="true"` либо эквивалентную
доступную структуру; проверить остальные модальные окна на единообразие.
- Добавить доступные названия/`title` там, где действие выражено только иконкой
или символом `x`.
Готово, когда все действия доступны Tab/Enter/Space, focus виден, изображения
озвучиваются понятно, а модальные окна имеют корректную семантику.
### 3. Границы компонентов и типизация — P1
- Оставить `*View.vue` маршрутными прокси. Перенести содержимое и стили
`src/views/HomeView.vue` в `src/components/HomePage.vue`; стиль сделать
`scoped`. Вьюхи документов с `DocsPage` и `HeaderMenu` отдельно проверить на
соответствие этому правилу.
- Перевести runtime-описания props на typed `defineProps` там, где нет причины
сохранять `PropType`: `HeaderMenu.vue`, `PlaceBlock.vue`,
`GameInputForm.vue`, `IntroBlock.vue`, `QuestionBlock.vue`.
- В `PlaceBlock.vue` и `TeamStoryPage.vue` проверить типы режимов и callback-ов:
заменить широкие `string`/необязательные утверждения на существующие типы,
не дублируя generated API.
- Не выделять новые composable или универсальные обёртки: выносить только
реально повторяющийся flow после исправления конкретных callers.
Готово, когда маршрутные страницы не содержат экранной логики, props/emits
типизированы, а `any` и необоснованные `as` отсутствуют.
### 4. Формы и единообразие UI — P1
- Проверить обязательные поля и сообщения ошибок в формах
`LoginPage.vue`, `GameInputForm.vue`, `TeamStoryPage.vue` и
`ScenariosEditorPage.vue`.
- Использовать Naive UI для обычных UI-контролов. Нативные контролы в
`GameInputForm.vue:96-117` и `TeamStoryPage.vue:272,321` оставлять только
там, где они нужны бумажному визуальному стилю; в таком случае сохранить
доступную семантику и focus.
- Проверить, что кнопки с мутациями имеют `loading`/`disabled`, а пустые и
ошибочные ответы явно видны пользователю.
### 5. CSS-токены и локальность стилей — P2
- Сгруппировать повторяющиеся цвета из компонентов в уже существующую палитру
`src/assets/base.css`; новые токены добавлять только с семантическими именами.
- Не расширять глобальные стили. После переноса `HomeView.vue` проверить,
что одноразовые классы не попали в `main.css`.
- Сохранять алфавитный порядок CSS-свойств и существующие mobile-first
брейкпоинты.
## Порядок выполнения
1. Исправить ошибки/loading и доступность в общих и часто используемых
компонентах (`HeaderMenu`, `PlaceBlock`, `GameInputForm`).
2. Исправить `GamePage`, `TeamStoryPage`, `ScenariosEditorPage` по месту,
не расширяя diff несвязанным рефакторингом.
3. Перенести `HomeView` в page-компонент и типизировать props.
4. Выполнить точечную миграцию цветов и стилей только затронутых файлов.
5. Запустить обязательные проверки:
```bash
npm run type-check
npm run lint
npm run lint:css
npm run build
```
6. Выполнить ручной smoke-check: вход/регистрация, меню с клавиатуры, загрузка
и ошибка API, создание/редактирование сценария, игровой ход, модальные окна,
просмотр изображений и мобильная ширина.
## Не входит в исправление
- Переписывание всего существующего кода только ради косметического соответствия.
- Изменение `src/api/generated/**`, protobuf-контрактов и продуктового поведения.
- Новые зависимости, новый state manager, общие абстракции «на будущее».
- Редизайн и массовая замена бумажного визуального языка.