Skip to content

Commit

Permalink
Fixed import bugs and refactored grid interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
ystxn committed Apr 10, 2024
1 parent 532612e commit 0ffa123
Show file tree
Hide file tree
Showing 10 changed files with 400 additions and 365 deletions.
6 changes: 3 additions & 3 deletions src/dashboard/summary.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatDecimal, formatDecimalRaw } from '../util/formatters';
import { formatDecimal } from '../util/formatters';
import { HorizontalLoader } from '../core/loader';
import { useEffect, useState, Fragment } from 'react';
import { useNavigate } from 'react-router-dom';
Expand Down Expand Up @@ -146,7 +146,7 @@ const Summary = ({ setRoute }) => {
value = <IssuerChip label={issuer.name} color={issuer.colour} />;
break;
case 'balance':
value = formatDecimalRaw(row[column.field]);
value = formatDecimal(row.balance);
break;
case 'name':
if (row.multiCurrency) {
Expand Down Expand Up @@ -230,7 +230,7 @@ const Summary = ({ setRoute }) => {
<tfoot>
<tr>
<td colSpan={2}>Total Net Worth</td>
<td>{ formatDecimalRaw(netWorth) }</td>
<td>{ formatDecimal(netWorth) }</td>
</tr>
</tfoot>
</Table>
Expand Down
10 changes: 7 additions & 3 deletions src/transactions/add-transaction-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const ForeignCurrencyBar = styled.div`
`;

const AddTransactionDialog = ({
setShowAddDialog, transactionToEdit, setTransactionToEdit, setSelectedRows,
setShowAddDialog, transactionToEdit, setTransactionToEdit, setSelectedRows, apiRef,
}) => {
dayjs.extend(utc);
dayjs.extend(minMax);
Expand All @@ -51,7 +51,7 @@ const AddTransactionDialog = ({
medisaveAmount: transactionToEdit?.medisaveAmount || 0,
});
const [ loading, setLoading ] = state.useState(state.loading);
const [ transactions, setTransactions ] = state.useState(state.transactions);
const [ transactions ] = state.useState(state.transactions);
const [ accounts, setAccounts ] = state.useState(state.accounts);
const selectedAccount = !transactionToEdit ? state.useState(state.selectedAccount)[0]
: accounts.find(({ id }) => id === transactionToEdit.accountId);
Expand Down Expand Up @@ -151,7 +151,11 @@ const AddTransactionDialog = ({
: o.category;
return { ...o, category };
});
setTransactions(processedTx);

processedTx
.filter((row) => !apiRef.current.getRow(row.id) || row.balance !== apiRef.current.getRow(row.id).balance)
.forEach((row) => apiRef.current.updateRows([ row ]));

setSelectedRows(response.map(({ id }) => id));
setShowAddDialog(false);
showStatus('success', 'Transaction ' + (transactionToEdit ? 'edited' : 'added'));
Expand Down
20 changes: 9 additions & 11 deletions src/transactions/bulk-transaction-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import useMediaQuery from '@mui/material/useMediaQuery';
import utc from 'dayjs/plugin/utc';

const BulkTransactionDialog = ({
setShowBulkDialog, transactionToEdit, setTransactionToEdit,
setShowBulkDialog, transactionToEdit, setTransactionToEdit, apiRef,
}) => {
dayjs.extend(utc);
const theme = useTheme();
Expand Down Expand Up @@ -77,16 +77,14 @@ const BulkTransactionDialog = ({
? `${values.category}: ${values.subCategory}`
: values.category;

const revised = [ ...transactions ].map((t) =>
(transactionToEdit.indexOf(t.id) === -1) ? t : ({
...t,
billingMonth: values.billingMonth || t.billingMonth,
category: category || t.category,
subCategory: values.subCategory || t.subCategory,
remarks: values.remarks || t.remarks,
})
);
setTransactions(revised);
const changes = {};
if (category) { changes.category = category; }
if (values.billingMonth) { changes.billingMonth = values.billingMonth; }
if (values.subCategory) { changes.subCategory = values.subCategory; }
if (values.remarks) { changes.remarks = values.remarks; }

transactionToEdit.forEach((id) => apiRef.current.updateRows([{ id, ...changes }]));

setShowBulkDialog(false);
showStatus('success', 'Transactions edited');
setTransactionToEdit(undefined);
Expand Down
58 changes: 58 additions & 0 deletions src/transactions/dropzone.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { red, green, blue, grey } from '@mui/material/colors';
import api from '../core/api';
import Dropzone from 'react-dropzone';
import styled from 'styled-components';

const ImportZone = styled.div`
display: flex;
flex: 1 1 1px;
justify-content: center;
align-items: center;
cursor: pointer;
border-width: 2px;
border-style: dashed;
border-radius: .3rem;
color: ${props => props.isDragAccept ? green[400] : props.isDragReject ? red[400] : props.isFocused ? blue[400] : grey[400] };
border-color: ${props => props.isDragAccept ? green[400] : props.isDragReject ? red[400] : props.isFocused ? blue[400] : grey[400] };
`;

const DropZone = ({ selectedAccountId, setLoading, setImportTransactions }) => {
const { uploadImport } = api();

const onDrop = (acceptedFiles) => {
const data = new FormData();
data.append('file', acceptedFiles[0]);
data.append('accountId', selectedAccountId);
setLoading(true);

uploadImport(data, (response) => {
const processedResponse = response.map((r) => ({
...r,
category: r.subCategory && r.subCategory !== r.category
? `${r.category}: ${r.subCategory}`
: r.category,
}))
setImportTransactions(processedResponse);
setLoading(false);
});
};

return (
<Dropzone
accept={{
'application/vnd.ms-excel': [ '.csv' ],
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': [ '.xlsx' ],
}}
multiple={false}
onDropAccepted={onDrop}
>
{({ getRootProps, getInputProps, isFocused, isDragAccept, isDragReject }) => (
<ImportZone {...getRootProps()} {...{ isFocused, isDragAccept, isDragReject }}>
<input {...getInputProps()} />
Click to select exported file or drag file here
</ImportZone>
)}
</Dropzone>
);
};
export default DropZone;
13 changes: 9 additions & 4 deletions src/transactions/transactions-action-buttons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import state from '../core/state';
import useMediaQuery from '@mui/material/useMediaQuery';

const TransactionsActionButtons = ({
transactions, setTransactions, setAccounts, showAddDialog, setShowAddDialog,
transactionToEdit, setTransactionToEdit, setImportMode, canImport,
transactions, setAccounts, showAddDialog, setShowAddDialog,
transactionToEdit, setTransactionToEdit, setImportMode, canImport, apiRef,
}) => {
const theme = useTheme();
const setLoading = state.useState(state.loading)[1];
Expand All @@ -31,13 +31,16 @@ const TransactionsActionButtons = ({
deleteTransaction(selectedRows, () => {
const plural = selectedLength > 1 ? 's' : '';
if (selectedLength === 1 && txDate.isSame(maxDate)) {
setTransactions((t) => t.filter((r) => r.id !== selectedRows[0]));
apiRef.current.updateRows([{ id: selectedRows[0], _action: 'delete' }]);
showStatus('success', selectedLength + ` transaction${plural} deleted`);
setLoading(false);
setShowConfirmDelete(false);
} else {
listTransactions(selectedAccount.id, (response) => {
setTransactions(response);
selectedRows.forEach((id) => apiRef.current.updateRows([{ id, _action: 'delete' }]));
response
.filter((updatedRow) => updatedRow.balance !== apiRef.current.getRow(updatedRow.id).balance)
.forEach((updatedRow) => apiRef.current.updateRows([{ id: updatedRow.id, balance: updatedRow.balance }]));
showStatus('success', selectedLength + ` transaction${plural} deleted`);
setLoading(false);
setShowConfirmDelete(false);
Expand Down Expand Up @@ -80,6 +83,7 @@ const TransactionsActionButtons = ({
transactionToEdit,
setTransactionToEdit,
setSelectedRows,
apiRef,
}} />
)}

Expand All @@ -88,6 +92,7 @@ const TransactionsActionButtons = ({
setShowBulkDialog,
transactionToEdit,
setTransactionToEdit,
apiRef,
}} />
)}

Expand Down
27 changes: 9 additions & 18 deletions src/transactions/transactions-grid.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import {
DataGrid,
GridToolbar,
useGridApiRef,
gridFilteredSortedRowEntriesSelector,
gridPaginatedVisibleSortedGridRowIdsSelector,
gridPageSelector,
gridPageCountSelector,
gridPageSizeSelector,
} from '@mui/x-data-grid';
import {
formatNumber, formatDecimal, formatDecimalRaw, formatDecimalAbs, formatDate, formatMonth,
formatNumber, formatDecimal, formatDecimalHideZero, formatDecimalAbs, formatDate, formatMonth,
} from '../util/formatters';
import { GridPagination } from '@mui/x-data-grid';
import { HorizontalLoader } from '../core/loader';
Expand Down Expand Up @@ -40,7 +39,7 @@ const FooterRoot = styled.div`
.MuiButtonBase-root { padding: .2rem }
`;

const TransactionsGrid = ({ accounts, setShowAddDialog, setTransactionToEdit }) => {
const TransactionsGrid = ({ accounts, setShowAddDialog, setTransactionToEdit, apiRef }) => {
const theme = useTheme();
const isSmallHeight = useMediaQuery('(max-height:600px)');
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
Expand All @@ -63,7 +62,7 @@ const TransactionsGrid = ({ accounts, setShowAddDialog, setTransactionToEdit })
if (selectedAccount.id !== transactionsAccountId) {
console.debug(`Selected account ${selectedAccount.id} is not transactions account ${transactionsAccountId}`);
apiRef.current = {};
setTransactions(undefined);
setTransactions([]);
setParentPaginationModel(undefined);
setPaginationModel(undefined);
setSelectedRows([]);
Expand Down Expand Up @@ -108,12 +107,12 @@ const TransactionsGrid = ({ accounts, setShowAddDialog, setTransactionToEdit })
date: { flex: 2.5, field: 'date', headerName: 'Date', type: 'date', valueFormatter: formatDate },
billingMonth: { flex: 2, field: 'billingMonth', headerName: 'Bill', type: 'date', valueFormatter: formatMonth },
forMonth: { flex: 2, field: 'forMonth', headerName: 'Month', type: 'date', valueFormatter: formatMonth },
credit: { flex: 2, field: 'credit', headerName: 'Credit', type: 'number', valueGetter: getAmount, valueFormatter: formatDecimal, cellClassName: 'green' },
debit: { flex: 2, field: 'debit', headerName: 'Debit', type: 'number', valueGetter: getAmount, valueFormatter: formatDecimal, cellClassName: 'red' },
credit: { flex: 2, field: 'credit', headerName: 'Credit', type: 'number', valueGetter: getAmount, valueFormatter: formatDecimalHideZero, cellClassName: 'green' },
debit: { flex: 2, field: 'debit', headerName: 'Debit', type: 'number', valueGetter: getAmount, valueFormatter: formatDecimalHideZero, cellClassName: 'red' },
amount: { flex: 2.5, field: 'amount', headerName: 'Amount', type: 'number', valueFormatter: formatDecimal, cellClassName: getColourClassForValue },
originalAmount: { flex: 2, field: 'originalAmount', type: 'number', headerName: 'Original', valueFormatter: formatDecimalAbs },
fx: { flex: 2, field: 'fx', headerName: 'FX', type: 'number', valueGetter: getFx },
balance: { flex: 2, field: 'balance', headerName: 'Balance', type: 'number', valueFormatter: formatDecimalRaw },
balance: { flex: 2, field: 'balance', headerName: 'Balance', type: 'number', valueFormatter: formatDecimal },
remarks: { flex: 4, field: 'remarks', headerName: 'Remarks' },
category: { flex: 2, field: 'category', headerName: 'Category' },
code: { flex: 2, field: 'code', headerName: 'Code' },
Expand Down Expand Up @@ -173,14 +172,6 @@ const TransactionsGrid = ({ accounts, setShowAddDialog, setTransactionToEdit })
maxHeight: `calc(100vh - ${isSmallHeight ? 5.5 : isMobile ? 12.1 : 13}rem)`,
};

const apiRef = useGridApiRef();
useEffect(() => {
// Weird MUI-X bug
if (apiRef.current === null) {
apiRef.current = {};
}
}, [ apiRef.current ]);

useEffect(() => {
if (!visibleTransactionId) {
return;
Expand All @@ -192,7 +183,7 @@ const TransactionsGrid = ({ accounts, setShowAddDialog, setTransactionToEdit })
.map(({ id }) => id)
.indexOf(visibleTransactionId) + 1;
const pageSize = gridPageSizeSelector(apiRef);
setTimeout(() => api.current.setPage(Math.floor(index / pageSize)), 100);
setTimeout(() => api.current?.setPage(Math.floor(index / pageSize)), 100);
}
setVisibleTransactionId(undefined);
}, [ visibleTransactionId ]);
Expand All @@ -203,11 +194,11 @@ const TransactionsGrid = ({ accounts, setShowAddDialog, setTransactionToEdit })
gridFilteredSortedRowEntriesSelector(apiRef).map(({ model }) => model);
const length = data.length;
const plural = length > 1 ? 's' : '';
const amountSum = { value: data.reduce((acc, obj) => acc + obj.amount, 0) };
const amountSum = data.reduce((acc, obj) => acc + obj.amount, 0);

return (
<Box sx={{ marginLeft: '1rem' }}>
{formatNumber(length, false)} row{plural}: {formatDecimalRaw(amountSum)}
{formatNumber(length, false)} row{plural}: {formatDecimal(amountSum)}
</Box>
);
};
Expand Down
Loading

0 comments on commit 0ffa123

Please sign in to comment.