mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 14:20:31 +00:00
feat: add view detail cash flow transaction.
This commit is contained in:
@@ -7,6 +7,7 @@ import { useDeleteCashflowTransaction } from 'hooks/query';
|
||||
|
||||
import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect';
|
||||
import withAlertActions from 'containers/Alert/withAlertActions';
|
||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
@@ -22,6 +23,9 @@ function AccountDeleteTransactionAlert({
|
||||
|
||||
// #withAlertActions
|
||||
closeAlert,
|
||||
|
||||
// #withDrawerActions
|
||||
closeDrawer,
|
||||
}) {
|
||||
const { mutateAsync: deleteTransactionMutate, isLoading } =
|
||||
useDeleteCashflowTransaction();
|
||||
@@ -39,6 +43,7 @@ function AccountDeleteTransactionAlert({
|
||||
message: intl.get('cash_flow_transaction.delete.alert_message'),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
closeDrawer('cashflow-transaction-drawer');
|
||||
})
|
||||
.catch(
|
||||
({
|
||||
@@ -77,4 +82,5 @@ function AccountDeleteTransactionAlert({
|
||||
export default compose(
|
||||
withAlertStoreConnect(),
|
||||
withAlertActions,
|
||||
withDrawerActions,
|
||||
)(AccountDeleteTransactionAlert);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { DataTable, TableFastCell } from 'components';
|
||||
import { DataTable, TableFastCell, FormattedMessage as T } from 'components';
|
||||
import { TABLES } from 'common/tables';
|
||||
|
||||
import TableVirtualizedListRows from 'components/Datatable/TableVirtualizedRows';
|
||||
@@ -10,6 +10,7 @@ import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
|
||||
|
||||
import withSettings from '../../Settings/withSettings';
|
||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||
import withDrawerActions from 'containers/Drawer/withDrawerActions';
|
||||
|
||||
import { useMemorizedColumnsWidths } from '../../../hooks';
|
||||
import { useAccountTransactionsColumns, ActionsMenu } from './components';
|
||||
@@ -25,6 +26,9 @@ function AccountTransactionsDataTable({
|
||||
|
||||
// #withAlertsActions
|
||||
openAlert,
|
||||
|
||||
// #withDrawerActions
|
||||
openDrawer,
|
||||
}) {
|
||||
// Retrieve table columns.
|
||||
const columns = useAccountTransactionsColumns();
|
||||
@@ -42,6 +46,39 @@ function AccountTransactionsDataTable({
|
||||
openAlert('account-transaction-delete', { referenceId: reference_id });
|
||||
};
|
||||
|
||||
const handleViewDetailCashflowTransaction = ({
|
||||
reference_id,
|
||||
reference_type,
|
||||
}) => {
|
||||
switch (reference_type) {
|
||||
case 'SaleReceipt':
|
||||
return openDrawer('receipt-detail-drawer', {
|
||||
receiptId: reference_id,
|
||||
});
|
||||
case 'Journal':
|
||||
return openDrawer('journal-drawer', {
|
||||
manualJournalId: reference_id,
|
||||
});
|
||||
case 'Expense':
|
||||
return openDrawer('expense-drawer', {
|
||||
expenseId: reference_id,
|
||||
});
|
||||
case 'PaymentReceive':
|
||||
return openDrawer('payment-receive-detail-drawer', {
|
||||
paymentReceiveId: reference_id,
|
||||
});
|
||||
case 'BillPayment':
|
||||
return openDrawer('payment-made-detail-drawer', {
|
||||
paymentMadeId: reference_id,
|
||||
});
|
||||
|
||||
default:
|
||||
return openDrawer('cashflow-transaction-drawer', {
|
||||
referenceId: reference_id,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CashflowTransactionsTable
|
||||
noInitialFetch={true}
|
||||
@@ -64,10 +101,15 @@ function AccountTransactionsDataTable({
|
||||
initialColumnsWidths={initialColumnsWidths}
|
||||
onColumnResizing={handleColumnResizing}
|
||||
noResults={
|
||||
'There is deposit/withdrawal transactions on the current account.'
|
||||
<T
|
||||
id={
|
||||
'cash_flow_there_is_deposit_withdrawal_transactions_on_the_current_account'
|
||||
}
|
||||
/>
|
||||
}
|
||||
className="table-constrant"
|
||||
payload={{
|
||||
onViewDetails: handleViewDetailCashflowTransaction,
|
||||
onDelete: handleDeleteTransaction,
|
||||
}}
|
||||
/>
|
||||
@@ -79,6 +121,7 @@ export default compose(
|
||||
cashflowTansactionsTableSize: cashflowTransactionsSettings?.tableSize,
|
||||
})),
|
||||
withAlertsActions,
|
||||
withDrawerActions,
|
||||
)(AccountTransactionsDataTable);
|
||||
|
||||
const DashboardConstrantTable = styled(DataTable)`
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Popover,
|
||||
@@ -61,7 +62,7 @@ function AccountBalanceItem() {
|
||||
|
||||
return (
|
||||
<AccountBalanceItemWrap>
|
||||
Balance in Bigcapital{' '}
|
||||
{intl.get('cash_flow_balance_in', { name: 'Bigcapital' })}
|
||||
<AccountBalanceAmount>
|
||||
{currentAccount.formatted_amount}
|
||||
</AccountBalanceAmount>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
import { Intent, Menu, MenuItem } from '@blueprintjs/core';
|
||||
import { Intent, Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
|
||||
|
||||
import { MaterialProgressBar } from 'components';
|
||||
import { FormatDateCell, If, Icon } from 'components';
|
||||
@@ -9,18 +9,27 @@ import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
import { TRANSACRIONS_TYPE } from 'common/cashflowOptions';
|
||||
import { safeCallback } from 'utils';
|
||||
|
||||
export function ActionsMenu({ payload: { onDelete }, row: { original } }) {
|
||||
export function ActionsMenu({
|
||||
payload: { onDelete, onViewDetails },
|
||||
row: { original },
|
||||
}) {
|
||||
return (
|
||||
<If condition={TRANSACRIONS_TYPE.includes(original.reference_type)}>
|
||||
<Menu>
|
||||
<Menu>
|
||||
<MenuItem
|
||||
icon={<Icon icon="reader-18" />}
|
||||
text={intl.get('view_details')}
|
||||
onClick={safeCallback(onViewDetails, original)}
|
||||
/>
|
||||
<If condition={TRANSACRIONS_TYPE.includes(original.reference_type)}>
|
||||
<MenuDivider />
|
||||
<MenuItem
|
||||
text={intl.get('delete_transaction')}
|
||||
intent={Intent.DANGER}
|
||||
onClick={safeCallback(onDelete, original)}
|
||||
icon={<Icon icon="trash-16" iconSize={16} />}
|
||||
/>
|
||||
</Menu>
|
||||
</If>
|
||||
</If>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
BankAccount,
|
||||
If,
|
||||
Icon,
|
||||
T,
|
||||
} from '../../../components';
|
||||
import AccountsAlerts from './../../Accounts/AccountsAlerts';
|
||||
|
||||
@@ -169,7 +170,11 @@ function CashflowAccountsEmptyState() {
|
||||
return (
|
||||
<AccountsEmptyStateBase>
|
||||
<AccountsEmptyStateTitle>
|
||||
There is no cashflow accounts with current filter criteria.
|
||||
<T
|
||||
id={
|
||||
'cash_flow_there_is_no_cashflow_accounts_with_current_filter_criteria'
|
||||
}
|
||||
/>
|
||||
</AccountsEmptyStateTitle>
|
||||
</AccountsEmptyStateBase>
|
||||
);
|
||||
@@ -248,14 +253,14 @@ function CashflowAccountContextMenu({
|
||||
/>
|
||||
<MenuDivider />
|
||||
<MenuItem
|
||||
text={'Money In'}
|
||||
text={<T id={'cash_flow_money_in'} />}
|
||||
icon={<Icon icon={'arrow-downward'} iconSize={16} />}
|
||||
>
|
||||
<CashflowAccountMoneyInContextMenu onClick={onMoneyInClick} />
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
text={'Money Out'}
|
||||
text={<T id={'cash_flow_money_out'} />}
|
||||
icon={<Icon icon={'arrow-upward'} iconSize={16} />}
|
||||
>
|
||||
<CashflowAccountMoneyOutContextMenu onClick={onMoneyOutClick} />
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import Icon from 'components/Icon';
|
||||
import { Button, Classes, NavbarGroup, Intent } from '@blueprintjs/core';
|
||||
import { FormattedMessage as T } from 'components';
|
||||
|
||||
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
|
||||
import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider';
|
||||
import withAlertsActions from 'containers/Alert/withAlertActions';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Cashflow transaction drawer action bar.
|
||||
*/
|
||||
function CashflowTransactionDrawerActionBar({
|
||||
// #withAlertsDialog
|
||||
openAlert,
|
||||
}) {
|
||||
const { referenceId } = useCashflowTransactionDrawerContext();
|
||||
|
||||
// Handle cashflow transaction delete action.
|
||||
const handleDeleteCashflowTransaction = () => {
|
||||
openAlert('account-transaction-delete', { referenceId });
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<NavbarGroup>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="trash-16" iconSize={16} />}
|
||||
text={<T id={'delete'} />}
|
||||
intent={Intent.DANGER}
|
||||
onClick={handleDeleteCashflowTransaction}
|
||||
/>
|
||||
</NavbarGroup>
|
||||
</DashboardActionsBar>
|
||||
);
|
||||
}
|
||||
export default compose(withAlertsActions)(CashflowTransactionDrawerActionBar);
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
|
||||
import 'style/components/Drawers/CashflowTransactionDrawer.scss';
|
||||
|
||||
import { DrawerBody } from 'components';
|
||||
import { CashflowTransactionDrawerProvider } from './CashflowTransactionDrawerProvider';
|
||||
import CashflowTransactionDrawerDetails from './CashflowTransactionDrawerDetails';
|
||||
|
||||
/**
|
||||
* Cash flow transction drawer content.
|
||||
*/
|
||||
export default function CashflowTransactionDrawerContent({
|
||||
// #ownProp
|
||||
referenceId,
|
||||
}) {
|
||||
return (
|
||||
<CashflowTransactionDrawerProvider referenceId={referenceId}>
|
||||
<DrawerBody>
|
||||
<CashflowTransactionDrawerDetails />
|
||||
</DrawerBody>
|
||||
</CashflowTransactionDrawerProvider>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Card } from 'components';
|
||||
|
||||
import CashflowTransactionDrawerActionBar from './CashflowTransactionDrawerActionBar';
|
||||
import CashflowTransactionDrawerHeader from './CashflowTransactionDrawerHeader';
|
||||
import CashflowTransactionDrawerTable from './CashflowTransactionDrawerTable';
|
||||
import CashflowTransactionDrawerFooter from './CashflowTransactionDrawerFooter';
|
||||
/**
|
||||
* Cashflow transaction view details.
|
||||
*/
|
||||
export default function CashflowTransactionDrawerDetails() {
|
||||
return (
|
||||
<div className={'cashflow-drawer'}>
|
||||
<CashflowTransactionDrawerActionBar />
|
||||
<div className="cashflow-drawer__content">
|
||||
<Card>
|
||||
<CashflowTransactionDrawerHeader />
|
||||
<CashflowTransactionDrawerTable />
|
||||
<CashflowTransactionDrawerFooter />
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider';
|
||||
import { T, FormatNumber } from '../../../components';
|
||||
|
||||
export default function CashflowTransactionDrawerFooter() {
|
||||
const {
|
||||
cashflowTransaction: { amount },
|
||||
} = useCashflowTransactionDrawerContext();
|
||||
|
||||
return (
|
||||
<div className="cashflow-drawer__content-footer">
|
||||
<div class="total-lines">
|
||||
<div class="total-lines__line total-lines__line--subtotal">
|
||||
<div class="title">
|
||||
<T id={'manual_journal.details.subtotal'} />
|
||||
</div>
|
||||
<div class="debit">
|
||||
<FormatNumber value={amount} />
|
||||
</div>
|
||||
<div class="credit">
|
||||
<FormatNumber value={amount} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="total-lines__line total-lines__line--total">
|
||||
<div class="title">
|
||||
<T id={'manual_journal.details.total'} />
|
||||
</div>
|
||||
<div class="debit">{amount}</div>
|
||||
<div class="credit">{amount}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import { defaultTo } from 'lodash';
|
||||
import {
|
||||
DetailsMenu,
|
||||
DetailItem,
|
||||
FormatDate,
|
||||
FormattedMessage as T,
|
||||
} from 'components';
|
||||
import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider';
|
||||
|
||||
/**
|
||||
* Cashlflow transaction drawer detail Header.
|
||||
*/
|
||||
export default function CashflowTransactionDrawerHeader() {
|
||||
const {
|
||||
cashflowTransaction: {
|
||||
amount,
|
||||
transaction_type,
|
||||
transaction_number,
|
||||
reference_no,
|
||||
date,
|
||||
description,
|
||||
},
|
||||
} = useCashflowTransactionDrawerContext();
|
||||
|
||||
return (
|
||||
<div className={'cashflow-drawer__content-header'}>
|
||||
<DetailsMenu>
|
||||
<DetailItem name={'total'} label={<T id={'total'} />}>
|
||||
<h3 class="amount">{amount}</h3>
|
||||
</DetailItem>
|
||||
|
||||
<DetailItem
|
||||
name={'transaction_type'}
|
||||
label={<T id={'cash_flow_drawer.label_transaction_type'} />}
|
||||
>
|
||||
{transaction_type}
|
||||
</DetailItem>
|
||||
|
||||
<DetailItem
|
||||
name={'transaction_number'}
|
||||
label={<T id={'cash_flow.drawer.label_transaction_no'} />}
|
||||
>
|
||||
{transaction_number}
|
||||
</DetailItem>
|
||||
<DetailItem
|
||||
label={<T id={'date'} />}
|
||||
children={<FormatDate value={date} />}
|
||||
/>
|
||||
<DetailItem name={'reference-no'} label={<T id={'reference_no'} />}>
|
||||
{defaultTo(reference_no, '-')}
|
||||
</DetailItem>
|
||||
</DetailsMenu>
|
||||
|
||||
<div class="cashflow-drawer__content-description">
|
||||
<b class="title">
|
||||
<T id={'description'} />
|
||||
</b>
|
||||
: {defaultTo(description, '—')}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import { useCashflowTransaction } from 'hooks/query';
|
||||
|
||||
import { DrawerLoading, DrawerHeaderContent } from 'components';
|
||||
|
||||
const CashflowTransactionDrawerContext = React.createContext();
|
||||
|
||||
/**
|
||||
* Cashflow transaction drawer provider.
|
||||
*/
|
||||
function CashflowTransactionDrawerProvider({ referenceId, ...props }) {
|
||||
// Fetch the specific cashflow transaction details.
|
||||
const {
|
||||
data: cashflowTransaction,
|
||||
isLoading: isCashflowTransactionLoading,
|
||||
isFetching: isCashflowTransactionFetching,
|
||||
} = useCashflowTransaction(referenceId, {
|
||||
enabled: !!referenceId,
|
||||
});
|
||||
|
||||
// Provider.
|
||||
const provider = {
|
||||
referenceId,
|
||||
cashflowTransaction,
|
||||
|
||||
isCashflowTransactionFetching,
|
||||
isCashflowTransactionLoading,
|
||||
};
|
||||
|
||||
return (
|
||||
<DrawerLoading loading={isCashflowTransactionLoading}>
|
||||
<DrawerHeaderContent
|
||||
name={'cashflow-transaction-drawer'}
|
||||
title={intl.get('cash_flow.drawer.label_transaction', {
|
||||
number: cashflowTransaction?.transaction_number,
|
||||
})}
|
||||
/>
|
||||
<CashflowTransactionDrawerContext.Provider value={provider} {...props} />
|
||||
</DrawerLoading>
|
||||
);
|
||||
}
|
||||
|
||||
const useCashflowTransactionDrawerContext = () =>
|
||||
React.useContext(CashflowTransactionDrawerContext);
|
||||
|
||||
export {
|
||||
CashflowTransactionDrawerProvider,
|
||||
useCashflowTransactionDrawerContext,
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
|
||||
import { DataTable, If, FormattedMessage as T } from 'components';
|
||||
|
||||
import { useCashflowTransactionColumns } from './utils';
|
||||
import { useCashflowTransactionDrawerContext } from './CashflowTransactionDrawerProvider';
|
||||
|
||||
/**
|
||||
* Cashflow transaction drawer table.
|
||||
*/
|
||||
export default function CashflowTransactionDrawerTable() {
|
||||
const columns = useCashflowTransactionColumns();
|
||||
const {
|
||||
cashflowTransaction: { transactions },
|
||||
} = useCashflowTransactionDrawerContext();
|
||||
|
||||
return (
|
||||
<div className="cashflow-drawer__content-table">
|
||||
<DataTable columns={columns} data={transactions} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Drawer, DrawerSuspense } from 'components';
|
||||
import withDrawers from 'containers/Drawer/withDrawers';
|
||||
|
||||
import { compose } from 'utils';
|
||||
|
||||
const CashFlowTransactionDrawerContent = React.lazy(() =>
|
||||
import('./CashflowTransactionDrawerContent'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Cash flow transaction drawer
|
||||
*/
|
||||
function CashflowTransactionDetailDrawer({
|
||||
name,
|
||||
// #withDrawer
|
||||
isOpen,
|
||||
payload: { referenceId },
|
||||
}) {
|
||||
return (
|
||||
<Drawer
|
||||
isOpen={isOpen}
|
||||
name={name}
|
||||
size={'65%'}
|
||||
style={{ minWidth: '700px', maxWidth: '900px' }}
|
||||
>
|
||||
<DrawerSuspense>
|
||||
<CashFlowTransactionDrawerContent referenceId={referenceId} />
|
||||
</DrawerSuspense>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDrawers())(CashflowTransactionDetailDrawer);
|
||||
@@ -0,0 +1,76 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import React from 'react';
|
||||
import { Classes, Tooltip, Position } from '@blueprintjs/core';
|
||||
|
||||
import { FormatNumberCell, If, Icon } from '../../../components';
|
||||
|
||||
/**
|
||||
* Note column accessor.
|
||||
*/
|
||||
export function NoteAccessor(row) {
|
||||
return (
|
||||
<If condition={row.note}>
|
||||
<Tooltip
|
||||
className={Classes.TOOLTIP_INDICATOR}
|
||||
content={row.note}
|
||||
position={Position.LEFT_TOP}
|
||||
hoverOpenDelay={50}
|
||||
>
|
||||
<Icon icon={'file-alt'} iconSize={16} />
|
||||
</Tooltip>
|
||||
</If>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve cashflow transaction entries columns.
|
||||
*/
|
||||
export const useCashflowTransactionColumns = () =>
|
||||
React.useMemo(
|
||||
() => [
|
||||
{
|
||||
Header: intl.get('account_name'),
|
||||
accessor: 'account.name',
|
||||
width: 130,
|
||||
disableSortBy: true,
|
||||
className: 'account',
|
||||
},
|
||||
{
|
||||
Header: intl.get('contact'),
|
||||
accessor: 'contact.display_name',
|
||||
width: 130,
|
||||
disableSortBy: true,
|
||||
className: 'contact',
|
||||
},
|
||||
{
|
||||
Header: intl.get('note'),
|
||||
accessor: NoteAccessor,
|
||||
width: 80,
|
||||
disableSortBy: true,
|
||||
className: 'note',
|
||||
},
|
||||
{
|
||||
Header: intl.get('credit'),
|
||||
accessor: 'credit',
|
||||
Cell: FormatNumberCell,
|
||||
width: 100,
|
||||
disableResizable: true,
|
||||
disableSortBy: true,
|
||||
formatNumber: { noZero: true },
|
||||
className: 'credit',
|
||||
align: 'right',
|
||||
},
|
||||
{
|
||||
Header: intl.get('debit'),
|
||||
accessor: 'debit',
|
||||
Cell: FormatNumberCell,
|
||||
width: 100,
|
||||
disableResizable: true,
|
||||
disableSortBy: true,
|
||||
formatNumber: { noZero: true },
|
||||
className: 'debit',
|
||||
align: 'right',
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
Reference in New Issue
Block a user