refactor(frontend): deduplicate analytics metric cells and restore text states

This commit is contained in:
Sergey Krylov 2026-06-27 13:52:37 +03:00
parent d7b65e256f
commit 58b8075583
2 changed files with 40 additions and 102 deletions

View File

@ -1,4 +1,4 @@
import { Metric } from '@moex-vibe/design-system'
import { Metric, Text } from '@moex-vibe/design-system'
import { Box } from '@mui/material'
import type { BrokerAnalytics } from '@/shared/api'
import {
@ -17,6 +17,19 @@ type AnalyticsField =
| 'totalCoupons'
| 'totalReceived'
const ANALYTICS_METRICS: readonly {
field: AnalyticsField
label: string
testId: string
}[] = [
{ field: 'totalDeposits', label: 'Пополнения', testId: 'dashboard-analytics-totalDeposits' },
{ field: 'totalWithdrawn', label: 'Выводы', testId: 'dashboard-analytics-totalWithdrawn' },
{ field: 'netInvested', label: 'Нетто', testId: 'dashboard-analytics-netInvested' },
{ field: 'totalDividends', label: 'Дивиденды', testId: 'dashboard-analytics-totalDividends' },
{ field: 'totalCoupons', label: 'Купоны', testId: 'dashboard-analytics-totalCoupons' },
{ field: 'totalReceived', label: 'Всего получено', testId: 'dashboard-analytics-totalReceived' },
]
function analyticsTone(field: AnalyticsField, value: number): MoneyTone {
if (field === 'totalWithdrawn') {
return value > 0 ? 'negative' : moneyTone(value)
@ -40,13 +53,13 @@ export function BrokerDashboardAnalyticsCard({
isError: boolean
}) {
return (
<BrokerDashboardCard title="Аналитика доходности" ariaLabel="Аналитика доходности">
<BrokerDashboardCard title="Аналитика доходности">
{isError ? (
<Metric label="Ошибка" value="Не удалось загрузить аналитику" />
<Text tone="negative">Не удалось загрузить аналитику</Text>
) : isLoading ? (
<Metric label="Загрузка" value="Загрузка аналитики…" />
<Text tone="muted">Загрузка аналитики</Text>
) : !data ? (
<Metric label="Нет данных" value="Нет данных для аналитики" />
<Text tone="muted">Нет данных для аналитики</Text>
) : (
<Box
sx={{
@ -55,102 +68,26 @@ export function BrokerDashboardAnalyticsCard({
gap: 2,
}}
>
<Metric
label="Пополнения"
value={
<Box
component="span"
data-testid="dashboard-analytics-totalDeposits"
data-tone={analyticsTone('totalDeposits', data.totalDeposits)}
sx={{
color: moneyToneToColor(analyticsTone('totalDeposits', data.totalDeposits)),
fontWeight: 700,
}}
>
{analyticsDisplay('totalDeposits', data.totalDeposits, data.currency)}
</Box>
}
/>
<Metric
label="Выводы"
value={
<Box
component="span"
data-testid="dashboard-analytics-totalWithdrawn"
data-tone={analyticsTone('totalWithdrawn', data.totalWithdrawn)}
sx={{
color: moneyToneToColor(analyticsTone('totalWithdrawn', data.totalWithdrawn)),
fontWeight: 700,
}}
>
{analyticsDisplay('totalWithdrawn', data.totalWithdrawn, data.currency)}
</Box>
}
/>
<Metric
label="Нетто"
value={
<Box
component="span"
data-testid="dashboard-analytics-netInvested"
data-tone={analyticsTone('netInvested', data.netInvested)}
sx={{
color: moneyToneToColor(analyticsTone('netInvested', data.netInvested)),
fontWeight: 700,
}}
>
{analyticsDisplay('netInvested', data.netInvested, data.currency)}
</Box>
}
/>
<Metric
label="Дивиденды"
value={
<Box
component="span"
data-testid="dashboard-analytics-totalDividends"
data-tone={analyticsTone('totalDividends', data.totalDividends)}
sx={{
color: moneyToneToColor(analyticsTone('totalDividends', data.totalDividends)),
fontWeight: 700,
}}
>
{analyticsDisplay('totalDividends', data.totalDividends, data.currency)}
</Box>
}
/>
<Metric
label="Купоны"
value={
<Box
component="span"
data-testid="dashboard-analytics-totalCoupons"
data-tone={analyticsTone('totalCoupons', data.totalCoupons)}
sx={{
color: moneyToneToColor(analyticsTone('totalCoupons', data.totalCoupons)),
fontWeight: 700,
}}
>
{analyticsDisplay('totalCoupons', data.totalCoupons, data.currency)}
</Box>
}
/>
<Metric
label="Всего получено"
value={
<Box
component="span"
data-testid="dashboard-analytics-totalReceived"
data-tone={analyticsTone('totalReceived', data.totalReceived)}
sx={{
color: moneyToneToColor(analyticsTone('totalReceived', data.totalReceived)),
fontWeight: 700,
}}
>
{analyticsDisplay('totalReceived', data.totalReceived, data.currency)}
</Box>
}
/>
{ANALYTICS_METRICS.map(({ field, label, testId }) => {
const value = data[field]
const tone = analyticsTone(field, value)
return (
<Metric
key={field}
label={label}
value={
<Box
component="span"
data-testid={testId}
data-tone={tone}
sx={{ color: moneyToneToColor(tone), fontWeight: 700 }}
>
{analyticsDisplay(field, value, data.currency)}
</Box>
}
/>
)
})}
</Box>
)}
</BrokerDashboardCard>

View File

@ -19,10 +19,11 @@ export function BrokerDashboardCard({
sx,
ariaLabel,
}: BrokerDashboardCardProps) {
const resolvedAriaLabel = ariaLabel ?? title
return (
<Box
component="section"
aria-label={ariaLabel}
aria-label={resolvedAriaLabel}
sx={{
border: '1px solid',
borderColor: 'divider',