410 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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(
<MemoryRouter initialEntries={['/broker']}>
<AppRoutes />
</MemoryRouter>,
);
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"
```