From e2e8f9ce5e71eee576ff4fd040f7f9e030b324c5 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Mon, 28 Apr 2025 19:10:46 +0200 Subject: [PATCH] Can move entries between accounts --- .../src/dialogs/SelectAccountDialog.tsx | 2 +- .../ChooseAccountDialogProvider.tsx | 6 +- moneymgr_web/src/routes/AccountRoute.tsx | 57 ++++++++++++++++++- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/moneymgr_web/src/dialogs/SelectAccountDialog.tsx b/moneymgr_web/src/dialogs/SelectAccountDialog.tsx index cd2c1a8..c099dc9 100644 --- a/moneymgr_web/src/dialogs/SelectAccountDialog.tsx +++ b/moneymgr_web/src/dialogs/SelectAccountDialog.tsx @@ -23,7 +23,7 @@ export function SelectAccountDialog(p: { onClose: () => void; onSelected: (c: Account) => void; title: string; - description: string; + description: string | React.ReactElement; confirmButton?: string; excludedAccounts?: Account[]; }): React.ReactElement { diff --git a/moneymgr_web/src/hooks/context_providers/ChooseAccountDialogProvider.tsx b/moneymgr_web/src/hooks/context_providers/ChooseAccountDialogProvider.tsx index c88ac52..043c3c9 100644 --- a/moneymgr_web/src/hooks/context_providers/ChooseAccountDialogProvider.tsx +++ b/moneymgr_web/src/hooks/context_providers/ChooseAccountDialogProvider.tsx @@ -4,7 +4,7 @@ import { SelectAccountDialog } from "../../dialogs/SelectAccountDialog"; type DialogContext = ( title: string, - description: string, + description: string | React.ReactElement, confirmButton?: string, excludedAccounts?: Account[] ) => Promise; @@ -15,7 +15,9 @@ export function ChooseAccountDialogProvider( p: React.PropsWithChildren ): React.ReactElement { const [title, setTitle] = React.useState(""); - const [description, setDescription] = React.useState(""); + const [description, setDescription] = React.useState< + string | React.ReactElement + >(""); const [confirmButton, setConfirmButton] = React.useState< string | undefined >(); diff --git a/moneymgr_web/src/routes/AccountRoute.tsx b/moneymgr_web/src/routes/AccountRoute.tsx index dac2341..49dfdf0 100644 --- a/moneymgr_web/src/routes/AccountRoute.tsx +++ b/moneymgr_web/src/routes/AccountRoute.tsx @@ -108,7 +108,7 @@ function MovementsTable(p: { // Change account of movement const handleMoveClick = async (movement: Movement) => { const targetAccount = await chooseAccount( - "Transfer movementd", + "Transfer movement", `Please select the target account that will receive the movement: ${movement.label} (${movement.amount} €)`, "Transfer movement", [accounts.get(movement.account_id)!] @@ -152,6 +152,50 @@ function MovementsTable(p: { } }; + // Move multiple movements + const moveMultiple = async () => { + try { + const movements = p.movements.filter((m) => + rowSelectionModel.includes(m.id) + ); + + const targetAccount = await chooseAccount( + "Transfer movements", + <> + Please select the target account that will receive the selected + movements: + + , + "Transfer movement", + [accounts.get(movements[0].account_id)!] + ); + + if (!targetAccount) return; + + for (const [num, m] of movements.entries()) { + loadingMessage.show(`Moveing movement ${num}/${movements.length}`); + + m.account_id = targetAccount.id; + await MovementApi.Update(m); + } + + snackbar("The movements have been successfully moved!"); + + p.needReload(false); + } catch (e) { + console.error("Failed to delete multiple movements!", e); + alert(`Failed to delete multiple movements! ${e}`); + } finally { + loadingMessage.hide(); + } + }; + // Delete multiple movements const deleteMultiple = async () => { try { @@ -274,6 +318,17 @@ function MovementsTable(p: { return ( <>
+ + + + +