feat: enhance transactions page with total amount and count display; integrate collapsible statistics card and update chart data handling

This commit is contained in:
Julien Froidefond
2025-12-21 07:35:35 +01:00
parent aa2c656c00
commit b4dace0673
2 changed files with 113 additions and 15 deletions

View File

@@ -2,7 +2,14 @@
import { useCallback, useState } from "react";
import { PageLayout, PageHeader } from "@/components/layout";
import { RefreshCw, Maximize2, Minimize2 } from "lucide-react";
import {
RefreshCw,
Maximize2,
Minimize2,
Receipt,
Euro,
ChevronDown,
} from "lucide-react";
import {
TransactionFilters,
TransactionBulkActions,
@@ -16,6 +23,12 @@ import { OFXImportDialog } from "@/components/import/ofx-import-dialog";
import { MonthlyChart } from "@/components/statistics";
import { useQueryClient } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { Upload } from "lucide-react";
import {
Dialog,
@@ -98,7 +111,12 @@ export default function TransactionsPage() {
});
// Chart data
const { monthlyData, isLoading: isLoadingChart } = useTransactionsChartData({
const {
monthlyData,
isLoading: isLoadingChart,
totalAmount: chartTotalAmount,
totalCount: chartTotalCount,
} = useTransactionsChartData({
selectedAccounts,
selectedCategories,
period,
@@ -138,6 +156,10 @@ export default function TransactionsPage() {
? Math.round((uncategorizedCount / totalTransactions) * 100)
: 0;
// Use total from chart data (all filtered transactions) or fallback to paginated data
const totalAmount = chartTotalAmount ?? 0;
const displayTotalCount = chartTotalCount ?? totalTransactions;
// For filter comboboxes, we'll use empty arrays for now
// They can be enhanced later with separate queries if needed
const transactionsForAccountFilter: never[] = [];
@@ -199,19 +221,80 @@ export default function TransactionsPage() {
transactionsForCategoryFilter={transactionsForCategoryFilter}
/>
{(!isLoadingChart || !isLoadingTransactions) && (
<Card className="mb-6">
<Collapsible defaultOpen={true}>
<CardHeader className="flex flex-row items-center justify-between space-y-0 py-3 px-6">
<CardTitle className="text-base font-semibold">
Statistiques
</CardTitle>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="sm" className="h-8">
<ChevronDown className="w-4 h-4 mr-1" />
Réduire
</Button>
</CollapsibleTrigger>
</CardHeader>
<CollapsibleContent>
<CardContent className="pt-0">
{/* Summary cards */}
{!isLoadingTransactions && (
<div className="grid gap-4 grid-cols-2 mb-6">
<Card>
<CardContent className="pt-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-muted-foreground">
Nombre de transactions
</p>
<p className="text-2xl font-bold mt-1">
{displayTotalCount}
</p>
</div>
<Receipt className="w-8 h-8 text-muted-foreground" />
</div>
</CardContent>
</Card>
<Card>
<CardContent className="pt-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-muted-foreground">
Total
</p>
<p
className={`text-2xl font-bold mt-1 ${
totalAmount >= 0
? "text-emerald-600"
: "text-red-600"
}`}
>
{formatCurrency(totalAmount)}
</p>
</div>
<Euro className="w-8 h-8 text-muted-foreground" />
</div>
</CardContent>
</Card>
</div>
)}
{/* Chart */}
{!isLoadingChart && monthlyData.length > 0 && (
<div className="mb-6">
<MonthlyChart
data={monthlyData}
formatCurrency={formatCurrency}
collapsible
defaultExpanded={true}
collapsible={false}
showDots={
period !== "all" &&
(period === "12months" || monthlyData.length <= 12)
}
/>
</div>
)}
</CardContent>
</CollapsibleContent>
</Collapsible>
</Card>
)}
<TransactionBulkActions

View File

@@ -191,10 +191,25 @@ export function useTransactionsChartData({
return categoryChartData;
}, [transactionsData, metadata]);
// Calculate total amount and count from all filtered transactions
const totalAmount = useMemo(() => {
if (!transactionsData) return 0;
return transactionsData.transactions.reduce(
(sum, t) => sum + t.amount,
0
);
}, [transactionsData]);
const totalCount = useMemo(() => {
return transactionsData?.total || 0;
}, [transactionsData?.total]);
return {
monthlyData,
categoryData,
isLoading,
totalAmount,
totalCount,
};
}