28 KiB
План реализации редизайна обзора брокерского счёта
Для агентных исполнителей: ОБЯЗАТЕЛЬНЫЙ SUB-SKILL: использовать
superpowers:subagent-driven-development(предпочтительно) илиsuperpowers:executing-plansдля пошагового выполнения. Шаги ведутся чекбоксами- [ ].
Цель: превратить /broker/:accountId в компактный инвестиционный дашборд на текущей светлой теме без изменения backend-контрактов и URL-структуры.
Архитектура: маршрут и FSD-границы остаются прежними. Композиция собирается в widgets/broker-dashboard, данные продолжают приходить из существующих entities/* hooks. Навигация счёта остаётся в BrokerAccountLayout, а dashboard использует только локальные presentation/helpers без выноса брокерской логики в design system.
Технологии: React 18, TanStack Router, TanStack Query, MUI через @moex-vibe/design-system, MUI X DateCalendar community (@mui/x-date-pickers) с Day.js, Vitest, Testing Library.
HTML parity update: согласованный визуальный эталон находится в docs/research/2026-06-27-broker-account-redesign.html.
Следующая итерация переносит его детали в реальную страницу без изменения backend-контрактов.
Область реализации
Файлы
- Modify:
apps/frontend/src/widgets/broker-account-layout/ui/BrokerAccountLayout.tsx— горизонтальные вкладки над контентом обзора и подробных разделов. - Modify:
apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx— точка входа обзора через dashboard. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/index.ts— публичный API dashboard-виджета. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx— верхнеуровневая композиция и управление filter state. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardHero.tsx— hero KPI с fallback-значениями и выравниваниемMetric. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardCard.tsx— локальный паттерн карточки. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardEventsCard.tsx— карточка событий. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardDateFilter.tsx— переиспользуемое управление периодом с draft/apply поведением. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardIncomeCard.tsx— карточка доходов. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardAnalyticsCard.tsx— карточка аналитики доходности. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardAllocationCard.tsx— карточка аллокации с горизонтальными барами. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardSkeleton.tsx— skeleton-форма dashboard. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx— компонентные тесты композиции и фильтров. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/lib/dashboardIncome.ts— чистые helpers доходных операций. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/lib/dashboardIncome.test.ts— unit-тесты income helpers. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/lib/dashboardFilters.ts— пресеты дат, validate и mapping income types. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/lib/dashboardFormatters.ts— локальные formatter/helpers для fallback и event labels. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/lib/dashboardVisual.ts— локальные helpers визуальной семантики dashboard: tone сумм, tone типов, отображение инструмента, символ валюты. - Create/Modify:
apps/frontend/src/widgets/broker-dashboard/lib/dashboardVisual.test.ts— unit-тесты визуальных helpers. - Modify:
apps/frontend/package.json— добавить community-пакет@mui/x-date-pickers, если зависимость ещё не подключена;@mui/x-date-pickers-proне добавлять. - Modify:
docs/features/broker-dashboard-redesign/tasks.md— фиксация статусов выполнения.
Источники данных
- Портфель:
useBrokerAccountContext().portfolio. - События:
useBrokerEvents(accountId, { from, to, types }). - Операции:
useBrokerOperations(accountId, { from, to, operationTypes, cursor, limit: 10 }). - Аналитика:
useBrokerAnalytics(accountId). - Аллокация:
buildBrokerAllocation(portfolio).
Технические решения
1. Композиция страницы
- Dashboard на desktop и mobile строится в одну колонку:
Hero,События,Доходы,Аналитика доходности,Аллокация. - Двухколоночный layout из прототипа не переносится.
- Навигация счёта находится над контентом в
BrokerAccountLayoutи не дублируется внутри dashboard.
2. Hero KPI
- Hero показывает название счёта, стоимость портфеля, доходность, дневное изменение и всего полученных доходов.
- Приоритет доходности:
analytics.totalReturnPercent, затемportfolio.yields.expectedPercent, иначе—. - Дневное изменение берётся из
portfolio.yields.dailyиportfolio.yields.dailyPercent, при недоступности показывается—. - Все
Metricдолжны иметь одинаковую высоту; supporting text не должен ломать вертикальный ритм.
3. События
- Типы событий переключаются chip-фильтрами с немедленным применением.
- Диапазон дат по умолчанию:
сегодня - 7 дней/сегодня + 7 дней, чтобы обзор сразу показывал ближайшие будущие события. - Диапазон дат редактируется отдельно от применённого состояния: draft state меняется локально, запрос уходит только по действию применения периода.
- В шапке управления периодом не используется слово
Фильтр; роль управления считывается через иконку календаря, применённый диапазон, раскрытие панели и пресеты. - Native
<input type="date">не используется; период выбирается через одно визуальное поле и popover с communityDateCalendarиз@mui/x-date-pickers. DateRangePickerи@mui/x-date-pickers-proне используются; выбор начала/конца периода реализуется локальной логикой dashboard.- При пустом выборе типов запрос отключается, карточка показывает валидационное сообщение.
- Пагинация локальная, по 10 событий на страницу, сбрасывается при смене применённых фильтров.
- При загрузке карточка показывает skeleton таблицы событий с колонками дата, инструмент, тип, сумма, статус.
- В toolbar карточки используются count badge, label
Тип, кнопкаОбновитьи footer-summary по паттерну HTML-эталона.
4. Доходы
- Доходы строятся на существующем endpoint операций только для
OPERATION_TYPE_DIVIDEND,OPERATION_TYPE_DIV_EXT,OPERATION_TYPE_COUPON. - Типы доходов переключаются chip-фильтрами с немедленным применением.
- Диапазон дат по умолчанию:
сегодня - 7 дней/сегодня, чтобы не загружать большой объём операций на первом открытии. - Диапазон дат использует тот же draft/apply паттерн, что и события.
- В шапке управления периодом не используется слово
Фильтр; действие применения периода не называетсяПоказать. - Native
<input type="date">не используется; период выбирается через одно визуальное поле и popover с communityDateCalendarиз@mui/x-date-pickers. DateRangePickerи@mui/x-date-pickers-proне используются; выбор начала/конца периода реализуется локальной логикой dashboard.- Пагинация cursor-based, размер страницы 10, сбрасывается при смене применённых фильтров.
- При загрузке карточка показывает skeleton таблицы доходов с колонками дата, инструмент, тип, сумма.
5. Аналитика и аллокация
- Карточка аналитики использует существующий analytics endpoint и показывает спокойное empty state при отсутствии данных.
- Карточка аллокации не использует donut chart. Она строит список горизонтальных bar rows по
buildBrokerAllocation. - Отрицательные значения показываются текстом без полосы.
6. Ошибки и пустые состояния
- Ошибка
portfolioроняет весь обзор. - Ошибки
events,income,analyticsлокальны соответствующим карточкам. - Пустые данные показываются отдельными сообщениями, а не нулевыми значениями.
7. HTML parity visual layer
- Реальная страница
/broker/:accountIdдолжна визуально соответствоватьdocs/research/2026-06-27-broker-account-redesign.html, но использовать существующие React-компоненты и FSD-границы. - Не менять backend и OpenAPI: блок
Доходыостаётся на текущем endpoint операций и текущем наборе income-типов. Отрицательный tone должен поддерживаться для строк, которые уже отображаются или будут отображаться без расширения контракта. - Ввести локальные helpers в
widgets/broker-dashboard/lib/dashboardVisual.ts:moneyTone(value, source?) -> 'positive' | 'negative' | 'planned' | 'neutral',eventTypeTone(type),incomeTypeTone(typeLabel),formatDashboardCurrency(moneyOrValue),instrumentDisplay({ ticker, name, description }). formatDashboardCurrencyдля RUB должен выводить₽. Для неизвестных валют использовать код валюты.instrumentDisplayдолжен возвращать основную строку и опциональную подпись: для событий приоритетticker/isinкак main иnameкак subtitle; для операций приоритетtickerкак main иname/descriptionкак subtitle. Если ticker отсутствует, main берётся из name/description, subtitle не дублируется.BrokerDashboardCardдолжен поддержать компактный заголовок карточки уровня HTML-прототипа, не используя крупныйHeading size="title".BrokerDashboardDateFilterдолжен использовать иконку раскрытия вместо текстового символа и сохранять единый toolbar-паттерн дляСобытияиДоходы.- Для
Событияperiod presets должны поддерживать будущую часть диапазона, а не обрезаться текущим днём. - Таблицы
СобытияиДоходыдолжны иметьthead, type badges, двухстрочный инструмент при наличии названия и semantic amount colors. BrokerDashboardAnalyticsCardдолжен окрашивать KPI-карточки по смыслу и показывать RUB через₽.- Skeleton таблиц событий и доходов должен использовать один компонент/паттерн и различаться только числом колонок.
Задачи
Задача 1: Базовые helpers и локальные dashboard-patterns
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/lib/dashboardIncome.ts -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardIncome.test.ts -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardFilters.ts -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardFormatters.ts -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardCard.tsx -
Убедиться, что income helpers покрывают только допустимые типы доходов и умеют считать итог отображаемых строк.
-
Убедиться, что filter helpers содержат default state, date presets, validate и mapping income type -> operation types.
-
Убедиться, что formatters покрывают fallback-значения, label типов событий и label статусов.
-
Использовать локальный
BrokerDashboardCardкак основной контейнер карточек; design system расширять только если без этого нельзя реализовать требования спецификации.
Задача 2: Hero и layout overview
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardHero.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardSkeleton.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx -
apps/frontend/src/pages/broker-account/ui/BrokerAccountOverviewPage.tsx -
apps/frontend/src/widgets/broker-account-layout/ui/BrokerAccountLayout.tsx -
Собрать обзор через
BrokerDashboardиBrokerDashboardSkeleton. -
Оставить навигацию счёта в
BrokerAccountLayoutкак горизонтальные вкладки над контентом. -
Исправить hero так, чтобы все
Metricбыли одной высоты и поддерживающий текст не поднимал одну ячейку выше остальных. -
Проверить, что dashboard остаётся одноколоночным и на desktop, и на mobile.
Задача 3: Карточка событий
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardDateFilter.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardEventsCard.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardFilters.ts -
apps/frontend/package.json -
Добавить или подтвердить зависимость community-пакета
@mui/x-date-pickersи использовать Day.js adapter. -
Не добавлять
@mui/x-date-pickers-proи не использоватьDateRangePicker. -
Обновить
BrokerDashboardDateFilter: убрать словоФильтриз пользовательского текста, заменитьПоказатьна понятное действие применения периода и визуально собрать chips, диапазон, сброс и применение в аккуратную шапку. -
Заменить native date inputs на одно визуальное поле периода, которое открывает MUI
Popoverс communityDateCalendar. -
Реализовать локальную логику выбора диапазона: первый клик задаёт начало, второй — конец; если конец раньше начала, диапазон пересобирается от выбранной даты.
-
Настроить default range событий на
сегодня - 7 дней/сегодня + 7 дней. -
Подключить для событий draft/applied state: типы применяются сразу, даты только по действию применения периода.
-
Сохранять локальную пагинацию по 10 событий и сбрасывать её при смене применённых фильтров.
-
Заменить текстовую загрузку событий на skeleton таблицы.
-
Оставить локальные error/empty states внутри карточки.
Задача 4: Карточка доходов
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardIncomeCard.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.tsx -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardFilters.ts -
Подключить тот же
BrokerDashboardDateFilterдля доходов с draft/applied state. -
Настроить default range доходов на
сегодня - 7 дней/сегоднявместо периода с начала года. -
Оставить chip-фильтры типов доходов с немедленным применением.
-
Сохранить cursor pagination по 10 операций и сбрасывать её при смене применённых фильтров.
-
Заменить текстовую загрузку доходов на skeleton таблицы.
-
Если endpoint операций даёт недостаточно релевантных строк для dashboard, зафиксировать ограничение в заметках по реализации, а не расширять backend в рамках этой фичи.
Задача 5: Карточки аналитики и аллокации
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardAnalyticsCard.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardAllocationCard.tsx -
Довести карточку аналитики до соответствия спецификации по полям и состояниям.
-
Заменить donut chart на горизонтальные бары, построенные из
buildBrokerAllocation. -
Отрицательные значения аллокации выводить отдельно текстом без bar.
Задача 6: Тесты и верификация
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx -
docs/features/broker-dashboard-redesign/tasks.md -
Обновить компонентные тесты dashboard так, чтобы они покрывали текущую композицию, фильтры и основные empty/error states.
-
Обновить тесты, которые ищут
Фильтр датилиПоказать, под новые тексты и accessible labels единого поля периода. -
Добавить/обновить тесты default weekly range для событий и доходов.
-
Добавить/обновить тесты skeleton-таблиц для loading state событий и доходов.
-
Прогнать
rtk npm run test:frontend -- --run src/widgets/broker-dashboard. -
Прогнать
rtk npm run test:frontend. -
Прогнать
rtk npm run test:design-system && rtk npm run lint -w apps/frontend && rtk npm run build:frontend. -
Проверить вручную desktop layout
/broker/2084014113. -
Проверить вручную mobile layout
/broker/2084014113на viewport390x844. -
После завершения обновить
docs/features/broker-dashboard-redesign/tasks.mdи выполнитьgraphify update ..
Задача 7: Visual helpers для HTML parity
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/lib/dashboardVisual.ts -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardVisual.test.ts -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardIncome.ts -
apps/frontend/src/widgets/broker-dashboard/lib/dashboardIncome.test.ts -
Добавить
moneyTone, который возвращаетnegativeдля отрицательных значений,positiveдля положительных фактических значений,plannedдля прогнозных/нефактических значений иneutralдля нуля/недоступного значения. -
Добавить
formatDashboardCurrency, который дляRUBвыводит₽, а для неизвестной валюты оставляет код валюты. -
Добавить
instrumentDisplayс приоритетами main/subtitle из технического решения 7. -
Добавить type tone helpers для event types и income labels.
-
Расширить
DashboardIncomeRow: хранитьinstrumentMainиinstrumentSubtitle, сохранив совместимость через существующийinstrumentтолько если это нужно текущим тестам. -
Покрыть helpers unit-тестами: RUB symbol, unknown currency fallback, negative/positive/planned tones, event/income type tones, отсутствие дублирования subtitle.
Задача 8: Hero, карточка и toolbar parity
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardHero.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardCard.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardDateFilter.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx -
Применить semantic color к hero: отрицательная доходность красная, положительная зелёная, дневное изменение окрашивается по знаку,
Всего доходовзелёный при значении больше нуля. -
Сделать заголовки dashboard-card компактными, соответствующими HTML-прототипу.
-
Собрать filters area карточек в единый toolbar: слева типы, справа поле периода и действие.
-
Заменить текстовую стрелку раскрытия периода на иконку: использовать уже подключённые
CalendarTodayRoundedиExpandMoreRoundedиз@mui/icons-material, без добавления новой icon dependency. -
Обновить component tests: проверять отсутствие текста
RUBдля RUB-значений, отсутствие символаvв period button и наличие accessible name у управления периодом.
Задача 9: Таблицы событий и доходов как в HTML
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardEventsCard.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardIncomeCard.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardTableSkeleton.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx -
Добавить
theadв обе dashboard-таблицы с колонками из спецификации. -
В колонке инструмента выводить main и subtitle из
instrumentDisplay. -
Заменить текстовые типы на компактные бейджи с tone из visual helpers.
-
Окрашивать суммы через
moneyTone: поступления зелёным, списания красным, прогноз/ожидание серым. -
Окрашивать статусные бейджи:
Поступилозелёный, прогноз/ожидание серый. -
Сохранить горизонтальный scroll только внутри таблицы на mobile, без общего page overflow.
-
Обновить skeleton так, чтобы
СобытияиДоходыиспользовали один визуальный паттерн строк. -
Обновить tests на наличие type badges, subtitle инструмента, semantic amount classes и skeleton.
Задача 10: Analytics parity и визуальная проверка
Файлы:
-
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboardAnalyticsCard.tsx -
apps/frontend/src/widgets/broker-dashboard/ui/BrokerDashboard.test.tsx -
docs/features/broker-dashboard-redesign/tasks.md -
Отображать RUB как
₽во всех analytics KPI. -
Окрашивать analytics cards: positive для пополнений/дивидендов/купонов/всего получено, negative для выводов и отрицательного нетто, neutral для нулевых/недоступных значений.
-
Обновить component tests для analytics:
₽вместоRUB, positive/negative tone cards. -
Прогнать
rtk npm run test:frontend -- --run src/widgets/broker-dashboard. -
Прогнать
rtk npm run test:frontend. -
Прогнать
rtk npm run lint -w apps/frontend && rtk npm run build:frontend. -
Проверить
/broker/2084014113вручную на desktop и mobile390x844противdocs/research/2026-06-27-broker-account-redesign.html. -
После проверки обновить
docs/features/broker-dashboard-redesign/tasks.md.
Проверка покрытия спецификации
- Общая композиция и горизонтальная навигация: задачи 2 и 6.
- Hero KPI и equal-height
Metric: задача 2. - События с chip filters, date filters и локальной пагинацией: задача 3.
- Доходы с chip filters, date filters и cursor pagination: задача 4.
- Community DateCalendar range control, weekly default range и skeleton loading tables: задачи 3, 4 и 6.
- Аналитика и аллокация с горизонтальными барами: задача 5.
- Ошибки, empty states, тесты и ручная верификация: задача 6.
- HTML parity: visual helpers — задача 7, hero/card/toolbar — задача 8, dashboard tables — задача 9, analytics — задача 10.