docs: add frontend fsd portfolios plan and tasks

This commit is contained in:
Sergey Krylov 2026-06-20 20:57:30 +03:00
parent 110f8c7f55
commit 39da5da12a
2 changed files with 335 additions and 0 deletions

View File

@ -0,0 +1,294 @@
# Frontend FSD — Portfolio Pages Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Migrate portfolio UI components from flat `components/portfolios/` to `widgets/` per FSD, following the broker domain pattern.
**Architecture:** 6 widgets created under `widgets/`, each with `index.ts` barrel + `ui/Component.tsx`. Pages in `pages/portfolios/` switch imports to widgets. `components/portfolios/` deleted. `entities/portfolio/` unchanged.
**Tech Stack:** React 18, TypeScript, Vite, Vitest
---
### Task 1: Create widget directory structure and barrel files
**Files:**
- Create: `apps/frontend/src/widgets/portfolio-card/index.ts`
- Create: `apps/frontend/src/widgets/portfolio-form/index.ts`
- Create: `apps/frontend/src/widgets/portfolio-summary/index.ts`
- Create: `apps/frontend/src/widgets/portfolio-analytics/index.ts`
- Create: `apps/frontend/src/widgets/share-positions-table/index.ts`
- Create: `apps/frontend/src/widgets/bond-positions-table/index.ts`
- Create: `apps/frontend/src/widgets/portfolio-card/ui/PortfolioCard.tsx`
- Create: `apps/frontend/src/widgets/portfolio-form/ui/PortfolioForm.tsx`
- Create: `apps/frontend/src/widgets/portfolio-summary/ui/PortfolioSummary.tsx`
- Create: `apps/frontend/src/widgets/portfolio-summary/ui/AllocationChart.tsx`
- Create: `apps/frontend/src/widgets/portfolio-analytics/ui/AnalyticsSummary.tsx`
- Create: `apps/frontend/src/widgets/share-positions-table/ui/SharePositionTable.tsx`
- Create: `apps/frontend/src/widgets/share-positions-table/ui/SharePositionRow.tsx`
- Create: `apps/frontend/src/widgets/bond-positions-table/ui/BondPositionTable.tsx`
- Create: `apps/frontend/src/widgets/bond-positions-table/ui/BondPositionRow.tsx`
- [ ] **Step 1: Create all widget barrel files**
```ts
// widgets/portfolio-card/index.ts
export { PortfolioCard } from './ui/PortfolioCard';
```
```ts
// widgets/portfolio-form/index.ts
export { PortfolioForm } from './ui/PortfolioForm';
```
```ts
// widgets/portfolio-summary/index.ts
export { PortfolioSummary } from './ui/PortfolioSummary';
```
```ts
// widgets/portfolio-analytics/index.ts
export { AnalyticsSummary } from './ui/AnalyticsSummary';
```
```ts
// widgets/share-positions-table/index.ts
export { SharePositionTable } from './ui/SharePositionTable';
```
```ts
// widgets/bond-positions-table/index.ts
export { BondPositionTable } from './ui/BondPositionTable';
```
- [ ] **Step 2: Copy and update imports for each component**
For each component from `components/portfolios/`, copy to `widgets/<name>/ui/<Component>.tsx` and fix imports:
**PortfolioCard.tsx** (copy from `components/portfolios/PortfolioCard.tsx`, no import changes needed):
```tsx
// Same content as original — imports @/shared/api/responses which stays valid
```
**PortfolioForm.tsx** (copy from `components/portfolios/PortfolioForm.tsx`, no import changes):
```tsx
// Same content — imports @/shared/api/responses
```
**PortfolioSummary.tsx** (copy from `components/portfolios/PortfolioSummary.tsx`, update import path):
```tsx
import { AllocationChart } from './AllocationChart';
import type { PortfolioDetail } from '@/shared/api/responses';
// rest identical to original
```
**AllocationChart.tsx** (copy from `components/portfolios/AllocationChart.tsx`, no import changes):
```tsx
// Same content — imports @/shared/api/responses
```
**AnalyticsSummary.tsx** (copy from `components/portfolios/AnalyticsSummary.tsx`, no import changes):
```tsx
// Same content — imports @/shared/api/responses
```
**SharePositionRow.tsx** (copy from `components/portfolios/SharePositionRow.tsx`, no import changes):
```tsx
// Same content — imports @/shared/api/responses
```
**SharePositionTable.tsx** (copy from `components/portfolios/SharePositionTable.tsx`, update import path):
```tsx
import { SharePositionRow } from './SharePositionRow';
import type { PositionWithPrice } from '@/shared/api/responses';
// rest identical to original
```
**BondPositionRow.tsx** (copy from `components/portfolios/BondPositionRow.tsx`, no import changes):
```tsx
// Same content — imports @/shared/api/responses
```
**BondPositionTable.tsx** (copy from `components/portfolios/BondPositionTable.tsx`, update import path):
```tsx
import { BondPositionRow } from './BondPositionRow';
import type { PositionWithPrice } from '@/shared/api/responses';
// rest identical to original
```
- [ ] **Step 3: Verify build**
Run: `npm run build -w apps/frontend`
Expected: PASS
- [ ] **Step 4: Run tests**
Run: `npm test -w apps/frontend`
Expected: PASS
- [ ] **Step 5: Commit**
```bash
git add apps/frontend/src/widgets/portfolio-card/ \
apps/frontend/src/widgets/portfolio-form/ \
apps/frontend/src/widgets/portfolio-summary/ \
apps/frontend/src/widgets/portfolio-analytics/ \
apps/frontend/src/widgets/share-positions-table/ \
apps/frontend/src/widgets/bond-positions-table/
git commit -m "feat(frontend): create portfolio widgets in FSD structure"
```
---
### Task 2: Update pages to use widgets
**Files:**
- Modify: `apps/frontend/src/pages/portfolios/PortfoliosListPage.tsx`
- Modify: `apps/frontend/src/pages/portfolios/PortfolioDetailPage.tsx`
- [ ] **Step 1: Update PortfoliosListPage.tsx**
```tsx
import { useState } from 'react';
import { usePortfolios, usePortfolioMutations } from '../../entities/portfolio';
import { PortfolioCard } from '../../widgets/portfolio-card';
import { PortfolioForm } from '../../widgets/portfolio-form';
```
- [ ] **Step 2: Update PortfolioDetailPage.tsx**
```tsx
import { useState } from 'react';
import { useParams, Link } from 'react-router-dom';
import {
usePortfolio,
usePortfolioMutations,
usePositionMutations,
} from '../../entities/portfolio';
import { PortfolioForm } from '../../widgets/portfolio-form';
import { PortfolioSummary } from '../../widgets/portfolio-summary';
import { AnalyticsSummary } from '../../widgets/portfolio-analytics';
import { SharePositionTable } from '../../widgets/share-positions-table';
import { BondPositionTable } from '../../widgets/bond-positions-table';
```
- [ ] **Step 3: Verify build**
Run: `npm run build -w apps/frontend`
Expected: PASS
- [ ] **Step 4: Run tests**
Run: `npm test -w apps/frontend`
Expected: PASS
- [ ] **Step 5: Commit**
```bash
git add apps/frontend/src/pages/portfolios/
git commit -m "refactor(frontend): switch pages/portfolios to widget imports"
```
---
### Task 3: Remove flat components/portfolios/
**Files:**
- Delete: `apps/frontend/src/components/portfolios/AllocationChart.tsx`
- Delete: `apps/frontend/src/components/portfolios/AnalyticsSummary.tsx`
- Delete: `apps/frontend/src/components/portfolios/BondPositionRow.tsx`
- Delete: `apps/frontend/src/components/portfolios/BondPositionTable.tsx`
- Delete: `apps/frontend/src/components/portfolios/PortfolioCard.tsx`
- Delete: `apps/frontend/src/components/portfolios/PortfolioForm.tsx`
- Delete: `apps/frontend/src/components/portfolios/PortfolioSummary.tsx`
- Delete: `apps/frontend/src/components/portfolios/SharePositionRow.tsx`
- Delete: `apps/frontend/src/components/portfolios/SharePositionTable.tsx`
- [ ] **Step 1: Delete all files in components/portfolios/**
Run: `rm apps/frontend/src/components/portfolios/*.tsx`
- [ ] **Step 2: Check for remaining imports from components/portfolios**
Run: `rg "components/portfolios" apps/frontend/src`
Expected: no matches
- [ ] **Step 3: Verify build**
Run: `npm run build -w apps/frontend`
Expected: PASS
- [ ] **Step 4: Run tests**
Run: `npm test -w apps/frontend`
Expected: PASS
- [ ] **Step 5: Lint check**
Run: `npm run lint -w apps/frontend`
Expected: PASS
- [ ] **Step 6: Commit**
```bash
git rm apps/frontend/src/components/portfolios/*.tsx
git commit -m "refactor(frontend): remove flat components/portfolios"
```
---
### Task 4: Update documentation
**Files:**
- Modify: `apps/docs/docs/frontend/hooks.md`
- Modify: `apps/docs/docs/frontend/routes.md`
- [ ] **Step 1: Update hooks.md**
Remove any references to legacy `components/portfolios/` paths.
Update import examples to use `@/widgets/portfolio-*` paths where applicable.
- [ ] **Step 2: Update routes.md**
Ensure portfolio route documentation reflects FSD structure.
- [ ] **Step 3: Run doc build**
Run: `npm run build -w apps/docs`
Expected: PASS
- [ ] **Step 4: Commit documentation**
```bash
git add apps/docs/docs/frontend/
git commit -m "docs: update frontend docs for portfolio FSD structure"
```
---
### Task 5: Final verification
- [ ] **Step 1: Test**
Run: `npm test -w apps/frontend`
Expected: PASS
- [ ] **Step 2: Lint**
Run: `npm run lint -w apps/frontend`
Expected: PASS
- [ ] **Step 3: Build**
Run: `npm run build -w apps/frontend`
Expected: PASS
- [ ] **Step 4: Deep import check**
Run: `rg "components/portfolios" apps/frontend/src`
Expected: no matches
- [ ] **Step 5: Docs build**
Run: `npm run build -w apps/docs`
Expected: PASS

View File

@ -0,0 +1,41 @@
# Frontend FSD — Portfolio Pages Tasks
## 1. Create widget directory structure and barrel files
- [ ] Create 6 widget barrels in `widgets/`
- [ ] Copy components to `widgets/*/ui/` with updated imports
- [ ] `npm run build -w apps/frontend` — PASS
- [ ] `npm test -w apps/frontend` — PASS
- [ ] Commit
## 2. Update pages to use widgets
- [ ] Update `PortfoliosListPage.tsx` imports
- [ ] Update `PortfolioDetailPage.tsx` imports
- [ ] `npm run build -w apps/frontend` — PASS
- [ ] `npm test -w apps/frontend` — PASS
- [ ] Commit
## 3. Remove flat components/portfolios/
- [ ] Delete `components/portfolios/*.tsx`
- [ ] No remaining imports from `components/portfolios`
- [ ] `npm run build -w apps/frontend` — PASS
- [ ] `npm test -w apps/frontend` — PASS
- [ ] `npm run lint -w apps/frontend` — PASS
- [ ] Commit
## 4. Update documentation
- [ ] Update `apps/docs/docs/frontend/hooks.md`
- [ ] Update `apps/docs/docs/frontend/routes.md`
- [ ] `npm run build -w apps/docs` — PASS
- [ ] Отдельный коммит
## 5. Final verification
- [ ] `npm test -w apps/frontend` — PASS
- [ ] `npm run lint -w apps/frontend` — PASS
- [ ] `npm run build -w apps/frontend` — PASS
- [ ] `rg "components/portfolios"` — no matches
- [ ] `npm run build -w apps/docs` — PASS