Start to build attach multiple entries dialog

This commit is contained in:
Pierre HUBERT 2025-05-14 21:57:39 +02:00
parent cc512e648c
commit 91e5d8af31
3 changed files with 108 additions and 1 deletions

View File

@ -0,0 +1,31 @@
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
} from "@mui/material";
import { InboxEntry } from "../api/InboxApi";
import { Movement } from "../api/MovementsApi";
export function AttachMultipleInboxEntriesDialog(p: {
open: boolean;
entries: InboxEntry[];
movements: Movement[][];
onClose: () => void;
onSelected: (mapping: Array<number | undefined>) => void;
}): React.ReactElement {
const handleSubmit = () => {};
return (
<Dialog open={p.open} onClose={p.onClose}>
<DialogTitle>Attach multiple entries to movements</DialogTitle>
<DialogContent>TODO</DialogContent>
<DialogActions>
<Button onClick={p.onClose}>Cancel</Button>
<Button onClick={handleSubmit} autoFocus>
Perform mapping
</Button>
</DialogActions>
</Dialog>
);
}

View File

@ -29,7 +29,9 @@ export function SelectAccountDialog(p: {
}): React.ReactElement {
const accounts = useAccounts();
const [choice, setChoice] = React.useState<Account | null>(null);
const [choice, setChoice] = React.useState<Account | null>(
accounts.list.default
);
const submit = () => {
if (choice) p.onSelected(choice);

View File

@ -24,7 +24,9 @@ import React from "react";
import { InboxApi, InboxEntry } from "../api/InboxApi";
import { Movement, MovementApi } from "../api/MovementsApi";
import { AttachInboxEntryToMovementDialog } from "../dialogs/AttachInboxEntryToMovementDialog";
import { AttachMultipleInboxEntriesDialog } from "../dialogs/AttachMultipleInboxEntriesDialog";
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
import { useSelectAccount } from "../hooks/context_providers/ChooseAccountDialogProvider";
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
import { useLoadingMessage } from "../hooks/context_providers/LoadingMessageProvider";
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
@ -120,6 +122,7 @@ function InboxTable(p: {
const confirm = useConfirm();
const snackbar = useSnackbar();
const loadingMessage = useLoadingMessage();
const selectAccount = useSelectAccount();
const [labelFilter, setLabelFilter] = React.useState("");
@ -225,6 +228,59 @@ function InboxTable(p: {
}
};
// Attach multiple entries to movements
const [attachMultipleEntries, setAttachMultipleEntries] =
React.useState<InboxEntry[]>();
const [attachMultipleMovements, setAttachMultipleMovements] =
React.useState<Movement[][]>();
const attachMultiple = async () => {
try {
const targetAccount = await selectAccount(
"Attach multiple entries",
"Select the target account for automatic attaching",
"Start search"
);
if (!targetAccount) return;
const entries = p.entries.filter((m) => rowSelectionModel.includes(m.id));
const movements: Movement[][] = [];
for (const [num, e] of entries.entries()) {
loadingMessage.show(
`Searching for proper movements ${num}/${entries.length}`
);
movements.push(
await MovementApi.GetAccountMovements(targetAccount.id, {
amount_min: e.amount ? e.amount - 0.5 : undefined,
amount_max: e.amount ? e.amount + 0.5 : undefined,
label: e.label,
limit: 5,
time_min: e.time ? e.time - 3600 * 24 : undefined,
time_max: e.time ? e.time + 3600 * 24 : undefined,
})
);
}
setAttachMultipleEntries(entries);
setAttachMultipleMovements(movements);
} catch (e) {
console.error("Failed to attach multiple accounts to movements!", e);
alert(`Failed to attach multiple accounts to movements! ${e}`);
} finally {
loadingMessage.hide();
}
};
const handleCancelAttachMultiple = () => {
setAttachMultipleEntries(undefined);
setAttachMultipleMovements(undefined);
};
const handlePerformAttachMultiple = (mapping: Array<number | undefined>) => {
console.info(attachMultipleEntries, attachMultipleMovements, mapping);
};
// Delete multiple inbox entries
const deleteMultiple = async () => {
try {
@ -368,6 +424,16 @@ function InboxTable(p: {
/>
)}
{attachMultipleEntries && attachMultipleMovements && (
<AttachMultipleInboxEntriesDialog
open
entries={attachMultipleEntries}
movements={attachMultipleMovements}
onClose={handleCancelAttachMultiple}
onSelected={handlePerformAttachMultiple}
/>
)}
<div style={{ display: "flex" }}>
<TextField
placeholder="Filter by label"
@ -385,6 +451,14 @@ function InboxTable(p: {
<RefreshIcon />
</IconButton>
</Tooltip>
<Tooltip title="Attach all the selected inbox entries to movements">
<IconButton
disabled={rowSelectionModel.length === 0}
onClick={attachMultiple}
>
<SearchIcon />
</IconButton>
</Tooltip>
<Tooltip title="Delete all the selected inbox entries">
<IconButton
disabled={