"use client"; import { RiPieChartLine } from "@remixicon/react"; import { useMemo } from "react"; import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts"; import { EmptyState } from "@/components/empty-state"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { currencyFormatter } from "@/lib/lancamentos/formatting-helpers"; import type { CategoryChartData } from "@/lib/relatorios/fetch-category-chart-data"; import { CATEGORY_COLORS } from "@/lib/utils/category-colors"; interface CategoryReportChartProps { data: CategoryChartData; } const CHART_COLORS = CATEGORY_COLORS; const MAX_CATEGORIES_IN_CHART = 15; export function CategoryReportChart({ data }: CategoryReportChartProps) { const { chartData, categories } = data; // Check if there's no data if (categories.length === 0 || chartData.length === 0) { return ( } mediaVariant="icon" /> ); } // Get top 10 categories by total spending const { topCategories, filteredChartData } = useMemo(() => { // Calculate total for each category across all periods const categoriesWithTotal = categories.map((category) => { const total = chartData.reduce((sum, dataPoint) => { const value = dataPoint[category.name]; return sum + (typeof value === "number" ? value : 0); }, 0); return { ...category, total }; }); // Sort by total (descending) and take top 10 const sorted = categoriesWithTotal .sort((a, b) => b.total - a.total) .slice(0, MAX_CATEGORIES_IN_CHART); // Filter chartData to include only top categories const _topCategoryNames = new Set(sorted.map((cat) => cat.name)); const filtered = chartData.map((dataPoint) => { const filteredPoint: { month: string; [key: string]: number | string } = { month: dataPoint.month, }; // Only include data for top categories for (const cat of sorted) { if (dataPoint[cat.name] !== undefined) { filteredPoint[cat.name] = dataPoint[cat.name]; } } return filteredPoint; }); return { topCategories: sorted, filteredChartData: filtered }; }, [categories, chartData]); return ( Evolução por Categoria - Top {topCategories.length}
{topCategories.map((category, index) => { const color = CHART_COLORS[index % CHART_COLORS.length]; return ( ); })} { if (value >= 1000) { return `${(value / 1000).toFixed(0)}k`; } return value.toString(); }} /> { if (!active || !payload || payload.length === 0) { return null; } return (
{payload[0]?.payload?.month}
{payload.map((entry, index) => { if (entry.dataKey === "month") return null; return (
{entry.name}
{currencyFormatter.format( Number(entry.value) || 0, )}
); })}
); }} /> {topCategories.map((category, index) => { const color = CHART_COLORS[index % CHART_COLORS.length]; return ( ); })}
{/* Legend */}
{topCategories.map((category, index) => { const color = CHART_COLORS[index % CHART_COLORS.length]; return (
{category.name}
); })}
); }