Files
fintrack/components/statistics/category-bar-chart.tsx

119 lines
3.9 KiB
TypeScript

"use client";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { CategoryIcon } from "@/components/ui/category-icon";
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
Cell,
} from "recharts";
import type { CategoryChartData } from "./category-pie-chart";
interface CategoryBarChartProps {
data: CategoryChartData[];
formatCurrency: (amount: number) => string;
title?: string;
maxItems?: number;
}
export function CategoryBarChart({
data,
formatCurrency,
title = "Top catégories de dépenses",
maxItems = 10,
}: CategoryBarChartProps) {
const displayData = data.slice(0, maxItems).reverse(); // Reverse pour avoir le plus grand en haut
return (
<Card>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>
{displayData.length > 0 ? (
<div className="h-[400px]">
<ResponsiveContainer width="100%" height="100%">
<BarChart
data={displayData}
layout="vertical"
margin={{ left: 100, right: 20, top: 20, bottom: 20 }}
>
<CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
<XAxis
type="number"
className="text-xs"
tickFormatter={(v) => {
if (Math.abs(v) >= 1000) {
return `${(v / 1000).toFixed(1)}k€`;
}
return `${Math.round(v)}`;
}}
tick={{ fill: "var(--muted-foreground)" }}
/>
<YAxis
type="category"
dataKey="name"
className="text-xs"
width={90}
tick={{ fill: "var(--muted-foreground)" }}
tickFormatter={(value) => {
const item = displayData.find((d) => d.name === value);
return item ? value : "";
}}
/>
<Tooltip
content={({ active, payload }) => {
if (!active || !payload?.length) return null;
const item = payload[0].payload as CategoryChartData;
return (
<div
className="px-3 py-2 rounded-lg shadow-lg"
style={{
backgroundColor: "var(--card)",
border: "1px solid var(--border)",
}}
>
<div className="flex items-center gap-2 mb-1">
<CategoryIcon
icon={item.icon}
color={item.color}
size={16}
/>
<span
className="font-medium"
style={{ color: item.color }}
>
{item.name}
</span>
</div>
<div className="text-foreground font-semibold">
{formatCurrency(item.value)}
</div>
</div>
);
}}
/>
<Bar dataKey="value" radius={[4, 0, 0, 4]}>
{displayData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Bar>
</BarChart>
</ResponsiveContainer>
</div>
) : (
<div className="h-[400px] flex items-center justify-center text-muted-foreground">
Pas de données pour cette période
</div>
)}
</CardContent>
</Card>
);
}