Can detach movement from inbox entry

This commit is contained in:
Pierre HUBERT 2025-05-12 21:02:46 +02:00
parent 2f807b4c73
commit 11d140826d
2 changed files with 58 additions and 10 deletions

View File

@ -24,8 +24,6 @@ export function UnmatchedInboxEntriesCountProvider(
}; };
const onReload = async () => { const onReload = async () => {
loadKey.current += 1;
load(); load();
return new Promise<void>((res) => { return new Promise<void>((res) => {

View File

@ -1,4 +1,5 @@
import DeleteIcon from "@mui/icons-material/DeleteOutlined"; import DeleteIcon from "@mui/icons-material/DeleteOutlined";
import LinkOffIcon from "@mui/icons-material/LinkOff";
import MoreVertIcon from "@mui/icons-material/MoreVert"; import MoreVertIcon from "@mui/icons-material/MoreVert";
import RefreshIcon from "@mui/icons-material/Refresh"; import RefreshIcon from "@mui/icons-material/Refresh";
import { import {
@ -88,6 +89,11 @@ export function InboxRoute(): React.ReactElement {
build={() => ( build={() => (
<InboxTable <InboxTable
entries={entries!} entries={entries!}
onDeleteEntry={(del) => {
setEntries((entries) => {
return entries?.filter((m) => m.id !== del.id);
});
}}
onReload={reload} onReload={reload}
showMovements={includeAttached} showMovements={includeAttached}
/> />
@ -102,6 +108,7 @@ export function InboxRoute(): React.ReactElement {
function InboxTable(p: { function InboxTable(p: {
entries: InboxEntry[]; entries: InboxEntry[];
onDeleteEntry: (entry: InboxEntry) => void;
onReload: (skipEntries: boolean) => void; onReload: (skipEntries: boolean) => void;
showMovements?: boolean; showMovements?: boolean;
}): React.ReactElement { }): React.ReactElement {
@ -127,13 +134,37 @@ function InboxTable(p: {
await InboxApi.Delete(entry); await InboxApi.Delete(entry);
const id = p.entries.findIndex((m) => entry.id === m.id); p.onDeleteEntry(entry);
p.entries.slice(id, id);
p.onReload(false); p.onReload(true);
} catch (e) { } catch (e) {
console.error("Failed to delete movement!", e); console.error("Failed to delete entry!", e);
alert(`Failed to delete movement! ${e}`); alert(`Failed to delete entry! ${e}`);
}
};
// Detach inbox entry from movement
const handleDetachClick = async (entry: InboxEntry) => {
try {
if (
!(await confirm(
`Do you really want to detach this inbox entry ${
entry.label ?? ""
} (${entry.amount ?? 0} ) from its movement?`,
"Detach inbox entry from movement",
"Detach"
))
)
return;
entry.movement_id = undefined;
await InboxApi.Update(entry);
p.onReload(true);
} catch (e) {
console.error("Failed to detach movement from entry!", e);
alert(`Failed to detach movement from entry! ${e}`);
} }
}; };
@ -206,8 +237,9 @@ function InboxTable(p: {
return [ return [
<InboxEntryActionMenu <InboxEntryActionMenu
key="menu" key="menu"
movement={params.row} entry={params.row}
onDelete={handleDeleteClick} onDelete={handleDeleteClick}
onDetach={handleDetachClick}
/>, />,
]; ];
}, },
@ -252,8 +284,9 @@ function InboxTable(p: {
} }
function InboxEntryActionMenu(p: { function InboxEntryActionMenu(p: {
movement: InboxEntry; entry: InboxEntry;
onDelete: (entry: InboxEntry) => void; onDelete: (entry: InboxEntry) => void;
onDetach: (entry: InboxEntry) => void;
}): React.ReactElement { }): React.ReactElement {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl); const open = Boolean(anchorEl);
@ -273,11 +306,28 @@ function InboxEntryActionMenu(p: {
<MoreVertIcon /> <MoreVertIcon />
</IconButton> </IconButton>
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}> <Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
{/* Unlink entry */}
{p.entry.movement_id && (
<MenuItem
onClick={() => {
handleClose();
p.onDetach(p.entry);
}}
>
<ListItemIcon>
<LinkOffIcon />
</ListItemIcon>
<ListItemText secondary={"Detach the entry from its movement"}>
Detach from movement
</ListItemText>
</MenuItem>
)}
{/* Delete */} {/* Delete */}
<MenuItem <MenuItem
onClick={() => { onClick={() => {
handleClose(); handleClose();
p.onDelete(p.movement); p.onDelete(p.entry);
}} }}
> >
<ListItemIcon> <ListItemIcon>