moex-vibe/docs/superpowers/specs/2026-06-14-portfolio-allocation-chart-design.md
Sergey Krylov 4c15bda30e
Some checks failed
CI / lint (pull_request) Successful in 1m54s
CI / test (pull_request) Successful in 1m51s
CI / build (pull_request) Failing after 1m51s
CI / lint (push) Successful in 1m54s
CI / test (push) Successful in 1m36s
CI / build (push) Failing after 1m54s
feat: add allocation donut chart to portfolio summary
2026-06-14 13:02:24 +03:00

3.1 KiB
Raw Blame History

Диаграмма распределения портфеля — Спецификация

Обзор

Добавить аналитическую диаграмму (donut) на страницу детального просмотра портфеля, показывающую распределение стоимости между акциями и облигациями, с количеством позиций в легенде.

Источник данных

PortfolioDetail.positions[] — бэкенд уже возвращает:

  • type: 'share' | 'bond'
  • currentValue: number | null
  • quantity: number

Агрегация на клиенте. Изменений бэкенда не требуется.

Компонент: AllocationChart

  • Чистый SVG (два сектора + текст в центре)
  • Без внешних зависимостей
  • Размещается внутри PortfolioSummary первым ребенком flex-ряда
  • В центре — общая стоимость портфеля (или «Нет позиций»)
  • Справа — легенда с разбивкой по типу: количество / процент

Цветовая схема

Сектор Цвет Легенда
Акции var(--color-primary) / #1976d2 Акции: N / XX.X%
Облигации #f57c00 Облигации: N / XX.X%

Состояния

  • Обычное (оба типа): две дуги пропорционально стоимости, в центре — сумма
  • Один тип (только акции или только облигации): полный круг цветом сектора
  • Пусто (нет позиций): серый круг, в центре «Нет позиций»

Расположение

┌────────────────────────────────────────────────────────┐
│  [⭕ donut]  Общая стоимость               Позиций      │
│  [xxx,xxx]   xxx,xxx.xx RUB                12          │
│  Акции: 8 / 70.5%                                      │
│  Облигации: 4 / 29.5%                                  │
└────────────────────────────────────────────────────────┘

Изменяемые файлы

Новый

  • apps/frontend/src/components/portfolios/AllocationChart.tsx

Изменяемый

  • apps/frontend/src/components/portfolios/PortfolioSummary.tsx — импорт и рендер AllocationChart

Граничные случаи

  • currentValue === null — считается как 0
  • У всех позиций currentValue === 0 — серый круг, в центре «0»
  • Один из типов отсутствует (0 позиций) — в легенде 0 / 0.0%, дуга заполняет 100% для непустого типа