diff --git a/.ai/architecture.md b/.ai/architecture.md index 0a9788f..4ca0420 100644 --- a/.ai/architecture.md +++ b/.ai/architecture.md @@ -8,7 +8,7 @@ Vitest — отдельную JSDOM конфигурацию. Точные versi [package.json](../package.json), реализация — source of truth. ```text -app → pages → widgets → features → entities → shared +app → pages → features → entities → shared page container → page VM → entity/feature query → shared/api → backend /api/v1 ↓ props → state/section views @@ -30,14 +30,13 @@ contract; frontend не читает его checkout для генерации | --- | --- | | Bootstrap, глобальные providers, routes | `app` | | Композиция маршрута и поведение, нужное только этому экрану | `pages/` | -| Крупная переиспользуемая композиция экрана | `widgets/` | | Самостоятельная пользовательская возможность с собственным смыслом | `features/` | | Представление/поведение бизнес-сущности | `entities/` | | Переиспользуемый код без WealthLedger domain meaning | `shared` | -Локальный FSD profile: `app → pages → widgets → features → entities → shared`. -Widget собирает несколько нижних слоёв в самостоятельный UI-блок; компонент для -одной page остаётся у page. Form, mutation или click handler сами по себе не +Локальный FSD profile: `app → pages → features → entities → shared`. +Слой `widgets` не используется: композиция экрана и компонент для одной page +остаются у page. Form, mutation или click handler сами по себе не требуют feature. Два callers не делают domain helper generic shared. Slice именуется по ответственности, а не `helpers`, `hooks` или `types`. @@ -49,12 +48,12 @@ Slice именуется по ответственности, а не `helpers`, Cross-slice consumer использует `@/` и `index.ts` владельца, например `@/entities/portfolio`. Alias Vite и TypeScript согласован. Другой slice не -импортирует внутренний файл напрямую. Slices `pages`, `widgets`, `features`, `entities` не зависят от соседнего slice своего слоя; +импортирует внутренний файл напрямую. Slices `pages`, `features`, `entities` не зависят от соседнего slice своего слоя; композиция принадлежит вышележащему owner. Existing меж-slice исключения не являются разрешением добавлять новые. Направление зависимостей, public imports и запрет соседних slices в -`pages`, `widgets`, `features`, `entities` проверяет `npm run deps`. Внутренние imports +`pages`, `features`, `entities` проверяет `npm run deps`. Внутренние imports одного slice и связи shared segments этот запрет не ограничивает. Knip проверяет использование exports, а не смысл placement. diff --git a/dependency-cruiser.cjs b/dependency-cruiser.cjs index 7aae82c..39beab8 100644 --- a/dependency-cruiser.cjs +++ b/dependency-cruiser.cjs @@ -29,17 +29,17 @@ module.exports = { }, { from: { - path: "^src/(app|pages|widgets|features|entities|shared)/([^/]+)/", + path: "^src/(app|pages|features|entities|shared)/([^/]+)/", }, name: "slices-must-use-public-api", severity: "error", to: { - path: String.raw`^src/(app|pages|widgets|features|entities|shared)/([^/]+)/(?!index\.ts$)`, + path: String.raw`^src/(app|pages|features|entities|shared)/([^/]+)/(?!index\.ts$)`, pathNot: "^src/$1/$2/", }, }, { - from: { path: "^src/(pages|widgets|features|entities)/([^/]+)/" }, + from: { path: "^src/(pages|features|entities)/([^/]+)/" }, name: "no-same-layer-cross-slice-imports", severity: "error", to: { path: "^src/$1/", pathNot: "^src/$1/$2/" }, @@ -48,24 +48,18 @@ module.exports = { from: { path: "^src/shared/" }, name: "shared-must-not-depend-on-layers", severity: "error", - to: { path: "^src/(entities|features|widgets|pages|app)/" }, + to: { path: "^src/(entities|features|pages|app)/" }, }, { from: { path: "^src/entities/" }, name: "entities-must-not-depend-on-higher-layers", severity: "error", - to: { path: "^src/(features|widgets|pages|app)/" }, + to: { path: "^src/(features|pages|app)/" }, }, { from: { path: "^src/features/" }, name: "features-must-not-depend-on-higher-layers", severity: "error", - to: { path: "^src/(widgets|pages|app)/" }, - }, - { - from: { path: "^src/widgets/" }, - name: "widgets-must-not-depend-on-higher-layers", - severity: "error", to: { path: "^src/(pages|app)/" }, }, { diff --git a/src/pages/account/ui/AccountPage/components/AccountPageEmpty.view.tsx b/src/pages/account/ui/AccountPage/components/AccountPageEmpty.view.tsx index 8fe13e3..41a688c 100644 --- a/src/pages/account/ui/AccountPage/components/AccountPageEmpty.view.tsx +++ b/src/pages/account/ui/AccountPage/components/AccountPageEmpty.view.tsx @@ -9,7 +9,6 @@ import type { InvestmentResourceMeta } from "@/shared/api"; import { BrokerageEventsPreview } from "@/entities/brokerage-event"; import { ReadRetry, type ReadRetryProps, SourceSyncStatus } from "@/shared/ui"; -import { PortfolioStructure } from "@/widgets/portfolio-structure"; import type { AccountPageIncomeSummary, @@ -19,6 +18,7 @@ import type { import { AccountHeading } from "./AccountHeading.view"; import { IncomeSummary } from "./IncomeSummary.view"; +import { PortfolioStructure } from "./PortfolioStructure/PortfolioStructure"; import { RecentOperations } from "./RecentOperations.view"; type AccountPageEmptyProps = { diff --git a/src/pages/account/ui/AccountPage/components/AccountPageLoaded.view.tsx b/src/pages/account/ui/AccountPage/components/AccountPageLoaded.view.tsx index 86bbe73..3611ae5 100644 --- a/src/pages/account/ui/AccountPage/components/AccountPageLoaded.view.tsx +++ b/src/pages/account/ui/AccountPage/components/AccountPageLoaded.view.tsx @@ -16,7 +16,6 @@ import type { InvestmentResourceMeta } from "@/shared/api"; import { BrokerageEventsPreview } from "@/entities/brokerage-event"; import { formatMoney } from "@/shared/lib"; import { ReadRetry, type ReadRetryProps, SourceSyncStatus } from "@/shared/ui"; -import { PortfolioStructure } from "@/widgets/portfolio-structure"; import type { Concentration as ConcentrationModel, Slice } from "../../../model/concentration"; import type { AccountPagePositionSection } from "../../../model/positions"; @@ -31,6 +30,7 @@ import { AccountHeading } from "./AccountHeading.view"; import { Concentration } from "./Concentration/Concentration.view"; import { CurrencyCards } from "./CurrencyCards/CurrencyCards.view"; import { IncomeSummary } from "./IncomeSummary.view"; +import { PortfolioStructure } from "./PortfolioStructure/PortfolioStructure"; import { PositionSection } from "./PositionSection.view"; import { RecentOperations } from "./RecentOperations.view"; diff --git a/src/widgets/portfolio-structure/ui/PortfolioStructure.module.css b/src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.module.css similarity index 100% rename from src/widgets/portfolio-structure/ui/PortfolioStructure.module.css rename to src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.module.css diff --git a/src/widgets/portfolio-structure/ui/PortfolioStructure.stories.tsx b/src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.stories.tsx similarity index 98% rename from src/widgets/portfolio-structure/ui/PortfolioStructure.stories.tsx rename to src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.stories.tsx index aecd386..38900e5 100644 --- a/src/widgets/portfolio-structure/ui/PortfolioStructure.stories.tsx +++ b/src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.stories.tsx @@ -28,7 +28,7 @@ const meta = { }, }, tags: ["autodocs"], - title: "Widgets/PortfolioStructure", + title: "Product/PortfolioStructure", } satisfies Meta; export default meta; diff --git a/src/widgets/portfolio-structure/ui/PortfolioStructure.test.tsx b/src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.test.tsx similarity index 100% rename from src/widgets/portfolio-structure/ui/PortfolioStructure.test.tsx rename to src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.test.tsx diff --git a/src/widgets/portfolio-structure/ui/PortfolioStructure.tsx b/src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.tsx similarity index 100% rename from src/widgets/portfolio-structure/ui/PortfolioStructure.tsx rename to src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.tsx diff --git a/src/widgets/portfolio-structure/ui/PortfolioStructure.view.tsx b/src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.view.tsx similarity index 100% rename from src/widgets/portfolio-structure/ui/PortfolioStructure.view.tsx rename to src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.view.tsx diff --git a/src/widgets/portfolio-structure/ui/PortfolioStructure.vm.ts b/src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.vm.ts similarity index 100% rename from src/widgets/portfolio-structure/ui/PortfolioStructure.vm.ts rename to src/pages/account/ui/AccountPage/components/PortfolioStructure/PortfolioStructure.vm.ts diff --git a/src/widgets/portfolio-structure/index.ts b/src/widgets/portfolio-structure/index.ts deleted file mode 100644 index b89160e..0000000 --- a/src/widgets/portfolio-structure/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { PortfolioStructure } from "./ui/PortfolioStructure";