refactor: colocate frontend component files
Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Successful in 5m10s
Conventional commits / commits (pull_request) Successful in 25s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 5m10s
Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Successful in 5m10s
Conventional commits / commits (pull_request) Successful in 25s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 5m10s
This commit is contained in:
+2
-2
@@ -76,8 +76,8 @@ Add/Edit/Delete; restore/category SVG остаются локальными.
|
|||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
|
|
||||||
- Общая busy-область: существующий [LoadingSkeleton](../packages/ui/src/LoadingSkeleton.tsx), а не domain widget в shared.
|
- Общая busy-область: существующий [LoadingSkeleton](../packages/ui/src/LoadingSkeleton/LoadingSkeleton.tsx), а не domain widget в shared.
|
||||||
- Account-income state views: [страница](../src/pages/account-income/ui/AccountIncomePage.tsx) и её flat `components/*.view.tsx`; новый page-local filter остаётся здесь.
|
- Account-income state views: [страница](../src/pages/account-income/ui/AccountIncomePage/AccountIncomePage.tsx) и её `components/`; новый page-local filter остаётся здесь. Комплекты файлов группируются по [UI convention](conventions/ui.md#размещение-файлов-компонента).
|
||||||
- Portfolio query: [entity public API](../src/entities/portfolio/index.ts); новая UI-сводка с бизнес-смыслом не становится shared только из-за нескольких экранов.
|
- Portfolio query: [entity public API](../src/entities/portfolio/index.ts); новая UI-сводка с бизнес-смыслом не становится shared только из-за нескольких экранов.
|
||||||
|
|
||||||
## Проверка
|
## Проверка
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Stories не достигают application API, auth, VM и query providers д
|
|||||||
контракт: keyboard activation, доступность действия, local callback. Не повторяй
|
контракт: keyboard activation, доступность действия, local callback. Не повторяй
|
||||||
RTL suite и не тестируй внутренности Mantine. Существующий
|
RTL suite и не тестируй внутренности Mantine. Существующий
|
||||||
[Button](../../src/shared/ui/Button.stories.tsx) показывает themed control
|
[Button](../../src/shared/ui/Button.stories.tsx) показывает themed control
|
||||||
без production wrapper; [LoadingSkeleton](../../packages/ui/src/LoadingSkeleton.stories.tsx)
|
без production wrapper; [LoadingSkeleton](../../packages/ui/src/LoadingSkeleton/LoadingSkeleton.stories.tsx)
|
||||||
— значимые busy states.
|
— значимые busy states.
|
||||||
|
|
||||||
`npm run typecheck`, `npm run deps:storybook`, `npm run build:catalog` проверяют
|
`npm run typecheck`, `npm run deps:storybook`, `npm run build:catalog` проверяют
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ Finance: loading/error/empty/loaded, cached snapshot при refetch failure, ret
|
|||||||
отсутствие старых данных после session/connection switch. ErrorBoundary: test-only
|
отсутствие старых данных после session/connection switch. ErrorBoundary: test-only
|
||||||
throwing route, безопасная ссылка и reset после navigation.
|
throwing route, безопасная ссылка и reset после navigation.
|
||||||
|
|
||||||
Примеры: [AuthForm test](../../src/features/auth/ui/AuthForm.test.tsx),
|
Примеры: [AuthForm test](../../src/features/auth/ui/AuthForm/AuthForm.test.tsx),
|
||||||
[client test](../../src/shared/api/client.test.ts),
|
[client test](../../src/shared/api/client.test.ts),
|
||||||
[usePortfolio test](../../src/entities/portfolio/api/usePortfolio.test.tsx).
|
[usePortfolio test](../../src/entities/portfolio/api/usePortfolio.test.tsx).
|
||||||
Не копируй fixtures/сценарии целиком, если задача затрагивает один исход.
|
Не копируй fixtures/сценарии целиком, если задача затрагивает один исход.
|
||||||
|
|||||||
+29
-6
@@ -12,7 +12,7 @@ Mantine component и общую тему. Для выпадающего выбо
|
|||||||
Семантический HTML для структуры страницы остаётся уместным.
|
Семантический HTML для структуры страницы остаётся уместным.
|
||||||
|
|
||||||
Icons ищи у существующего owner (например,
|
Icons ищи у существующего owner (например,
|
||||||
[BankOperationIcon](../../src/entities/bank-card/ui/BankOperationIcon.tsx));
|
[BankOperationIcon](../../src/entities/bank-card/ui/BankOperationIcon/BankOperationIcon.tsx));
|
||||||
статичные Add/Edit/Delete доступны в `@wealthledger/icons`. Их SVG декоративны
|
статичные Add/Edit/Delete доступны в `@wealthledger/icons`. Их SVG декоративны
|
||||||
по умолчанию; имя action принадлежит кнопке. Standalone meaningful icon получает
|
по умолчанию; имя action принадлежит кнопке. Standalone meaningful icon получает
|
||||||
`aria-hidden={false}`, `role="img"` и доступное имя. Category/kind mappings
|
`aria-hidden={false}`, `role="img"` и доступное имя. Category/kind mappings
|
||||||
@@ -56,11 +56,34 @@ retry callbacks, domain grouping и derived presentation data. View получа
|
|||||||
image fallback) и formatter одного переданного значения. Группировка/доли
|
image fallback) и formatter одного переданного значения. Группировка/доли
|
||||||
коллекции готовятся в VM. Перенос fetch во view ради меньшего container нарушает границу.
|
коллекции готовятся в VM. Перенос fetch во view ради меньшего container нарушает границу.
|
||||||
|
|
||||||
Отдельный state/section с самостоятельной responsibility выноси в flat
|
Отдельный state/section с самостоятельной responsibility выноси в
|
||||||
`components/*.view.tsx`. Небольшой tightly-coupled renderer оставляй рядом.
|
`components/` своего component. Небольшой tightly-coupled renderer оставляй
|
||||||
Не создавай folder/barrel/test/CSS для каждого view и не дроби по line count.
|
рядом; размер файла сам по себе не требует разделения.
|
||||||
Пример: [AccountIncomePage](../../src/pages/account-income/ui/AccountIncomePage.tsx)
|
Пример: [AccountIncomePage](../../src/pages/account-income/ui/AccountIncomePage/AccountIncomePage.tsx)
|
||||||
и [его VM](../../src/pages/account-income/ui/AccountIncomePage.vm.ts).
|
и [его VM](../../src/pages/account-income/ui/AccountIncomePage/AccountIncomePage.vm.ts).
|
||||||
|
|
||||||
|
## Размещение файлов компонента
|
||||||
|
|
||||||
|
Правило действует в `src` и `packages`: компонент с сопутствующими файлами
|
||||||
|
(view, VM, types, CSS, tests, stories) размещай в папке `Component/`.
|
||||||
|
Сохраняй полные имена файлов: `Component.tsx`, `Component.view.tsx`,
|
||||||
|
`Component.test.tsx`. Создавай только нужные файлы; одиночный компонент
|
||||||
|
оставляй непосредственно в `ui`, `components` или source-каталоге пакета.
|
||||||
|
|
||||||
|
Внутренние части принадлежат папке родителя; для набора state/section views
|
||||||
|
используй её `components/`. Внутри него действует то же правило: отдельная
|
||||||
|
папка объединяет комплект файлов, одиночный view остаётся файлом.
|
||||||
|
Стили и хуки нескольких соседних компонентов остаются у ближайшего общего
|
||||||
|
владельца; не копируй их и не прячь внутрь одного потребителя.
|
||||||
|
|
||||||
|
Папка компонента не создаёт новую FSD-границу. Публичные exports остаются в
|
||||||
|
существующем `index.ts` slice/segment или entry пакета; внутри используй
|
||||||
|
прямые относительные imports без дополнительных barrels на каждый компонент.
|
||||||
|
При переносе обновляй imports, ссылки документации и проверки, зависящие от пути.
|
||||||
|
|
||||||
|
Пример: [BankCardForm](../../src/entities/bank-card/ui/BankCardForm/BankCardForm.tsx)
|
||||||
|
лежит рядом со своим view, тестом и story; общий `BankForms.module.css`
|
||||||
|
остаётся в `bank-card/ui`.
|
||||||
|
|
||||||
## Формы
|
## Формы
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module.exports = {
|
|||||||
severity: "error",
|
severity: "error",
|
||||||
from: { path: "\\.stories\\.tsx$|^\\.storybook/preview\\.tsx$" },
|
from: { path: "\\.stories\\.tsx$|^\\.storybook/preview\\.tsx$" },
|
||||||
to: {
|
to: {
|
||||||
path: "^src/(shared/api|features/auth|app/routes|app/ui)/|^src/(entities|features)/[^/]+/api/|\\.vm\\.ts$|^src/pages/[^/]+/ui/[^/]+Page\\.tsx$|node_modules/(@tanstack/react-query|openapi-fetch|openapi-react-query)/",
|
path: "^src/(shared/api|features/auth|app/routes|app/ui)/|^src/(entities|features)/[^/]+/api/|\\.vm\\.ts$|^src/pages/[^/]+/ui/.*Page\\.tsx$|node_modules/(@tanstack/react-query|openapi-fetch|openapi-react-query)/",
|
||||||
reachable: true,
|
reachable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { MantineProvider } from "@mantine/core";
|
import { MantineProvider } from "@mantine/core";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { render, screen } from "@testing-library/react";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { LoadingSkeleton } from "./LoadingSkeleton";
|
import { LoadingSkeleton } from "../LoadingSkeleton/LoadingSkeleton";
|
||||||
import { StateView } from "./StateView";
|
import { StateView } from "./StateView";
|
||||||
|
|
||||||
describe("StateView", () => {
|
describe("StateView", () => {
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
export { EntryCard } from "./EntryCard";
|
export { EntryCard } from "./EntryCard/EntryCard";
|
||||||
export { LoadingSkeleton } from "./LoadingSkeleton";
|
export { LoadingSkeleton } from "./LoadingSkeleton/LoadingSkeleton";
|
||||||
export { StateView } from "./StateView";
|
export { StateView } from "./StateView/StateView";
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { lazy } from "react";
|
import { lazy } from "react";
|
||||||
import { Navigate, Route, Routes } from "react-router";
|
import { Navigate, Route, Routes } from "react-router";
|
||||||
import { LazyPage } from "./RouteFallback";
|
import { LazyPage } from "../RouteFallback";
|
||||||
import { Protected, Public } from "./RouteGuards";
|
import { Protected, Public } from "../RouteGuards";
|
||||||
|
|
||||||
const CardPage = lazy(async () => {
|
const CardPage = lazy(async () => {
|
||||||
const { CardPage } = await import("@/pages/card");
|
const { CardPage } = await import("@/pages/card");
|
||||||
@@ -65,7 +65,7 @@ const SettingsPage = lazy(async () => {
|
|||||||
return { default: SettingsPage };
|
return { default: SettingsPage };
|
||||||
});
|
});
|
||||||
const ProtectedLayout = lazy(async () => {
|
const ProtectedLayout = lazy(async () => {
|
||||||
const { ProtectedLayout } = await import("./ProtectedLayout");
|
const { ProtectedLayout } = await import("../ProtectedLayout");
|
||||||
return { default: ProtectedLayout };
|
return { default: ProtectedLayout };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { AppBreadcrumbs, AppShell } from "@/app/ui";
|
import { AppBreadcrumbs, AppShell } from "@/app/ui";
|
||||||
import { ProtectedDocumentTitle } from "./DocumentTitle";
|
import { ProtectedDocumentTitle } from "./DocumentTitle/DocumentTitle";
|
||||||
|
|
||||||
const ProtectedLayout: FC = () => {
|
const ProtectedLayout: FC = () => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export { AppRoutes } from "./AppRoutes";
|
export { AppRoutes } from "./AppRoutes/AppRoutes";
|
||||||
export { RouteErrorBoundary } from "./RouteErrorBoundary";
|
export { RouteErrorBoundary } from "./RouteErrorBoundary/RouteErrorBoundary";
|
||||||
|
|||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
export { AppBreadcrumbs } from "./AppBreadcrumbs";
|
export { AppBreadcrumbs } from "./AppBreadcrumbs/AppBreadcrumbs";
|
||||||
export { AppShell } from "./AppShell";
|
export { AppShell } from "./AppShell/AppShell";
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ export {
|
|||||||
} from "./model/form-validation";
|
} from "./model/form-validation";
|
||||||
export { bankOperationKinds } from "./model/operation-kinds";
|
export { bankOperationKinds } from "./model/operation-kinds";
|
||||||
export { bankPeriod } from "./model/period";
|
export { bankPeriod } from "./model/period";
|
||||||
export { BankCardFace } from "./ui/BankCardFace";
|
export { BankCardFace } from "./ui/BankCardFace/BankCardFace";
|
||||||
export { BankCardForm } from "./ui/BankCardForm";
|
export { BankCardForm } from "./ui/BankCardForm/BankCardForm";
|
||||||
export { BankFeedback } from "./ui/BankFeedback";
|
export { BankFeedback } from "./ui/BankFeedback";
|
||||||
export { BankOperationIcon } from "./ui/BankOperationIcon";
|
export { BankOperationIcon } from "./ui/BankOperationIcon/BankOperationIcon";
|
||||||
export { BankPeriodPicker } from "./ui/BankPeriodPicker";
|
export { BankPeriodPicker } from "./ui/BankPeriodPicker";
|
||||||
export { BankSummaryView } from "./ui/BankSummary.view";
|
export { BankSummaryView } from "./ui/BankSummary/BankSummary.view";
|
||||||
export { CategoryManager } from "./ui/CategoryManager";
|
export { CategoryManager } from "./ui/CategoryManager/CategoryManager";
|
||||||
export { useBankFormFocus } from "./ui/useBankFormFocus";
|
export { useBankFormFocus } from "./ui/useBankFormFocus";
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { formatMoney } from "@/shared/lib";
|
import { formatMoney } from "@/shared/lib";
|
||||||
import type { BankCard } from "../api/queries";
|
import type { BankCard } from "../../api/queries";
|
||||||
import classes from "./BankCardFace.module.css";
|
import classes from "./BankCardFace.module.css";
|
||||||
|
|
||||||
type BankCardFaceProps = { card: BankCard };
|
type BankCardFaceProps = { card: BankCard };
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||||
import { FormProvider, useForm } from "react-hook-form";
|
import { FormProvider, useForm } from "react-hook-form";
|
||||||
import type { BankCardValues } from "../model/form-validation";
|
import type { BankCardValues } from "../../model/form-validation";
|
||||||
import { BankCardFields } from "./BankCardForm.view";
|
import { BankCardFields } from "./BankCardForm.view";
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
+1
-1
@@ -6,7 +6,7 @@ import { describe, expect, it, vi } from "vitest";
|
|||||||
import { configureAuthClient } from "@/shared/api";
|
import { configureAuthClient } from "@/shared/api";
|
||||||
import { createTestQueryClient } from "@/test/query";
|
import { createTestQueryClient } from "@/test/query";
|
||||||
import { server } from "@/test/server";
|
import { server } from "@/test/server";
|
||||||
import type { BankCard } from "../api/queries";
|
import type { BankCard } from "../../api/queries";
|
||||||
import { BankCardForm } from "./BankCardForm";
|
import { BankCardForm } from "./BankCardForm";
|
||||||
|
|
||||||
const card: BankCard = {
|
const card: BankCard = {
|
||||||
+6
-6
@@ -4,18 +4,18 @@ import { type FC, useState } from "react";
|
|||||||
import { FormProvider, useForm } from "react-hook-form";
|
import { FormProvider, useForm } from "react-hook-form";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { formatDate } from "@/shared/lib";
|
import { formatDate } from "@/shared/lib";
|
||||||
import { useBankMutations } from "../api/mutations";
|
import { useBankMutations } from "../../api/mutations";
|
||||||
import { type BankCard, useBankCard } from "../api/queries";
|
import { type BankCard, useBankCard } from "../../api/queries";
|
||||||
import {
|
import {
|
||||||
type BankCardValues,
|
type BankCardValues,
|
||||||
bankCardSchema,
|
bankCardSchema,
|
||||||
bankMoneyValue,
|
bankMoneyValue,
|
||||||
bankToday,
|
bankToday,
|
||||||
} from "../model/form-validation";
|
} from "../../model/form-validation";
|
||||||
|
import { BankFeedback } from "../BankFeedback";
|
||||||
|
import classes from "../BankForms.module.css";
|
||||||
|
import { useBankFormFocus } from "../useBankFormFocus";
|
||||||
import { BankCardFields } from "./BankCardForm.view";
|
import { BankCardFields } from "./BankCardForm.view";
|
||||||
import { BankFeedback } from "./BankFeedback";
|
|
||||||
import classes from "./BankForms.module.css";
|
|
||||||
import { useBankFormFocus } from "./useBankFormFocus";
|
|
||||||
|
|
||||||
type BankCardFormProps = { card?: BankCard; onClose: () => void };
|
type BankCardFormProps = { card?: BankCard; onClose: () => void };
|
||||||
const BankCardForm: FC<BankCardFormProps> = (props) => {
|
const BankCardForm: FC<BankCardFormProps> = (props) => {
|
||||||
+1
-1
@@ -8,7 +8,7 @@ import {
|
|||||||
bankDateInputValue,
|
bankDateInputValue,
|
||||||
bankDateSchema,
|
bankDateSchema,
|
||||||
bankToday,
|
bankToday,
|
||||||
} from "../model/form-validation";
|
} from "../../model/form-validation";
|
||||||
|
|
||||||
type BankCardFieldsProps = { archived: boolean };
|
type BankCardFieldsProps = { archived: boolean };
|
||||||
const BankCardFields: FC<BankCardFieldsProps> = (props) => {
|
const BankCardFields: FC<BankCardFieldsProps> = (props) => {
|
||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { bindIconAnimation } from "@/shared/lib";
|
import { bindIconAnimation } from "@/shared/lib";
|
||||||
import type { BankOperation } from "../api/queries";
|
import type { BankOperation } from "../../api/queries";
|
||||||
|
|
||||||
import { bankOperationAppearance } from "../model/operation-appearance";
|
import { bankOperationAppearance } from "../../model/operation-appearance";
|
||||||
import classes from "./BankOperationIcon.module.css";
|
import classes from "./BankOperationIcon.module.css";
|
||||||
|
|
||||||
type BankOperationIconProps = {
|
type BankOperationIconProps = {
|
||||||
+2
-2
@@ -3,8 +3,8 @@ import { LoadingSkeleton } from "@wealthledger/ui";
|
|||||||
import type { CSSProperties, FC } from "react";
|
import type { CSSProperties, FC } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { formatMoney } from "@/shared/lib";
|
import { formatMoney } from "@/shared/lib";
|
||||||
import type { BankSummary } from "../api/queries";
|
import type { BankSummary } from "../../api/queries";
|
||||||
import { BankOperationIcon } from "./BankOperationIcon";
|
import { BankOperationIcon } from "../BankOperationIcon/BankOperationIcon";
|
||||||
import classes from "./BankSummary.module.css";
|
import classes from "./BankSummary.module.css";
|
||||||
|
|
||||||
type BankSummaryViewProps = {
|
type BankSummaryViewProps = {
|
||||||
+6
-6
@@ -18,12 +18,12 @@ import {
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { validationMessage } from "@/shared/i18n";
|
import { validationMessage } from "@/shared/i18n";
|
||||||
import { useBankMutations } from "../api/mutations";
|
import { useBankMutations } from "../../api/mutations";
|
||||||
import { type ExpenseCategory, useBankCategories } from "../api/queries";
|
import { type ExpenseCategory, useBankCategories } from "../../api/queries";
|
||||||
import { BankFeedback } from "./BankFeedback";
|
import { BankFeedback } from "../BankFeedback";
|
||||||
import classes from "./BankForms.module.css";
|
import classes from "../BankForms.module.css";
|
||||||
import { BankOperationIcon } from "./BankOperationIcon";
|
import { BankOperationIcon } from "../BankOperationIcon/BankOperationIcon";
|
||||||
import { useBankFormFocus } from "./useBankFormFocus";
|
import { useBankFormFocus } from "../useBankFormFocus";
|
||||||
|
|
||||||
const MAX_CATEGORY_NAME_LENGTH = 80;
|
const MAX_CATEGORY_NAME_LENGTH = 80;
|
||||||
|
|
||||||
@@ -8,4 +8,4 @@ export {
|
|||||||
type BrokerageAccountCard,
|
type BrokerageAccountCard,
|
||||||
brokerageAccountCards,
|
brokerageAccountCards,
|
||||||
} from "./model/display";
|
} from "./model/display";
|
||||||
export { BrokerageAccountList } from "./ui/BrokerageAccountList";
|
export { BrokerageAccountList } from "./ui/BrokerageAccountList/BrokerageAccountList";
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||||
import { MemoryRouter } from "react-router";
|
import { MemoryRouter } from "react-router";
|
||||||
import type { BrokerageAccount } from "../api/useBrokerageAccounts";
|
import type { BrokerageAccount } from "../../api/useBrokerageAccounts";
|
||||||
import { brokerageAccountCards } from "../model/display";
|
import { brokerageAccountCards } from "../../model/display";
|
||||||
import { BrokerageAccountList } from "./BrokerageAccountList";
|
import { BrokerageAccountList } from "./BrokerageAccountList";
|
||||||
|
|
||||||
const syntheticAccount = {
|
const syntheticAccount = {
|
||||||
+1
-1
@@ -2,7 +2,7 @@ import { MantineProvider } from "@mantine/core";
|
|||||||
import { render, screen, within } from "@testing-library/react";
|
import { render, screen, within } from "@testing-library/react";
|
||||||
import { MemoryRouter } from "react-router";
|
import { MemoryRouter } from "react-router";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { brokerageAccountCards } from "../model/display";
|
import { brokerageAccountCards } from "../../model/display";
|
||||||
import { BrokerageAccountList } from "./BrokerageAccountList";
|
import { BrokerageAccountList } from "./BrokerageAccountList";
|
||||||
|
|
||||||
describe("BrokerageAccountList", () => {
|
describe("BrokerageAccountList", () => {
|
||||||
+2
-2
@@ -3,8 +3,8 @@ import type { FC } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import { formatDate, formatMoney } from "@/shared/lib";
|
import { formatDate, formatMoney } from "@/shared/lib";
|
||||||
import type { BrokerageAccountCard } from "../model/display";
|
import type { BrokerageAccountCard } from "../../model/display";
|
||||||
import { accountTypeKey } from "../model/display";
|
import { accountTypeKey } from "../../model/display";
|
||||||
import classes from "./BrokerageAccountList.module.css";
|
import classes from "./BrokerageAccountList.module.css";
|
||||||
|
|
||||||
type BrokerageAccountListProps = { accounts: BrokerageAccountCard[] };
|
type BrokerageAccountListProps = { accounts: BrokerageAccountCard[] };
|
||||||
@@ -6,4 +6,4 @@ export { BrokerageEventCard } from "./ui/BrokerageEventCard";
|
|||||||
export {
|
export {
|
||||||
BrokerageEventsPreview,
|
BrokerageEventsPreview,
|
||||||
type BrokerageEventsPreviewState,
|
type BrokerageEventsPreviewState,
|
||||||
} from "./ui/BrokerageEventsPreview";
|
} from "./ui/BrokerageEventsPreview/BrokerageEventsPreview";
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||||
import { MemoryRouter } from "react-router";
|
import { MemoryRouter } from "react-router";
|
||||||
import type { BrokerageEvent } from "../api/useBrokerageEvents";
|
import type { BrokerageEvent } from "../../api/useBrokerageEvents";
|
||||||
import { BrokerageEventsPreview } from "./BrokerageEventsPreview";
|
import { BrokerageEventsPreview } from "./BrokerageEventsPreview";
|
||||||
|
|
||||||
const syntheticEvent = {
|
const syntheticEvent = {
|
||||||
+2
-2
@@ -3,8 +3,8 @@ import { LoadingSkeleton } from "@wealthledger/ui";
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import type { BrokerageEvent } from "../api/useBrokerageEvents";
|
import type { BrokerageEvent } from "../../api/useBrokerageEvents";
|
||||||
import { BrokerageEventCard } from "./BrokerageEventCard";
|
import { BrokerageEventCard } from "../BrokerageEventCard";
|
||||||
|
|
||||||
type BrokerageEventsPreviewProps = {
|
type BrokerageEventsPreviewProps = {
|
||||||
events: BrokerageEventsPreviewState;
|
events: BrokerageEventsPreviewState;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export { AuthProvider, useAuth } from "./model/auth";
|
export { AuthProvider, useAuth } from "./model/auth";
|
||||||
export { AuthPageLayout } from "./ui/AuthPageLayout";
|
export { AuthPageLayout } from "./ui/AuthPageLayout/AuthPageLayout";
|
||||||
export { LoginForm } from "./ui/LoginForm";
|
export { LoginForm } from "./ui/LoginForm";
|
||||||
export { RegisterForm } from "./ui/RegisterForm";
|
export { RegisterForm } from "./ui/RegisterForm";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
type AuthFormValues,
|
type AuthFormValues,
|
||||||
loginSchema,
|
loginSchema,
|
||||||
registerSchema,
|
registerSchema,
|
||||||
} from "../model/validation";
|
} from "../../model/validation";
|
||||||
import classes from "./AuthForm.module.css";
|
import classes from "./AuthForm.module.css";
|
||||||
|
|
||||||
type AuthFormProps = {
|
type AuthFormProps = {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useLocation, useNavigate } from "react-router";
|
import { useLocation, useNavigate } from "react-router";
|
||||||
import { useAuth } from "../model/auth";
|
import { useAuth } from "../model/auth";
|
||||||
import { AuthForm } from "./AuthForm";
|
import { AuthForm } from "./AuthForm/AuthForm";
|
||||||
|
|
||||||
const LoginForm: FC = () => {
|
const LoginForm: FC = () => {
|
||||||
const { login } = useAuth();
|
const { login } = useAuth();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useLocation, useNavigate } from "react-router";
|
import { useLocation, useNavigate } from "react-router";
|
||||||
import { useAuth } from "../model/auth";
|
import { useAuth } from "../model/auth";
|
||||||
import { AuthForm } from "./AuthForm";
|
import { AuthForm } from "./AuthForm/AuthForm";
|
||||||
|
|
||||||
const RegisterForm: FC = () => {
|
const RegisterForm: FC = () => {
|
||||||
const { register } = useAuth();
|
const { register } = useAuth();
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { TbankConnectionSection } from "./ui/TbankConnectionSection";
|
export { TbankConnectionSection } from "./ui/TbankConnectionSection/TbankConnectionSection";
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import { useAuthenticatedQuery } from "@/shared/api";
|
import { useAuthenticatedQuery } from "@/shared/api";
|
||||||
import { tbankConnectionQueryOptions } from "../model/connection-boundary";
|
import { tbankConnectionQueryOptions } from "../../model/connection-boundary";
|
||||||
|
|
||||||
function useTbankConnectionViewModel() {
|
function useTbankConnectionViewModel() {
|
||||||
const status = useAuthenticatedQuery({
|
const status = useAuthenticatedQuery({
|
||||||
+1
-1
@@ -15,7 +15,7 @@ import { apiErrorCode, apiQueryClient } from "@/shared/api";
|
|||||||
import {
|
import {
|
||||||
commitTbankConnectionBoundary,
|
commitTbankConnectionBoundary,
|
||||||
type TbankConnectionStatus,
|
type TbankConnectionStatus,
|
||||||
} from "../model/connection-boundary";
|
} from "../../model/connection-boundary";
|
||||||
|
|
||||||
type TbankConnectionSectionLoadedProps = {
|
type TbankConnectionSectionLoadedProps = {
|
||||||
status: TbankConnectionStatus;
|
status: TbankConnectionStatus;
|
||||||
@@ -1 +1 @@
|
|||||||
export { AccountEventsPage } from "./ui/AccountEventsPage";
|
export { AccountEventsPage } from "./ui/AccountEventsPage/AccountEventsPage";
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { AccountIncomePage } from "./ui/AccountIncomePage";
|
export { AccountIncomePage } from "./ui/AccountIncomePage/AccountIncomePage";
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ import type { IncomeAnalytics } from "@/entities/income";
|
|||||||
import { configureAuthClient } from "@/shared/api";
|
import { configureAuthClient } from "@/shared/api";
|
||||||
import { createQueryWrapper } from "@/test/query";
|
import { createQueryWrapper } from "@/test/query";
|
||||||
import { server } from "@/test/server";
|
import { server } from "@/test/server";
|
||||||
import { isDate } from "../model/period";
|
import { isDate } from "../../model/period";
|
||||||
import { AccountIncomePage } from "./AccountIncomePage";
|
import { AccountIncomePage } from "./AccountIncomePage";
|
||||||
import { toIncomeDisplayModel } from "./AccountIncomePage.vm";
|
import { toIncomeDisplayModel } from "./AccountIncomePage.vm";
|
||||||
import { IncomePayments } from "./components/IncomePayments.view";
|
import { IncomePayments } from "./components/IncomePayments.view";
|
||||||
+1
-1
@@ -13,7 +13,7 @@ import {
|
|||||||
isDate,
|
isDate,
|
||||||
moscowDate,
|
moscowDate,
|
||||||
parseDraftDate,
|
parseDraftDate,
|
||||||
} from "../model/period";
|
} from "../../model/period";
|
||||||
|
|
||||||
const ISO_MONTH_LENGTH = 7;
|
const ISO_MONTH_LENGTH = 7;
|
||||||
|
|
||||||
+1
-1
@@ -15,7 +15,7 @@ import classes from "../AccountIncomePage.module.css";
|
|||||||
import type { AccountIncomePageViewModel } from "../AccountIncomePage.vm";
|
import type { AccountIncomePageViewModel } from "../AccountIncomePage.vm";
|
||||||
import { IncomeComparisons } from "./IncomeComparisons.view";
|
import { IncomeComparisons } from "./IncomeComparisons.view";
|
||||||
import { IncomePayments } from "./IncomePayments.view";
|
import { IncomePayments } from "./IncomePayments.view";
|
||||||
import { IncomePeriodForm } from "./IncomePeriodForm.view";
|
import { IncomePeriodForm } from "./IncomePeriodForm/IncomePeriodForm.view";
|
||||||
import { IncomeSummary } from "./IncomeSummary.view";
|
import { IncomeSummary } from "./IncomeSummary.view";
|
||||||
|
|
||||||
type LoadedProps = Extract<AccountIncomePageViewModel, { state: "loaded" }>;
|
type LoadedProps = Extract<AccountIncomePageViewModel, { state: "loaded" }>;
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { FormProvider, useForm, useFormState } from "react-hook-form";
|
import { FormProvider, useForm, useFormState } from "react-hook-form";
|
||||||
import type { IncomeForm } from "../../model/period";
|
import type { IncomeForm } from "../../../../model/period";
|
||||||
import { IncomePeriodForm } from "./IncomePeriodForm.view";
|
import { IncomePeriodForm } from "./IncomePeriodForm.view";
|
||||||
|
|
||||||
const period = { from: "01.08.2026", to: "27.08.2026" };
|
const period = { from: "01.08.2026", to: "27.08.2026" };
|
||||||
+2
-2
@@ -8,8 +8,8 @@ import {
|
|||||||
type IncomeForm,
|
type IncomeForm,
|
||||||
moscowDate,
|
moscowDate,
|
||||||
parseDraftDate,
|
parseDraftDate,
|
||||||
} from "../../model/period";
|
} from "../../../../model/period";
|
||||||
import classes from "../AccountIncomePage.module.css";
|
import classes from "../../AccountIncomePage.module.css";
|
||||||
|
|
||||||
type IncomePeriodFormProps = {
|
type IncomePeriodFormProps = {
|
||||||
onSubmit: FormEventHandler<HTMLFormElement>;
|
onSubmit: FormEventHandler<HTMLFormElement>;
|
||||||
@@ -1 +1 @@
|
|||||||
export { AccountOperationsPage } from "./ui/AccountOperationsPage";
|
export { AccountOperationsPage } from "./ui/AccountOperationsPage/AccountOperationsPage";
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user