);
}
export function SpendingByCategoryCard({ items }: SpendingByCategoryCardProps) {
const { t } = useTranslation();
// The breakdown lives in a modal, not expanded inline โ a category with
// many subcategories (or many split purchases) would otherwise push this
// row taller than the fixed-height donut next to it, throwing the
// side-by-side layout out of alignment.
const [breakdownItem, setBreakdownItem] = useState(null);
const hasData = items.length > 0;
// Recharts needs a numeric dataKey โ API amounts arrive as strings (Decimal
// is serialized as string to avoid float precision loss).
const chartData = items.map((item) => ({ ...item, amount: Number(item.amount) }));
return (
{t("dashboard.spendingByCategoryTitle")}
{!hasData ? (
{translateCategoryName(item.name)}
{formatCurrency(item.amount)}
{/* Fixed-width slot on every row, populated or not โ a
chevron shown only on rows with children would shift
their amount left relative to every other row's. */}
{hasChildren && (
)}