# Frontend FSD Broker Pilot Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking. **Goal:** Перевести broker-домен frontend на первый вертикальный FSD-срез без изменения пользовательского поведения и с сохранением текущих data contracts. **Architecture:** Миграция идёт по вертикали: сначала создаётся FSD-каркас `pages/widgets/entities/shared`, затем broker-specific API/query/read-model логика переносится ближе к доменным срезам, а route entrypoints остаются тонкими оболочками. На время перехода допускаются совместимые re-export entrypoints, чтобы маршруты и тесты можно было переводить постепенно без big-bang переписывания. **Tech Stack:** React 18, TypeScript, React Router v6, TanStack Query v5, Vitest, Testing Library, ESLint, Docusaurus. --- ## Карта файлов - Create `apps/frontend/src/pages/broker-accounts/index.ts` — public entrypoint страницы списка счетов. - Create `apps/frontend/src/pages/broker-account/index.ts` — public entrypoint layout/overview route shell. - Create `apps/frontend/src/pages/broker-positions/index.ts` — public entrypoint страниц позиций. - Create `apps/frontend/src/pages/broker-operations/index.ts` — public entrypoint страницы операций. - Create `apps/frontend/src/widgets/broker-account-card/index.ts` — public API карточки счёта. - Create `apps/frontend/src/widgets/broker-account-card/ui/BrokerAccountCard.tsx` — screen-level карточка счёта. - Create `apps/frontend/src/widgets/broker-accounts-summary/index.ts` — public API общей сводки. - Create `apps/frontend/src/widgets/broker-accounts-summary/ui/BrokerAccountsSummary.tsx` — summary widget. - Create `apps/frontend/src/widgets/broker-allocation-chart/index.ts` — public API allocation chart widget. - Create `apps/frontend/src/widgets/broker-allocation-chart/ui/BrokerAllocationChart.tsx` — account allocation widget. - Create `apps/frontend/src/widgets/broker-operations-table/index.ts` — public API operations table widget. - Create `apps/frontend/src/widgets/broker-operations-table/ui/BrokerOperationsTable.tsx` — reusable broker operations widget. - Create `apps/frontend/src/entities/broker-account/index.ts` — public API account slice. - Create `apps/frontend/src/entities/broker-account/api/brokerAccountApi.ts` — broker account endpoints и query parameter helpers. - Create `apps/frontend/src/entities/broker-account/model/useBrokerAccounts.ts` — accounts query hook. - Create `apps/frontend/src/entities/broker-account/model/useBrokerAccountPortfolios.ts` — list portfolio queries. - Create `apps/frontend/src/entities/broker-account/model/useBrokerPortfolio.ts` — single account portfolio query. - Create `apps/frontend/src/entities/broker-account/model/brokerAccountsOverview.ts` — aggregation/read-model helpers. - Create `apps/frontend/src/entities/broker-account/model/brokerAccountsOverview.test.ts` — unit-тесты агрегатов. - Create `apps/frontend/src/entities/broker-account/ui/BrokerAccountLayout.tsx` — nested account route shell и context. - ~~Create `apps/frontend/src/entities/broker-account/ui/BrokerAccountLayout.test.tsx` — тесты route shell.~~ (покрывается интеграционными тестами в `BrokerPages.test.tsx`) - Create `apps/frontend/src/entities/broker-position/index.ts` — public API position slice. - Create `apps/frontend/src/entities/broker-position/api/brokerPositionApi.ts` — positions endpoint wrapper. - Create `apps/frontend/src/entities/broker-position/model/useBrokerPositions.ts` — positions query hook. - Create `apps/frontend/src/entities/broker-position/model/brokerDisplay.ts` — instrument path helpers for positions. - Create `apps/frontend/src/entities/broker-position/model/brokerAllocation.ts` — allocation helpers for chart/table composition. - Create `apps/frontend/src/entities/broker-position/model/brokerAllocation.test.ts` — allocation unit-тесты. - Create `apps/frontend/src/entities/broker-position/model/brokerDisplay.test.ts` — unit-тесты instrument-path mapping. - Create `apps/frontend/src/entities/broker-operation/index.ts` — public API operation slice. - Create `apps/frontend/src/entities/broker-operation/api/brokerOperationApi.ts` — operations endpoint wrapper and query type. - Create `apps/frontend/src/entities/broker-operation/model/useBrokerOperations.ts` — operations query hook. - Create `apps/frontend/src/entities/broker-operation/model/operationFilters.ts` — filter options and guards. - Create `apps/frontend/src/entities/broker-operation/model/operationFilters.test.ts` — unit-тесты фильтров/guards. - Create `apps/frontend/src/entities/broker-operation/model/useBrokerOperations.test.tsx` — hook-тесты операций. - Create `apps/frontend/src/pages/broker-accounts/ui/BrokerAccountsPage.tsx` — тонкий page entrypoint списка счетов. - Create `apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx` — overview page composition. - Create `apps/frontend/src/pages/broker-positions/ui/BrokerPositionsPage.tsx` — positions page composition. - Create `apps/frontend/src/pages/broker-operations/ui/BrokerOperationsPage.tsx` — operations page composition. - Create `apps/frontend/src/pages/broker-accounts/ui/BrokerAccountsPage.test.tsx` — component/page tests списка счетов. - Modify `apps/frontend/src/pages/broker/BrokerPages.test.tsx` — integration coverage брокерских route entrypoints через новые public entrypoints. - Modify `apps/frontend/src/routes.tsx` — переключить маршруты на новые FSD entrypoints. - Modify `apps/frontend/src/styles.css` — скорректировать только импорто-независимые broker selectors, если это нужно после перемещения компонентов, без изменения UX. - Modify `apps/frontend/src/api/broker.test.ts` — оставить покрытие общего request-контракта после выноса wrappers. - Modify `apps/docs/docs/frontend/overview.md` — зафиксировать coexistence старой структуры и broker FSD pilot. - Modify `docs/features/frontend-fsd-broker-pilot/tasks.md` — отмечать прогресс по фазам. ## Task 1: Создать FSD entrypoints и безопасный маршрутный каркас **Files:** - Create: `apps/frontend/src/pages/broker-accounts/index.ts` - Create: `apps/frontend/src/pages/broker-account/index.ts` - Create: `apps/frontend/src/pages/broker-positions/index.ts` - Create: `apps/frontend/src/pages/broker-operations/index.ts` - Create: `apps/frontend/src/pages/broker-accounts/ui/BrokerAccountsPage.tsx` - Create: `apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx` - Create: `apps/frontend/src/pages/broker-positions/ui/BrokerPositionsPage.tsx` - Create: `apps/frontend/src/pages/broker-operations/ui/BrokerOperationsPage.tsx` - Modify: `apps/frontend/src/routes.tsx` - [x] **Step 1: Написать smoke-тест на broker routes** ```tsx import { MemoryRouter } from 'react-router-dom'; import { render, screen } from '@testing-library/react'; import { AppRoutes } from '../../routes'; it('renders broker routes through fsd entrypoints', () => { render( , ); expect(screen.getByRole('heading', { name: /брокерские счета/i })).toBeInTheDocument(); }); ``` - [x] **Step 2: Запустить route smoke-test и подтвердить RED** Run: `npm test -w apps/frontend -- BrokerPages.test.tsx` Expected: FAIL, потому что новые page entrypoints ещё не существуют. - [x] **Step 3: Создать public entrypoints страниц и временно реэкспортировать текущие реализации** ```ts // apps/frontend/src/pages/broker-accounts/index.ts export { BrokerAccountsPage } from './ui/BrokerAccountsPage'; ``` ```tsx // apps/frontend/src/pages/broker-accounts/ui/BrokerAccountsPage.tsx export { BrokerAccountsPage } from '../../broker/BrokerAccountsPage'; ``` ```tsx // apps/frontend/src/routes.tsx import { BrokerAccountsPage } from './pages/broker-accounts'; import { BrokerAccountOverviewPage } from './pages/broker-account'; import { BrokerPositionsPage } from './pages/broker-positions'; import { BrokerOperationsPage } from './pages/broker-operations'; ``` - [x] **Step 4: Запустить route smoke-test и подтвердить GREEN** Run: `npm test -w apps/frontend -- BrokerPages.test.tsx` Expected: PASS. - [x] **Step 5: Закоммитить безопасный FSD routing shell** ```bash git add apps/frontend/src/routes.tsx apps/frontend/src/pages/broker-accounts apps/frontend/src/pages/broker-account apps/frontend/src/pages/broker-positions apps/frontend/src/pages/broker-operations git commit -m "refactor(frontend): add broker fsd page entrypoints" ``` ## Task 2: Перенести broker-account slice и read-model списка счетов **Files:** - Create: `apps/frontend/src/entities/broker-account/index.ts` - Create: `apps/frontend/src/entities/broker-account/api/brokerAccountApi.ts` - Create: `apps/frontend/src/entities/broker-account/model/useBrokerAccounts.ts` - Create: `apps/frontend/src/entities/broker-account/model/useBrokerAccountPortfolios.ts` - Create: `apps/frontend/src/entities/broker-account/model/useBrokerPortfolio.ts` - Create: `apps/frontend/src/entities/broker-account/model/brokerAccountsOverview.ts` - Create: `apps/frontend/src/entities/broker-account/model/brokerAccountsOverview.test.ts` - Create: `apps/frontend/src/widgets/broker-account-card/index.ts` - Create: `apps/frontend/src/widgets/broker-account-card/ui/BrokerAccountCard.tsx` - Create: `apps/frontend/src/widgets/broker-accounts-summary/index.ts` - Create: `apps/frontend/src/widgets/broker-accounts-summary/ui/BrokerAccountsSummary.tsx` - Modify: `apps/frontend/src/pages/broker-accounts/ui/BrokerAccountsPage.tsx` - [x] **Step 1: Перенести unit-тесты read-model в новый slice path** ```ts import { aggregateBrokerAccounts } from '../model/brokerAccountsOverview'; describe('aggregateBrokerAccounts', () => { it('keeps currencies separate and preserves daily percent rules', () => { // reuse current brokerAccountsOverview.test.ts scenarios verbatim }); }); ``` - [x] **Step 2: Запустить read-model unit-тест и подтвердить RED** Run: `npm test -w apps/frontend -- brokerAccountsOverview.test.ts` Expected: FAIL, потому что новый entity path пока не экспортирует implementation. - [x] **Step 3: Перенести broker account API/hooks/aggregation и подключить widgets через public API** ```ts // apps/frontend/src/entities/broker-account/index.ts export { useBrokerAccounts } from './model/useBrokerAccounts'; export { useBrokerAccountPortfolios } from './model/useBrokerAccountPortfolios'; export { useBrokerPortfolio } from './model/useBrokerPortfolio'; export { aggregateBrokerAccounts } from './model/brokerAccountsOverview'; export { getBrokerAccounts, getBrokerPortfolio, type BrokerOperationQuery, } from './api/brokerAccountApi'; ``` ```tsx // apps/frontend/src/pages/broker-accounts/ui/BrokerAccountsPage.tsx import { aggregateBrokerAccounts, useBrokerAccounts, useBrokerAccountPortfolios, } from '../../../entities/broker-account'; import { BrokerAccountCard } from '../../../widgets/broker-account-card'; import { BrokerAccountsSummary } from '../../../widgets/broker-accounts-summary'; ``` - [x] **Step 4: Запустить account slice тесты и страницы списка** Run: `npm test -w apps/frontend -- brokerAccountsOverview.test.ts BrokerAccountsPage.test.tsx useBrokerAccountPortfolios.test.tsx useBrokerAccounts.test.tsx` Expected: PASS. - [x] **Step 5: Удалить или превратить старые `src/hooks/useBrokerAccounts.ts`, `src/hooks/useBrokerAccountPortfolios.ts`, `src/hooks/useBrokerPortfolio.ts`, `src/pages/broker/BrokerAccountCard.tsx`, `src/pages/broker/BrokerAccountsSummary.tsx`, `src/pages/broker/brokerAccountsOverview.ts` в совместимые re-export shim-файлы** ```ts export { useBrokerAccounts, useBrokerAccountPortfolios, useBrokerPortfolio, aggregateBrokerAccounts, } from '../entities/broker-account'; ``` - [x] **Step 6: Закоммитить broker-account slice** ```bash git add apps/frontend/src/entities/broker-account apps/frontend/src/widgets/broker-account-card apps/frontend/src/widgets/broker-accounts-summary apps/frontend/src/pages/broker-accounts apps/frontend/src/hooks/useBrokerAccounts.ts apps/frontend/src/hooks/useBrokerAccountPortfolios.ts apps/frontend/src/hooks/useBrokerPortfolio.ts apps/frontend/src/pages/broker/BrokerAccountCard.tsx apps/frontend/src/pages/broker/BrokerAccountsSummary.tsx apps/frontend/src/pages/broker/brokerAccountsOverview.ts git commit -m "refactor(frontend): move broker account slice to fsd" ``` ## Task 3: Перенести broker-position slice и allocation/instrument helpers **Files:** - Create: `apps/frontend/src/entities/broker-position/index.ts` - Create: `apps/frontend/src/entities/broker-position/api/brokerPositionApi.ts` - Create: `apps/frontend/src/entities/broker-position/model/useBrokerPositions.ts` - Create: `apps/frontend/src/entities/broker-position/model/brokerAllocation.ts` - Create: `apps/frontend/src/entities/broker-position/model/brokerAllocation.test.ts` - Create: `apps/frontend/src/entities/broker-position/model/brokerDisplay.ts` - Create: `apps/frontend/src/entities/broker-position/model/brokerDisplay.test.ts` - Create: `apps/frontend/src/widgets/broker-allocation-chart/index.ts` - Create: `apps/frontend/src/widgets/broker-allocation-chart/ui/BrokerAllocationChart.tsx` - Modify: `apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx` - Modify: `apps/frontend/src/pages/broker-positions/ui/BrokerPositionsPage.tsx` - [x] **Step 1: Переместить существующие unit-тесты `brokerAllocation` и `brokerDisplay` в новый entity slice** ```ts import { buildBrokerAllocation } from '../model/brokerAllocation'; import { getBrokerInstrumentPath } from '../model/brokerDisplay'; ``` - [x] **Step 2: Запустить position-related unit-тесты и подтвердить RED** Run: `npm test -w apps/frontend -- brokerAllocation.test.ts brokerDisplay.test.ts` Expected: FAIL, потому что новые entity exports ещё не подключены. - [x] **Step 3: Перенести positions API/query/model и переключить overview/positions pages на public API** ```ts // apps/frontend/src/entities/broker-position/index.ts export { useBrokerPositions } from './model/useBrokerPositions'; export { buildBrokerAllocation } from './model/brokerAllocation'; export { getBrokerInstrumentPath } from './model/brokerDisplay'; ``` ```tsx // apps/frontend/src/pages/broker-positions/ui/BrokerPositionsPage.tsx import { useBrokerPositions, getBrokerInstrumentPath } from '../../../entities/broker-position'; ``` - [x] **Step 4: Запустить position page tests** Run: `npm test -w apps/frontend -- BrokerPages.test.tsx brokerAllocation.test.ts brokerDisplay.test.ts` Expected: PASS. - [x] **Step 5: Перевести старые files `src/hooks/useBrokerPositions.ts`, `src/pages/broker/brokerAllocation.ts`, `src/pages/broker/brokerDisplay.ts`, `src/pages/broker/BrokerAllocationChart.tsx`, `src/pages/broker/BrokerPositionsPage.tsx` в re-export shim или удалить после переключения импортов** ```bash git add apps/frontend/src/entities/broker-position apps/frontend/src/widgets/broker-allocation-chart apps/frontend/src/pages/broker-account apps/frontend/src/pages/broker-positions apps/frontend/src/hooks/useBrokerPositions.ts apps/frontend/src/pages/broker/brokerAllocation.ts apps/frontend/src/pages/broker/brokerDisplay.ts apps/frontend/src/pages/broker/BrokerAllocationChart.tsx apps/frontend/src/pages/broker/BrokerPositionsPage.tsx git commit -m "refactor(frontend): move broker position slice to fsd" ``` ## Task 4: Перенести broker-operation slice, layout shell и page composition **Files:** - Create: `apps/frontend/src/entities/broker-operation/index.ts` - Create: `apps/frontend/src/entities/broker-operation/api/brokerOperationApi.ts` - Create: `apps/frontend/src/entities/broker-operation/model/useBrokerOperations.ts` - Create: `apps/frontend/src/entities/broker-operation/model/operationFilters.ts` - Create: `apps/frontend/src/entities/broker-operation/model/operationFilters.test.ts` - Create: `apps/frontend/src/entities/broker-operation/model/useBrokerOperations.test.tsx` - Create: `apps/frontend/src/widgets/broker-operations-table/index.ts` - Create: `apps/frontend/src/widgets/broker-operations-table/ui/BrokerOperationsTable.tsx` - Create: `apps/frontend/src/entities/broker-account/ui/BrokerAccountLayout.tsx` - Modify: `apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx` - Modify: `apps/frontend/src/pages/broker-operations/ui/BrokerOperationsPage.tsx` - Modify: `apps/frontend/src/routes.tsx` - [x] **Step 1: Добавить unit-тесты для guards и filters операций** ```ts import { BROKER_OPERATION_TYPE_OPTIONS, isBrokerOperationType, } from '../model/operationFilters'; it('accepts only declared broker operation types', () => { expect(isBrokerOperationType('OPERATION_TYPE_BUY')).toBe(true); expect(isBrokerOperationType('unexpected')).toBe(false); }); ``` - [x] **Step 2: Запустить tests операций и подтвердить RED** Run: `npm test -w apps/frontend -- operationFilters.test.ts BrokerPages.test.tsx` Expected: FAIL, потому что filters/layout/operations public API ещё не созданы. - [x] **Step 3: Перенести operations API/query/filter logic, route shell и operations table widget** ```ts // apps/frontend/src/entities/broker-operation/index.ts export { useBrokerOperations } from './model/useBrokerOperations'; export { BROKER_OPERATION_TYPE_OPTIONS, isBrokerOperationType, } from './model/operationFilters'; ``` ```tsx // apps/frontend/src/entities/broker-account/ui/BrokerAccountLayout.tsx import { useBrokerPortfolio } from '../model/useBrokerPortfolio'; ``` ```tsx // apps/frontend/src/pages/broker-operations/ui/BrokerOperationsPage.tsx import { BROKER_OPERATION_TYPE_OPTIONS, isBrokerOperationType, useBrokerOperations, } from '../../../entities/broker-operation'; import { BrokerOperationsTable } from '../../../widgets/broker-operations-table'; ``` - [x] **Step 4: Запустить operations/layout/page tests** Run: `npm test -w apps/frontend -- BrokerPages.test.tsx BrokerAccountsPage.test.tsx operationFilters.test.ts useBrokerOperations.test.tsx` Expected: PASS. - [x] **Step 5: Перевести старые files `src/hooks/useBrokerOperations.ts`, `src/pages/broker/BrokerOperationsPage.tsx`, `src/pages/broker/BrokerOperationsTable.tsx`, `src/pages/broker/BrokerAccountLayout.tsx` в shim или удалить** ```bash git add apps/frontend/src/entities/broker-operation apps/frontend/src/entities/broker-account/ui/BrokerAccountLayout.tsx apps/frontend/src/widgets/broker-operations-table apps/frontend/src/pages/broker-operations apps/frontend/src/routes.tsx apps/frontend/src/hooks/useBrokerOperations.ts apps/frontend/src/pages/broker/BrokerOperationsPage.tsx apps/frontend/src/pages/broker/BrokerOperationsTable.tsx apps/frontend/src/pages/broker/BrokerAccountLayout.tsx git commit -m "refactor(frontend): move broker operations and layout to fsd" ``` ## Task 5: Завершить cleanup, документацию и verification **Files:** - Modify: `apps/frontend/src/pages/broker/BrokerPages.test.tsx` - Modify: `apps/frontend/src/styles.css` - Modify: `apps/docs/docs/frontend/overview.md` - Modify: `docs/features/frontend-fsd-broker-pilot/tasks.md` - [x] **Step 1: Сконцентрировать broker route coverage вокруг новых FSD entrypoints** ```tsx // keep behaviour assertions, but import only through new public routes/pages expect(screen.getByRole('heading', { name: /брокерские счета/i })).toBeInTheDocument(); expect(screen.getByRole('link', { name: /вся история/i })).toHaveAttribute('href'); ``` - [x] **Step 2: Обновить опубликованную frontend-документацию** ```md ## Структура исходников Broker-домен переведён в пилотный FSD-срез: - `pages/broker-*` — route entrypoints - `widgets/broker-*` — screen-level композиция - `entities/broker-account|broker-position|broker-operation` — доменные срезы Остальные домены пока остаются в исторической технической структуре. ``` - [x] **Step 3: Отметить выполнение в `tasks.md` и прогнать обязательные проверки** Run: `npm test -w apps/frontend` Expected: PASS. Run: `npm run lint -w apps/frontend` Expected: PASS. Run: `npm run build -w apps/frontend` Expected: PASS. Run: `npm run build -w apps/docs` Expected: PASS. - [x] **Step 4: Выполнить финальный diff-review перед завершением** Run: `git diff --stat main...HEAD` Expected: только broker FSD pilot, docs и связанные test/style updates без затрагивания других доменов. - [x] **Step 5: Закоммитить cleanup и docs** ```bash git add apps/frontend/src/pages/broker/BrokerPages.test.tsx apps/frontend/src/styles.css apps/docs/docs/frontend/overview.md docs/features/frontend-fsd-broker-pilot/tasks.md git commit -m "docs: document broker fsd pilot" ```