partial (source-backed; Today/Projects integrations and runtime evidence remain open)

Spec: F65 — Recharts (Dashboard Charts & Visualizations)

Status: partial (source-backed; Today/Projects integrations and runtime evidence remain open)

1. Problem & CEO Job

See clearly (job 1) — Lumi needs compact trends and proportions without making the CEO read every list. Recharts wrappers provide the responsive, localized chart states and token-based palette needed by dashboard surfaces.

2. User Stories & Acceptance Criteria

  • As a CEO, when I open the Today dashboard, I want a visual summary of this week’s activity, so that I see trends without reading every item.

    • Given the Today page, a mini-chart shows task counts by status (open/in_progress/done) for the last 7 days (TodayPage.tsx: BarChart with taskStatusData, ChartCard wrapper)
    • Given the Today page, a mini-chart shows commitment/risk/decision counts (TodayPage.tsx: signalData BarChart in “Signals” ChartCard)
  • As a CEO, when I open the Deals page, I want a pipeline value chart, so that I see total deal value per stage at a glance.

    • Given the Deals page, a funnel/bar chart shows total value per stage (DealsPage.tsx: PipelineBarChart using analytics.by_stage)
  • As a CEO, when I open the Projects page, I want a project progress overview, so that I see which projects are on track vs stalled.

    • Given the Projects page, a small bar or donut chart shows project status distribution (ProjectsPage.tsx: BarChart with projectStatusData by active/paused/completed/archived, shown only when projects exist)

3. Scope Boundaries

  • In: Installation (recharts), <ChartCard> wrapper component (shadcn Card + Recharts chart), chart components on Today dashboard, Deals pipeline, Projects overview
  • Out: Interactive drill-down, real-time updating charts, complex multi-axis charts, export to image/PDF, chart builder/customizer

4. Data Model

n/a — charts consume existing API data. No new backend endpoints needed (aggregation is done client-side on already-fetched lists).

5. API Contract

n/a — existing endpoints return enough data.

6. UI / UX

  • Components: <ChartCard> in frontend/src/components/charts/ChartCard.tsx — wraps <Card> with a title, optional period selector, and a Recharts <ResponsiveContainer>
  • Chart types: <BarChart> (status counts), <PieChart> / <DonutChart> (proportions), <AreaChart> (trends over time)
  • Theming: Use CSS variable tokens from DESIGN.md — var(--color-chart-1) through var(--color-chart-5) for series colors. shadcn’s chart components already define these tokens. No hardcoded hex colors.
  • States:
    • Loading: <ChartSkeleton /> — animate-pulse rectangle at chart aspect ratio
    • Empty: <ChartEmpty /> — centered text “Chưa có dữ liệu” with icon
    • Error: <ChartError /> — toast + inline message “Không thể tải biểu đồ”
    • Populated: Responsive chart with hover tooltips
  • i18n: New charts namespace — charts.today_tasks, charts.deal_pipeline, charts.project_status, charts.vs_last_week, charts.no_data
  • Responsive: Charts stack vertically on mobile (<768px), show 2-column grid on desktop

7. Test Plan

#CaseTypeWhere
1ChartCard renders with datafrontendfrontend/src/test/ChartCard.test.tsx
2ChartCard shows empty statefrontendfrontend/src/test/ChartCard.test.tsx
3ChartCard shows error statefrontendfrontend/src/test/ChartCard.test.tsx
4Today dashboard shows chartse2elumi.spec.ts existing Today block
5Charts use design tokens (not hardcoded colors)frontendfrontend/src/test/ChartCard.test.tsx

8. Current Behavior

The shared chart source is present: ChartCard exposes loading/empty/error/populated states, reusable bar/line/pie widgets use responsive containers and chart tokens, and current integrations include the Deals pipeline, HQ analytics, Projects status distribution, and Today signal counts. The historical Today task series is not present in the current payload and remains an explicit gap. Browser and frontend runner evidence is also open.

9. Error States

  • No data: <ChartEmpty> with friendly message — not an error
  • Fetch failure: <ChartError> inline + toast — retry via TanStack Query refetch
  • Empty series: Recharts renders nothing gracefully (no crash)
  • Zero division (percentage): Check total > 0 before computing percentages

10. Diagrams & Docs Touched

  • frontend/DIAGRAMS.md §1 route tree — no new routes
  • TASTE.md — add chart rule (no hardcoded colors, use design tokens)
  • DESIGN.md — ensure --color-chart-* tokens are documented

11. Implementation Audit

#ClaimStatusEvidence
1ChartCard.tsx — shared wrapper with loading/empty/error states + ResponsiveContainer✅ matchfrontend/src/components/charts/ChartCard.tsx
2BarChartWidget.tsx — reusable bar chart accepting BarChartDataPoint[], --color-chart-* tokens✅ matchfrontend/src/components/charts/BarChartWidget.tsx
3LineChartWidget.tsx — reusable line/trend chart; color via --color-chart-1✅ matchfrontend/src/components/charts/LineChartWidget.tsx
4PieChartWidget.tsx — reusable pie/donut chart; innerRadius prop enables donut✅ matchfrontend/src/components/charts/PieChartWidget.tsx
5charts i18n namespace (no_data, error_load, task_status, deal_pipeline etc.) in en/ + vi/✅ matchfrontend/src/i18n/locales/en/charts.json + vi/charts.json
6Current Deals/HQ/Projects/Today-signal chart integrations✅ source matchDealsPage.tsx, HqAnalyticsPage.tsx, ProjectsPage.tsx, TodayPage.tsx
7Chart unit/source tests✅ source matchChartCard.test.tsx, charts.test.tsx, F65 convention tests; runtime collection remains open
8Today task/signal and Projects status chart integration⚠️ partialTodayPage.tsx now renders current signal counts and ProjectsPage.tsx renders status; Today still lacks an honest historical task series

12. Open Questions / Decisions

  • Client-side aggregation vs dedicated analytics endpoint? Decision: Client-side for v1. Recharts works with plain arrays, and Today/Deals pages already fetch all items. If a page fetches >500 items, add a backend aggregation endpoint.
  • Chart library alternative (Recharts vs Nivo vs visx)? Decision: Recharts — simplest API, shadcn has first-class support with --color-* tokens, same team ecosystem.

13. Bug / Change Log

2026-07-16 — Contract Graph audit

Added the Today signal-count chart from the existing list payload. The historical Today task series remains open because the current payload does not provide it.

2026-07-16 — Today chart progressive loading

The current signal-count chart remains available, but now follows the actionable Today queues and loads its Recharts renderer on viewport approach. This preserves the existing visualization without charging every cold Today visit for chart code before the CEO can act.