diff --git a/packages/server/src/api/controllers/Items/Items.ts b/packages/server/src/api/controllers/Items/Items.ts index 104de0b88..66deaffe4 100644 --- a/packages/server/src/api/controllers/Items/Items.ts +++ b/packages/server/src/api/controllers/Items/Items.ts @@ -177,7 +177,7 @@ export default class ItemsController extends BaseController { /** * Validate list query schema. */ - get validateListQuerySchema() { + private get validateListQuerySchema() { return [ query('column_sort_by').optional().trim().escape(), query('sort_order').optional().isIn(['desc', 'asc']), @@ -193,32 +193,20 @@ export default class ItemsController extends BaseController { ]; } - /** - * Validate autocomplete list query schema. - */ - get autocompleteQuerySchema() { - return [ - query('column_sort_by').optional().trim().escape(), - query('sort_order').optional().isIn(['desc', 'asc']), - - query('stringified_filter_roles').optional().isJSON(), - query('limit').optional().isNumeric().toInt(), - - query('keyword').optional().isString().trim().escape(), - ]; - } - /** * Stores the given item details to the storage. * @param {Request} req * @param {Response} res */ - async newItem(req: Request, res: Response, next: NextFunction) { + private async newItem(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const itemDTO: IItemDTO = this.matchedBodyData(req); try { - const storedItem = await this.itemsApplication.createItem(tenantId, itemDTO); + const storedItem = await this.itemsApplication.createItem( + tenantId, + itemDTO + ); return res.status(200).send({ id: storedItem.id, @@ -234,7 +222,7 @@ export default class ItemsController extends BaseController { * @param {Request} req * @param {Response} res */ - async editItem(req: Request, res: Response, next: NextFunction) { + private async editItem(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const itemId: number = req.params.id; const item: IItemDTO = this.matchedBodyData(req); @@ -257,7 +245,7 @@ export default class ItemsController extends BaseController { * @param {Response} res * @param {NextFunction} next */ - async activateItem(req: Request, res: Response, next: NextFunction) { + private async activateItem(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const itemId: number = req.params.id; @@ -279,7 +267,11 @@ export default class ItemsController extends BaseController { * @param {Response} res * @param {NextFunction} next */ - async inactivateItem(req: Request, res: Response, next: NextFunction) { + private async inactivateItem( + req: Request, + res: Response, + next: NextFunction + ) { const { tenantId } = req; const itemId: number = req.params.id; @@ -300,7 +292,7 @@ export default class ItemsController extends BaseController { * @param {Request} req * @param {Response} res */ - async deleteItem(req: Request, res: Response, next: NextFunction) { + private async deleteItem(req: Request, res: Response, next: NextFunction) { const itemId: number = req.params.id; const { tenantId } = req; @@ -322,7 +314,7 @@ export default class ItemsController extends BaseController { * @param {Response} res * @return {Response} */ - async getItem(req: Request, res: Response, next: NextFunction) { + private async getItem(req: Request, res: Response, next: NextFunction) { const itemId: number = req.params.id; const { tenantId } = req; @@ -342,7 +334,7 @@ export default class ItemsController extends BaseController { * @param {Request} req * @param {Response} res */ - async getItemsList(req: Request, res: Response, next: NextFunction) { + private async getItemsList(req: Request, res: Response, next: NextFunction) { const { tenantId } = req; const filter = { diff --git a/packages/server/src/interfaces/Account.ts b/packages/server/src/interfaces/Account.ts index d89616135..278840c3a 100644 --- a/packages/server/src/interfaces/Account.ts +++ b/packages/server/src/interfaces/Account.ts @@ -42,6 +42,7 @@ export enum AccountNormal { export interface IAccountsTransactionsFilter { accountId?: number; + limit?: number; } export interface IAccountTransaction { diff --git a/packages/server/src/services/Accounts/AccountTransactionTransformer.ts b/packages/server/src/services/Accounts/AccountTransactionTransformer.ts index 2c16aac76..e239b4da9 100644 --- a/packages/server/src/services/Accounts/AccountTransactionTransformer.ts +++ b/packages/server/src/services/Accounts/AccountTransactionTransformer.ts @@ -106,7 +106,7 @@ export default class AccountTransactionTransformer extends Transformer { * @returns {string} */ protected formattedFcCredit(transaction: IAccountTransaction) { - return this.formatMoney(this.fcDebit(transaction), { + return this.formatMoney(this.fcCredit(transaction), { currencyCode: transaction.currencyCode, excerptZero: true, }); @@ -117,7 +117,7 @@ export default class AccountTransactionTransformer extends Transformer { * @returns {string} */ protected formattedFcDebit(transaction: IAccountTransaction) { - return this.formatMoney(this.fcCredit(transaction), { + return this.formatMoney(this.fcDebit(transaction), { currencyCode: transaction.currencyCode, excerptZero: true, }); diff --git a/packages/webapp/src/components/Dashboard/DashboardBackLink.tsx b/packages/webapp/src/components/Dashboard/DashboardBackLink.tsx index e68501dfb..2471a46e0 100644 --- a/packages/webapp/src/components/Dashboard/DashboardBackLink.tsx +++ b/packages/webapp/src/components/Dashboard/DashboardBackLink.tsx @@ -2,7 +2,7 @@ import React from 'react'; import withBreadcrumbs from 'react-router-breadcrumbs-hoc'; import { useHistory } from 'react-router-dom'; -import { getDashboardRoutes } from '@/routes/dashboard'; + import { If, Icon } from '@/components'; import { FormattedMessage as T } from '@/components'; import withDashboard from '@/containers/Dashboard/withDashboard'; diff --git a/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTable.tsx b/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTable.tsx index 785ed93f9..1b08f102c 100644 --- a/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTable.tsx +++ b/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTable.tsx @@ -4,23 +4,24 @@ import intl from 'react-intl-universal'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; -import { compose } from '@/utils'; import { TableStyle } from '@/constants'; import { Card, DataTable, If } from '@/components'; +import { AccountDrawerTableOptionsProvider } from './AccountDrawerTableOptionsProvider'; +import { AccountDrawerTableHeader } from './AccountDrawerTableHeader'; + import { useAccountReadEntriesColumns } from './utils'; import { useAppIntlContext } from '@/components/AppIntlProvider'; import { useAccountDrawerContext } from './AccountDrawerProvider'; import withDrawerActions from '@/containers/Drawer/withDrawerActions'; +import { compose } from '@/utils'; + /** * account drawer table. */ function AccountDrawerTable({ closeDrawer }) { - const { account, accounts, drawerName } = useAccountDrawerContext(); - - // Account read-only entries table columns. - const columns = useAccountReadEntriesColumns(); + const { accounts, drawerName } = useAccountDrawerContext(); // Handle view more link click. const handleLinkClick = () => { @@ -31,27 +32,41 @@ function AccountDrawerTable({ closeDrawer }) { return ( - + + + - 0}> - - - {isRTL ? '→' : '←'} {intl.get('view_more_transactions')} - - - + 0}> + + + {isRTL ? '→' : '←'} {intl.get('view_more_transactions')} + + + + ); } +function AccountDrawerDataTable() { + const { account, accounts } = useAccountDrawerContext(); + + // Account read-only entries table columns. + const columns = useAccountReadEntriesColumns(); + + return ( + + ); +} + export default compose(withDrawerActions)(AccountDrawerTable); const TableFooter = styled.div` diff --git a/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTableHeader.tsx b/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTableHeader.tsx new file mode 100644 index 000000000..cd063cf5b --- /dev/null +++ b/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTableHeader.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { Button, ButtonGroup } from '@blueprintjs/core'; +import styled from 'styled-components'; +import { useAccountDrawerTableOptionsContext } from './AccountDrawerTableOptionsProvider'; + +export function AccountDrawerTableHeader() { + const { + setBCYCurrencyType, + setFYCCurrencyType, + isBCYCurrencyType, + isFCYCurrencyType, + } = useAccountDrawerTableOptionsContext(); + + const handleBCYBtnClick = () => { + setBCYCurrencyType(); + }; + const handleFCYBtnClick = () => { + setFYCCurrencyType(); + }; + + return ( + + + + + + + ); +} + +const TableHeaderRoot = styled.div` + margin-bottom: 1rem; +`; diff --git a/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTableOptionsProvider.tsx b/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTableOptionsProvider.tsx new file mode 100644 index 000000000..0156c6420 --- /dev/null +++ b/packages/webapp/src/containers/Drawers/AccountDrawer/AccountDrawerTableOptionsProvider.tsx @@ -0,0 +1,57 @@ +import React, { useState, useCallback } from 'react'; + +interface AccountDrawerTableOptionsContextValue { + setFYCCurrencyType: () => void; + setBCYCurrencyType: () => void; + isFCYCurrencyType: boolean; + isBCYCurrencyType: boolean; + currencyType: ForeignCurrencyType; +} + +const AccountDrawerTableOptionsContext = React.createContext( + {} as AccountDrawerTableOptionsContextValue, +); + +enum ForeignCurrencyTypes { + FCY = 'FCY', + BCY = 'BCY', +} +type ForeignCurrencyType = ForeignCurrencyTypes.FCY | ForeignCurrencyTypes.BCY; + +function AccountDrawerTableOptionsProvider({ + initialCurrencyType = ForeignCurrencyTypes.FCY, + ...props +}) { + const [currencyType, setCurrentType] = + useState(initialCurrencyType); + + const setFYCCurrencyType = useCallback( + () => setCurrentType(ForeignCurrencyTypes.FCY), + [setCurrentType], + ); + const setBCYCurrencyType = useCallback( + () => setCurrentType(ForeignCurrencyTypes.BCY), + [setCurrentType], + ); + + // Provider. + const provider = { + setFYCCurrencyType, + setBCYCurrencyType, + isFCYCurrencyType: currencyType === ForeignCurrencyTypes.FCY, + isBCYCurrencyType: currencyType === ForeignCurrencyTypes.BCY, + currencyType, + }; + + return ( + + ); +} + +const useAccountDrawerTableOptionsContext = () => + React.useContext(AccountDrawerTableOptionsContext); + +export { + AccountDrawerTableOptionsProvider, + useAccountDrawerTableOptionsContext, +}; diff --git a/packages/webapp/src/containers/Drawers/AccountDrawer/utils.tsx b/packages/webapp/src/containers/Drawers/AccountDrawer/utils.tsx index de1a237ea..564c4fdc7 100644 --- a/packages/webapp/src/containers/Drawers/AccountDrawer/utils.tsx +++ b/packages/webapp/src/containers/Drawers/AccountDrawer/utils.tsx @@ -3,27 +3,15 @@ import intl from 'react-intl-universal'; import React from 'react'; import { FormatDateCell } from '@/components'; -import { isBlank } from '@/utils'; - -/** - * Debit/credit table cell. - */ -function DebitCreditTableCell({ value, payload: { account } }) { - return !isBlank(value) && value !== 0 ? account.formatted_amount : null; -} - -/** - * Running balance table cell. - */ -function RunningBalanceTableCell({ value, payload: { account } }) { - return account.formatted_amount; -} +import { useAccountDrawerTableOptionsContext } from './AccountDrawerTableOptionsProvider'; /** * Retrieve entries columns of read-only account view. */ -export const useAccountReadEntriesColumns = () => - React.useMemo( +export const useAccountReadEntriesColumns = () => { + const { isFCYCurrencyType } = useAccountDrawerTableOptionsContext(); + + return React.useMemo( () => [ { Header: intl.get('transaction_date'), @@ -34,14 +22,15 @@ export const useAccountReadEntriesColumns = () => }, { Header: intl.get('transaction_type'), - accessor: 'reference_type_formatted', + accessor: 'transaction_type_formatted', width: 100, textOverview: true, }, { Header: intl.get('credit'), - accessor: 'credit', - Cell: DebitCreditTableCell, + accessor: isFCYCurrencyType + ? 'formatted_fc_credit' + : 'formatted_credit', width: 80, className: 'credit', align: 'right', @@ -49,22 +38,13 @@ export const useAccountReadEntriesColumns = () => }, { Header: intl.get('debit'), - accessor: 'debit', - Cell: DebitCreditTableCell, + accessor: isFCYCurrencyType ? 'formatted_fc_debit' : 'formatted_debit', width: 80, className: 'debit', align: 'right', textOverview: true, }, - { - Header: intl.get('running_balance'), - Cell: RunningBalanceTableCell, - accessor: 'running_balance', - width: 110, - className: 'running_balance', - align: 'right', - textOverview: true, - }, ], - [], + [isFCYCurrencyType], ); +};