Extract loading/error/loaded state views from the single AccountOperationsPage.view.tsx into dedicated files under components/. Document the "one state per view file" rule as a mandatory review convention in CONVENTIONS.md and UI-PATTERN.md. Co-Authored-By: opencode <opencode@anthropic.com>
50 lines
4.1 KiB
Markdown
50 lines
4.1 KiB
Markdown
# Conventions
|
||
|
||
## Must
|
||
|
||
- Использовать Biome: `npm run lint`; табы и двойные кавычки определяет `biome.json`.
|
||
- Для type-only импортов использовать `import type`; не использовать `enum` и `namespace`.
|
||
- UI-строки хранить в `src/shared/i18n/locales/ru.ts` и получать через `useTranslation()`.
|
||
- Zod-схемы не содержат пользовательских строк: использовать `validationMessage(key)` из `src/shared/i18n/zod.ts`.
|
||
- Публичный импорт слайса идёт через его `index.ts`.
|
||
- Тесты лежат рядом с исходником как `*.test.tsx`.
|
||
- Зависимости используют exact versions; не добавлять semver ranges.
|
||
- Главный `*.view.tsx` страницы не содержит несколько state-компонентов:
|
||
каждый state/section — отдельный `*.view.tsx` в `components/` (см. File roles).
|
||
- Полный локальный gate: `npm run verify`. Pre-commit запускает staged formatting, OpenAPI check и FSD dependency checks; commit message должен следовать Conventional Commits.
|
||
|
||
## React component style
|
||
|
||
Biome-enforced guardrails:
|
||
|
||
- Named React components объявлять как const-valued components, а не function declarations.
|
||
- Не использовать default exports.
|
||
- Export statements держать после declarations тела module.
|
||
|
||
Mandatory review conventions:
|
||
|
||
- React components типизировать через `FC`: `const Component: FC<Props> = (props) => { ... }`; если props нет — `const Component: FC = () => { ... }`.
|
||
- Props описывать named type рядом с component либо в `Component.types.ts`, если type переиспользуется или file становится крупным.
|
||
- Не использовать inline props typing в component parameters.
|
||
- Для components только с `children` использовать `FC<PropsWithChildren>` без отдельного props alias. Если кроме `children` есть другие props, использовать named props type на основе `PropsWithChildren<{ ... }>`.
|
||
- Не destructure props в component parameters; принимать `props` и destructure внутри component body.
|
||
- Обычный module export surface сводить к одному нижнему named export block, когда это выражается читаемо без потери public API.
|
||
- Чистые barrel files должны использовать прямой re-export без промежуточного import: `export { Component } from "./Component";`.
|
||
|
||
## File roles
|
||
|
||
- `Component.tsx` - контейнер или публичный компонент; для data-driven pages вызывает page VM hook и выбирает top-level state view.
|
||
- `Component.vm.ts` - hook с данными, действиями, state selection и derived presentation data.
|
||
- `Component.view.tsx` - чистое представление: получает props, рендерит JSX и не вызывает data/auth/router/navigation/VM hooks.
|
||
- `Component.types.ts` - props и локальные типы.
|
||
- `Component.module.css` - локальные стили.
|
||
|
||
State-компоненты страницы не колоцируются в одном `*.view.tsx`. Каждый
|
||
top-level state (loading, error, empty, loaded) и каждый именуемый section
|
||
выносится в отдельный `*.view.tsx` в подпапку `components/`. Имя файла
|
||
отражает state/section: `AccountOperationsPageLoaded.view.tsx`,
|
||
`AccountOperationsPageLoading.view.tsx`, `AccountOperationsPageError.view.tsx`.
|
||
Контейнер (`AccountOperationsPage.tsx`) импортирует их из `./components` и
|
||
выбирает нужный по `viewModel.state`. Нельзя держать несколько state components
|
||
внутри одного файла view — это mandatory review convention.
|