Skip to content

Commit

Permalink
feat: Add ability to delete multiple entities
Browse files Browse the repository at this point in the history
Not connected to backend
  • Loading branch information
tklein1801 committed Jan 17, 2024
1 parent 013ce1c commit 9e19ecd
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 40 deletions.
1 change: 1 addition & 0 deletions src/components/Base/Select/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export interface ISelectionHandler<T> {
onSelectAll: (shouldSelectAll: boolean) => void;
onSelect: (entity: T) => void;
isSelected: (entity: T) => boolean;
onDeleteMultiple?: () => void;
}
81 changes: 51 additions & 30 deletions src/components/Base/Table/Table.component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import {
Box,
Button,
Skeleton,
TableBody,
TableCell,
Expand All @@ -19,6 +20,7 @@ import {
import { TableContainer } from './TableContainer.component';
import { CircularProgress } from '@/components/Loading';
import { type ISelectionHandler, SelectAll } from '../Select';
import { DeleteRounded, PropaneSharp } from '@mui/icons-material';

Check failure on line 23 in src/components/Base/Table/Table.component.tsx

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 16.x)

'PropaneSharp' is declared but its value is never read.

Check failure on line 23 in src/components/Base/Table/Table.component.tsx

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 18.x)

'PropaneSharp' is declared but its value is never read.

Check failure on line 23 in src/components/Base/Table/Table.component.tsx

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20.x)

'PropaneSharp' is declared but its value is never read.

export type TTableProps<T> = {
title?: string;
Expand All @@ -33,6 +35,7 @@ export type TTableProps<T> = {
| {
withSelection: true;
onSelectAll: ISelectionHandler<T>['onSelectAll'];
onDelete?: () => void;
amountOfSelectedEntities: number;
}
| { withSelection?: false }
Expand Down Expand Up @@ -104,39 +107,57 @@ export const Table = <T,>({
{isLoading ? (
<CircularProgress />
) : currentPageData.length > 0 ? (
<TableContainer>
<TableHead>
<TableRow>
{props.withSelection && (
<SelectAll
checked={checked}
indeterminate={
props.amountOfSelectedEntities > 0 &&
props.amountOfSelectedEntities < data.length
}
onChange={(_event, checked) => {
const indeterminate =
props.amountOfSelectedEntities > 0 &&
props.amountOfSelectedEntities < data.length;
props.onSelectAll(indeterminate ? false : checked);
<React.Fragment>
{props.withSelection && props.amountOfSelectedEntities > 0 && (
<Box sx={{ px: 2, pt: 1.5 }}>
{props.onDelete && (
<Button
startIcon={<DeleteRounded />}
onClick={() => {
if (props.onDelete) props.onDelete();
}}
wrapWithTableCell
/>
sx={{ mr: 1 }}
>
Delete
</Button>
)}
</Box>
)}

{headerCells.map((headerCell) =>
renderHeaderCell ? (
renderHeaderCell(headerCell)
) : (
<TableCell key={headerCell.replaceAll(' ', '_').toLowerCase()}>
<Typography fontWeight={'bold'}>{headerCell}</Typography>
</TableCell>
)
)}
</TableRow>
</TableHead>
<TableBody>{currentPageData.map(renderRow)}</TableBody>
</TableContainer>
<TableContainer>
<TableHead>
<TableRow>
{props.withSelection && (
<SelectAll
checked={checked}
indeterminate={
props.amountOfSelectedEntities > 0 &&
props.amountOfSelectedEntities < data.length
}
onChange={(_event, checked) => {
const indeterminate =
props.amountOfSelectedEntities > 0 &&
props.amountOfSelectedEntities < data.length;
props.onSelectAll(indeterminate ? false : checked);
}}
wrapWithTableCell
/>
)}

{headerCells.map((headerCell) =>
renderHeaderCell ? (
renderHeaderCell(headerCell)
) : (
<TableCell key={headerCell.replaceAll(' ', '_').toLowerCase()}>
<Typography fontWeight={'bold'}>{headerCell}</Typography>
</TableCell>
)
)}
</TableRow>
</TableHead>
<TableBody>{currentPageData.map(renderRow)}</TableBody>
</TableContainer>
</React.Fragment>
) : (
<NoResults sx={{ mx: 2, mt: 2 }} />
)}
Expand Down
51 changes: 41 additions & 10 deletions src/routes/Transactions.route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
TransactionService,
useFetchTransactions,
} from '@/core/Transaction';
import { Grid, IconButton, TableCell, TableRow, Typography } from '@mui/material';
import { Checkbox, Grid, IconButton, TableCell, TableRow, Typography } from '@mui/material';
import { TTransaction } from '@budgetbuddyde/types';
import { DeleteDialog } from '@/components/DeleteDialog.component';
import { SearchInput } from '@/components/Base/Search';
Expand All @@ -23,12 +23,14 @@ import { useFilterStore } from '@/core/Filter';
import { filterTransactions } from '@/utils/filter.util';
import { CategoryChip } from '@/core/Category';
import { PaymentMethodChip } from '@/core/PaymentMethod';
import { type ISelectionHandler } from '@/components/Base/Select';

interface ITransactionsHandler {
onSearch: (keyword: string) => void;
onTransactionDelete: (transaction: TTransaction) => void;
onConfirmTransactionDelete: () => void;
onEditTransaction: (transaction: TTransaction) => void;
selection: ISelectionHandler<TTransaction>;
}

export const Transactions = () => {
Expand All @@ -44,7 +46,8 @@ export const Transactions = () => {
const [showEditTransactionDrawer, setShowEditTransactionDrawer] = React.useState(false);
const [editTransaction, setEditTransaction] = React.useState<TTransaction | null>(null);
const [showDeleteTransactionDialog, setShowDeleteTransactionDialog] = React.useState(false);
const [deleteTransaction, setDeleteTransaction] = React.useState<TTransaction | null>(null);
const [deleteTransactions, setDeleteTransactions] = React.useState<TTransaction[]>([]);
const [selectedTransactions, setSelectedTransactions] = React.useState<TTransaction[]>([]);
const [keyword, setKeyword] = React.useState('');
const displayedTransactions: TTransaction[] = React.useMemo(() => {
return filterTransactions(keyword, filters, transactions);
Expand All @@ -60,9 +63,10 @@ export const Transactions = () => {
},
async onConfirmTransactionDelete() {
try {
if (!deleteTransaction) return;
// FIXME: Implement support for deletion of multiple entities after backend-endpoint was updated
if (!deleteTransactions[0]) return;
const [deletedItem, error] = await TransactionService.delete(
{ transactionId: deleteTransaction.id },
{ transactionId: deleteTransactions[0].id },
authOptions
);
if (error) {
Expand All @@ -73,7 +77,7 @@ export const Transactions = () => {
}

setShowDeleteTransactionDialog(false);
setDeleteTransaction(null);
setDeleteTransactions([]);
refreshTransactions(); // FIXME: Wrap inside startTransition
showSnackbar({ message: `Deleted the transaction` });
} catch (error) {
Expand All @@ -82,12 +86,27 @@ export const Transactions = () => {
},
onTransactionDelete(transaction) {
setShowDeleteTransactionDialog(true);
setDeleteTransaction(transaction);
setDeleteTransactions([transaction]);
},
selection: {
onSelectAll(shouldSelectAll) {
setSelectedTransactions(shouldSelectAll ? displayedTransactions : []);
},
onSelect(entity) {
if (this.isSelected(entity)) {
setSelectedTransactions((prev) => prev.filter(({ id }) => id !== entity.id));
} else setSelectedTransactions((prev) => [...prev, entity]);
},
isSelected(entity) {
return selectedTransactions.find((elem) => elem.id === entity.id) !== undefined;
},
onDeleteMultiple() {
setShowDeleteTransactionDialog(true);
setDeleteTransactions(selectedTransactions);
},
},
};

React.useEffect(() => console.log(displayedTransactions), [displayedTransactions]);

return (
<ContentGrid title={'Transactions'}>
<Grid item xs={12} md={12} lg={12} xl={12}>
Expand Down Expand Up @@ -121,6 +140,12 @@ export const Transactions = () => {
whiteSpace: 'nowrap',
}}
>
<TableCell>
<Checkbox
checked={handler.selection.isSelected(transaction)}
onChange={() => handler.selection.onSelect(transaction)}
/>
</TableCell>
<TableCell size={AppConfig.table.cellSize}>
<Typography fontWeight="bolder">{`${format(
new Date(transaction.processedAt),
Expand Down Expand Up @@ -174,6 +199,12 @@ export const Transactions = () => {
</IconButton>
</React.Fragment>
}
withSelection
onSelectAll={handler.selection.onSelectAll}
amountOfSelectedEntities={selectedTransactions.length}
onDelete={() => {
if (handler.selection.onDeleteMultiple) handler.selection.onDeleteMultiple();
}}
/>
</Grid>

Expand All @@ -195,11 +226,11 @@ export const Transactions = () => {
open={showDeleteTransactionDialog}
onClose={() => {
setShowDeleteTransactionDialog(false);
setDeleteTransaction(null);
setDeleteTransactions([]);
}}
onCancel={() => {
setShowDeleteTransactionDialog(false);
setDeleteTransaction(null);
setDeleteTransactions([]);
}}
onConfirm={handler.onConfirmTransactionDelete}
withTransition
Expand Down

0 comments on commit 9e19ecd

Please sign in to comment.