From a01345c1fbf6b5a8ce38b9a2354e1b30d9dd1989 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sun, 21 Dec 2025 08:26:01 +0100 Subject: [PATCH] feat: implement category breakdown by parent in dashboard; enhance chart data handling to include totals for parent categories --- components/dashboard/category-breakdown.tsx | 39 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/components/dashboard/category-breakdown.tsx b/components/dashboard/category-breakdown.tsx index c4df927..e8e2390 100644 --- a/components/dashboard/category-breakdown.tsx +++ b/components/dashboard/category-breakdown.tsx @@ -36,10 +36,43 @@ export function CategoryBreakdown({ data }: CategoryBreakdownProps) { value: total, color: category?.color || "#94a3b8", icon: category?.icon || "HelpCircle", + categoryId: categoryId === "uncategorized" ? null : categoryId, }; }) - .sort((a, b) => b.value - a.value) - .slice(0, 6); + .sort((a, b) => b.value - a.value); + + // Category breakdown grouped by parent + const categoryTotalsByParent = new Map(); + monthExpenses.forEach((t) => { + const category = data.categories.find((c) => c.id === t.categoryId); + // Use parent category ID if exists, otherwise use the category itself + let groupId: string; + if (!category) { + groupId = "uncategorized"; + } else if (category.parentId) { + groupId = category.parentId; + } else { + // Category is a parent itself + groupId = category.id; + } + const current = categoryTotalsByParent.get(groupId) || 0; + categoryTotalsByParent.set(groupId, current + Math.abs(t.amount)); + }); + + const chartDataByParent: CategoryChartData[] = Array.from( + categoryTotalsByParent.entries(), + ) + .map(([groupId, total]) => { + const category = data.categories.find((c) => c.id === groupId); + return { + name: category?.name || "Non catégorisé", + value: total, + color: category?.color || "#94a3b8", + icon: category?.icon || "HelpCircle", + categoryId: groupId === "uncategorized" ? null : groupId, + }; + }) + .sort((a, b) => b.value - a.value); const formatCurrency = (value: number) => { return new Intl.NumberFormat("fr-FR", { @@ -51,6 +84,8 @@ export function CategoryBreakdown({ data }: CategoryBreakdownProps) { return (