fix: separate portfolio cash presentation
This commit is contained in:
@@ -12,10 +12,9 @@ import type {
|
||||
AccountPageRecentOperations,
|
||||
} from "../AccountPage.vm";
|
||||
import { AccountHeading } from "./AccountHeading.view";
|
||||
import { CashBalances } from "./CashBalances.view";
|
||||
import { CurrencyCards } from "./CurrencyCards.view";
|
||||
import { IncomeSummary } from "./IncomeSummary.view";
|
||||
import { PortfolioRefreshState } from "./PortfolioRefreshState.view";
|
||||
import { PortfolioTotals } from "./PortfolioTotals.view";
|
||||
import { PositionSection } from "./PositionSection.view";
|
||||
import { RecentEvents } from "./RecentEvents.view";
|
||||
import { RecentOperations } from "./RecentOperations.view";
|
||||
@@ -50,7 +49,7 @@ const AccountPageLoaded: FC<AccountPageLoadedProps> = (props) => {
|
||||
date: formatSnapshotTime(props.portfolio.lastSuccessfulAt),
|
||||
})}
|
||||
</Text>
|
||||
<PortfolioTotals totals={props.portfolio.totalsByCurrency} />
|
||||
<CurrencyCards amounts={props.portfolio.totalsByCurrency} />
|
||||
<Accordion
|
||||
multiple
|
||||
defaultValue={[
|
||||
@@ -80,7 +79,7 @@ const AccountPageLoaded: FC<AccountPageLoadedProps> = (props) => {
|
||||
<Accordion.Item value="cash">
|
||||
<Accordion.Control>{t("portfolio.cashBalances")}</Accordion.Control>
|
||||
<Accordion.Panel>
|
||||
<CashBalances balances={props.portfolio.cashBalances} />
|
||||
<CurrencyCards amounts={props.portfolio.cashBalances} />
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item value="recentOperations">
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Paper, Text } from "@mantine/core";
|
||||
import type { FC } from "react";
|
||||
import type { Portfolio } from "@/entities/portfolio";
|
||||
import { formatMoney } from "@/shared/lib";
|
||||
import classes from "../AccountPage.module.css";
|
||||
|
||||
type CashBalancesProps = {
|
||||
balances: Portfolio["cashBalances"];
|
||||
};
|
||||
|
||||
const CashBalances: FC<CashBalancesProps> = (props) => {
|
||||
const { balances } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
{balances.map((balance) => (
|
||||
<Paper className={classes.cash} key={balance.currency} withBorder>
|
||||
<Text>{balance.currency}</Text>
|
||||
<Text fw={700}>{formatMoney(balance)}</Text>
|
||||
</Paper>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { CashBalances };
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
import { MantineProvider } from "@mantine/core";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { PortfolioTotals } from "./PortfolioTotals.view";
|
||||
import { CurrencyCards } from "./CurrencyCards.view";
|
||||
|
||||
describe("PortfolioTotals currency presentation", () => {
|
||||
describe("CurrencyCards currency presentation", () => {
|
||||
it.each([0, 1, 3, 5])(
|
||||
"renders only the %i supplied totals in upstream order",
|
||||
(count) => {
|
||||
@@ -16,7 +16,7 @@ describe("PortfolioTotals currency presentation", () => {
|
||||
].slice(0, count);
|
||||
const { container } = render(
|
||||
<MantineProvider>
|
||||
<PortfolioTotals totals={totals} />
|
||||
<CurrencyCards amounts={totals} />
|
||||
</MantineProvider>,
|
||||
);
|
||||
expect(
|
||||
@@ -52,7 +52,7 @@ describe("PortfolioTotals currency presentation", () => {
|
||||
(currency, value, expected, name, symbol) => {
|
||||
render(
|
||||
<MantineProvider>
|
||||
<PortfolioTotals totals={[{ currency, value }]} />
|
||||
<CurrencyCards amounts={[{ currency, value }]} />
|
||||
</MantineProvider>,
|
||||
);
|
||||
const term = screen.getByRole("term");
|
||||
@@ -70,8 +70,8 @@ describe("PortfolioTotals currency presentation", () => {
|
||||
it("keeps USD and CAD as distinct supplied values", () => {
|
||||
render(
|
||||
<MantineProvider>
|
||||
<PortfolioTotals
|
||||
totals={[
|
||||
<CurrencyCards
|
||||
amounts={[
|
||||
{ currency: "USD", value: "1.00" },
|
||||
{ currency: "CAD", value: "2.00" },
|
||||
]}
|
||||
+11
-11
@@ -5,12 +5,12 @@ import type { Portfolio } from "@/entities/portfolio";
|
||||
import { formatDecimal } from "@/shared/lib";
|
||||
import classes from "../AccountPage.module.css";
|
||||
|
||||
type PortfolioTotalsProps = {
|
||||
totals: Portfolio["totalsByCurrency"];
|
||||
type CurrencyCardsProps = {
|
||||
amounts: Portfolio["totalsByCurrency"];
|
||||
};
|
||||
|
||||
const PortfolioTotals: FC<PortfolioTotalsProps> = (props) => {
|
||||
const { totals } = props;
|
||||
const CurrencyCards: FC<CurrencyCardsProps> = (props) => {
|
||||
const { amounts } = props;
|
||||
const { t } = useTranslation();
|
||||
const currencies: Record<string, { symbol: string; name: string }> = {
|
||||
RUB: { symbol: "₽", name: t("portfolio.currencies.RUB") },
|
||||
@@ -20,22 +20,22 @@ const PortfolioTotals: FC<PortfolioTotalsProps> = (props) => {
|
||||
|
||||
return (
|
||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing={10}>
|
||||
{totals.map((total) => {
|
||||
const amount = formatDecimal(total.value);
|
||||
{amounts.map((money) => {
|
||||
const amount = formatDecimal(money.value);
|
||||
return (
|
||||
<Paper
|
||||
component="dl"
|
||||
m={0}
|
||||
className={classes.total}
|
||||
key={total.currency}
|
||||
key={money.currency}
|
||||
withBorder
|
||||
>
|
||||
<Text component="dt" className={classes.totalBadge}>
|
||||
<span aria-hidden="true">
|
||||
{currencies[total.currency]?.symbol ?? total.currency}
|
||||
{currencies[money.currency]?.symbol ?? money.currency}
|
||||
</span>
|
||||
<VisuallyHidden>
|
||||
{currencies[total.currency]?.name ?? total.currency}
|
||||
{currencies[money.currency]?.name ?? money.currency}
|
||||
</VisuallyHidden>
|
||||
</Text>
|
||||
<Text component="dd" m={0} className={classes.totalAmount}>
|
||||
@@ -49,7 +49,7 @@ const PortfolioTotals: FC<PortfolioTotalsProps> = (props) => {
|
||||
) : (
|
||||
amount
|
||||
)}{" "}
|
||||
{currencies[total.currency]?.symbol ?? total.currency}
|
||||
{currencies[money.currency]?.symbol ?? money.currency}
|
||||
</Text>
|
||||
</Paper>
|
||||
);
|
||||
@@ -58,4 +58,4 @@ const PortfolioTotals: FC<PortfolioTotalsProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export { PortfolioTotals };
|
||||
export { CurrencyCards };
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Stack } from "@mantine/core";
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { fn } from "storybook/test";
|
||||
import { CurrencyCards } from "./CurrencyCards.view";
|
||||
import { PortfolioRefreshState } from "./PortfolioRefreshState.view";
|
||||
import { PortfolioTotals } from "./PortfolioTotals.view";
|
||||
|
||||
const meta = {
|
||||
title: "Product/PortfolioRefreshState",
|
||||
@@ -18,14 +18,14 @@ const meta = {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"Обновление уже показанных данных портфеля. Реальные PortfolioTotals остаются видимыми вместе с PortfolioRefreshState при refetch и его ошибке. Суммы синтетические; это presentation Client Cached Snapshot, без QueryClient и запроса API. Retry регистрирует локальное действие в Actions и не доказывает восстановление API.",
|
||||
"Обновление уже показанных данных портфеля. Реальные CurrencyCards остаются видимыми вместе с PortfolioRefreshState при refetch и его ошибке. Суммы синтетические; это presentation Client Cached Snapshot, без QueryClient и запроса API. Retry регистрирует локальное действие в Actions и не доказывает восстановление API.",
|
||||
},
|
||||
},
|
||||
},
|
||||
render: (args) => (
|
||||
<Stack>
|
||||
<PortfolioTotals
|
||||
totals={[
|
||||
<CurrencyCards
|
||||
amounts={[
|
||||
{ currency: "RUB", value: "125000.50" },
|
||||
{ currency: "USD", value: "320" },
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user