From 36f39d2d3f11d21642553f68c0372174d253701f Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Sat, 20 Jun 2026 20:57:30 +0300 Subject: [PATCH] docs: add frontend fsd portfolios plan and tasks --- docs/features/frontend-fsd-portfolios/plan.md | 294 ++++++++++++++++++ .../features/frontend-fsd-portfolios/tasks.md | 41 +++ 2 files changed, 335 insertions(+) create mode 100644 docs/features/frontend-fsd-portfolios/plan.md create mode 100644 docs/features/frontend-fsd-portfolios/tasks.md diff --git a/docs/features/frontend-fsd-portfolios/plan.md b/docs/features/frontend-fsd-portfolios/plan.md new file mode 100644 index 0000000..aae9aad --- /dev/null +++ b/docs/features/frontend-fsd-portfolios/plan.md @@ -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//ui/.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 diff --git a/docs/features/frontend-fsd-portfolios/tasks.md b/docs/features/frontend-fsd-portfolios/tasks.md new file mode 100644 index 0000000..75a06c7 --- /dev/null +++ b/docs/features/frontend-fsd-portfolios/tasks.md @@ -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