diff --git a/src/common/tables.js b/src/common/tables.js
index 6f0bf1fce..9acd9bd5c 100644
--- a/src/common/tables.js
+++ b/src/common/tables.js
@@ -12,10 +12,12 @@ export const TABLES = {
ACCOUNTS: 'accounts',
MANUAL_JOURNALS: 'manual_journal',
EXPENSES: 'expenses',
+ CASHFLOW_ACCOUNTS: 'cashflow_accounts',
+ CASHFLOW_Transactions: 'cashflow_transactions',
};
export const TABLE_SIZE = {
COMPACT: 'compact',
SMALL: 'small',
MEDIUM: 'medium',
-}
\ No newline at end of file
+};
diff --git a/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsActionsBar.js b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsActionsBar.js
new file mode 100644
index 000000000..d250f7257
--- /dev/null
+++ b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsActionsBar.js
@@ -0,0 +1,113 @@
+import React from 'react';
+import classNames from 'classnames';
+
+import { isEmpty } from 'lodash';
+import {
+ Button,
+ NavbarGroup,
+ Classes,
+ NavbarDivider,
+ Alignment,
+} from '@blueprintjs/core';
+
+import {
+ Icon,
+ DashboardRowsHeightButton,
+ FormattedMessage as T,
+} from 'components';
+
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import { useCashFlowAccountsContext } from './CashFlowAccountsProvider';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withSettings from '../../Settings/withSettings';
+import withSettingsActions from '../../Settings/withSettingsActions';
+
+import { compose } from 'utils';
+
+/**
+ * Cash Flow accounts actions bar.
+ */
+function CashFlowAccountsActionsBar({
+ // #withDialogActions
+ openDialog,
+
+ // #withSettings
+ cashflowTableSize,
+
+ // #withSettingsActions
+ addSetting,
+}) {
+ // Handle table row size change.
+ const handleTableRowSizeChange = (size) => {
+ addSetting('cashflowAccounts', 'tableSize', size);
+ };
+
+ // Handle click a refresh
+ const handleRefreshBtnClick = () => {};
+
+ // Handle add bank account.
+ const handleAddBankAccount = () => {
+ openDialog('account-form', {});
+ };
+
+ // Handle add cash account.
+ const handleAddCashAccount = () => {
+ openDialog('account-form', {});
+ };
+
+ return (
+
+
+ }
+ text={}
+ onClick={handleAddBankAccount}
+ />
+ }
+ text={}
+ onClick={handleAddCashAccount}
+ />
+
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+
+
+
+
+
+ }
+ onClick={handleRefreshBtnClick}
+ />
+
+
+ );
+}
+export default compose(
+ withDialogActions,
+ withSettingsActions,
+ withSettings(({ cashflowSettings }) => ({
+ cashflowTableSize: cashflowSettings?.tableSize,
+ })),
+)(CashFlowAccountsActionsBar);
diff --git a/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsDataTable.js b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsDataTable.js
new file mode 100644
index 000000000..579574c7c
--- /dev/null
+++ b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsDataTable.js
@@ -0,0 +1,67 @@
+import React from 'react';
+
+import { DataTable, TableFastCell } from 'components';
+import { TABLES } from 'common/tables';
+
+import TableVirtualizedListRows from 'components/Datatable/TableVirtualizedRows';
+import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
+import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
+import withSettings from '../../Settings/withSettings';
+
+import { useMemorizedColumnsWidths } from '../../../hooks';
+import { useCashFlowAccountsContext } from './CashFlowAccountsProvider';
+import { useCashFlowAccountsTableColumns } from './components';
+import { compose } from 'utils';
+
+/**
+ * Cash flow accounts data table.
+ */
+function CashFlowAccountsDataTable({
+ // #withSettings
+ cashflowTableSize,
+}) {
+ // Retrieve list context.
+ const {
+ cashflowAccounts,
+ isCashFlowAccountsFetching,
+ isCashFlowAccountsLoading,
+ } = useCashFlowAccountsContext();
+
+ // Retrieve table columns.
+ const columns = useCashFlowAccountsTableColumns();
+
+ // Local storage memorizing columns widths.
+ const [initialColumnsWidths, , handleColumnResizing] =
+ useMemorizedColumnsWidths(TABLES.CASHFLOW_ACCOUNTS);
+ return (
+
+ );
+}
+
+export default compose(
+ withSettings(({ cashflowSettings }) => ({
+ cashflowTableSize: cashflowSettings?.tableSize,
+ })),
+)(CashFlowAccountsDataTable);
diff --git a/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsList.js b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsList.js
new file mode 100644
index 000000000..0010b4ab6
--- /dev/null
+++ b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsList.js
@@ -0,0 +1,28 @@
+import React from 'react';
+
+import 'style/pages/CashFlow/CashFlowAccounts/List.scss';
+
+import { DashboardPageContent, DashboardContentTable } from 'components';
+
+import { CashFlowAccountsProvider } from './CashFlowAccountsProvider';
+
+import CashFlowAccountsActionsBar from './CashFlowAccountsActionsBar';
+import CashFlowAccountsDataTable from './CashFlowAccountsDataTable';
+
+/**
+ * Cash flow accounts list.
+ */
+function CashFlowAccountsList({}) {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
+
+export default CashFlowAccountsList;
diff --git a/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsProvider.js b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsProvider.js
new file mode 100644
index 000000000..1b33985a4
--- /dev/null
+++ b/src/containers/CashFlow/CashFlowAccounts/CashFlowAccountsProvider.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import DashboardInsider from 'components/Dashboard/DashboardInsider';
+
+import { useCashflowAccounts } from 'hooks/query';
+
+const CashFlowAccountsContext = React.createContext();
+
+/**
+ * Cash Flow data provider.
+ */
+function CashFlowAccountsProvider({ query, tableStateChanged, ...props }) {
+ // Fetch cash flow list .
+ const {
+ data: cashflowAccounts,
+ isFetching: isCashFlowAccountsFetching,
+ isLoading: isCashFlowAccountsLoading,
+ } = useCashflowAccounts(query, { keepPreviousData: true });
+
+ // Provider payload.
+ const provider = {
+ cashflowAccounts,
+ isCashFlowAccountsFetching,
+ isCashFlowAccountsLoading,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useCashFlowAccountsContext = () =>
+ React.useContext(CashFlowAccountsContext);
+export { CashFlowAccountsProvider, useCashFlowAccountsContext };
diff --git a/src/containers/CashFlow/CashFlowAccounts/components.js b/src/containers/CashFlow/CashFlowAccounts/components.js
new file mode 100644
index 000000000..b5a8ed329
--- /dev/null
+++ b/src/containers/CashFlow/CashFlowAccounts/components.js
@@ -0,0 +1,89 @@
+import React from 'react';
+
+import intl from 'react-intl-universal';
+import { Intent, Tag } from '@blueprintjs/core';
+import { isBlank } from 'utils';
+import { Link } from 'react-router-dom';
+
+
+/**
+ * Account code accessor.
+ */
+export const AccountCodeAccessor = (row) =>
+ !isBlank(row.code) ? (
+
+ {row.code}
+
+ ) : null;
+
+/**
+ * Balance cell.
+ */
+export const BalanceCell = ({ cell }) => {
+ const account = cell.row.original;
+
+ return account.amount !== null ? (
+ {account.formatted_amount}
+ ) : (
+ —
+ );
+};
+
+/**
+ * Account cell.
+ */
+const AccountCell = ({ row }) => {
+ const account = row.original;
+ return {account.name};
+};
+
+/**
+ * Retrieve Cash flow table columns.
+ */
+export function useCashFlowAccountsTableColumns() {
+ return React.useMemo(
+ () => [
+ {
+ id: 'name',
+ Header: intl.get('account_name'),
+ accessor: 'name',
+ Cell: AccountCell,
+
+ className: 'account_name',
+ width: 200,
+ textOverview: true,
+ },
+ {
+ id: 'code',
+ Header: intl.get('code'),
+ accessor: 'code',
+ className: 'code',
+ width: 80,
+ },
+ {
+ id: 'type',
+ Header: intl.get('type'),
+ accessor: 'account_type_label',
+ className: 'type',
+ width: 140,
+ textOverview: true,
+ },
+ {
+ id: 'currency',
+ Header: intl.get('currency'),
+ accessor: 'currency_code',
+ width: 75,
+ },
+ {
+ id: 'balance',
+ Header: intl.get('balance'),
+ accessor: 'amount',
+ className: 'balance',
+ Cell: BalanceCell,
+ width: 150,
+ align: 'right',
+ },
+ ],
+ [],
+ );
+}
diff --git a/src/containers/Settings/withSettings.js b/src/containers/Settings/withSettings.js
index 2cca4753e..f9bc3ba26 100644
--- a/src/containers/Settings/withSettings.js
+++ b/src/containers/Settings/withSettings.js
@@ -16,6 +16,9 @@ export default (mapState) => {
accountsSettings: state.settings.data.accounts,
customersSettings: state.settings.data.customers,
vendorsSettings: state.settings.data.vendors,
+ cashflowSettings: state.settings.data.cashflowAccounts,
+ cashflowTransactionsSettings: state.settings.data.cashflowTransactions,
+
};
return mapState ? mapState(mapped, state, props) : mapped;
};
diff --git a/src/hooks/query/cashflowAccounts.js b/src/hooks/query/cashflowAccounts.js
new file mode 100644
index 000000000..3bf25b0fd
--- /dev/null
+++ b/src/hooks/query/cashflowAccounts.js
@@ -0,0 +1,75 @@
+import { useMutation, useQueryClient } from 'react-query';
+import { useRequestQuery } from '../useQueryRequest';
+import useApiRequest from '../useRequest';
+import t from './types';
+
+const commonInvalidateQueries = (queryClient) => {
+ // queryClient.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
+ queryClient.invalidateQueries(t.CASH_FLOW_TRANSACTION);
+};
+
+/**
+ * Retrieve accounts list.
+ */
+export function useCashflowAccounts(query, props) {
+ return useRequestQuery(
+ [t.CASH_FLOW_ACCOUNTS, query],
+ { method: 'get', url: 'cashflow/accounts', params: query },
+ {
+ select: (res) => res.data.cashflow_accounts,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+/**
+ * Retrieve account transactions list.
+ */
+export function useCashflowTransactions(id, props) {
+ return useRequestQuery(
+ [t.CASH_FLOW_TRANSACTIONS, id],
+ { method: 'get', url: `cashflow/account/${1000}/transactions` },
+ {
+ select: (res) => res.data.cashflow_transactions,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
+
+/**
+ * Create Money in owner contribution .
+ */
+export function useCreateCashflowTransaction(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (values) => apiRequest.post('cashflow/transactions', values),
+ {
+ onSuccess: () => {
+ // Invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+/**
+ * Deletes the given sale invoice.
+ */
+export function useDeleteCashflowTransaction(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation((id) => apiRequest.delete(`cashflow/transactions/${id}`), {
+ onSuccess: (res, id) => {
+ queryClient.invalidateQueries([t.CASH_FLOW_TRANSACTION, id]);
+
+ // Invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ });
+}
diff --git a/src/store/settings/settings.reducer.js b/src/store/settings/settings.reducer.js
index 54962940b..28ceaa9e8 100644
--- a/src/store/settings/settings.reducer.js
+++ b/src/store/settings/settings.reducer.js
@@ -44,8 +44,14 @@ const initialState = {
tableSize: 'medium',
},
accounts: {
- tableSize: 'medium'
- }
+ tableSize: 'medium',
+ },
+ cashflowAccounts: {
+ tableSize: 'medium',
+ },
+ cashflowTransactions: {
+ tableSize: 'medium',
+ },
},
};
diff --git a/src/style/pages/CashFlow/CashFlowAccounts/List.scss b/src/style/pages/CashFlow/CashFlowAccounts/List.scss
new file mode 100644
index 000000000..149cec4d6
--- /dev/null
+++ b/src/style/pages/CashFlow/CashFlowAccounts/List.scss
@@ -0,0 +1,33 @@
+.dashboard__insider--cashflow-accounts {
+ .bigcapital-datatable {
+ .table {
+ .tbody {
+ .td.balance {
+ .cell-inner {
+ > span {
+ font-weight: 600;
+ }
+ }
+ }
+ .account_name {
+ .bp3-popover-wrapper--inactive-semafro {
+ margin-left: 8px;
+ margin-right: 6px;
+ float: right;
+ border: 0;
+ }
+ .bp3-popover-wrapper--account-desc {
+ border-bottom-color: #bbb;
+ }
+ .inactive-semafro {
+ height: 7px;
+ width: 7px;
+ background: #bbb;
+ display: inline-block;
+ border-radius: 8px;
+ }
+ }
+ }
+ }
+ }
+}