5.7 KiB
5.7 KiB
FSD Frontend Refactor
Цель
Довести фронтенд-архитектуру до эталонного Feature-Sliced Design (FSD) — устранить существующие нарушения, вынести жирные страницы в виджеты/фичи, внедрить автоматический контроль FSD-правил.
Текущее состояние: 4.2/5 по FSD-зрелости. Цель: 5/5.
Задачи
1. Исправить нарушение слоёв в shared/lib/test
shared/lib/test/test-utils.tsxимпортируетSessionProviderиз@/app/providers- Это единственное нарушение FSD (shared → app)
- Решение: вынести
TestSessionProviderвshared/lib/test/и переключитьtest-utils.tsxна него - Тесты не должны сломаться:
TestSessionProviderпредоставляет те же значения контекста (замоканые)
2. Вынести BrokerPositionTable из страницы в виджет
pages/broker-positions/ui/BrokerPositionsPage.tsx(310 строк) содержит внутренние компоненты:BrokerPositionTable(~190 строк) — таблица с пагинацией, skeleton, inline-стилямиPositionTicker(~20 строк) — ссылка на инструментformatQuantity— хелпер
- Решение: создать
widgets/broker-positions-table/с:ui/BrokerPositionTable.tsxui/PositionTicker.tsxindex.ts
- Страница сокращается до ~100 строк (только cursor-логика + композиция)
3. Вынести BrokerSummary, BrokerAssetCards, BrokerOverviewSkeleton в виджет
pages/broker-account/ui/BrokerAccountOverviewPage.tsx(160 строк) содержит:BrokerSummary— сводка портфеля (карточки стоимости и денег)BrokerAssetCards— карточки классов активов (акции/облигации)BrokerOverviewSkeleton— скелетон загрузкиallocationPercent,formatAllocationPercent— хелперы
- Решение: создать
widgets/broker-overview/с:ui/BrokerSummary.tsxui/BrokerAssetCards.tsxui/BrokerOverviewSkeleton.tsxindex.ts
- Страница сокращается до ~40 строк (только loading/error guard + композиция)
4. Вынести AddPositionForm в фичу
pages/portfolios/ui/PortfolioDetailPage.tsx(290 строк) содержит inline-форму добавления позиции:- 4 state-переменные (newSecid, newQty, newPrice, newDate)
- 4 input-поля с inline-стилями
- Валидация и submit
- Это полноценная бизнес-фича, не место в странице
- Решение: создать
features/add-position/с:api/useAddPosition.ts— мутация (обёртка над usePositionMutations)model/useAddPositionForm.ts— управление формойui/AddPositionForm.tsx— UI формыindex.ts
- Страница сокращается до ~140 строк (showAddForm toggle +
<AddPositionForm portfolioId={id} />)
5. Вынести cursor-пагинацию в shared-хук
- 25 строк cursor-логики дублируются в:
pages/broker-positions/ui/BrokerPositionsPage.tsxpages/broker-operations/ui/BrokerOperationsPage.tsx
- Решение: создать
shared/lib/useCursorPagination.ts
function useCursorPagination() {
// cursor, pageNumber, handleNext(cursor), handlePrevious, reset
}
6. Добавить ESLint-плагин FSD
- Текущий
import/no-restricted-pathsпроверяет только межслойные границы - Плагин
@conarti/eslint-plugin-feature-slicedдобавит:- Проверки public API (запрет импорта из внутренних модулей в обход index.ts)
- Проверки сегментов (api/ui/model не импортируют друг друга напрямую)
- Решение: установить плагин и включить recommended rules
Критерии приёмки (Acceptance Criteria)
- AC1:
test-utils.tsxне импортирует из@/app/* - AC2:
widgets/broker-positions-tableсоздан, страница использует его - AC3:
widgets/broker-overviewсоздан, страница использует его - AC4:
features/add-positionсоздана, страница использует её - AC5:
shared/lib/useCursorPagination.tsсоздан, обе страницы используют его - AC6:
@conarti/eslint-plugin-feature-slicedустановлен и настроен - AC7:
npm run lintпроходит без ошибок - AC8:
npm run buildпроходит без ошибок - AC9: Все существующие тесты проходят (включая тесты рефакторимых компонентов)
- AC10: Визуально поведение страниц не изменилось
Ограничения
- Не менять API-контракты компонентов (пропсы, типы). Только перемещение кода.
- Не добавлять новую функциональность — только рефакторинг.
- inline-стили переносятся вместе с компонентами; централизация UI-кита — отдельная задача.