diff --git a/client/src/containers/Accounts/AccountsDataTable.js b/client/src/containers/Accounts/AccountsDataTable.js
index c89eba307..4e5e7b983 100644
--- a/client/src/containers/Accounts/AccountsDataTable.js
+++ b/client/src/containers/Accounts/AccountsDataTable.js
@@ -13,6 +13,7 @@ import { useAccountsChartContext } from './AccountsChartProvider';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDialogActions from 'containers/Dialog/withDialogActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
/**
* Accounts data-table.
@@ -23,6 +24,9 @@ function AccountsDataTable({
// #withDial
openDialog,
+
+ // #withDrawerActions
+ openDrawer,
}) {
const {
isAccountsLoading,
@@ -59,6 +63,11 @@ function AccountsDataTable({
openDialog('account-form', { action: 'edit', id: account.id });
};
+ // Handle view detail account.
+ const handleViewDetailAccount = ({ id, name, code }) => {
+ openDrawer('account-drawer', { accountId: id, title: `${name} ${code}` });
+ };
+
// Handle new child button click.
const handleNewChildAccount = (account) => {
openDialog('account-form', {
@@ -76,40 +85,38 @@ function AccountsDataTable({
selectionColumn={true}
expandable={true}
sticky={true}
-
loading={isAccountsLoading}
headerLoading={isAccountsLoading}
progressBarLoading={isAccountsFetching}
-
rowClassNames={rowClassNames}
-
autoResetExpanded={false}
autoResetSortBy={false}
autoResetSelectedRows={false}
-
expandColumnSpace={1}
expandToggleColumn={2}
selectionColumnWidth={50}
-
TableCellRenderer={TableFastCell}
TableRowsRenderer={TableVirtualizedListRows}
TableLoadingRenderer={TableSkeletonRows}
TableHeaderSkeletonRenderer={TableSkeletonHeader}
ContextMenu={ActionsMenu}
-
// #TableVirtualizedListRows props.
vListrowHeight={42}
vListOverscanRowCount={0}
-
payload={{
onEdit: handleEditAccount,
onDelete: handleDeleteAccount,
onActivate: handleActivateAccount,
onInactivate: handleInactivateAccount,
- onNewChild: handleNewChildAccount
+ onNewChild: handleNewChildAccount,
+ onViewDetails: handleViewDetailAccount,
}}
/>
);
}
-export default compose(withAlertsActions, withDialogActions)(AccountsDataTable);
+export default compose(
+ withAlertsActions,
+ withDrawerActions,
+ withDialogActions,
+)(AccountsDataTable);
diff --git a/client/src/containers/Accounts/components.js b/client/src/containers/Accounts/components.js
index 28d5e541a..741293354 100644
--- a/client/src/containers/Accounts/components.js
+++ b/client/src/containers/Accounts/components.js
@@ -27,6 +27,7 @@ export function ActionsMenu({
onNewChild,
onActivate,
onInactivate,
+ // onDrawer,
},
}) {
return (
diff --git a/client/src/containers/Drawers/AccountDrawer/AccountDrawerActionBar.js b/client/src/containers/Drawers/AccountDrawer/AccountDrawerActionBar.js
new file mode 100644
index 000000000..7df7f3ade
--- /dev/null
+++ b/client/src/containers/Drawers/AccountDrawer/AccountDrawerActionBar.js
@@ -0,0 +1,85 @@
+import React from 'react';
+import Icon from 'components/Icon';
+import { Button, Classes, NavbarGroup, Intent } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import withAlertsActions from 'containers/Alert/withAlertActions';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+import { safeCallback } from 'utils';
+
+import { compose } from 'utils';
+
+/**
+ * Account drawer action bar.
+ */
+function AccountDrawerActionBar({
+ // #withDialog
+ openDialog,
+
+ // #withAlertsDialog
+ openAlert,
+
+ // #withDrawerActions
+ closeDrawer,
+
+ // #ownProps
+ account,
+}) {
+
+
+ // Handle new child button click.
+ const onNewChildAccount = () => {
+ openDialog('account-form', {
+ action: 'new_child',
+ parentAccountId: account.id,
+ accountType: account.account_type,
+ });
+ };
+
+ // Handle edit account action.
+ const onEditAccount = () => {
+ openDialog('account-form', { action: 'edit', id: account.id });
+ };
+
+ // Handle delete action account.
+ const onDeleteAccount = () => {
+ if (account) {
+ openAlert('account-delete', { accountId: account.id });
+ closeDrawer('account-drawer');
+ }
+ };
+
+ return (
+
+
+ }
+ text={}
+ onClick={safeCallback(onEditAccount)}
+ />
+ }
+ text={}
+ onClick={safeCallback(onNewChildAccount)}
+ />
+ }
+ text={}
+ // intent={Intent.DANGER}
+ onClick={safeCallback(onDeleteAccount)}
+ />
+
+
+ );
+}
+export default compose(
+ withDialogActions,
+ withAlertsActions,
+ withDrawerActions,
+)(AccountDrawerActionBar);
diff --git a/client/src/containers/Drawers/AccountDrawer/AccountDrawerContent.js b/client/src/containers/Drawers/AccountDrawer/AccountDrawerContent.js
new file mode 100644
index 000000000..adea3f343
--- /dev/null
+++ b/client/src/containers/Drawers/AccountDrawer/AccountDrawerContent.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import { AccountDrawerProvider } from './AccountDrawerProvider';
+import AccountDrawerDetails from './AccountDrawerDetails';
+
+/**
+ * Account drawer content.
+ */
+export default function AccountDrawerContent({
+ // #ownProp
+ accountId,
+}) {
+ return (
+
+
+
+ );
+}
diff --git a/client/src/containers/Drawers/AccountDrawer/AccountDrawerDetails.js b/client/src/containers/Drawers/AccountDrawer/AccountDrawerDetails.js
new file mode 100644
index 000000000..230d89beb
--- /dev/null
+++ b/client/src/containers/Drawers/AccountDrawer/AccountDrawerDetails.js
@@ -0,0 +1,23 @@
+import React from 'react';
+
+import AccountDrawerActionBar from './AccountDrawerActionBar';
+import AccountDrawerHeader from './AccountDrawerHeader';
+import AccountDrawerTable from './AccountDrawerTable';
+import { useAccountDrawerContext } from './AccountDrawerProvider';
+
+import 'style/components/Drawer/AccountDrawer.scss';
+
+/**
+ * Account view details.
+ */
+export default function AccountDrawerDetails() {
+ const { account, accounts } = useAccountDrawerContext();
+
+ return (
+
+ );
+}
diff --git a/client/src/containers/Drawers/AccountDrawer/AccountDrawerHeader.js b/client/src/containers/Drawers/AccountDrawer/AccountDrawerHeader.js
new file mode 100644
index 000000000..06305c208
--- /dev/null
+++ b/client/src/containers/Drawers/AccountDrawer/AccountDrawerHeader.js
@@ -0,0 +1,61 @@
+import React from 'react';
+import { FormattedMessage as T } from 'react-intl';
+import { If, Money } from 'components';
+
+/**
+ * Account drawer header.
+ */
+export default function AccountDrawerHeader({
+ account: {
+ account_normal,
+ account_type_label,
+ code,
+ amount,
+ currency_code,
+ description,
+ },
+}) {
+ return (
+
+
+
Closing Balance
+
+ {}
+
+
+
+
+
+
+
{account_type_label}
+
+
+
+
+
+
{account_normal}
+
+
+
+
+
+
+
{currency_code}
+
+
+
+
+
+
+
+ : {description}
+
+
+
+ );
+}
diff --git a/client/src/containers/Drawers/AccountDrawer/AccountDrawerProvider.js b/client/src/containers/Drawers/AccountDrawer/AccountDrawerProvider.js
new file mode 100644
index 000000000..c5b879ff8
--- /dev/null
+++ b/client/src/containers/Drawers/AccountDrawer/AccountDrawerProvider.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import { useAccount, useAccountTransactions } from 'hooks/query';
+import DashboardInsider from 'components/Dashboard/DashboardInsider';
+
+const AccountDrawerContext = React.createContext();
+
+/**
+ * Account drawer provider.
+ */
+function AccountDrawerProvider({ accountId, ...props }) {
+ // Fetches the specific account details.
+ const { data: account, isLoading: isAccountLoading } = useAccount(accountId, {
+ enabled: !!accountId,
+ });
+
+ // Load the specific account transactions.
+ const {
+ data: accounts,
+ isLoading: isAccountsLoading,
+ } = useAccountTransactions(accountId, {
+ enabled: !!accountId,
+ });
+
+ // provider.
+ const provider = {
+ accountId,
+ account,
+ accounts,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useAccountDrawerContext = () => React.useContext(AccountDrawerContext);
+
+export { AccountDrawerProvider, useAccountDrawerContext };
diff --git a/client/src/containers/Drawers/AccountDrawer/AccountDrawerTable.js b/client/src/containers/Drawers/AccountDrawer/AccountDrawerTable.js
new file mode 100644
index 000000000..bdaf1a041
--- /dev/null
+++ b/client/src/containers/Drawers/AccountDrawer/AccountDrawerTable.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import moment from 'moment';
+import { useAccountDrawerContext } from './AccountDrawerProvider';
+
+import { formatMessage } from 'services/intl';
+import { DataTable, Money } from 'components';
+import { isBlank } from 'utils';
+
+/**
+ * account drawer table.
+ */
+export default function AccountDrawerTable() {
+ const {
+ account: { currency_code },
+ accounts,
+ } = useAccountDrawerContext();
+
+ const columns = React.useMemo(
+ () => [
+ {
+ Header: formatMessage({ id: 'transaction_date' }),
+ accessor: ({ date }) => moment(date).format('YYYY MMM DD'),
+ width: 110,
+ },
+ {
+ Header: formatMessage({ id: 'transaction_type' }),
+ accessor: 'reference_type_formatted',
+ width: 100,
+ },
+ {
+ Header: formatMessage({ id: 'credit' }),
+ accessor: ({ credit }) =>
+ !isBlank(credit) && credit !== 0 ? (
+
+ ) : null,
+ width: 80,
+ },
+ {
+ Header: formatMessage({ id: 'debit' }),
+ accessor: ({ debit }) =>
+ !isBlank(debit) && debit !== 0 ? (
+
+ ) : null,
+ width: 80,
+ },
+ {
+ Header: formatMessage({ id: 'running_balance' }),
+ accessor: 'balance',
+ width: 110,
+ },
+ ],
+ [],
+ );
+
+ return (
+
+
+
+ );
+}
diff --git a/client/src/containers/Drawers/AccountDrawer/index.js b/client/src/containers/Drawers/AccountDrawer/index.js
new file mode 100644
index 000000000..add27e274
--- /dev/null
+++ b/client/src/containers/Drawers/AccountDrawer/index.js
@@ -0,0 +1,35 @@
+import React, { lazy } from 'react';
+import { Drawer, DrawerSuspense } from 'components';
+import withDrawers from 'containers/Drawer/withDrawers';
+import withDrawerActions from 'containers/Drawer/withDrawerActions';
+
+import { compose } from 'utils';
+
+const AccountDrawerContent = lazy(() => import('./AccountDrawerContent'));
+
+/**
+ * Account drawer.
+ */
+function AccountDrawer({
+ name,
+ //#withDrawer
+ isOpen,
+ payload: { accountId, title },
+
+ closeDrawer,
+}) {
+ // Handle close drawer.
+ const handleDrawerClose = () => {
+ closeDrawer(name);
+ };
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default compose(withDrawers(), withDrawerActions)(AccountDrawer);
diff --git a/client/src/hooks/query/accounts.js b/client/src/hooks/query/accounts.js
index 2a2d54738..7a5d3a0c4 100644
--- a/client/src/hooks/query/accounts.js
+++ b/client/src/hooks/query/accounts.js
@@ -144,3 +144,19 @@ export function useInactivateAccount(props) {
...props,
});
}
+
+/**
+ * Retrieve account transactions.
+ */
+export function useAccountTransactions(id, props) {
+ console.log(id, 'FF');
+ return useRequestQuery(
+ [t.ACCOUNT_TRANSACTION, id],
+ { method: 'get', url: `accounts/transactions?account_id=${id}` },
+ {
+ select: (res) => res.data.transactions,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
diff --git a/client/src/hooks/query/types.js b/client/src/hooks/query/types.js
index 11cdb869d..f63e8ce7b 100644
--- a/client/src/hooks/query/types.js
+++ b/client/src/hooks/query/types.js
@@ -1,5 +1,6 @@
const ACCOUNTS = {
ACCOUNT: 'ACCOUNT',
+ ACCOUNT_TRANSACTION: 'ACCOUNT_TRANSACTION',
ACCOUNTS: 'ACCOUNTS',
ACCOUNTS_TYPES: 'ACCOUNTS_TYPES',
};
@@ -126,5 +127,5 @@ export default {
...ORGANIZATIONS,
...SUBSCRIPTIONS,
...EXPENSES,
- ...MANUAL_JOURNALS
+ ...MANUAL_JOURNALS,
};
diff --git a/client/src/style/components/Drawer/AccountDrawer.scss b/client/src/style/components/Drawer/AccountDrawer.scss
new file mode 100644
index 000000000..d94fbbc0f
--- /dev/null
+++ b/client/src/style/components/Drawer/AccountDrawer.scss
@@ -0,0 +1,79 @@
+.account-drawer {
+ background-color: #fbfbfb;
+
+ &__content {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ margin: 18px;
+ padding: 15px;
+ background: white;
+ border: 1px solid #d2dce2;
+ color: #666666;
+
+ > div {
+ flex-grow: 1;
+ font-size: 14px;
+ margin: 15px 0;
+
+ .balance,
+ p {
+ text-transform: capitalize;
+ margin: 5px 0;
+ }
+ .balance {
+ font-size: 26px;
+ font-weight: 500;
+ color: #000;
+ margin: 10px 0;
+ }
+ }
+ &--desc {
+ flex-basis: 100%;
+ b {
+ color: #000;
+ }
+ }
+ }
+
+ &__table {
+ margin: 18px;
+ background: #fff;
+ border: 1px solid #d2dce2;
+
+ .table {
+ .thead .tr .th .resizer {
+ display: none;
+ }
+ .thead .th,
+ .tbody .tr .td {
+ padding: 0.8rem;
+ font-size: 14px;
+ font-weight: 400;
+ color: #666666;
+ }
+ }
+ }
+}
+
+.bp3-drawer.bp3-position-right {
+ bottom: 0;
+ right: 0;
+ top: 0;
+ overflow: auto;
+ height: 100%;
+
+ scrollbar-width: none;
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ .bp3-drawer-header {
+ margin-bottom: 2px;
+ box-shadow: (0, 0, 0);
+ background-color: #6a7993;
+ .bp3-heading,
+ .bp3-icon {
+ color: white;
+ }
+ }
+}
diff --git a/server/src/api/controllers/Accounts.ts b/server/src/api/controllers/Accounts.ts
index 00df6347f..c5e3c428e 100644
--- a/server/src/api/controllers/Accounts.ts
+++ b/server/src/api/controllers/Accounts.ts
@@ -209,7 +209,7 @@ export default class AccountsController extends BaseController {
tenantId,
accountId
);
- return res.status(200).send({ account });
+ return res.status(200).send({ account: this.transfromToResponse(account) });
} catch (error) {
next(error);
}
diff --git a/server/src/services/Accounts/AccountsService.ts b/server/src/services/Accounts/AccountsService.ts
index 30945705b..2aef28d9f 100644
--- a/server/src/services/Accounts/AccountsService.ts
+++ b/server/src/services/Accounts/AccountsService.ts
@@ -665,7 +665,7 @@ export default class AccountsService {
key: 'base_currency',
});
return {
- ...account,
+ ...account.toJSON(),
currencyCode: baseCurrency,
};
}