mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 13:50:31 +00:00
feat: cashflow account transactions infinity scroll loading.
This commit is contained in:
@@ -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"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
},
|
||||
],
|
||||
[],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user