codex/broker-dashboard-redesign #49

Merged
ksv741 merged 19 commits from codex/broker-dashboard-redesign into main 2026-06-27 16:55:04 +03:00
2 changed files with 40 additions and 102 deletions
Showing only changes of commit 58b8075583 - Show all commits

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

View File

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