refactor: enforce frontend view model boundaries
Frontend verify / commits (pull_request) Successful in 28s
Frontend verify / security (pull_request) Successful in 10s
Frontend verify / verify (pull_request) Successful in 8m19s

This commit is contained in:
2026-09-28 18:48:23 +03:00
parent 5b69003516
commit ca0ad4f824
287 changed files with 8558 additions and 4538 deletions
@@ -1,6 +1,7 @@
import type { FC } from "react";
import { Card, Group, SimpleGrid, Stack, Text } from "@mantine/core";
import { WalletIcon } from "@wealthledger/icons";
import { useTranslation } from "react-i18next";
import { Link } from "react-router";
@@ -40,13 +41,14 @@ const BrokerageAccountSummary: FC<BrokerageAccountSummaryProps> = (props) => {
{formatMoney(total)}
</Text>
))}
{!!(summary.remainingCurrencyCount) && ((
{!!summary.remainingCurrencyCount && (
<Text c="dimmed" size="sm">
{t("accounts.remainingCurrencies", {
count: summary.remainingCurrencyCount,
})}
</Text>
))}
)}
</Stack>
);
};
@@ -72,76 +74,78 @@ const BrokerageAccountList: FC<BrokerageAccountListProps> = (props) => {
<Text className={classes.kicker} fw={700} size="xs">
{t(accountTypeKey(account.type))}
</Text>
<svg
aria-hidden="true"
className={classes.accountIcon}
fill="none"
focusable="false"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
viewBox="0 0 24 24"
>
<rect height="15" rx="3" width="18" x="3" y="5" />
<path d="M3 9h18M7 15h3M14 5V3H7a4 4 0 0 0-4 4" />
</svg>
<WalletIcon className={classes.accountIcon} />
</Group>
<Text className={classes.name} component="h2" fw={700}>
{account.name}
</Text>
</Stack>
<Stack className={classes.balance} gap="xs">
<Text c="dimmed" size="sm">
{t("accounts.currentValue")}
</Text>
<BrokerageAccountSummary summary={summary} />
{!!(source?.lastSuccessfulAt) && ((
{!!source?.lastSuccessfulAt && (
<Text c="dimmed" size="xs">
{t("investment.sourceTime", {
date: formatSnapshotTime(source.lastSuccessfulAt),
})}
</Text>
))}
)}
{(source?.sync.state === "running"
|| source?.sync.state === "queued") && ((
|| source?.sync.state === "queued") && (
<Text role="status" size="xs">
{t("accounts.refreshing")}
</Text>
))}
{(source?.sync.state === "failed") && ((
)}
{source?.sync.state === "failed" && (
<Text size="xs">{t("accounts.refreshError")}</Text>
))}
{(source?.freshness === "stale") && ((
)}
{source?.freshness === "stale" && (
<Text size="xs">{t("investment.stale")}</Text>
))}
)}
</Stack>
{!!(positionCounts) && ((
{!!positionCounts && (
<dl className={classes.positions}>
<div className={classes.stocks}>
<dt>{t("accounts.stocks")}</dt>
<dd>
{new Intl.NumberFormat("ru-RU").format(positionCounts.stocks)}
</dd>
</div>
<div className={classes.bonds}>
<dt>{t("accounts.bonds")}</dt>
<dd>
{new Intl.NumberFormat("ru-RU").format(positionCounts.bonds)}
</dd>
</div>
</dl>
))}
)}
<Group className={classes.footer} gap="sm" justify="space-between">
{!!(account.openedOn) && ((
{!!account.openedOn && (
<Text c="dimmed" size="xs">
{t("accounts.openedOn", {
date: formatDate(account.openedOn),
})}
</Text>
))}
)}
<Text className={classes.open} component="span" fw={600} size="sm">
{t("accounts.openAccount")}
<span aria-hidden="true" className={classes.arrow}>
→
</span>