"use client"; import { useState, useMemo } from "react"; import { PageLayout, LoadingState, PageHeader } from "@/components/layout"; import { StatsSummaryCards, MonthlyChart, CategoryPieChart, BalanceLineChart, TopExpensesList, } from "@/components/statistics"; import { useBankingData } from "@/lib/hooks"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; type Period = "3months" | "6months" | "12months" | "all"; export default function StatisticsPage() { const { data, isLoading } = useBankingData(); const [period, setPeriod] = useState("6months"); const [selectedAccount, setSelectedAccount] = useState("all"); const stats = useMemo(() => { if (!data) return null; const now = new Date(); let startDate: Date; switch (period) { case "3months": startDate = new Date(now.getFullYear(), now.getMonth() - 3, 1); break; case "6months": startDate = new Date(now.getFullYear(), now.getMonth() - 6, 1); break; case "12months": startDate = new Date(now.getFullYear(), now.getMonth() - 12, 1); break; default: startDate = new Date(0); } let transactions = data.transactions.filter( (t) => new Date(t.date) >= startDate ); if (selectedAccount !== "all") { transactions = transactions.filter( (t) => t.accountId === selectedAccount ); } // Monthly breakdown const monthlyData = new Map(); transactions.forEach((t) => { const monthKey = t.date.substring(0, 7); const current = monthlyData.get(monthKey) || { income: 0, expenses: 0 }; if (t.amount >= 0) { current.income += t.amount; } else { current.expenses += Math.abs(t.amount); } monthlyData.set(monthKey, current); }); const monthlyChartData = Array.from(monthlyData.entries()) .sort((a, b) => a[0].localeCompare(b[0])) .map(([month, values]) => ({ month: new Date(month + "-01").toLocaleDateString("fr-FR", { month: "short", year: "2-digit", }), revenus: Math.round(values.income), depenses: Math.round(values.expenses), solde: Math.round(values.income - values.expenses), })); // Category breakdown (expenses only) const categoryTotals = new Map(); transactions .filter((t) => t.amount < 0) .forEach((t) => { const catId = t.categoryId || "uncategorized"; const current = categoryTotals.get(catId) || 0; categoryTotals.set(catId, current + Math.abs(t.amount)); }); const categoryChartData = Array.from(categoryTotals.entries()) .map(([categoryId, total]) => { const category = data.categories.find((c) => c.id === categoryId); return { name: category?.name || "Non catégorisé", value: Math.round(total), color: category?.color || "#94a3b8", }; }) .sort((a, b) => b.value - a.value) .slice(0, 8); // Top expenses const topExpenses = transactions .filter((t) => t.amount < 0) .sort((a, b) => a.amount - b.amount) .slice(0, 5); // Summary const totalIncome = transactions .filter((t) => t.amount >= 0) .reduce((sum, t) => sum + t.amount, 0); const totalExpenses = transactions .filter((t) => t.amount < 0) .reduce((sum, t) => sum + Math.abs(t.amount), 0); const avgMonthlyExpenses = monthlyData.size > 0 ? totalExpenses / monthlyData.size : 0; // Balance evolution const sortedTransactions = [...transactions].sort( (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime() ); let runningBalance = 0; const balanceByDate = new Map(); sortedTransactions.forEach((t) => { runningBalance += t.amount; balanceByDate.set(t.date, runningBalance); }); const balanceChartData = Array.from(balanceByDate.entries()).map( ([date, balance]) => ({ date: new Date(date).toLocaleDateString("fr-FR", { day: "2-digit", month: "short", }), solde: Math.round(balance), }) ); return { monthlyChartData, categoryChartData, topExpenses, totalIncome, totalExpenses, avgMonthlyExpenses, balanceChartData, transactionCount: transactions.length, }; }, [data, period, selectedAccount]); const formatCurrency = (amount: number) => { return new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR", }).format(amount); }; if (isLoading || !data || !stats) { return ; } return ( } />
); }