74 lines
2.3 KiB
TypeScript
74 lines
2.3 KiB
TypeScript
import { useCallback, useMemo } from "react";
|
|
import type { Transaction } from "../../types/api";
|
|
import styles from "./TransactionsTable.module.css";
|
|
import classNames from "classnames";
|
|
|
|
export type TransactionsTableProps = {
|
|
transactions: Transaction[];
|
|
deselected: number[];
|
|
deselect: (index: number) => void;
|
|
select: (index: number) => void;
|
|
readonly?: boolean;
|
|
}
|
|
|
|
const transactionEmoji = (transaction: Transaction): string => {
|
|
if (transaction.kind === 'transfer') {
|
|
return '➡️'
|
|
};
|
|
|
|
return transaction.amount > 0 ? '⬇️' : '⬆️';
|
|
};
|
|
|
|
const transactionType = (transaction: Transaction): string => {
|
|
if (transaction.kind === 'transfer') {
|
|
return 'Transfer'
|
|
};
|
|
|
|
return transaction.amount > 0 ? 'Inflow' : 'Outflow';
|
|
};
|
|
|
|
export default function TransactionsTable({ transactions, deselected, deselect, select, readonly }: TransactionsTableProps) {
|
|
|
|
const changeSelection = useCallback((index: number) => {
|
|
if (readonly) {
|
|
return;
|
|
}
|
|
|
|
if(deselected.includes(index)) {
|
|
select(index);
|
|
}
|
|
|
|
else {
|
|
deselect(index);
|
|
}
|
|
}, [deselected, deselect, select]);
|
|
|
|
const reversedTransactions = useMemo(() => transactions.slice().reverse(), [transactions]);
|
|
|
|
const renderRow = useCallback((transaction: Transaction, index: number) => (
|
|
<div
|
|
key={index}
|
|
onClick={() => changeSelection(index)}
|
|
className={classNames('notification', styles.transaction, {
|
|
'is-success': transaction.kind === 'regular' && transaction.amount > 0,
|
|
'is-danger': transaction.kind === 'regular' && transaction.amount < 0,
|
|
'is-info': transaction.kind === 'transfer',
|
|
'is-light': deselected.includes(index)
|
|
})}>
|
|
<h6 className="title is-6" title={transactionType(transaction)}>
|
|
{transactionEmoji(transaction)} {transaction.date}
|
|
</h6>
|
|
{transaction.id && (<><strong>ID:</strong> {transaction.id}<br /></>)}
|
|
<strong>From:</strong> {transaction.from}<br />
|
|
<strong>To:</strong> {transaction.to}<br />
|
|
<strong>Title:</strong> {transaction.title}<br />
|
|
<strong>Amount:</strong> <span className={styles.amount}>{transaction.amount}</span>
|
|
</div>
|
|
), [changeSelection]);
|
|
|
|
return (
|
|
<div className={styles.transactionsTable}>
|
|
{reversedTransactions.map(renderRow)}
|
|
</div>
|
|
);
|
|
} |