feart: optimize cashflow account transactions page.

This commit is contained in:
a.bouhuolia
2021-10-20 19:04:01 +02:00
parent 0bb1e57061
commit c7013caf12
16 changed files with 300 additions and 38 deletions

View File

@@ -187,6 +187,7 @@ export function BankAccount({
type, type,
balance, balance,
loading = false, loading = false,
to
}) { }) {
return ( return (
<BankAccountWrap> <BankAccountWrap>

View File

@@ -189,10 +189,6 @@ export default [
}, },
], ],
}, },
{
text: <T id={'banking'} />,
children: [],
},
{ {
text: <T id={'cash_flow'} />, text: <T id={'cash_flow'} />,
children: [ children: [

View File

@@ -1,5 +1,11 @@
import React from 'react'; import React from 'react';
import { Button, NavbarGroup, Classes, NavbarDivider } from '@blueprintjs/core'; import {
Button,
NavbarGroup,
Classes,
NavbarDivider,
Alignment,
} from '@blueprintjs/core';
import { import {
Icon, Icon,
DashboardRowsHeightButton, DashboardRowsHeightButton,
@@ -23,6 +29,7 @@ function AccountTransactionsActionsBar({
// #withSettings // #withSettings
cashflowTansactionsTableSize, cashflowTansactionsTableSize,
// #withSettingsActions // #withSettingsActions
addSetting, addSetting,
}) { }) {
@@ -47,6 +54,9 @@ function AccountTransactionsActionsBar({
account_id: accountId, account_id: accountId,
}); });
}; };
const handleRefreshBtnClick = () => {};
return ( return (
<DashboardActionsBar> <DashboardActionsBar>
<NavbarGroup> <NavbarGroup>
@@ -54,13 +64,18 @@ function AccountTransactionsActionsBar({
items={addMoneyIn} items={addMoneyIn}
onItemSelect={handleMoneyInFormTransaction} onItemSelect={handleMoneyInFormTransaction}
text={<T id={'cash_flow.label.add_money_in'} />} text={<T id={'cash_flow.label.add_money_in'} />}
buttonProps={{
icon: <Icon icon={'arrow-downward'} iconSize={20} />,
}}
/> />
<CashFlowMenuItems <CashFlowMenuItems
items={addMoneyOut} items={addMoneyOut}
onItemSelect={handlMoneyOutFormTransaction} onItemSelect={handlMoneyOutFormTransaction}
text={<T id={'cash_flow.label.add_money_out'} />} text={<T id={'cash_flow.label.add_money_out'} />}
buttonProps={{
icon: <Icon icon={'arrow-upward'} iconSize={20} />,
}}
/> />
<NavbarDivider /> <NavbarDivider />
<Button <Button
className={Classes.MINIMAL} className={Classes.MINIMAL}
@@ -84,6 +99,14 @@ function AccountTransactionsActionsBar({
/> />
<NavbarDivider /> <NavbarDivider />
</NavbarGroup> </NavbarGroup>
<NavbarGroup align={Alignment.RIGHT}>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="refresh-16" iconSize={14} />}
onClick={handleRefreshBtnClick}
/>
</NavbarGroup>
</DashboardActionsBar> </DashboardActionsBar>
); );
} }

View File

@@ -40,7 +40,6 @@ function AccountTransactionsDataTable({
noInitialFetch={true} noInitialFetch={true}
columns={columns} columns={columns}
data={cashflowTransactions} data={cashflowTransactions}
selectionColumn={true}
sticky={true} sticky={true}
loading={isCashFlowTransactionsLoading} loading={isCashFlowTransactionsLoading}
headerLoading={isCashFlowTransactionsLoading} headerLoading={isCashFlowTransactionsLoading}
@@ -59,6 +58,9 @@ function AccountTransactionsDataTable({
initialColumnsWidths={initialColumnsWidths} initialColumnsWidths={initialColumnsWidths}
onColumnResizing={handleColumnResizing} onColumnResizing={handleColumnResizing}
size={cashflowTansactionsTableSize} size={cashflowTansactionsTableSize}
noResults={'There is deposit/withdrawal transactions on the current account.'}
className="table-constrant"
/> />
); );
} }

View File

@@ -0,0 +1,182 @@
import React from 'react';
import styled from 'styled-components';
import {
Popover,
Menu,
Position,
Button,
MenuItem,
Classes,
} from '@blueprintjs/core';
import { useHistory } from 'react-router-dom';
import { curry } from 'lodash/fp';
import { Icon } from '../../../components';
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
function AccountSwitchButton() {
const { currentAccount } = useAccountTransactionsContext();
return (
<AccountSwitchButtonBase
minimal={true}
rightIcon={<Icon icon={'arrow-drop-down'} iconSize={24} />}
>
<AccountSwitchText>{currentAccount.name}</AccountSwitchText>
</AccountSwitchButtonBase>
);
}
function AccountSwitchItem() {
const { push } = useHistory();
const { cashflowAccounts } = useAccountTransactionsContext();
// Handle item click.
const handleItemClick = curry((account, event) => {
push(`/cashflow-accounts/${account.id}/transactions`);
});
const items = cashflowAccounts.map((account) => (
<AccountSwitchMenuItem
name={account.name}
onClick={handleItemClick(account)}
/>
));
return (
<Popover
content={<Menu>{items}</Menu>}
position={Position.BOTTOM_LEFT}
minimal={true}
>
<AccountSwitchButton />
</Popover>
);
}
function AccountBalanceItem() {
const { currentAccount } = useAccountTransactionsContext();
return (
<AccountBalanceItemWrap>
Balance in Bigcapital{' '}
<AccountBalanceAmount>
{currentAccount.formatted_amount}
</AccountBalanceAmount>
</AccountBalanceItemWrap>
);
}
function AccountTransactionsDetailsBarSkeleton() {
return (
<React.Fragment>
<DetailsBarSkeletonBase className={Classes.SKELETON}>
X
</DetailsBarSkeletonBase>
<DetailsBarSkeletonBase className={Classes.SKELETON}>
X
</DetailsBarSkeletonBase>
</React.Fragment>
);
}
function AccountTransactionsDetailsContent() {
return (
<React.Fragment>
<AccountSwitchItem />
<AccountBalanceItem />
</React.Fragment>
);
}
export function AccountTransactionsDetailsBar() {
const { isCurrentAccountLoading } = useAccountTransactionsContext();
return (
<AccountTransactionDetailsWrap>
{isCurrentAccountLoading ? (
<AccountTransactionsDetailsBarSkeleton />
) : (
<AccountTransactionsDetailsContent />
)}
</AccountTransactionDetailsWrap>
);
}
function AccountSwitchMenuItem({
name,
balance,
transactionsNumber,
...restProps
}) {
return (
<MenuItem
label={'LYD100,000'}
text={
<React.Fragment>
<AccountSwitchItemName>{name}</AccountSwitchItemName>
<AccountSwitchItemTranscations>
25 Transactions
</AccountSwitchItemTranscations>
<AccountSwitchItemUpdatedAt>
Updated before 2 days
</AccountSwitchItemUpdatedAt>
</React.Fragment>
}
{...restProps}
/>
);
}
const DetailsBarSkeletonBase = styled.div`
letter-spacing: 10px;
margin-right: 10px;
margin-left: 10px;
font-size: 8px;
width: 140px;
`;
const AccountBalanceItemWrap = styled.div`
margin-left: 18px;
color: #5f6d86;
`;
const AccountTransactionDetailsWrap = styled.div`
display: flex;
background: #fff;
border-bottom: 1px solid #d2dce2;
padding: 0 22px;
height: 42px;
align-items: center;
`;
const AccountSwitchText = styled.div`
font-weight: 600;
font-size: 14px;
`;
const AccountBalanceAmount = styled.span`
font-weight: 600;
display: inline-block;
margin-left: 10px;
color: rgb(31, 50, 85);
`;
const AccountSwitchItemName = styled.div`
font-weight: 600;
`;
const AccountSwitchItemTranscations = styled.div`
font-size: 12px;
opacity: 0.7;
`;
const AccountSwitchItemUpdatedAt = styled.div`
font-size: 12px;
opacity: 0.5;
`;
const AccountSwitchButtonBase = styled(Button)`
.bp3-button-text {
margin-right: 5px;
}
`;

View File

@@ -5,9 +5,11 @@ import 'style/pages/CashFlow/AccountTransactions/List.scss';
import { DashboardPageContent, DashboardContentTable } from 'components'; import { DashboardPageContent, DashboardContentTable } from 'components';
import { AccountTransactionsProvider } from './AccountTransactionsProvider'; import { AccountTransactionsProvider } from './AccountTransactionsProvider';
import AccountTransactionsActionsBar from './AccountTransactionsActionsBar'; import AccountTransactionsActionsBar from './AccountTransactionsActionsBar';
import AccountTransactionsDataTable from './AccountTransactionsDataTable'; import AccountTransactionsDataTable from './AccountTransactionsDataTable';
import { AccountTransactionsDetailsBar } from './AccountTransactionsDetailsBar';
import { AccountTransactionsProgressBar } from './components';
/** /**
* Account transactions list. * Account transactions list.
@@ -16,6 +18,9 @@ function AccountTransactionsList() {
return ( return (
<AccountTransactionsProvider> <AccountTransactionsProvider>
<AccountTransactionsActionsBar /> <AccountTransactionsActionsBar />
<AccountTransactionsDetailsBar />
<AccountTransactionsProgressBar />
<DashboardPageContent> <DashboardPageContent>
<DashboardContentTable> <DashboardContentTable>
<AccountTransactionsDataTable /> <AccountTransactionsDataTable />

View File

@@ -1,8 +1,11 @@
import React from 'react'; import React from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import DashboardInsider from 'components/Dashboard/DashboardInsider'; import DashboardInsider from 'components/Dashboard/DashboardInsider';
import {
import { useCashflowTransactions } from 'hooks/query'; useCashflowTransactions,
useCashflowAccounts,
useAccount,
} from 'hooks/query';
const AccountTransactionsContext = React.createContext(); const AccountTransactionsContext = React.createContext();
@@ -22,12 +25,31 @@ function AccountTransactionsProvider({ query, ...props }) {
enabled: !!accountId, enabled: !!accountId,
}); });
// Fetch cashflow accounts .
const {
data: cashflowAccounts,
isFetching: isCashFlowAccountsFetching,
isLoading: isCashFlowAccountsLoading,
} = useCashflowAccounts(query, { keepPreviousData: true });
const {
data: currentAccount,
isFetching: isCurrentAccountFetching,
isLoading: isCurrentAccountLoading,
} = useAccount(accountId, { keepPreviousData: true });
// Provider payload. // Provider payload.
const provider = { const provider = {
accountId, accountId,
cashflowTransactions, cashflowTransactions,
cashflowAccounts,
currentAccount,
isCashFlowTransactionsFetching, isCashFlowTransactionsFetching,
isCashFlowTransactionsLoading, isCashFlowTransactionsLoading,
isCashFlowAccountsFetching,
isCashFlowAccountsLoading,
isCurrentAccountFetching,
isCurrentAccountLoading,
}; };
return ( return (

View File

@@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import intl from 'react-intl-universal'; import intl from 'react-intl-universal';
import { MaterialProgressBar } from 'components';
import { FormatDateCell } from 'components'; import { FormatDateCell } from 'components';
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
/** /**
* Retrieve account transctions table columns. * Retrieve account transctions table columns.
@@ -60,3 +61,12 @@ export function useAccountTransactionsColumns() {
[], [],
); );
} }
/**
* Account transactions progress bar.
*/
export function AccountTransactionsProgressBar() {
const { isCashFlowTransactionsLoading } = useAccountTransactionsContext();
return isCashFlowTransactionsLoading ? <MaterialProgressBar /> : null;
}

View File

@@ -1,18 +1,20 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames';
import { import {
Button, Button,
PopoverInteractionKind, PopoverInteractionKind,
MenuItem, MenuItem,
Classes,
Position, Position,
} from '@blueprintjs/core'; } from '@blueprintjs/core';
import { Select } from '@blueprintjs/select'; import { Select } from '@blueprintjs/select';
import { Icon } from 'components'; import { Icon } from 'components';
export const CashFlowMenuItems = ({ text, items, onItemSelect }) => { export const CashFlowMenuItems = ({
text,
items,
onItemSelect,
buttonProps,
}) => {
// Menu items renderer. // Menu items renderer.
const itemsRenderer = (item, { handleClick, modifiers, query }) => ( const itemsRenderer = (item, { handleClick, modifiers, query }) => (
<MenuItem text={item.name} label={item.label} onClick={handleClick} /> <MenuItem text={item.name} label={item.label} onClick={handleClick} />
@@ -40,9 +42,8 @@ export const CashFlowMenuItems = ({ text, items, onItemSelect }) => {
<Button <Button
text={text} text={text}
icon={<Icon icon={'plus-24'} iconSize={20} />} icon={<Icon icon={'plus-24'} iconSize={20} />}
// rightIcon={'caret-down'}
// className={classNames(Classes.MINIMAL, 'button--table-views')}
minimal={true} minimal={true}
{...buttonProps}
/> />
</Select> </Select>
); );

View File

@@ -33,12 +33,13 @@ function CashFlowAccountsDataTable({
// Local storage memorizing columns widths. // Local storage memorizing columns widths.
const [initialColumnsWidths, , handleColumnResizing] = const [initialColumnsWidths, , handleColumnResizing] =
useMemorizedColumnsWidths(TABLES.CASHFLOW_ACCOUNTS); useMemorizedColumnsWidths(TABLES.CASHFLOW_ACCOUNTS);
return ( return (
<DataTable <DataTable
noInitialFetch={true} noInitialFetch={true}
columns={columns} columns={columns}
data={cashflowAccounts} data={cashflowAccounts}
selectionColumn={true} selectionColumn={false}
sticky={true} sticky={true}
loading={isCashFlowAccountsLoading} loading={isCashFlowAccountsLoading}
headerLoading={isCashFlowAccountsLoading} headerLoading={isCashFlowAccountsLoading}
@@ -47,11 +48,8 @@ function CashFlowAccountsDataTable({
expandToggleColumn={2} expandToggleColumn={2}
selectionColumnWidth={45} selectionColumnWidth={45}
TableCellRenderer={TableFastCell} TableCellRenderer={TableFastCell}
TableRowsRenderer={TableVirtualizedListRows}
TableLoadingRenderer={TableSkeletonRows} TableLoadingRenderer={TableSkeletonRows}
// #TableVirtualizedListRows props.
vListrowHeight={cashflowTableSize == 'small' ? 40 : 42}
vListOverscanRowCount={0}
TableHeaderSkeletonRenderer={TableSkeletonHeader} TableHeaderSkeletonRenderer={TableSkeletonHeader}
initialColumnsWidths={initialColumnsWidths} initialColumnsWidths={initialColumnsWidths}
onColumnResizing={handleColumnResizing} onColumnResizing={handleColumnResizing}

View File

@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { isNull } from 'lodash'; import { isNull } from 'lodash';
import styled from 'styled-components'; import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { BankAccountsList, BankAccount } from '../../../components'; import { BankAccountsList, BankAccount } from '../../../components';
import { useCashFlowAccountsContext } from './CashFlowAccountsProvider'; import { useCashFlowAccountsContext } from './CashFlowAccountsProvider';
@@ -23,12 +24,14 @@ function CashflowAccountsSkeleton() {
function CashflowAccountsGridItems({ accounts }) { function CashflowAccountsGridItems({ accounts }) {
return accounts.map((account) => ( return accounts.map((account) => (
<Link to={`/cashflow-accounts/${account.id}/transactions`}>
<BankAccount <BankAccount
title={account.name} title={account.name}
code={account.code} code={account.code}
balance={!isNull(account.amount) ? account.formattedAmount : '-'} balance={!isNull(account.amount) ? account.formattedAmount : '-'}
type={'cash'} type={'cash'}
/> />
</Link>
)); ));
} }

View File

@@ -221,7 +221,7 @@
"manual_journal": "Manual Journal", "manual_journal": "Manual Journal",
"make_journal": "Make Journal", "make_journal": "Make Journal",
"banking": "Banking", "banking": "Banking",
"cash_flow": "Cash Flow", "cash_flow": "Cash flow",
"sales": "Sales", "sales": "Sales",
"purchases": "Purchases", "purchases": "Purchases",
"financial_reports": "Financial Reports", "financial_reports": "Financial Reports",

View File

@@ -766,7 +766,7 @@ export const getDashboardRoutes = () => [
}, },
// Cash flow // Cash flow
{ {
path: `/account/:id/transactions`, path: `/cashflow-accounts/:id/transactions`,
component: lazy(() => component: lazy(() =>
import('containers/CashFlow/AccountTransactions/AccountTransactionsList'), import('containers/CashFlow/AccountTransactions/AccountTransactionsList'),
), ),

View File

@@ -481,7 +481,7 @@ export default {
}, },
'account-balance': { 'account-balance': {
path: [ path: [
'M6.5 10h-2v7h2v-7zm6 0h-2v7h2v-7zm8.5 9H2v2h19v-2zm-2.5-9h-2v7h2v-7zm-7-6.74L16.71 6H6.29l5.21-2.74m0-2.26L2 6v2h19V6l-9.5-5z' 'M6.5 10h-2v7h2v-7zm6 0h-2v7h2v-7zm8.5 9H2v2h19v-2zm-2.5-9h-2v7h2v-7zm-7-6.74L16.71 6H6.29l5.21-2.74m0-2.26L2 6v2h19V6l-9.5-5z',
], ],
viewBox: '0 0 24 24', viewBox: '0 0 24 24',
}, },
@@ -490,5 +490,17 @@ export default {
'M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z', 'M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z',
], ],
viewBox: '0 0 24 24', viewBox: '0 0 24 24',
},
'arrow-drop-down': {
path: ['M7 10l5 5 5-5H7z'],
viewBox: '0 0 24 24',
},
'arrow-downward': {
path: ['M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z'],
viewBox: '0 0 24 24',
},
'arrow-upward': {
path: ['M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z'],
viewBox: '0 0 24 24',
} }
}; };

View File

@@ -1,6 +1,8 @@
.dashboard__insider--account-transactions { .dashboard__insider--account-transactions {
.bigcapital-datatable { .bigcapital-datatable {
.tbody { position: relative;
} top: -1px;
.tbody {}
} }
} }

View File

@@ -1,5 +1,7 @@
.dashboard__insider--cashflow-accounts { .dashboard__insider--cashflow-accounts {
.bigcapital-datatable { .bigcapital-datatable {
.table { .table {
.tbody { .tbody {
.td.balance { .td.balance {
@@ -9,6 +11,7 @@
} }
} }
} }
.account_name { .account_name {
.bp3-popover-wrapper--inactive-semafro { .bp3-popover-wrapper--inactive-semafro {
margin-left: 8px; margin-left: 8px;
@@ -16,9 +19,11 @@
float: right; float: right;
border: 0; border: 0;
} }
.bp3-popover-wrapper--account-desc { .bp3-popover-wrapper--account-desc {
border-bottom-color: #bbb; border-bottom-color: #bbb;
} }
.inactive-semafro { .inactive-semafro {
height: 7px; height: 7px;
width: 7px; width: 7px;