feat: add account merging functionality with dialog support; update bulk actions to include merge option
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 1m39s

This commit is contained in:
Julien Froidefond
2025-12-20 11:42:42 +01:00
parent 376bc8f84e
commit 8b81dfe8c0
5 changed files with 367 additions and 2 deletions

View File

@@ -16,6 +16,7 @@ import { PageLayout, LoadingState, PageHeader } from "@/components/layout";
import {
AccountCard,
AccountEditDialog,
AccountMergeSelectDialog,
AccountBulkActions,
} from "@/components/accounts";
import { FolderEditDialog } from "@/components/folders";
@@ -112,6 +113,7 @@ export default function AccountsPage() {
});
const [activeId, setActiveId] = useState<string | null>(null);
const [isCompactView, setIsCompactView] = useState(false);
const [isMergeDialogOpen, setIsMergeDialogOpen] = useState(false);
const sensors = useSensors(
useSensor(PointerSensor, {
@@ -300,6 +302,43 @@ export default function AccountsPage() {
}
};
const handleMergeAccounts = async (
sourceAccountId: string,
targetAccountId: string,
) => {
try {
const response = await fetch("/api/banking/accounts/merge", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
sourceAccountId,
targetAccountId,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || "Failed to merge accounts");
}
const result = await response.json();
invalidateAllAccountQueries(queryClient);
// Réinitialiser la sélection
setSelectedAccounts(new Set());
// Afficher un message de succès
alert(
`Fusion réussie ! ${result.transactionCount} transactions déplacées vers le compte de destination.`,
);
} catch (error) {
console.error("Error merging accounts:", error);
throw error;
}
};
// Drag and drop handlers
const handleDragStart = (event: DragStartEvent) => {
setActiveId(event.active.id as string);
@@ -469,7 +508,13 @@ export default function AccountsPage() {
<>
<AccountBulkActions
selectedCount={selectedAccounts.size}
selectedAccountIds={Array.from(selectedAccounts)}
onDelete={handleBulkDelete}
onMerge={
selectedAccounts.size === 2
? () => setIsMergeDialogOpen(true)
: undefined
}
/>
<DndContext
sensors={sensors}
@@ -715,6 +760,21 @@ export default function AccountsPage() {
folders={metadata.folders}
onSave={handleSaveFolder}
/>
<AccountMergeSelectDialog
open={isMergeDialogOpen}
onOpenChange={(open) => {
setIsMergeDialogOpen(open);
if (!open) {
// Réinitialiser la sélection après fusion
setSelectedAccounts(new Set());
}
}}
accounts={accounts}
selectedAccountIds={Array.from(selectedAccounts)}
onMerge={handleMergeAccounts}
formatCurrency={formatCurrency}
/>
</PageLayout>
);
}