refactor: align frontend ownership boundaries

Close audit gaps across API drift, query policy, UI, and tests.
This commit is contained in:
2026-09-06 18:20:05 +03:00
parent 175727bc93
commit c97f62bd98
118 changed files with 2190 additions and 2254 deletions
+16 -113
View File
@@ -1,141 +1,44 @@
import { Breadcrumbs } from "@mantine/core";
import type { FC } from "react";
import { useTranslation } from "react-i18next";
import { Link, useMatch } from "react-router";
import { useBrokerageAccounts } from "@/entities/brokerage-account";
type Crumb = { label: string; to?: string };
type BreadcrumbTrailProps = {
items: Crumb[];
};
type AccountBreadcrumbsProps = {
accountId: string;
events: boolean;
income: boolean;
operations: boolean;
};
const BreadcrumbTrail: FC<BreadcrumbTrailProps> = (props) => {
const { items } = props;
const { t } = useTranslation();
return (
<Breadcrumbs
aria-label={t("breadcrumbs.label")}
component="nav"
data-depth={items.length}
separator={<span aria-hidden="true">→</span>}
>
{items.map((item) =>
item.to ? (
<Link key={item.to} to={item.to}>
{item.label}
</Link>
) : (
<span aria-current="page" key={item.label}>
{item.label}
</span>
),
)}
</Breadcrumbs>
);
};
const AccountBreadcrumbs: FC<AccountBreadcrumbsProps> = (props) => {
const { accountId, events, income, operations } = props;
const { data: accounts } = useBrokerageAccounts();
const { t } = useTranslation();
const accountName =
accounts?.find((account) => account.id === accountId)?.name ??
t("breadcrumbs.accountFallback");
const accountPath = `/accounts/${accountId}`;
return (
<BreadcrumbTrail
items={
events
? [
{ label: t("breadcrumbs.accounts"), to: "/accounts" },
{ label: accountName, to: accountPath },
{ label: t("breadcrumbs.events") },
]
: operations
? [
{ label: t("breadcrumbs.accounts"), to: "/accounts" },
{ label: accountName, to: accountPath },
{ label: t("breadcrumbs.operations") },
]
: income
? [
{ label: t("breadcrumbs.accounts"), to: "/accounts" },
{ label: accountName, to: accountPath },
{ label: t("breadcrumbs.income") },
]
: [
{ label: t("breadcrumbs.accounts"), to: "/accounts" },
{ label: accountName },
]
}
/>
);
};
import { useMatch } from "react-router";
import { AccountBreadcrumbs } from "./AccountBreadcrumbs";
import { BreadcrumbTrail } from "./BreadcrumbTrail";
const AppBreadcrumbs: FC = () => {
const { t } = useTranslation();
const accountOperations = useMatch({
const operations = useMatch({
path: "/accounts/:accountId/operations",
end: true,
});
const accountEvents = useMatch({
path: "/accounts/:accountId/events",
end: true,
});
const accountIncome = useMatch({
path: "/accounts/:accountId/income",
end: true,
});
const events = useMatch({ path: "/accounts/:accountId/events", end: true });
const income = useMatch({ path: "/accounts/:accountId/income", end: true });
const account = useMatch({ path: "/accounts/:accountId", end: true });
const accounts = useMatch({ path: "/accounts", end: true });
const settings = useMatch({ path: "/settings", end: true });
if (accountOperations)
if (operations)
return (
<AccountBreadcrumbs
accountId={accountOperations.params.accountId ?? ""}
events={false}
income={false}
operations
accountId={operations.params.accountId ?? ""}
section="operations"
/>
);
if (accountEvents)
if (events)
return (
<AccountBreadcrumbs
accountId={accountEvents.params.accountId ?? ""}
events
income={false}
operations={false}
accountId={events.params.accountId ?? ""}
section="events"
/>
);
if (accountIncome)
if (income)
return (
<AccountBreadcrumbs
accountId={accountIncome.params.accountId ?? ""}
events={false}
income
operations={false}
accountId={income.params.accountId ?? ""}
section="income"
/>
);
if (account)
return (
<AccountBreadcrumbs
accountId={account.params.accountId ?? ""}
events={false}
income={false}
operations={false}
/>
);
return <AccountBreadcrumbs accountId={account.params.accountId ?? ""} />;
if (accounts)
return <BreadcrumbTrail items={[{ label: t("breadcrumbs.accounts") }]} />;
if (settings)