"use client"; import { useState, useMemo } from "react"; import { Sidebar } from "@/components/dashboard/sidebar"; import { useBankingData } from "@/lib/hooks"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { RefreshCw, TrendingUp, TrendingDown, ArrowRight } from "lucide-react"; import { CategoryIcon } from "@/components/ui/category-icon"; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell, LineChart, Line, Legend, } from "recharts"; import { cn } from "@/lib/utils"; 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]); if (isLoading || !data || !stats) { return (
); } const formatCurrency = (amount: number) => { return new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR", }).format(amount); }; return (

Statistiques

Analysez vos dépenses et revenus

{/* Summary Cards */}
Total Revenus
{formatCurrency(stats.totalIncome)}
Total Dépenses
{formatCurrency(stats.totalExpenses)}
Moyenne mensuelle
{formatCurrency(stats.avgMonthlyExpenses)}
Économies
= 0 ? "text-emerald-600" : "text-red-600", )} > {formatCurrency(stats.totalIncome - stats.totalExpenses)}
{/* Charts */}
{/* Monthly Income vs Expenses */} Revenus vs Dépenses par mois {stats.monthlyChartData.length > 0 ? (
`${v}€`} /> formatCurrency(value)} contentStyle={{ backgroundColor: "hsl(var(--card))", border: "1px solid hsl(var(--border))", borderRadius: "8px", }} />
) : (
Pas de données pour cette période
)}
{/* Category Breakdown */} Répartition par catégorie {stats.categoryChartData.length > 0 ? (
{stats.categoryChartData.map((entry, index) => ( ))} formatCurrency(value)} contentStyle={{ backgroundColor: "hsl(var(--card))", border: "1px solid hsl(var(--border))", borderRadius: "8px", }} /> ( {value} )} />
) : (
Pas de données pour cette période
)}
{/* Balance Evolution */} Évolution du solde {stats.balanceChartData.length > 0 ? (
`${v}€`} /> formatCurrency(value)} contentStyle={{ backgroundColor: "hsl(var(--card))", border: "1px solid hsl(var(--border))", borderRadius: "8px", }} />
) : (
Pas de données pour cette période
)}
{/* Top Expenses */} Top 5 dépenses {stats.topExpenses.length > 0 ? (
{stats.topExpenses.map((expense, index) => { const category = data.categories.find( (c) => c.id === expense.categoryId, ); return (
{index + 1}

{expense.description}

{new Date(expense.date).toLocaleDateString( "fr-FR", )} {category && ( {category.name} )}
{formatCurrency(expense.amount)}
); })}
) : (
Pas de dépenses pour cette période
)}
); }