refactor: optimize TransactionsPage component by removing fullscreen functionality and stabilizing transactions reference with useMemo; clean up unused imports

This commit is contained in:
Julien Froidefond
2025-12-21 08:17:33 +01:00
parent dbcf8e7abd
commit b3e99a15d2
2 changed files with 19 additions and 110 deletions

View File

@@ -1,15 +1,8 @@
"use client";
import { useCallback, useState } from "react";
import { useCallback, useMemo } from "react";
import { PageLayout, PageHeader } from "@/components/layout";
import {
RefreshCw,
Maximize2,
Minimize2,
Receipt,
Euro,
ChevronDown,
} from "lucide-react";
import { RefreshCw, Receipt, Euro, ChevronDown } from "lucide-react";
import {
TransactionFilters,
TransactionBulkActions,
@@ -30,12 +23,6 @@ import {
CollapsibleTrigger,
} from "@/components/ui/collapsible";
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";
@@ -43,7 +30,6 @@ 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 {
@@ -147,7 +133,11 @@ export default function TransactionsPage() {
[handleBulkSetCategory, selectedTransactions, clearSelection]
);
const filteredTransactions = transactionsData?.transactions || [];
// Stabilize transactions reference to prevent unnecessary re-renders
const filteredTransactions = useMemo(
() => transactionsData?.transactions || [],
[transactionsData?.transactions]
);
const totalTransactions = transactionsData?.total || 0;
const hasMore = transactionsData?.hasMore || false;
const uncategorizedCount = transactionsData?.uncategorizedCount || 0;
@@ -310,19 +300,6 @@ 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}
@@ -355,74 +332,6 @@ 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}

View File

@@ -169,7 +169,7 @@ export function TransactionTable({
setFocusedIndex(index);
onMarkReconciled(transactionId);
},
[onMarkReconciled],
[onMarkReconciled]
);
const handleKeyDown = useCallback(
@@ -198,7 +198,7 @@ export function TransactionTable({
}
}
},
[focusedIndex, transactions, onMarkReconciled, virtualizer],
[focusedIndex, transactions, onMarkReconciled, virtualizer]
);
useEffect(() => {
@@ -215,7 +215,7 @@ export function TransactionTable({
(accountId: string) => {
return accounts.find((a) => a.id === accountId);
},
[accounts],
[accounts]
);
const getCategory = useCallback(
@@ -223,7 +223,7 @@ export function TransactionTable({
if (!categoryId) return null;
return categories.find((c) => c.id === categoryId);
},
[categories],
[categories]
);
return (
@@ -281,7 +281,7 @@ export function TransactionTable({
"p-4 space-y-3 hover:bg-muted/50 cursor-pointer border-b border-border",
transaction.isReconciled && "bg-emerald-500/5",
isFocused && "bg-primary/10 ring-1 ring-primary/30",
isDuplicate && "shadow-sm",
isDuplicate && "shadow-sm"
)}
>
<div className="flex items-start justify-between gap-2">
@@ -323,7 +323,7 @@ export function TransactionTable({
"font-semibold tabular-nums text-sm md:text-base shrink-0",
transaction.amount >= 0
? "text-emerald-600"
: "text-red-600",
: "text-red-600"
)}
>
{transaction.amount >= 0 ? "+" : ""}
@@ -358,7 +358,7 @@ export function TransactionTable({
showBadge
align="start"
disabled={updatingTransactionIds.has(
transaction.id,
transaction.id
)}
/>
</div>
@@ -391,7 +391,7 @@ export function TransactionTable({
e.stopPropagation();
if (
confirm(
`Êtes-vous sûr de vouloir supprimer cette transaction ?\n\n${transaction.description}\n${formatCurrency(transaction.amount)}`,
`Êtes-vous sûr de vouloir supprimer cette transaction ?\n\n${transaction.description}\n${formatCurrency(transaction.amount)}`
)
) {
onDelete(transaction.id);
@@ -464,7 +464,7 @@ export function TransactionTable({
<div className="p-3"></div>
</div>
</div>
{/* Body virtualisé */}
{/* Body virtualisé ou non selon le mode */}
<div
ref={parentRef}
className="overflow-auto"
@@ -507,7 +507,7 @@ export function TransactionTable({
"grid grid-cols-[auto_120px_2fr_150px_180px_140px_auto_auto] gap-0 border-b border-border hover:bg-muted/50 cursor-pointer",
transaction.isReconciled && "bg-emerald-500/5",
isFocused && "bg-primary/10 ring-1 ring-primary/30",
isDuplicate && "shadow-sm",
isDuplicate && "shadow-sm"
)}
>
<div className="p-3" onClick={(e) => e.stopPropagation()}>
@@ -576,7 +576,7 @@ export function TransactionTable({
"p-3 text-right font-semibold tabular-nums",
transaction.amount >= 0
? "text-emerald-600"
: "text-red-600",
: "text-red-600"
)}
>
{transaction.amount >= 0 ? "+" : ""}
@@ -643,7 +643,7 @@ export function TransactionTable({
e.stopPropagation();
if (
confirm(
`Êtes-vous sûr de vouloir supprimer cette transaction ?\n\n${transaction.description}\n${formatCurrency(transaction.amount)}`,
`Êtes-vous sûr de vouloir supprimer cette transaction ?\n\n${transaction.description}\n${formatCurrency(transaction.amount)}`
)
) {
onDelete(transaction.id);