refactor: enforce frontend view model boundaries
This commit is contained in:
+29
-11
@@ -11,13 +11,11 @@ Mantine component и общую тему. Для выпадающего выбо
|
||||
ограничения JSDOM решай в test setup, сохраняя production UI.
|
||||
Семантический HTML для структуры страницы остаётся уместным.
|
||||
|
||||
Icons ищи у существующего owner (например,
|
||||
[BankOperationIcon](../../src/entities/bank-card/ui/BankOperationIcon/BankOperationIcon.tsx));
|
||||
статичные Add/Edit/Delete доступны в `@wealthledger/icons`. Их SVG декоративны
|
||||
по умолчанию; имя action принадлежит кнопке. Standalone meaningful icon получает
|
||||
`aria-hidden={false}`, `role="img"` и доступное имя. Category/kind mappings
|
||||
и анимации остаются в entity. Не добавляй пакет ради одного символа. Business/domain
|
||||
components живут у feature/entity/page, даже при повторном использовании.
|
||||
Icons импортируй из `@wealthledger/icons`; геометрия, SVG assets и animation
|
||||
lifecycle принадлежат этому пакету. Domain/category lookup возвращает параметры
|
||||
иконки из model сущности. SVG декоративны по умолчанию; доступное имя action
|
||||
принадлежит кнопке. Meaningful icon получает `aria-hidden={false}`, `role="img"`
|
||||
и доступное имя. Приложение и Storybook подключают CSS пакета.
|
||||
|
||||
Wrapper нужен для проектной ответственности, а не ради нового имени
|
||||
для Button. Локальный CSS module принадлежит component; общий token вводи для
|
||||
@@ -51,10 +49,26 @@ retry callbacks, domain grouping и derived presentation data. View получа
|
||||
| `Component.types.ts` | Переиспользуемые props/local types, когда отдельный owner полезен |
|
||||
| `Component.module.css` | Локальные стили |
|
||||
|
||||
Во view нет data/auth/router/navigation/VM hooks и вычислений по domain collection.
|
||||
Допустимы `useTranslation`, form-context hooks, UI-only state (например failed
|
||||
image fallback) и formatter одного переданного значения. Группировка/доли
|
||||
коллекции готовятся в VM. Перенос fetch во view ради меньшего container нарушает границу.
|
||||
View получает готовые данные и именованные действия. Container вызывает VM;
|
||||
VM владеет запросами, формой, состоянием, обработчиками и derived values.
|
||||
Во view нет data/auth/router/navigation hooks и domain grouping. Data VM
|
||||
вызывает container; presentation hook не должен скрывать fetching во view.
|
||||
Presentation VM для form-context/UI-only state может использоваться автономно
|
||||
в каталоге: её граф зависимостей не достигает application data/API.
|
||||
`useTranslation` и декларативный вывод коллекции допустимы во view.
|
||||
|
||||
JSX props получают ссылки на функции, включая `onClick`, render props,
|
||||
`dateParser` и callbacks внутри объектов props. Для React Hook Form предпочитай
|
||||
`useController` в VM вместо inline `Controller.render`. Значение prop с условием
|
||||
сначала получает предметное имя: `projectedAmount`, `archiveActionLabel`.
|
||||
Проверяй narrowing при переносе: выражение не должно читать отсутствующие данные
|
||||
до ветки, которая раньше защищала доступ; обработчик сохраняет актуальный snapshot.
|
||||
|
||||
Внутри компонента нет именованных helpers. Чистые функции форматирования и
|
||||
адаптации UI inputs выноси в `shared/lib`, передавая явные аргументы. Domain
|
||||
преобразование остаётся в model своего owner; shared не импортирует entities/pages.
|
||||
Closure над состоянием, mutations и refs является действием VM, а не shared helper.
|
||||
Render-helper замени самостоятельным presentation component у того же owner.
|
||||
|
||||
Отдельный state/section с самостоятельной responsibility выноси в
|
||||
`components/` своего component. Небольшой tightly-coupled renderer оставляй
|
||||
@@ -87,6 +101,10 @@ image fallback) и formatter одного переданного значени
|
||||
|
||||
## Формы
|
||||
|
||||
Схемы Zod объявляй в `*.schema.ts`, включая `.refine`/`.superRefine`.
|
||||
Зависимая от текущих данных схема — фабрика с явными inputs в том же файле;
|
||||
VM вызывает фабрику. Сохраняй актуальность данных и deferred validation messages.
|
||||
|
||||
Используй `react-hook-form`, `zodResolver`, `FormProvider`. Container/VM создаёт
|
||||
form state, view получает `onSubmit`/`disabled`, fields используют `useFormContext`.
|
||||
Во время submit блокируй все действия формы. Zod errors показывай у поля;
|
||||
|
||||
Reference in New Issue
Block a user