feat: cashflow account transactions infinity scroll loading.

This commit is contained in:
a.bouhuolia
2021-10-23 23:10:48 +02:00
parent c7013caf12
commit 65e8d3f26a
11 changed files with 268 additions and 68 deletions

View File

@@ -52,14 +52,13 @@ function AccountTransactionsDataTable({
TableRowsRenderer={TableVirtualizedListRows}
TableHeaderSkeletonRenderer={TableSkeletonHeader}
// #TableVirtualizedListRows props.
vListrowHeight={cashflowTansactionsTableSize == 'small' ? 40 : 42}
vListrowHeight={cashflowTansactionsTableSize == 'small' ? 32 : 40}
vListOverscanRowCount={0}
TableHeaderSkeletonRenderer={TableSkeletonHeader}
initialColumnsWidths={initialColumnsWidths}
onColumnResizing={handleColumnResizing}
size={cashflowTansactionsTableSize}
noResults={'There is deposit/withdrawal transactions on the current account.'}
className="table-constrant"
/>
);

View File

@@ -29,7 +29,7 @@ function AccountSwitchButton() {
function AccountSwitchItem() {
const { push } = useHistory();
const { cashflowAccounts } = useAccountTransactionsContext();
const { cashflowAccounts, accountId } = useAccountTransactionsContext();
// Handle item click.
const handleItemClick = curry((account, event) => {
@@ -39,7 +39,9 @@ function AccountSwitchItem() {
const items = cashflowAccounts.map((account) => (
<AccountSwitchMenuItem
name={account.name}
balance={account.formatted_amount}
onClick={handleItemClick(account)}
active={account.id === accountId}
/>
));
@@ -111,7 +113,7 @@ function AccountSwitchMenuItem({
}) {
return (
<MenuItem
label={'LYD100,000'}
label={balance}
text={
<React.Fragment>
<AccountSwitchItemName>{name}</AccountSwitchItemName>

View File

@@ -1,14 +1,20 @@
import React from 'react';
import { useParams } from 'react-router-dom';
import { flatten, map } from 'lodash';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import { IntersectionObserver } from 'components';
import {
useCashflowTransactions,
useAccountTransactionsInfinity,
useCashflowAccounts,
useAccount,
} from 'hooks/query';
const AccountTransactionsContext = React.createContext();
function flattenInfinityPages(data) {
return flatten(map(data.pages, (page) => page.cashflow_transactions));
}
/**
* Account transctions provider.
*/
@@ -18,26 +24,44 @@ function AccountTransactionsProvider({ query, ...props }) {
// Fetch cashflow account transactions list
const {
data: cashflowTransactions,
data: cashflowTransactionsPages,
isFetching: isCashFlowTransactionsFetching,
isLoading: isCashFlowTransactionsLoading,
} = useCashflowTransactions(accountId, {
enabled: !!accountId,
isSuccess: isCashflowTransactionsSuccess,
fetchNextPage: fetchNextTransactionsPage,
isFetchingNextPage,
} = useAccountTransactionsInfinity(accountId, {
page_size: 50,
});
// Fetch cashflow accounts .
const cashflowTransactions = React.useMemo(
() =>
isCashflowTransactionsSuccess
? flattenInfinityPages(cashflowTransactionsPages)
: [],
[cashflowTransactionsPages, isCashflowTransactionsSuccess],
);
// Fetch cashflow accounts.
const {
data: cashflowAccounts,
isFetching: isCashFlowAccountsFetching,
isLoading: isCashFlowAccountsLoading,
} = useCashflowAccounts(query, { keepPreviousData: true });
// Retrieve specific account details.
const {
data: currentAccount,
isFetching: isCurrentAccountFetching,
isLoading: isCurrentAccountLoading,
} = useAccount(accountId, { keepPreviousData: true });
const handleObserverInteract = React.useCallback(() => {
if (!isFetchingNextPage) {
fetchNextTransactionsPage();
}
}, [isFetchingNextPage, fetchNextTransactionsPage]);
// Provider payload.
const provider = {
accountId,
@@ -55,6 +79,10 @@ function AccountTransactionsProvider({ query, ...props }) {
return (
<DashboardInsider name={'account-transactions'}>
<AccountTransactionsContext.Provider value={provider} {...props} />
<IntersectionObserver
onIntersect={handleObserverInteract}
// enabled={!isFetchingNextPage}
/>
</DashboardInsider>
);
}

View File

@@ -21,32 +21,41 @@ export function useAccountTransactionsColumns() {
{
id: 'type',
Header: intl.get('type'),
accessor: 'type',
accessor: 'reference_type_formatted',
className: 'type',
width: 140,
textOverview: true,
},
{
id: 'status',
Header: intl.get('status'),
// accessor:
id: 'transaction_number',
Header: intl.get('transaction_number'),
accessor: 'transaction_number',
width: 160,
className: 'status',
className: 'transaction_number',
},
{
id: 'reference_number',
Header: intl.get('reference_no'),
accessor: 'reference_number',
width: 160,
className: 'reference_number',
},
{
id: 'deposit',
Header: intl.get('cash_flow.label.deposit'),
accessor: 'formattedDeposit',
accessor: 'formatted_deposit',
width: 110,
className: 'deposit',
align: 'right',
textOverview: true,
align: 'right'
},
{
id: 'withdrawal',
Header: intl.get('cash_flow.label.withdrawal'),
accessor: 'formattedWithdrawal',
accessor: 'formatted_withdrawal',
className: 'withdrawal',
width: 150,
textOverview: true,
align: 'right',
},
{
@@ -55,7 +64,8 @@ export function useAccountTransactionsColumns() {
accessor: 'running_balance',
className: 'running_balance',
width: 150,
align: 'right',
textOverview: true,
align: 'right'
},
],
[],

View File

@@ -2,7 +2,9 @@ import React from 'react';
import { isNull } from 'lodash';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { BankAccountsList, BankAccount } from '../../../components';
import { Menu, MenuItem, MenuDivider, Intent } from '@blueprintjs/core';
import intl from 'react-intl-universal';
import { BankAccountsList, BankAccount, If, Icon } from '../../../components';
import { useCashFlowAccountsContext } from './CashFlowAccountsProvider';
const CashflowAccountsGridWrap = styled.div`
@@ -22,16 +24,22 @@ function CashflowAccountsSkeleton() {
));
}
function getUpdatedBeforeText(createdAt) {
return 'Updated before 2 years.';
}
function CashflowAccountsGridItems({ accounts }) {
return accounts.map((account) => (
<Link to={`/cashflow-accounts/${account.id}/transactions`}>
<CashflowAccountAnchor to={`/cashflow-accounts/${account.id}/transactions`}>
<BankAccount
title={account.name}
code={account.code}
balance={!isNull(account.amount) ? account.formattedAmount : '-'}
balance={!isNull(account.amount) ? account.formatted_amount : '-'}
type={'cash'}
contextMenuContent={CashflowAccountContextMenu}
updatedBeforeText={getUpdatedBeforeText(account.createdAt)}
/>
</Link>
</CashflowAccountAnchor>
));
}
@@ -52,3 +60,44 @@ export default function CashflowAccountsGrid() {
</CashflowAccountsGridWrap>
);
}
function CashflowAccountContextMenu() {
return (
<Menu>
<MenuItem
icon={<Icon icon="reader-18" />}
text={intl.get('view_details')}
/>
<MenuDivider />
<MenuItem icon={<Icon icon="pen-18" />} text={intl.get('edit_account')} />
<MenuDivider />
<If condition={false}>
<MenuItem
text={intl.get('inactivate_account')}
icon={<Icon icon="pause-16" iconSize={16} />}
/>
</If>
<If condition={!false}>
<MenuItem
text={intl.get('activate_account')}
icon={<Icon icon="play-16" iconSize={16} />}
/>
</If>
<MenuItem
text={intl.get('delete_account')}
icon={<Icon icon="trash-16" iconSize={16} />}
intent={Intent.DANGER}
/>
</Menu>
);
}
const CashflowAccountAnchor = styled(Link)`
&,
&:hover,
&:focus,
&:active {
color: inherit;
text-decoration: none;
}
`;