import { HorizontalBarChart } from "@/components/charts/HorizontalBarChart"; import { useMoney } from "@/hooks/useMoney"; import { cn } from "@/lib/utils"; import type { Category } from "@/lib/categories"; export interface CategoryDatum { name: Category; value: number; pct: number; } const getName = (d: CategoryDatum) => d.name; const getValue = (d: CategoryDatum) => d.value; /** * Spending by category as a sorted horizontal bar chart. * * Deliberately NOT the donut this app used to carry (which was never rendered * anywhere anyway). Two reasons: * - Part-to-whole across ~20 long-named categories is a bar chart's job; a pie * makes the reader compare angles and truncates its own labels. * - The donut assigned colors by `index % 6` AFTER sorting by value, so a * category's color changed whenever the ranking changed and repeated every * 7th slice. Bar length already encodes magnitude, so one hue is correct and * colour never lies about identity. */ export function SpendByCategoryChart({ data, onSelect, selected, }: { data: CategoryDatum[]; onSelect?: (category: Category) => void; selected?: Category | null; }) { const { money, compact } = useMoney(); if (data.length === 0) { return

No spending in this period.

; } return ( onSelect(d.name) : undefined} renderTooltip={(d) => ( <>

{d.name}

{money(d.value)} ยท {d.pct.toFixed(1)}% of spend

{onSelect &&

Click to see transactions

} )} /> ); } /** The same numbers as an accessible table, the chart's non-visual equivalent. */ export function SpendByCategoryTable({ data }: { data: CategoryDatum[] }) { const { money } = useMoney(); return ( {data.map((d) => ( ))}
Spending by category
Category Spent Share
{d.name} {money(d.value)} {d.pct.toFixed(1)}%
); }