feat: integrate monthly chart with collapsible feature in transactions page; update transaction period to default to last 3 months

This commit is contained in:
Julien Froidefond
2025-12-21 07:31:29 +01:00
parent 53798176a0
commit aa2c656c00
5 changed files with 766 additions and 51 deletions

View File

@@ -1,8 +1,8 @@
"use client";
import { useCallback } from "react";
import { useCallback, useState } from "react";
import { PageLayout, PageHeader } from "@/components/layout";
import { RefreshCw } from "lucide-react";
import { RefreshCw, Maximize2, Minimize2 } from "lucide-react";
import {
TransactionFilters,
TransactionBulkActions,
@@ -13,15 +13,24 @@ import {
} from "@/components/transactions";
import { RuleCreateDialog } from "@/components/rules";
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 { Upload } from "lucide-react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { useTransactionsPage } from "@/hooks/use-transactions-page";
import { useTransactionMutations } from "@/hooks/use-transaction-mutations";
import { useTransactionRules } from "@/hooks/use-transaction-rules";
import { useTransactionsChartData } from "@/hooks/use-transactions-chart-data";
export default function TransactionsPage() {
const queryClient = useQueryClient();
const [isFullscreen, setIsFullscreen] = useState(false);
// Main page state and logic
const {
@@ -88,6 +97,17 @@ export default function TransactionsPage() {
metadata,
});
// Chart data
const { monthlyData, isLoading: isLoadingChart } = useTransactionsChartData({
selectedAccounts,
selectedCategories,
period,
customStartDate,
customEndDate,
showReconciled,
searchQuery,
});
const invalidateAll = useCallback(() => {
invalidateTransactions();
queryClient.invalidateQueries({ queryKey: ["banking-metadata"] });
@@ -98,7 +118,7 @@ export default function TransactionsPage() {
handleBulkReconcile(reconciled, selectedTransactions);
clearSelection();
},
[handleBulkReconcile, selectedTransactions, clearSelection],
[handleBulkReconcile, selectedTransactions, clearSelection]
);
const handleBulkSetCategoryWithClear = useCallback(
@@ -106,7 +126,7 @@ export default function TransactionsPage() {
handleBulkSetCategory(categoryId, selectedTransactions);
clearSelection();
},
[handleBulkSetCategory, selectedTransactions, clearSelection],
[handleBulkSetCategory, selectedTransactions, clearSelection]
);
const filteredTransactions = transactionsData?.transactions || [];
@@ -179,6 +199,21 @@ export default function TransactionsPage() {
transactionsForCategoryFilter={transactionsForCategoryFilter}
/>
{!isLoadingChart && monthlyData.length > 0 && (
<div className="mb-6">
<MonthlyChart
data={monthlyData}
formatCurrency={formatCurrency}
collapsible
defaultExpanded={true}
showDots={
period !== "all" &&
(period === "12months" || monthlyData.length <= 12)
}
/>
</div>
)}
<TransactionBulkActions
selectedCount={selectedTransactions.size}
categories={metadata.categories}
@@ -192,6 +227,19 @@ export default function TransactionsPage() {
</div>
) : (
<>
<div className="flex items-center justify-between mb-4">
<div className="flex-1" />
<Button
variant="outline"
size="sm"
onClick={() => setIsFullscreen(true)}
className="gap-2"
>
<Maximize2 className="w-4 h-4" />
Plein écran
</Button>
</div>
<TransactionTable
transactions={filteredTransactions}
accounts={metadata.accounts}
@@ -224,6 +272,74 @@ export default function TransactionsPage() {
</>
)}
<Dialog open={isFullscreen} onOpenChange={setIsFullscreen}>
<DialogContent
className="!max-w-none !max-h-none !w-full !h-full !p-0 flex flex-col !rounded-none !translate-x-0 !translate-y-0 !top-0 !left-0 !right-0 !bottom-0 !m-0"
showCloseButton={false}
style={{
width: "100vw",
height: "100vh",
maxWidth: "100vw",
maxHeight: "100vh",
}}
>
<DialogHeader className="px-6 pt-6 pb-4 border-b shrink-0">
<div className="flex items-center justify-between">
<DialogTitle>Transactions</DialogTitle>
<Button
variant="ghost"
size="sm"
onClick={() => setIsFullscreen(false)}
className="gap-2"
>
<Minimize2 className="w-4 h-4" />
Réduire
</Button>
</div>
</DialogHeader>
<div className="flex-1 overflow-auto px-6 pb-6 min-h-0">
<div className="mb-4">
<TransactionBulkActions
selectedCount={selectedTransactions.size}
categories={metadata.categories}
onReconcile={handleBulkReconcileWithClear}
onSetCategory={handleBulkSetCategoryWithClear}
/>
</div>
<TransactionTable
transactions={filteredTransactions}
accounts={metadata.accounts}
categories={metadata.categories}
selectedTransactions={selectedTransactions}
sortField={sortField}
sortOrder={sortOrder}
onSortChange={onSortChange}
onToggleSelectAll={onToggleSelectAll}
onToggleSelectTransaction={onToggleSelectTransaction}
onToggleReconciled={toggleReconciled}
onMarkReconciled={markReconciled}
onSetCategory={setCategory}
onCreateRule={handleCreateRule}
onDelete={deleteTransaction}
formatCurrency={formatCurrency}
formatDate={formatDate}
updatingTransactionIds={updatingTransactionIds}
duplicateIds={duplicateIds}
highlightDuplicates={showDuplicates}
/>
<div className="mt-4">
<TransactionPagination
page={page}
pageSize={pageSize}
total={totalTransactions}
hasMore={hasMore}
onPageChange={onPageChange}
/>
</div>
</div>
</DialogContent>
</Dialog>
<RuleCreateDialog
open={ruleDialogOpen}
onOpenChange={setRuleDialogOpen}