Files
fintrack/components/dashboard/overview-cards.tsx
Julien Froidefond e9e44916fd chore: init from v0
2025-11-27 09:51:18 +01:00

97 lines
3.8 KiB
TypeScript

"use client"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { TrendingUp, TrendingDown, Wallet, CreditCard } from "lucide-react"
import type { BankingData } from "@/lib/types"
interface OverviewCardsProps {
data: BankingData
}
export function OverviewCards({ data }: OverviewCardsProps) {
const totalBalance = data.accounts.reduce((sum, acc) => sum + acc.balance, 0)
const thisMonth = new Date()
thisMonth.setDate(1)
const thisMonthStr = thisMonth.toISOString().slice(0, 7)
const monthTransactions = data.transactions.filter((t) => t.date.startsWith(thisMonthStr))
const income = monthTransactions.filter((t) => t.amount > 0).reduce((sum, t) => sum + t.amount, 0)
const expenses = monthTransactions.filter((t) => t.amount < 0).reduce((sum, t) => sum + Math.abs(t.amount), 0)
const reconciled = data.transactions.filter((t) => t.isReconciled).length
const total = data.transactions.length
const reconciledPercent = total > 0 ? Math.round((reconciled / total) * 100) : 0
const formatCurrency = (amount: number) => {
return new Intl.NumberFormat("fr-FR", {
style: "currency",
currency: "EUR",
}).format(amount)
}
return (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Solde Total</CardTitle>
<Wallet className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className={cn("text-2xl font-bold", totalBalance >= 0 ? "text-emerald-600" : "text-red-600")}>
{formatCurrency(totalBalance)}
</div>
<p className="text-xs text-muted-foreground mt-1">
{data.accounts.length} compte{data.accounts.length > 1 ? "s" : ""}
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Revenus du mois</CardTitle>
<TrendingUp className="h-4 w-4 text-emerald-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-emerald-600">{formatCurrency(income)}</div>
<p className="text-xs text-muted-foreground mt-1">
{monthTransactions.filter((t) => t.amount > 0).length} opération
{monthTransactions.filter((t) => t.amount > 0).length > 1 ? "s" : ""}
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Dépenses du mois</CardTitle>
<TrendingDown className="h-4 w-4 text-red-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-red-600">{formatCurrency(expenses)}</div>
<p className="text-xs text-muted-foreground mt-1">
{monthTransactions.filter((t) => t.amount < 0).length} opération
{monthTransactions.filter((t) => t.amount < 0).length > 1 ? "s" : ""}
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Pointage</CardTitle>
<CreditCard className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{reconciledPercent}%</div>
<p className="text-xs text-muted-foreground mt-1">
{reconciled} / {total} opérations pointées
</p>
</CardContent>
</Card>
</div>
)
}
import { cn } from "@/lib/utils"