),
},
],
[accountCurrency, onUndo],
)
const [search, setSearch] = useDebounceValue('', 250)
const [amountFilter, setAmountFilter] = useState<{ value: number, stringValue?: string | number }>({ value: 0, stringValue: '0.00' })
const [typeFilter, setTypeFilter] = useState('All')
const [status, setStatus] = useState<'Reconciled' | 'Unreconciled' | 'All' | 'Partially Reconciled'>('All')
const onSearchChange = (e: React.ChangeEvent) => {
setSearch(e.target.value)
}
const filteredResults = useMemo(() => {
if (!data) {
return []
}
return data.message.filter((transaction) => {
if (search && !transaction.description?.toLowerCase().includes(search.toLowerCase())) {
return false
}
if (typeFilter !== 'All') {
if (typeFilter === 'Debits' && transaction.deposit && transaction.deposit > 0) {
return false
}
if (typeFilter === 'Credits' && transaction.withdrawal && transaction.withdrawal > 0) {
return false
}
}
if (status !== 'All') {
if (status === 'Reconciled' && transaction.status !== 'Reconciled') {
return false
}
if (status === 'Unreconciled') {
if (transaction.status === 'Reconciled') {
return false
}
// Filter out partially reconciled transactions
if (transaction.allocated_amount && transaction.allocated_amount > 0 && transaction.unallocated_amount !== 0) {
return false
}
}
if (status === 'Partially Reconciled') {
if (transaction.status === 'Reconciled') {
return false
}
if ((transaction.allocated_amount ?? 0) === 0) {
return false
}
}
}
if (amountFilter.value > 0 && transaction.withdrawal !== amountFilter.value && transaction.deposit !== amountFilter.value) {
return false
}
return true
})
}, [data, search, amountFilter, typeFilter, status])
const content = _("Below is a list of all bank transactions imported in the system for the bank account {0} between {1} and {2}.", [`${bankAccount?.account_name}`, `${formattedFromDate}`, `${formattedToDate}`])
return
{error && }
row.name}
maxHeight="calc(100vh - 200px)"
scrollAreaClassName="min-h-[calc(100vh-200px)]"
emptyState={{_("No bank transactions found")}{_("There are no transactions in the system for the selected bank account and dates that match the filters.")}
{data && data.message.length === 0 ? : null}
}
/>
{
// If the input ends with a decimal or a decimal with trailing zeroes, store the string since we need the user to be able to type the decimals.
// When the user eventually types the decimals or blurs out, the value is formatted anyway.
// Otherwise store the float value
// Check if the value ends with a decimal or a decimal with trailing zeroes
const isDecimal = v?.endsWith(decimalSeparator) || v?.endsWith(decimalSeparator + '0')
const newValue = isDecimal ? v : values?.float ?? ''
setAmountFilter({
value: Number(newValue),
stringValue: newValue
})
}}
// @ts-expect-error - CurrencyInputProps doesn't have a variant prop but Input does
variant={"outline"}
customInput={Input}
/>