feat: style read-only drawers.

fix: empty state in resources tables.
This commit is contained in:
a.bouhuolia
2021-08-24 14:57:19 +02:00
parent f5fd2aa324
commit af34986aac
143 changed files with 1530 additions and 915 deletions

View File

@@ -1,6 +1,12 @@
import React from 'react';
import Icon from 'components/Icon';
import { Button, Classes, NavbarGroup, Intent } from '@blueprintjs/core';
import {
Button,
Classes,
NavbarGroup,
Intent,
NavbarDivider,
} from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
@@ -11,6 +17,7 @@ import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { safeCallback } from 'utils';
import { compose } from 'utils';
import { useAccountDrawerContext } from './AccountDrawerProvider';
/**
* Account drawer action bar.
@@ -24,10 +31,10 @@ function AccountDrawerActionBar({
// #withDrawerActions
closeDrawer,
// #ownProps
account,
}) {
// Account drawer context.
const { account } = useAccountDrawerContext();
// Handle new child button click.
const onNewChildAccount = () => {
openDialog('account-form', {
@@ -44,10 +51,8 @@ function AccountDrawerActionBar({
// Handle delete action account.
const onDeleteAccount = () => {
if (account) {
openAlert('account-delete', { accountId: account.id });
closeDrawer('account-drawer');
}
openAlert('account-delete', { accountId: account.id });
closeDrawer('account-drawer');
};
return (
@@ -65,9 +70,10 @@ function AccountDrawerActionBar({
text={<T id={'new_child_account'} />}
onClick={safeCallback(onNewChildAccount)}
/>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon icon="trash-18" iconSize={18} />}
icon={<Icon icon={'trash-16'} iconSize={16} />}
text={<T id={'delete'} />}
intent={Intent.DANGER}
onClick={safeCallback(onDeleteAccount)}

View File

@@ -1,20 +1,21 @@
import React from 'react';
import { Card } from 'components';
import AccountDrawerActionBar from './AccountDrawerActionBar';
import AccountDrawerHeader from './AccountDrawerHeader';
import AccountDrawerTable from './AccountDrawerTable';
import { useAccountDrawerContext } from './AccountDrawerProvider';
/**
* Account view details.
*/
export default function AccountDrawerDetails() {
const { account, accounts } = useAccountDrawerContext();
return (
<div className={'account-drawer'}>
<AccountDrawerActionBar account={account} />
<AccountDrawerHeader account={account} />
<div className={'account-drawer'}>
<AccountDrawerActionBar />
<Card className={'card-header'}>
<AccountDrawerHeader />
</Card>
<AccountDrawerTable />
</div>
);

View File

@@ -1,68 +1,56 @@
import React from 'react';
import { defaultTo } from 'lodash';
import { FormattedMessage as T } from 'components';
import { Icon, Money } from 'components';
import { Icon, Money, DetailsMenu, DetailItem } from 'components';
import { useAccountDrawerContext } from './AccountDrawerProvider';
/**
* Account drawer header.
*/
export default function AccountDrawerHeader({
account: {
account_normal,
account_type_label,
code,
amount,
currency_code,
description,
},
}) {
export default function AccountDrawerHeader() {
const { account } = useAccountDrawerContext();
return (
<div className={'account-drawer__content'}>
<div>
<span>
<T id={'closing_balance'} />
</span>
<p className={'balance'}>
{<Money amount={amount} currency={currency_code} />}
</p>
</div>
<div class={'account-type'}>
<span>
<T id={'account_type'} />
</span>
<p>{account_type_label}</p>
</div>
<div class={'account-normal'}>
<span>
<T id={'account_normal'} />
</span>
<p>
{' '}
{account_normal}{' '}
<div className={'account-drawer__content-header'}>
<DetailsMenu>
<DetailItem
name={'closing-balance'}
label={<T id={'closing_balance'} />}
>
<h3 class={'big-number'}>
<Money amount={account.amount} currency={account.currency_code} />
</h3>
</DetailItem>
<DetailItem name={'account-type'} label={<T id={'account_type'} />}>
{account.account_type_label}
</DetailItem>
<DetailItem name={'account-normal'} label={<T id={'account_normal'} />}>
{account.account_normal}
<Icon
iconSize={14}
icon={`arrow-${account_normal === 'credit' ? 'down' : 'up'}`}
icon={`arrow-${
account.account_normal === 'credit' ? 'down' : 'up'
}`}
/>
</p>
</div>
<div>
<span>
<T id={'code'} />
</span>
<p>{code}</p>
</div>
<div>
<span>
<T id={'currency'} />
</span>
<p>{currency_code}</p>
</div>
</DetailItem>
<p className={'account-drawer__content--desc'}>
<b>
<T id={'description'} />
</b>
: {description ? description : '--'}
</p>
<DetailItem name={'code'} label={<T id={'code'} />}>
{account.code}
</DetailItem>
<DetailItem name={'currency'} label={<T id={'currency'} />}>
{account.currency_code}
</DetailItem>
</DetailsMenu>
<DetailsMenu direction={'horizantal'}>
<DetailItem name={'description'} label={<T id={'description'} />}>
{defaultTo(account.description, '--')}
</DetailItem>
</DetailsMenu>
</div>
);
}

View File

@@ -14,12 +14,12 @@ function AccountDrawerProvider({ accountId, name, ...props }) {
});
// Load the specific account transactions.
const {
data: accounts,
isLoading: isAccountsLoading,
} = useAccountTransactions(accountId, {
enabled: !!accountId,
});
const { data: accounts, isLoading: isAccountsLoading } =
useAccountTransactions(accountId, {
enabled: !!accountId,
});
// Drawer title.
const drawerTitle = `${account.name} ${account.code}`;
// provider.

View File

@@ -1,61 +1,29 @@
import React from 'react';
import moment from 'moment';
import { Link } from 'react-router-dom';
import intl from 'react-intl-universal';
import { useAccountDrawerContext } from './AccountDrawerProvider';
import intl from 'react-intl-universal';
import { DataTable, Money } from 'components';
import { isBlank, compose } from 'utils';
import { DataTable, If } from 'components';
import { compose } from 'utils';
import { useAccountReadEntriesColumns } from './utils';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
/**
* account drawer table.
*/
function AccountDrawerTable({ closeDrawer }) {
const {
account: { currency_code },
account,
accounts,
drawerName,
} = useAccountDrawerContext();
const columns = React.useMemo(
() => [
{
Header: intl.get('transaction_date'),
accessor: ({ date }) => moment(date).format('YYYY MMM DD'),
width: 110,
},
{
Header: intl.get('transaction_type'),
accessor: 'reference_type_formatted',
width: 100,
},
{
Header: intl.get('credit'),
accessor: ({ credit }) =>
!isBlank(credit) && credit !== 0 ? (
<Money amount={credit} currency={currency_code} />
) : null,
width: 80,
},
{
Header: intl.get('debit'),
accessor: ({ debit }) =>
!isBlank(debit) && debit !== 0 ? (
<Money amount={debit} currency={currency_code} />
) : null,
width: 80,
},
{
Header: intl.get('running_balance'),
accessor: ({ running_balance }) => (
<Money amount={running_balance} currency={currency_code} />
),
width: 110,
},
],
[],
);
// Account read-only entries table columns.
const columns = useAccountReadEntriesColumns();
// Handle view more link click.
const handleLinkClick = () => {
@@ -64,16 +32,18 @@ function AccountDrawerTable({ closeDrawer }) {
return (
<div className={'account-drawer__table'}>
<DataTable columns={columns} data={accounts} />
<DataTable columns={columns} data={accounts} payload={{ account }}/>
<div class="account-drawer__table-footer">
<Link
to={`/financial-reports/general-ledger`}
onClick={handleLinkClick}
>
{intl.get('view_more_transactions')}
</Link>
</div>
<If condition={accounts.length > 0}>
<div class="account-drawer__table-footer">
<Link
to={`/financial-reports/general-ledger`}
onClick={handleLinkClick}
>
{intl.get('view_more_transactions')}
</Link>
</div>
</If>
</div>
);
}

View File

@@ -15,9 +15,16 @@ function AccountDrawer({
isOpen,
payload: { accountId },
}) {
return (
<Drawer isOpen={isOpen} name={name} size={'900px'}>
<Drawer
isOpen={isOpen}
name={name}
style={{
minWidth: '700px',
maxWidth: '900px',
}}
size={'65%'}
>
<DrawerSuspense>
<AccountDrawerContent name={name} accountId={accountId} />
</DrawerSuspense>

View File

@@ -0,0 +1,62 @@
import intl from 'react-intl-universal';
import React from 'react';
import moment from 'moment';
import { Money } from 'components';
import { isBlank } from 'utils';
/**
* Debit/credit table cell.
*/
function DebitCreditTableCell({ value, payload: { account } }) {
return !isBlank(value) && value !== 0 ? (
<Money amount={value} currency={account.currency_code} />
) : null;
}
/**
* Running balance table cell.
*/
function RunningBalanceTableCell({ value, payload: { account } }) {
return (
<Money amount={value} currency={account.currency_code} />
);
}
/**
* Retrieve entries columns of read-only account view.
*/
export const useAccountReadEntriesColumns = () =>
React.useMemo(
() => [
{
Header: intl.get('transaction_date'),
accessor: ({ date }) => moment(date).format('YYYY MMM DD'),
width: 110,
},
{
Header: intl.get('transaction_type'),
accessor: 'reference_type_formatted',
width: 100,
},
{
Header: intl.get('credit'),
accessor: 'credit',
Cell: DebitCreditTableCell,
width: 80,
},
{
Header: intl.get('debit'),
accessor: 'debit',
Cell: DebitCreditTableCell,
width: 80,
},
{
Header: intl.get('running_balance'),
Cell: RunningBalanceTableCell,
accessor: 'running_balance',
width: 110,
},
],
[],
);

View File

@@ -1,23 +1,26 @@
import React from 'react';
import { useHistory } from 'react-router-dom';
import Icon from 'components/Icon';
import { Button, Classes, NavbarGroup, Intent } from '@blueprintjs/core';
import {
Button,
Classes,
NavbarGroup,
Intent,
NavbarDivider,
} from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import { safeCallback } from 'utils';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { compose } from 'utils';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
/**
* Expense drawer action bar.
*/
function ExpenseDrawerActionBar({
// #ownProps
expense,
// #withAlertsDialog
openAlert,
@@ -25,21 +28,18 @@ function ExpenseDrawerActionBar({
closeDrawer,
}) {
const history = useHistory();
const { expense } = useExpenseDrawerContext();
// Handle the expense edit action.
const onEditExpense = () => {
if (expense) {
history.push(`/expenses/${expense.id}/edit`);
closeDrawer('expense-drawer');
}
const handleEditExpense = () => {
history.push(`/expenses/${expense.id}/edit`);
closeDrawer('expense-drawer');
};
// Handle the expense delete action.
const onDeleteExpense = () => {
if (expense) {
openAlert('expense-delete', { expenseId: expense.id });
closeDrawer('expense-drawer');
}
const handleDeleteExpense = () => {
openAlert('expense-delete', { expenseId: expense.id });
closeDrawer('expense-drawer');
};
return (
@@ -49,15 +49,15 @@ function ExpenseDrawerActionBar({
className={Classes.MINIMAL}
icon={<Icon icon="pen-18" />}
text={<T id={'edit_expense'} />}
onClick={safeCallback(onEditExpense)}
onClick={handleEditExpense}
/>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon style={{ color: 'red' }} icon="trash-18" iconSize={18} />}
icon={<Icon icon="trash-16" iconSize={16} />}
text={<T id={'delete'} />}
// intent={Intent.DANGER}
onClick={safeCallback(onDeleteExpense)}
intent={Intent.DANGER}
onClick={handleDeleteExpense}
/>
</NavbarGroup>
</DashboardActionsBar>

View File

@@ -1,6 +1,6 @@
import React from 'react';
import 'style/components/Drawers/ViewDetails.scss';
import 'style/components/Drawers/ExpenseDrawer.scss';
import { ExpenseDrawerProvider } from './ExpenseDrawerProvider';
import ExpenseDrawerDetails from './ExpenseDrawerDetails';

View File

@@ -1,22 +1,26 @@
import React from 'react';
import { Card } from 'components';
import ExpenseDrawerActionBar from './ExpenseDrawerActionBar';
import ExpenseDrawerHeader from './ExpenseDrawerHeader';
import ExpenseDrawerTable from './ExpenseDrawerTable';
import ExpenseDrawerFooter from './ExpenseDrawerFooter';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
/**
* Expense view details.
*/
export default function ExpenseDrawerDetails() {
const { expense } = useExpenseDrawerContext();
return (
<div className={'expense-drawer'}>
<ExpenseDrawerActionBar expense={expense} />
<ExpenseDrawerActionBar />
<div className="expense-drawer__content">
<ExpenseDrawerHeader expense={expense} />
<ExpenseDrawerTable expense={expense} />
<ExpenseDrawerFooter expense={expense} />
<Card>
<ExpenseDrawerHeader />
<ExpenseDrawerTable />
<ExpenseDrawerFooter />
</Card>
</div>
</div>
);

View File

@@ -1,20 +1,19 @@
import React from 'react';
import { If, Money } from 'components';
import { FormattedMessage as T } from 'components';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
export default function ExpenseDrawerFooter() {
const { expense: { total_amount } } = useExpenseDrawerContext();
export default function ExpenseDrawerFooter({
expense: { total_amount, currency_code },
}) {
return (
<div className="expense-drawer__content--footer">
<div className="wrapper">
<div>
<span><T id={'sub_total'}/></span>
<p>{<Money amount={total_amount} currency={currency_code} />}</p>
<div className="expense-drawer__content-footer">
<div class="total-lines">
<div class="total-lines__line total-lines__line--subtotal">
<div class="title">Subtotal</div>
<div class="amount">{total_amount}</div>
</div>
<div>
<span><T id={'total'}/></span>
<p>{<Money amount={total_amount} currency={currency_code} />}</p>
<div class="total-lines__line total-lines__line--total">
<div class="title">TOTAL</div>
<div class="amount">{total_amount}</div>
</div>
</div>
</div>

View File

@@ -1,68 +1,58 @@
import React from 'react';
import moment from 'moment';
import { If, Money } from 'components';
import { defaultTo } from 'lodash';
import { DetailItem, DetailsMenu, Money } from 'components';
import { FormattedMessage as T } from 'components';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
/**
* Expense drawer content.
*/
export default function ExpenseDrawerHeader({
expense: {
total_amount,
payment_account: { name },
payment_date,
currency_code,
reference_no,
description,
published_at,
},
}) {
export default function ExpenseDrawerHeader() {
const {
expense: {
total_amount,
payment_date,
currency_code,
reference_no,
description,
published_at,
},
} = useExpenseDrawerContext();
return (
<div className={'expense-drawer__content--header'}>
<div className={'info'}>
<span>
<T id={'full_amount'} />
</span>
<p className="balance">
{<Money amount={total_amount} currency={currency_code} />}
</p>
</div>
<div className={'info'}>
<span>
<T id={'date'} />
</span>
<p>{moment(payment_date).format('YYYY MMM DD')}</p>
</div>
<div className={'info'}>
<span>
<T id={'payment_account_'} />
</span>
<p>{name}</p>
</div>
<div className={'info'}>
<span>
<T id={'currency'} />
</span>
<p>{currency_code}</p>
</div>
<div className={'info'}>
<span>
<T id={'reference_no'} />
</span>
<p>{reference_no}</p>
</div>
<div className={'info'}>
<span>
<T id={'published_at'} />
</span>
<p>{moment(published_at).format('YYYY MMM DD')}</p>
</div>
<div className={'info'}>
<span>
<T id={'description'} />
</span>
<p>{description}</p>
</div>
<div className={'expense-drawer__content-header'}>
<DetailsMenu>
<DetailItem name={'amount'} label={<T id={'full_amount'} />}>
<h3 class="big-number">
<Money amount={total_amount} currency={currency_code} />
</h3>
</DetailItem>
<DetailItem name={'date'} label={<T id={'date'} />}>
{moment(payment_date).format('YYYY MMM DD')}
</DetailItem>
<DetailItem name={'currency'} label={<T id={'currency'} />}>
{currency_code}
</DetailItem>
<DetailItem name={'reference'} label={<T id={'reference_no'} />}>
{defaultTo(reference_no, '-')}
</DetailItem>
<DetailItem label={<T id={'published_at'} />}>
{moment(published_at).format('YYYY MMM DD')}
</DetailItem>
</DetailsMenu>
<DetailsMenu direction={'horizantal'}>
<DetailItem label={<T id={'description'} />}>
{defaultTo(description, '—')}
</DetailItem>
<DetailItem label={<T id={'created_at'} />}>2021 Aug 24</DetailItem>
</DetailsMenu>
</div>
);
}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { useExpense } from 'hooks/query';
import { DrawerHeaderContent, DashboardInsider } from 'components';
import { DashboardInsider } from 'components';
const ExpenseDrawerDrawerContext = React.createContext();
@@ -8,16 +8,22 @@ const ExpenseDrawerDrawerContext = React.createContext();
* Expense drawer provider.
*/
function ExpenseDrawerProvider({ expenseId, ...props }) {
// Fetch the expense details.
const { data: expense, isLoading: isExpenseLoading } = useExpense(expenseId, {
const {
data: expense,
isLoading: isExpenseLoading,
isFetching: isExpenseFetching,
} = useExpense(expenseId, {
enabled: !!expenseId,
});
// provider.
// Provider.
const provider = {
expenseId,
expense,
isExpenseFetching,
isExpenseLoading,
};
return (
<DashboardInsider loading={isExpenseLoading}>

View File

@@ -1,40 +1,18 @@
import React from 'react';
import intl from 'react-intl-universal';
import { DataTable, Money } from 'components';
import { DataTable } from 'components';
import { useExpenseReadEntriesColumns } from './utils';
import { useExpenseDrawerContext } from './ExpenseDrawerProvider';
/**
* Expense details table.
*/
export default function ExpenseDrawerTable({
expense: { currency_code, categories },
}) {
const columns = React.useMemo(
() => [
{
Header: intl.get('expense_account'),
accessor: 'expense_account.name',
width: 110,
},
{
Header: intl.get('amount'),
accessor: ({ amount }) => (
<Money amount={amount} currency={currency_code} />
),
width: 100,
},
{
Header: intl.get('description'),
accessor: 'description',
width: 110,
},
],
[],
);
export default function ExpenseDrawerTable() {
const columns = useExpenseReadEntriesColumns();
const { expense } = useExpenseDrawerContext();
return (
<div className="expense-drawer__content--table">
<DataTable columns={columns} data={categories} />
<DataTable columns={columns} data={expense.categories} />
</div>
);
}

View File

@@ -15,10 +15,19 @@ function ExpenseDrawer({
//#withDrawer
isOpen,
payload: { expenseId, title },
payload: { expenseId },
}) {
return (
<Drawer isOpen={isOpen} name={name} title={intl.get('expense')}>
<Drawer
isOpen={isOpen}
name={name}
title={intl.get('expense')}
size={'65%'}
style={{
minWidth: '700px',
maxWidth: '900px',
}}
>
<DrawerSuspense>
<ExpenseDrawerContent expenseId={expenseId} />
</DrawerSuspense>

View File

@@ -0,0 +1,27 @@
import React from 'react';
import intl from 'react-intl-universal';
export const useExpenseReadEntriesColumns = () =>
React.useMemo(
() => [
{
Header: intl.get('expense_account'),
accessor: 'expense_account.name',
width: 110,
disableSortBy: true,
},
{
Header: intl.get('description'),
accessor: 'description',
width: 110,
disableSortBy: true,
},
{
Header: intl.get('amount'),
accessor: 'amount',
width: 100,
disableSortBy: true,
},
],
[],
);

View File

@@ -1,23 +1,26 @@
import React from 'react';
import { useHistory } from 'react-router-dom';
import Icon from 'components/Icon';
import { Button, Classes, NavbarGroup, Intent } from '@blueprintjs/core';
import {
Button,
Classes,
NavbarGroup,
Intent,
NavbarDivider,
} from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import { safeCallback } from 'utils';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { compose } from 'utils';
import { useManualJournalDrawerContext } from './ManualJournalDrawerProvider';
/**
* Manual journal action bar.
*/
function ManualJournalDrawerActionBar({
// #ownProps
manualJournal,
// #withAlertsDialog
openAlert,
@@ -25,21 +28,17 @@ function ManualJournalDrawerActionBar({
closeDrawer,
}) {
const history = useHistory();
const { manualJournalId } = useManualJournalDrawerContext();
// Handle edit manual journal action.
const onEditManualJournal = () => {
if (manualJournal) {
history.push(`/manual-journals/${manualJournal.id}/edit`);
closeDrawer('journal-drawer');
}
const handleEditManualJournal = () => {
history.push(`/manual-journals/${manualJournalId}/edit`);
closeDrawer('journal-drawer');
};
// Handle manual journal delete action.
const onDeleteManualJournal = () => {
if (manualJournal) {
openAlert('journal-delete', { manualJournalId: manualJournal.id });
closeDrawer('journal-drawer');
}
const handleDeleteManualJournal = () => {
openAlert('journal-delete', { manualJournalId });
};
return (
@@ -49,14 +48,15 @@ function ManualJournalDrawerActionBar({
className={Classes.MINIMAL}
icon={<Icon icon="pen-18" />}
text={<T id={'edit_journal'} />}
onClick={safeCallback(onEditManualJournal)}
onClick={handleEditManualJournal}
/>
<NavbarDivider />
<Button
className={Classes.MINIMAL}
icon={<Icon style={{ color: 'red' }} icon="trash-18" iconSize={18} />}
icon={<Icon icon="trash-16" iconSize={16} />}
text={<T id={'delete'} />}
onClick={safeCallback(onDeleteManualJournal)}
intent={Intent.DANGER}
onClick={handleDeleteManualJournal}
/>
</NavbarGroup>
</DashboardActionsBar>

View File

@@ -1,4 +1,7 @@
import React from 'react';
import { Card } from 'components';
import ManualJournalDrawerActionBar from './ManualJournalDrawerActionBar';
import ManualJournalDrawerHeader from './ManualJournalDrawerHeader';
import ManualJournalDrawerTable from './ManualJournalDrawerTable';
@@ -15,10 +18,13 @@ export default function ManualJournalDrawerDetails() {
return (
<div className={'journal-drawer'}>
<ManualJournalDrawerActionBar manualJournal={manualJournal} />
<div className="journal-drawer__content">
<ManualJournalDrawerHeader manualJournal={manualJournal} />
<ManualJournalDrawerTable manualJournal={manualJournal} />
<ManualJournalDrawerFooter manualJournal={manualJournal} />
<Card>
<ManualJournalDrawerHeader />
<ManualJournalDrawerTable />
<ManualJournalDrawerFooter />
</Card>
</div>
</div>
);

View File

@@ -1,25 +1,27 @@
import React from 'react';
import { FormattedMessage as T } from 'components';
import { useManualJournalDrawerContext } from './ManualJournalDrawerProvider';
export default function ManualJournalDrawerFooter({}) {
const {
manualJournal: { amount },
} = useManualJournalDrawerContext();
export default function ManualJournalDrawerFooter({
manualJournal: { amount_formatted },
}) {
return (
<div className="journal-drawer__content--footer">
<div className="wrapper">
<div>
<span>
<T id={'sub_total'} />
</span>
<p>{amount_formatted}</p>
<div className="journal-drawer__content-footer">
<div class="total-lines">
<div class="total-lines__line total-lines__line--subtotal">
<div class="title">Subtotal</div>
<div class="debit">{amount}</div>
<div class="credit">{amount} </div>
</div>
<div>
<span>
<T id={'total'} />
</span>
<p>{amount_formatted}</p>
<div class="total-lines__line total-lines__line--total">
<div class="title">TOTAL</div>
<div class="debit">{amount}</div>
<div class="credit">{amount}</div>
</div>
</div>
</div>
);
}

View File

@@ -1,47 +1,49 @@
import React from 'react';
import { FormattedMessage as T } from 'components';
import { defaultTo } from 'lodash';
import { DetailsMenu, DetailItem, FormattedMessage as T } from 'components';
import { useManualJournalDrawerContext } from './ManualJournalDrawerProvider';
/**
* Manual journal details header.
* Manual journal details header.
*/
export default function ManualJournalDrawerHeader({
manualJournal: {
amount_formatted,
journal_type,
journal_number,
reference,
currency_code,
},
}) {
export default function ManualJournalDrawerHeader() {
const {
manualJournal: {
formatted_amount,
journal_type,
journal_number,
reference,
currency_code,
description,
},
} = useManualJournalDrawerContext();
return (
<div className={'journal-drawer__content--header'}>
<div>
<T id={'total'} />
<p className="balance">{amount_formatted}</p>
</div>
<div>
<span>
<T id={'journal_type'} />
</span>
<p>{journal_type}</p>
</div>
<div>
<span>
<T id={'journal_no'} />
</span>
<p>{journal_number}</p>
</div>
<div>
<span>
<T id={'reference_no'} />
</span>
<p>{reference}</p>
</div>
<div>
<span>
<T id={'currency'} />
</span>
<p>{currency_code}</p>
<div className={'journal-drawer__content-header'}>
<DetailsMenu>
<DetailItem name={'total'} label={<T id={'total'} />}>
<h3 class="amount">{formatted_amount}</h3>
</DetailItem>
<DetailItem name={'journal-type'} label={<T id={'journal_type'} />}>
{journal_type}
</DetailItem>
<DetailItem name={'journal-number'} label={<T id={'journal_no'} />}>
{journal_number}
</DetailItem>
<DetailItem name={'reference-no'} label={<T id={'reference_no'} />}>
{defaultTo(reference, '-')}
</DetailItem>
<DetailItem name={'currency'} label={<T id={'currency'} />}>
{currency_code}
</DetailItem>
</DetailsMenu>
<div class="journal-drawer__content-description">
<b class="title">Description</b>: {defaultTo(description, '')}
</div>
</div>
);

View File

@@ -9,17 +9,22 @@ const ManualJournalDrawerContext = React.createContext();
* Manual journal drawer provider.
*/
function ManualJournalDrawerProvider({ manualJournalId, ...props }) {
// fetch the specific manual journal details.
const { data: manualJournal, isLoading: isJournalLoading } = useJournal(
manualJournalId,
{
enabled: !!manualJournalId,
},
);
// provider.
// Fetch the specific manual journal details.
const {
data: manualJournal,
isLoading: isJournalLoading,
isFetching: isJournalFetching,
} = useJournal(manualJournalId, {
enabled: !!manualJournalId,
});
// Provider.
const provider = {
manualJournalId,
manualJournal,
isJournalFetching,
isJournalLoading,
};
return (

View File

@@ -1,73 +1,20 @@
import React from 'react';
import { Classes, Tooltip, Position } from '@blueprintjs/core';
import intl from 'react-intl-universal';
import { DataTable, Money, If, Icon } from 'components';
import { isBlank } from 'utils';
/**
* 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>
);
}
import { DataTable, If } from 'components';
import { useManualJournalEntriesColumns } from './utils';
import { useManualJournalDrawerContext } from './ManualJournalDrawerProvider';
/**
* Manual journal drawer table.
*/
export default function ManualJournalDrawerTable({
manualJournal: { entries, description, currency_code },
}) {
const columns = React.useMemo(
() => [
{
Header: intl.get('account_name'),
accessor: 'account.name',
width: 130,
},
{
Header: intl.get('contact'),
accessor: 'contact.display_name',
width: 130,
},
{
Header: intl.get('credit'),
accessor: ({ credit }) =>
!isBlank(credit) && credit !== 0 ? (
<Money amount={credit} currency={currency_code} />
) : null,
width: 80,
},
{
Header: intl.get('debit'),
accessor: ({ debit }) =>
!isBlank(debit) && debit !== 0 ? (
<Money amount={debit} currency={currency_code} />
) : null,
width: 80,
},
{
Header: intl.get('note'),
accessor: NoteAccessor,
width: 80,
},
],
[],
);
export default function ManualJournalDrawerTable() {
const columns = useManualJournalEntriesColumns();
const {
manualJournal: { entries, description },
} = useManualJournalDrawerContext();
return (
<div className="journal-drawer__content--table">
<div className="journal-drawer__content-table">
<DataTable columns={columns} data={entries} />
<If condition={description}>

View File

@@ -19,7 +19,15 @@ function ManualJournalDrawer({
payload: { manualJournalId },
}) {
return (
<Drawer isOpen={isOpen} name={name} size={'900px'}>
<Drawer
isOpen={isOpen}
name={name}
size={'65%'}
style={{
minWidth: '700px',
maxWidth: '900px',
}}
>
<DrawerSuspense>
<ManualJournalDrawerContent manualJournalId={manualJournalId} />
</DrawerSuspense>

View File

@@ -0,0 +1,65 @@
import intl from 'react-intl-universal';
import React from 'react';
import { Classes, Tooltip, Position } from '@blueprintjs/core';
import { 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 read-only manual journal entries columns.
*/
export const useManualJournalEntriesColumns = () =>
React.useMemo(
() => [
{
Header: intl.get('account_name'),
accessor: 'account.name',
width: 130,
disableSortBy: true,
},
{
Header: intl.get('contact'),
accessor: 'contact.display_name',
width: 130,
disableSortBy: true,
},
{
Header: intl.get('note'),
accessor: NoteAccessor,
width: 80,
disableSortBy: true,
},
{
Header: intl.get('credit'),
accessor: 'credit',
width: 100,
disableResizable: true,
disableSortBy: true,
},
{
Header: intl.get('debit'),
accessor: 'debit',
width: 100,
disableResizable: true,
disableSortBy: true,
},
],
[],
);