diff --git a/moneymgr_web/src/routes/InboxRoute.tsx b/moneymgr_web/src/routes/InboxRoute.tsx index b34abea..0cff2ea 100644 --- a/moneymgr_web/src/routes/InboxRoute.tsx +++ b/moneymgr_web/src/routes/InboxRoute.tsx @@ -10,6 +10,7 @@ import { ListItemText, Menu, MenuItem, + TextField, Tooltip, } from "@mui/material"; import { DataGrid, GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; @@ -117,6 +118,14 @@ function InboxTable(p: { const snackbar = useSnackbar(); const loadingMessage = useLoadingMessage(); + const [labelFilter, setLabelFilter] = React.useState(""); + + const filteredList = React.useMemo(() => { + return p.entries.filter((m) => + (m.label ?? "").toLowerCase().includes(labelFilter.toLowerCase()) + ); + }, [p.entries, labelFilter]); + const [rowSelectionModel, setRowSelectionModel] = React.useState([]); @@ -168,6 +177,50 @@ function InboxTable(p: { } }; + // Delete multiple inbox entries + const deleteMultiple = async () => { + try { + const deletedEntries = p.entries.filter((m) => + rowSelectionModel.includes(m.id) + ); + + if ( + !(await confirm( + <> + Do you really want to delete the following inbox entries: + + + )) + ) + return; + + for (const [num, e] of deletedEntries.entries()) { + loadingMessage.show( + `Deleting inbox entry ${num}/${deletedEntries.length}` + ); + + await InboxApi.Delete(e); + + p.onDeleteEntry(e); + } + + snackbar("The inbox entries have been successfully deleted!"); + + p.onReload(false); + } catch (e) { + console.error("Failed to delete multiple inbox entries!", e); + alert(`Failed to delete multiple inbox entries! ${e}`); + } finally { + loadingMessage.hide(); + } + }; + const columns: GridColDef<(typeof p.entries)[number]>[] = [ { field: "time", @@ -247,39 +300,65 @@ function InboxTable(p: { ]; return ( -
- - columns={columns} - rows={p.entries} - autoPageSize - checkboxSelection - initialState={{ - sorting: { - sortModel: [{ field: "time", sort: "desc" }], - }, - columns: { - columnVisibilityModel: { - movement_id: p.showMovements!!, + <> +
+ { + setLabelFilter(e.target.value); + }} + style={{ padding: "0px", flex: 1 }} + /> + + + + + + +
+
+ + columns={columns} + rows={filteredList} + autoPageSize + checkboxSelection + initialState={{ + sorting: { + sortModel: [{ field: "time", sort: "desc" }], }, - }, - }} - onRowSelectionModelChange={(newRowSelectionModel) => { - setRowSelectionModel(newRowSelectionModel); - }} - rowSelectionModel={rowSelectionModel} - processRowUpdate={async (n) => { - try { - return await InboxApi.Update(n); - } catch (e) { - console.error("Failed to update movement information!", e); - alert(`Failed to update row! ${e}`); - throw e; - } finally { - p.onReload(true); - } - }} - /> -
+ columns: { + columnVisibilityModel: { + movement_id: p.showMovements!!, + }, + }, + }} + onRowSelectionModelChange={(newRowSelectionModel) => { + setRowSelectionModel(newRowSelectionModel); + }} + rowSelectionModel={rowSelectionModel} + processRowUpdate={async (n) => { + try { + return await InboxApi.Update(n); + } catch (e) { + console.error("Failed to update inbox entry information!", e); + alert(`Failed to update row! ${e}`); + throw e; + } finally { + p.onReload(true); + } + }} + /> +
+ ); }