From 0a1ae0552c13b6c929ebf34ece6b62f8efa84307 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Sat, 27 Jun 2026 13:07:06 +0300 Subject: [PATCH] feat(frontend): apply hero, card and toolbar HTML parity --- .../ui/BrokerDashboard.test.tsx | 26 +++++++- .../broker-dashboard/ui/BrokerDashboard.tsx | 4 -- .../ui/BrokerDashboardCard.tsx | 4 +- .../ui/BrokerDashboardDateFilter.tsx | 59 +++++++++++++------ .../ui/BrokerDashboardEventsCard.tsx | 16 ++++- .../ui/BrokerDashboardHero.tsx | 43 ++++++++++++-- .../ui/BrokerDashboardIncomeCard.tsx | 16 ++++- 7 files changed, 133 insertions(+), 35 deletions(-) diff --git a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx index 38f65c6..944d1ed 100644 --- a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx +++ b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx @@ -138,14 +138,14 @@ describe('BrokerDashboard', () => { }) }) - it('shows date filter toggle button with apply action', async () => { + it('shows date filter toggle button with apply action and accessible name', async () => { const user = userEvent.setup() renderWithProviders() const applyButtons = screen.getAllByRole('button', { name: /Применить период/ }) expect(applyButtons).toHaveLength(2) - const toggleButtons = screen.getAllByRole('button', { name: /📅/ }) + const toggleButtons = screen.getAllByRole('button', { name: /^Период/ }) expect(toggleButtons).toHaveLength(2) await user.click(toggleButtons[0]) @@ -158,6 +158,28 @@ describe('BrokerDashboard', () => { expect(screen.getByText('Сбросить')).toBeInTheDocument() }) + it('does not render a text chevron glyph inside the period toggle button', () => { + renderWithProviders() + + const toggleButtons = screen.getAllByRole('button', { name: /^Период/ }) + expect(toggleButtons).toHaveLength(2) + for (const button of toggleButtons) { + const text = button.textContent ?? '' + expect(text).not.toMatch(/[▼▲vV]/) + expect(button.querySelector('svg')).not.toBeNull() + } + }) + + it('renders hero "Всего доходов" with the ₽ symbol and no "RUB" code', () => { + renderWithProviders() + + expect(screen.getByText('Всего доходов')).toBeInTheDocument() + const hero = screen.getByLabelText('Ключевые показатели брокерского счёта') + const heroText = hero.textContent ?? '' + expect(heroText).toContain('₽') + expect(heroText).not.toContain('RUB') + }) + it('shows skeleton table while events are loading', () => { hookMocks.useBrokerEvents.mockReturnValue({ data: undefined, diff --git a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx index 8315dd2..ffcee25 100644 --- a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx +++ b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx @@ -123,7 +123,6 @@ export function BrokerDashboard({ to: draftEventFilters.to, preset: draftEventFilters.preset, })) - setEventFilterPanelOpen(false) setEventPage(1) }, [draftEventFilters.from, draftEventFilters.to, draftEventFilters.preset]) @@ -131,7 +130,6 @@ export function BrokerDashboard({ const defaults = defaultEventsFilters() setAppliedEventFilters(defaults) setDraftEventFilters(defaults) - setEventFilterPanelOpen(false) setEventPage(1) }, []) @@ -142,7 +140,6 @@ export function BrokerDashboard({ to: draftIncomeFilters.to, preset: draftIncomeFilters.preset, })) - setIncomeFilterPanelOpen(false) incomePagination.reset() }, [draftIncomeFilters.from, draftIncomeFilters.to, draftIncomeFilters.preset, incomePagination]) @@ -150,7 +147,6 @@ export function BrokerDashboard({ const defaults = defaultIncomeFilters() setAppliedIncomeFilters(defaults) setDraftIncomeFilters(defaults) - setIncomeFilterPanelOpen(false) incomePagination.reset() }, [incomePagination]) diff --git a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardCard.tsx b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardCard.tsx index b572c95..abd1a07 100644 --- a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardCard.tsx +++ b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardCard.tsx @@ -40,7 +40,9 @@ export function BrokerDashboardCard({ mb: 1.5, }} > - {title} + + {title} + {action} {filters && {filters}} diff --git a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardDateFilter.tsx b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardDateFilter.tsx index 08bd69a..6384840 100644 --- a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardDateFilter.tsx +++ b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardDateFilter.tsx @@ -1,4 +1,6 @@ import { Chip, Text } from '@moex-vibe/design-system' +import CalendarTodayRounded from '@mui/icons-material/CalendarTodayRounded' +import ExpandMoreRounded from '@mui/icons-material/ExpandMoreRounded' import { Box, Popover } from '@mui/material' import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs' import { DateCalendar } from '@mui/x-date-pickers/DateCalendar' @@ -88,6 +90,7 @@ export function BrokerDashboardDateFilter({ const selectingLabel = selectingStage === 'from' ? 'Выберите начало периода' : 'Выберите конец периода' + const periodAriaLabel = appliedLabel ? `Период: ${appliedLabel}` : 'Период' return ( @@ -96,30 +99,38 @@ export function BrokerDashboardDateFilter({ component="button" type="button" onClick={handleToggle} + aria-label={periodAriaLabel} + aria-expanded={isOpen} sx={{ display: 'inline-flex', alignItems: 'center', gap: 1, - bgcolor: 'grey.800', - color: 'common.white', - border: 'none', - borderRadius: 1.5, - px: 1.5, - py: 0.75, - fontSize: 13, + bgcolor: 'background.paper', + color: 'text.primary', + border: '1px solid', + borderColor: 'divider', + borderRadius: 1, + px: 1.25, + py: 0.5, + fontSize: 12, + fontWeight: 600, cursor: 'pointer', - '&:hover': { bgcolor: 'grey.700' }, + '&:hover': { borderColor: 'primary.main' }, }} > - 📅 + {appliedLabel && ( )} - {isOpen ? '▲' : '▼'} + Все события} filters={ - - + + {EVENT_FILTERS.map((filter) => ( + {percentValue(returnPercent)} + + } + supportingText={ + + За день: {formatBrokerMoney(portfolio.yields.daily)} + + } /> - + + {totalReceivedDisplay} + + } + /> ) diff --git a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardIncomeCard.tsx b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardIncomeCard.tsx index 606993e..6c32cae 100644 --- a/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardIncomeCard.tsx +++ b/apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardIncomeCard.tsx @@ -73,8 +73,20 @@ export function BrokerDashboardIncomeCard({ title="Доходы" action={Все операции} filters={ - - + + {INCOME_FILTERS.map((filter) => (