From 2fc98341a6cbe222cbf50bd987793dbfaa7c770a Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Sat, 20 Jun 2026 21:23:01 +0300 Subject: [PATCH] docs: add FSD screener feature spec, plan, and tasks --- docs/features/frontend-fsd-screener/plan.md | 69 ++++++++++++++++++++ docs/features/frontend-fsd-screener/spec.md | 49 ++++++++++++++ docs/features/frontend-fsd-screener/tasks.md | 47 +++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 docs/features/frontend-fsd-screener/plan.md create mode 100644 docs/features/frontend-fsd-screener/spec.md create mode 100644 docs/features/frontend-fsd-screener/tasks.md diff --git a/docs/features/frontend-fsd-screener/plan.md b/docs/features/frontend-fsd-screener/plan.md new file mode 100644 index 0000000..ce90f65 --- /dev/null +++ b/docs/features/frontend-fsd-screener/plan.md @@ -0,0 +1,69 @@ +# Frontend FSD Screener — Implementation Plan + +> **For agentic workers:** Implement task-by-task using the tasks.md checklist. Steps use checkbox (`- [ ]`) syntax. + +**Goal:** Перевести скринер в FSD-структуру с созданием первого feature-slice (`features/screener/`). + +**Architecture:** Скринер — пользовательский сценарий (фильтрация + сортировка + пагинация), а не бизнес-сущность, поэтому размещается в `features/` слое. `features/screener/` содержит API, модель (URLSearchParams + TanStack Query) и UI. `pages/screener/` — тонкая композиция. Legacy-файлы удаляются без shim-совместимости. + +**Tech Stack:** React 18, TypeScript, React Router v6, TanStack Query v5, Vitest, ESLint, Vite. + +## Карта файлов + +### Create +- `docs/features/frontend-fsd-screener/spec.md` +- `docs/features/frontend-fsd-screener/plan.md` +- `docs/features/frontend-fsd-screener/tasks.md` +- `apps/frontend/src/features/screener/api/screenerApi.ts` — ScreenerQuery, getScreenerResults +- `apps/frontend/src/features/screener/model/useScreener.ts` — URLSearchParams + TanStack Query +- `apps/frontend/src/features/screener/model/index.ts` — barrel +- `apps/frontend/src/features/screener/ui/FilterPanel.tsx` — фильтры +- `apps/frontend/src/features/screener/ui/FilterPanelShare.tsx` — share-фильтры +- `apps/frontend/src/features/screener/ui/FilterPanelBond.tsx` — bond-фильтры +- `apps/frontend/src/features/screener/ui/ScreenerTable.tsx` — таблица +- `apps/frontend/src/features/screener/ui/index.ts` — barrel +- `apps/frontend/src/features/screener/index.ts` — public API +- `apps/frontend/src/pages/screener/ui/ScreenerPage.tsx` — page entrypoint +- `apps/frontend/src/pages/screener/index.ts` — public API + +### Modify +- `apps/frontend/src/app/routing/AppRoutes.tsx` — import from `@/pages/screener` + +### Delete +- `apps/frontend/src/api/screener.ts` +- `apps/frontend/src/hooks/useScreener.ts` +- `apps/frontend/src/components/screener/FilterPanel.tsx` +- `apps/frontend/src/components/screener/FilterPanelShare.tsx` +- `apps/frontend/src/components/screener/FilterPanelBond.tsx` +- `apps/frontend/src/components/screener/ScreenerTable.tsx` +- `apps/frontend/src/pages/screener/ScreenerPage.tsx` + +## Порядок реализации + +1. Создать `features/screener/api/screenerApi.ts` — перенести `ScreenerQuery` + `getScreenerResults` из `api/screener.ts`, обновить импорты на `@/shared/api/client` +2. Создать `features/screener/model/useScreener.ts` — перенести хук из `hooks/useScreener.ts`, обновить импорты +3. Создать `features/screener/ui/` — перенести 4 компонента из `components/screener/`, обновить импорты +4. Создать barrel-файлы (`model/index.ts`, `ui/index.ts`, `features/screener/index.ts`) +5. Создать `pages/screener/ui/ScreenerPage.tsx` — обновить импорты на `@/features/screener` +6. Создать `pages/screener/index.ts` — barrel export +7. Обновить `AppRoutes.tsx` — `import { ScreenerPage } from '@/pages/screener'` +8. Удалить legacy-файлы +9. Verification: `test`, `lint`, `build` + +## Verification + +```bash +npm test -w apps/frontend +npm run lint -w apps/frontend +npm run build -w apps/frontend + +# Проверка отсутствия deep imports в новые model/ и ui/ +rg -n "@features/screener/(model|ui)" apps/frontend/src --type ts --type tsx || echo "OK: no deep imports from outside" +# Проверка импорта pages/screener только через barrel +rg -n "@/pages/screener/(ui|ScreenerPage)" apps/frontend/src --type ts --type tsx || echo "OK: no deep page imports" + +# Проверка, что legacy удалены +! test -f apps/frontend/src/api/screener.ts || echo "FAIL" +! test -f apps/frontend/src/hooks/useScreener.ts || echo "FAIL" +! test -d apps/frontend/src/components/screener || echo "FAIL" +``` diff --git a/docs/features/frontend-fsd-screener/spec.md b/docs/features/frontend-fsd-screener/spec.md new file mode 100644 index 0000000..21a1420 --- /dev/null +++ b/docs/features/frontend-fsd-screener/spec.md @@ -0,0 +1,49 @@ +# Frontend FSD Screener + +Дата: 2026-06-20 +Статус: спецификация + +## Контекст + +Предыдущие FSD-итерации мигрировали broker-домен, shared-слой, entities, app-слой c auth, market pages и portfolios. + +Скринер остаётся единственным крупным блоком кода вне FSD-структуры: `api/screener.ts`, `hooks/useScreener.ts`, `components/screener/` (4 файла), плоская `pages/screener/ScreenerPage.tsx`. Также это первая возможность создать слой `features/` — первый feature-slice в проекте. + +## Цель + +Перевести скринер в FSD, создав `features/screener/` — первый feature-slice, и мигрировав `pages/screener/` в FSD-структуру. + +## Область изменений + +- `features/screener/` — новый слой; включает API-функцию, хук с URLSearchParams + TanStack Query, UI-компоненты (FilterPanel, FilterPanelShare, FilterPanelBond, ScreenerTable) +- `pages/screener/` — миграция из плоской страницы в FSD с barrel export +- `app/routing/AppRoutes.tsx` — обновление импорта +- Удаление legacy: `api/screener.ts`, `hooks/useScreener.ts`, `components/screener/` (4 файла), `pages/screener/ScreenerPage.tsx` + +## Требования + +### 1. Features слой + +- `features/screener/` содержит полную реализацию скринера: API, модель (URLSearchParams + TanStack Query), UI (фильтры, таблица) +- Public API (`index.ts`) экспортирует: `useScreener`, `FilterPanel`, `FilterPanelShare`, `FilterPanelBond`, `ScreenerTable` +- Запрещены глубокие импорты в `model/` или `ui/` извне `features/screener/` + +### 2. Pages слой + +- `pages/screener/` — тонкая композиция, только импортирует из `features/screener` +- Public API (`index.ts`) экспортирует `ScreenerPage` + +### 3. Совместимость + +- Никаких shim-файлов не требуется — скринер не имеет внешних потребителей кроме `AppRoutes` +- Поведение страницы скринера не меняется + +## Критерии приемки (Acceptance Criteria) + +- [ ] `npm test -w apps/frontend` — PASS +- [ ] `npm run lint -w apps/frontend` — PASS +- [ ] `npm run build -w apps/frontend` — PASS +- [ ] Нет deep imports в `features/screener/model/` или `features/screener/ui/` извне +- [ ] `pages/screener/` импортируется только через barrel (`@/pages/screener`) +- [ ] `features/screener/` импортируется только через barrel (`@/features/screener`) +- [ ] Все legacy-файлы удалены diff --git a/docs/features/frontend-fsd-screener/tasks.md b/docs/features/frontend-fsd-screener/tasks.md new file mode 100644 index 0000000..5a51cfe --- /dev/null +++ b/docs/features/frontend-fsd-screener/tasks.md @@ -0,0 +1,47 @@ +# Frontend FSD Screener — задачи + +Статус: в работе + +Подробные шаги, карта файлов и verification-команды находятся в [plan.md](plan.md). + +## 1. API слой + +- [ ] Создать `features/screener/api/screenerApi.ts` — перенос `ScreenerQuery` + `getScreenerResults` +- [ ] Обновить импорты: `@/shared/api/client`, `@/shared/api/responses` + +## 2. Модель + +- [ ] Создать `features/screener/model/useScreener.ts` — перенос хука +- [ ] Создать `features/screener/model/index.ts` + +## 3. UI компоненты + +- [ ] Перенести `FilterPanel.tsx` в `features/screener/ui/` +- [ ] Перенести `FilterPanelShare.tsx` в `features/screener/ui/` +- [ ] Перенести `FilterPanelBond.tsx` в `features/screener/ui/` +- [ ] Перенести `ScreenerTable.tsx` в `features/screener/ui/` +- [ ] Создать `features/screener/ui/index.ts` +- [ ] Создать `features/screener/index.ts` + +## 4. Pages + +- [ ] Создать `pages/screener/ui/ScreenerPage.tsx` — обновить импорты на `@/features/screener` +- [ ] Создать `pages/screener/index.ts` + +## 5. Роутинг + +- [ ] Обновить `app/routing/AppRoutes.tsx` — import from `@/pages/screener` + +## 6. Удаление legacy + +- [ ] Удалить `api/screener.ts` +- [ ] Удалить `hooks/useScreener.ts` +- [ ] Удалить `components/screener/` (директория) + +## 7. Verification + +- [ ] `npm test -w apps/frontend` — PASS +- [ ] `npm run lint -w apps/frontend` — PASS +- [ ] `npm run build -w apps/frontend` — PASS +- [ ] Нет deep imports в `features/screener/` извне +- [ ] `pages/screener/` импортируется только через barrel