feat: add new categorized statistics card to dashboard with gradient styling and percentage display
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 1m27s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 1m27s
This commit is contained in:
@@ -594,4 +594,30 @@
|
|||||||
);
|
);
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stat-card-gradient-5 {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
color-mix(in srgb, var(--chart-5) 12%, var(--card)) 0%,
|
||||||
|
color-mix(in srgb, var(--chart-5) 8%, var(--card)) 50%,
|
||||||
|
color-mix(in srgb, var(--chart-5) 6%, var(--card)) 100%
|
||||||
|
);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card-gradient-5::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
right: -50%;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle,
|
||||||
|
color-mix(in srgb, var(--chart-5) 20%, transparent) 0%,
|
||||||
|
transparent 70%
|
||||||
|
);
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { TrendingUp, TrendingDown, Wallet, CreditCard } from "lucide-react";
|
import {
|
||||||
|
TrendingUp,
|
||||||
|
TrendingDown,
|
||||||
|
Wallet,
|
||||||
|
CreditCard,
|
||||||
|
Tag,
|
||||||
|
} from "lucide-react";
|
||||||
import type { BankingData } from "@/lib/types";
|
import type { BankingData } from "@/lib/types";
|
||||||
import { getAccountBalance } from "@/lib/account-utils";
|
import { getAccountBalance } from "@/lib/account-utils";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
@@ -37,6 +43,12 @@ export function OverviewCards({ data }: OverviewCardsProps) {
|
|||||||
const reconciledPercent =
|
const reconciledPercent =
|
||||||
total > 0 ? Math.round((reconciled / total) * 100) : 0;
|
total > 0 ? Math.round((reconciled / total) * 100) : 0;
|
||||||
|
|
||||||
|
const categorized = data.transactions.filter(
|
||||||
|
(t) => t.categoryId !== null
|
||||||
|
).length;
|
||||||
|
const categorizedPercent =
|
||||||
|
total > 0 ? Math.round((categorized / total) * 100) : 0;
|
||||||
|
|
||||||
const formatCurrency = (amount: number) => {
|
const formatCurrency = (amount: number) => {
|
||||||
return new Intl.NumberFormat("fr-FR", {
|
return new Intl.NumberFormat("fr-FR", {
|
||||||
style: "currency",
|
style: "currency",
|
||||||
@@ -45,7 +57,7 @@ export function OverviewCards({ data }: OverviewCardsProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid gap-4 sm:gap-6 grid-cols-2 lg:grid-cols-4">
|
<div className="grid gap-4 sm:gap-6 grid-cols-2 lg:grid-cols-5">
|
||||||
<Card className="stat-card-gradient-1 card-hover group relative overflow-hidden">
|
<Card className="stat-card-gradient-1 card-hover group relative overflow-hidden">
|
||||||
<CardHeader className="flex flex-row items-start justify-between space-y-0 pb-4 px-6 pt-6 sm:px-7 sm:pt-7 lg:px-5 lg:pt-5 relative z-10">
|
<CardHeader className="flex flex-row items-start justify-between space-y-0 pb-4 px-6 pt-6 sm:px-7 sm:pt-7 lg:px-5 lg:pt-5 relative z-10">
|
||||||
<CardTitle className="text-xs font-bold text-muted-foreground/70 leading-tight uppercase tracking-widest">
|
<CardTitle className="text-xs font-bold text-muted-foreground/70 leading-tight uppercase tracking-widest">
|
||||||
@@ -134,6 +146,25 @@ export function OverviewCards({ data }: OverviewCardsProps) {
|
|||||||
</p>
|
</p>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card className="stat-card-gradient-5 card-hover group relative overflow-hidden">
|
||||||
|
<CardHeader className="flex flex-row items-start justify-between space-y-0 pb-4 px-6 pt-6 sm:px-7 sm:pt-7 lg:px-5 lg:pt-5 relative z-10">
|
||||||
|
<CardTitle className="text-xs font-bold text-muted-foreground/70 leading-tight uppercase tracking-widest">
|
||||||
|
Catégorisation
|
||||||
|
</CardTitle>
|
||||||
|
<div className="rounded-2xl bg-gradient-to-br from-chart-5/30 via-chart-5/20 to-chart-5/10 p-3 shrink-0 shadow-lg shadow-chart-5/20">
|
||||||
|
<Tag className="h-5 w-5 text-chart-5" />
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="px-6 pb-6 sm:px-7 sm:pb-7 lg:px-5 lg:pb-5 pt-0 relative z-10">
|
||||||
|
<div className="text-2xl sm:text-3xl md:text-3xl lg:text-xl xl:text-xl font-black tracking-tight mb-4 leading-none break-words">
|
||||||
|
{categorizedPercent}%
|
||||||
|
</div>
|
||||||
|
<p className="text-xs sm:text-sm font-semibold text-muted-foreground/60">
|
||||||
|
{categorized} / {total} opérations catégorisées
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user