diff --git a/docs/features/frontend-fsd-portfolios/spec.md b/docs/features/frontend-fsd-portfolios/spec.md new file mode 100644 index 0000000..bd10f6e --- /dev/null +++ b/docs/features/frontend-fsd-portfolios/spec.md @@ -0,0 +1,82 @@ +# Frontend FSD — Portfolio Pages + +Дата: 2026-06-20 +Статус: черновик + +## Контекст + +FSD-миграция фронтенда выполнена для большинства доменов. Остались 3 домена, +намеренно не затронутые финальной cleanup-фазой: screener, portfolios, auth pages. + +Домен портфелей — второй по величине: entities/portfolio уже мигрирован в FSD, +но UI-компоненты остаются в плоской `components/portfolios/`, а страницы — +в `pages/portfolios/` с импортами из плоской структуры. + +## Цель + +Мигрировать portfolio pages и сопутствующие UI-компоненты в FSD, следуя тому же +паттерну, что и broker domain (entities → widgets → pages). + +## Требования + +1. Все UI-компоненты из `components/portfolios/` размещаются в `widgets/` по принципу + «один виджет — одна композиционная единица» +2. Страницы в `pages/portfolios/` переключаются на импорты из виджетов +3. Никакие внутренние компоненты виджетов не импортируются напрямую из других слоёв — + только через barrel-файл виджета +4. API-хуки и бизнес-логика остаются в `entities/portfolio/` — не дублируются +5. `components/portfolios/` удаляется после миграции всех потребителей + +## Область изменений + +### Мигрируемые файлы + +Из `components/portfolios/` в `widgets/`: + +- `AllocationChart.tsx` → внутренний компонент `widgets/portfolio-summary/ui/` +- `AnalyticsSummary.tsx` → `widgets/portfolio-analytics/ui/AnalyticsSummary.tsx` +- `BondPositionRow.tsx` → внутренний компонент `widgets/bond-positions-table/ui/` +- `BondPositionTable.tsx` → `widgets/bond-positions-table/ui/BondPositionTable.tsx` +- `PortfolioCard.tsx` → `widgets/portfolio-card/ui/PortfolioCard.tsx` +- `PortfolioForm.tsx` → `widgets/portfolio-form/ui/PortfolioForm.tsx` +- `PortfolioSummary.tsx` → `widgets/portfolio-summary/ui/PortfolioSummary.tsx` +- `SharePositionRow.tsx` → внутренний компонент `widgets/share-positions-table/ui/` +- `SharePositionTable.tsx` → `widgets/share-positions-table/ui/SharePositionTable.tsx` + +Обновляемые страницы: + +- `pages/portfolios/PortfoliosListPage.tsx` — импорты из `../../components/portfolios/*` → `@/widgets/portfolio-*` +- `pages/portfolios/PortfolioDetailPage.tsx` — импорты из `../../components/portfolios/*` → `@/widgets/portfolio-*` + +### Удаляемые файлы + +- `components/portfolios/` — весь каталог (9 файлов) + +## Ограничения + +- Изменения ограничены frontend-пакетом. +- `entities/portfolio/` не изменяется (уже FSD). +- Не мигрируется screener и auth pages. +- Не меняется поведение UI, API-контракты, роутинг. +- Не вводятся ESLint import boundaries. + +## Список виджетов + +| Виджет | Компоненты | Назначение | +|--------|-----------|------------| +| `portfolio-card` | PortfolioCard | Карточка портфеля для списка | +| `portfolio-form` | PortfolioForm | Форма создания/редактирования | +| `portfolio-summary` | PortfolioSummary, AllocationChart | Сводка: график + общая стоимость | +| `portfolio-analytics` | AnalyticsSummary | Метрики: инвестировано, P&L, доходность | +| `share-positions-table` | SharePositionTable, SharePositionRow | Таблица позиций-акций | +| `bond-positions-table` | BondPositionTable, BondPositionRow | Таблица позиций-облигаций | + +## Acceptance Criteria + +- Все 6 виджетов созданы в `widgets/` по FSD-структуре (index.ts + ui/) +- `components/portfolios/` удалён +- `pages/portfolios/` импортируют только из `@/widgets/*` и `@/entities/portfolio` +- `npm test -w apps/frontend` — PASS +- `npm run lint -w apps/frontend` — PASS +- `npm run build -w apps/frontend` — PASS +- Deep import check: `rg "components/portfolios" apps/frontend/src` — no matches