feat: add style of bill.

This commit is contained in:
elforjani13
2021-12-20 15:31:03 +02:00
parent a0098382e7
commit 3511348d04
15 changed files with 265 additions and 152 deletions

View File

@@ -16,7 +16,13 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { Can, If, Icon, FormattedMessage as T } from 'components';
import {
Can,
If,
Icon,
DrawerActionsBar,
FormattedMessage as T,
} from 'components';
import {
BillAction,
PaymentMadeAction,
@@ -56,7 +62,7 @@ function BillDetailActionsBar({
};
return (
<DashboardActionsBar>
<DrawerActionsBar>
<NavbarGroup>
<Can I={BillAction.Edit} a={AbilitySubject.Bill}>
<Button
@@ -71,7 +77,7 @@ function BillDetailActionsBar({
<If condition={bill.is_open && !bill.is_fully_paid}>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="quick-payment-16" iconSize={16} />}
icon={<Icon icon="arrow-upward" iconSize={16} />}
text={<T id={'add_payment'} />}
onClick={handleQuickBillPayment}
/>
@@ -88,7 +94,7 @@ function BillDetailActionsBar({
/>
</Can>
</NavbarGroup>
</DashboardActionsBar>
</DrawerActionsBar>
);
}

View File

@@ -1,12 +1,21 @@
import React from 'react';
import intl from 'react-intl-universal';
import { defaultTo } from 'lodash';
import clsx from 'classnames';
import styled from 'styled-components';
import { FormatDate, DetailsMenu, DetailItem } from 'components';
import {
FormatDate,
DetailsMenu,
DetailItem,
ButtonLink,
Row,
Col,
CommercialDocHeader,
CommercialDocTopHeader,
} from 'components';
import { useBillDrawerContext } from './BillDrawerProvider';
import BillDrawerCls from 'style/components/Drawers/BillDrawer.module.scss';
import { BillDetailsStatus } from './utils';
/**
* Bill detail header.
@@ -15,44 +24,65 @@ export default function BillDetailHeader() {
const { bill } = useBillDrawerContext();
return (
<div className={clsx(BillDrawerCls.detail_panel_header)}>
<DetailsMenu>
<DetailItem
label={intl.get('amount')}
children={<h3 class="big-number">{bill.formatted_amount}</h3>}
/>
<DetailItem
label={intl.get('bill.details.bill_number')}
children={defaultTo(bill.bill_number, '-')}
/>
<DetailItem
label={intl.get('bill_date')}
children={<FormatDate value={bill.bill_date} />}
/>
<DetailItem
label={intl.get('vendor_name')}
children={bill.vendor?.display_name}
/>
<DetailItem
label={intl.get('due_date')}
children={<FormatDate value={bill.due_date} />}
/>
</DetailsMenu>
<DetailsMenu direction={'horizantal'} minLabelSize={'140px'}>
<DetailItem
label={intl.get('due_amount')}
children={bill.formatted_due_amount}
/>
<DetailItem
label={intl.get('reference')}
children={defaultTo(bill.reference_no, '--')}
/>
<DetailItem
label={intl.get('bill.details.created_at')}
children={<FormatDate value={bill.created_at} />}
/>
</DetailsMenu>
</div>
<CommercialDocHeader>
<CommercialDocTopHeader>
<DetailsMenu>
<AmountDetailItem label={intl.get('amount')}>
<h3 class="big-number">{bill.formatted_amount}</h3>
</AmountDetailItem>
<StatusDetailItem>
<BillDetailsStatus bill={bill} />
</StatusDetailItem>
</DetailsMenu>
</CommercialDocTopHeader>
<Row>
<Col xs={6}>
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
<DetailItem label={intl.get('bill_date')}>
<FormatDate value={bill.bill_date} />
</DetailItem>
<DetailItem label={intl.get('due_date')}>
<FormatDate value={bill.due_date} />
</DetailItem>
<DetailItem label={intl.get('vendor_name')}>
<ButtonLink>{bill.vendor?.display_name}</ButtonLink>
</DetailItem>
<DetailItem label={intl.get('bill.details.bill_number')}>
{defaultTo(bill.bill_number, '-')}
</DetailItem>
</DetailsMenu>
</Col>
<Col xs={6}>
<DetailsMenu
direction={'horizantal'}
minLabelSize={'140px'}
textAlign={'right'}
>
<DetailItem label={intl.get('due_amount')}>
<strong>{bill.formatted_due_amount}</strong>
</DetailItem>
<DetailItem
label={intl.get('reference')}
children={defaultTo(bill.reference_no, '--')}
/>
<DetailItem
label={intl.get('bill.details.created_at')}
children={<FormatDate value={bill.created_at} />}
/>
</DetailsMenu>
</Col>
</Row>
</CommercialDocHeader>
);
}
const StatusDetailItem = styled(DetailItem)`
width: 50%;
text-align: right;
position: relative;
top: -5px;
`;
const AmountDetailItem = styled(DetailItem)`
width: 50%;
`;

View File

@@ -1,14 +1,10 @@
import React from 'react';
import clsx from 'classnames';
import { Card } from 'components';
import { CommercialDocBox } from 'components';
import BillDetailActionsBar from './BillDetailActionsBar';
import BillDetailHeader from './BillDetailHeader';
import BillDetailTable from './BillDetailTable';
import { BillDetailFooter } from './BillDetailFooter'
import BillDrawerCls from 'style/components/Drawers/BillDrawer.module.scss';
import { BillDetailFooter } from './BillDetailFooter';
/**
@@ -16,14 +12,10 @@ import BillDrawerCls from 'style/components/Drawers/BillDrawer.module.scss';
*/
export default function BillDetailTab() {
return (
<div className={clsx(BillDrawerCls.detail_panel)}>
<BillDetailActionsBar />
<Card>
<BillDetailHeader />
<BillDetailTable />
<BillDetailFooter />
</Card>
</div>
<CommercialDocBox>
<BillDetailHeader />
<BillDetailTable />
<BillDetailFooter />
</CommercialDocBox>
);
}

View File

@@ -1,26 +1,25 @@
import React from 'react';
import clsx from 'classnames';
import { DataTable } from 'components';
import { CommercialDocEntriesTable } from 'components';
import { useBillDrawerContext } from './BillDrawerProvider';
import { useBillReadonlyEntriesTableColumns } from './utils';
import BillDrawerCls from 'style/components/Drawers/BillDrawer.module.scss';
import { TableStyle } from '../../../common';
export default function BillDetailTable() {
const { bill: { entries } } = useBillDrawerContext();
const {
bill: { entries },
} = useBillDrawerContext();
// Retrieve bill readonly entries table columns.
const columns = useBillReadonlyEntriesTableColumns();
return (
<div className={clsx(BillDrawerCls.detail_panel_table)}>
<DataTable
columns={columns}
data={entries}
className={'table-constrant'}
/>
</div>
<CommercialDocEntriesTable
columns={columns}
data={entries}
styleName={TableStyle.Constrant}
/>
);
}

View File

@@ -1,13 +0,0 @@
import React from 'react';
import BillLocatedLandedCostDeleteAlert from 'containers/Alerts/Bills/BillLocatedLandedCostDeleteAlert';
/**
* Bill drawer alert.
*/
export default function BillDrawerAlerts() {
return (
<div class="bills-alerts">
<BillLocatedLandedCostDeleteAlert name="bill-located-cost-delete" />
</div>
);
}

View File

@@ -1,10 +1,8 @@
import React from 'react';
import { DrawerBody } from 'components';
import { BillDrawerProvider } from './BillDrawerProvider';
import BillDrawerDetails from './BillDrawerDetails';
import BillDrawerAlerts from './BillDrawerAlerts';
/**
* Bill drawer content.
@@ -17,7 +15,6 @@ export default function BillDrawerContent({
<BillDrawerProvider billId={billId}>
<DrawerBody>
<BillDrawerDetails />
<BillDrawerAlerts />
</DrawerBody>
</BillDrawerProvider>
);

View File

@@ -1,53 +1,60 @@
import React from 'react';
import { Tab } from '@blueprintjs/core';
import intl from 'react-intl-universal';
import clsx from 'classnames';
import styled from 'styled-components';
import { DrawerMainTabs } from 'components';
import BillDetailTab from './BillDetailTab';
import LocatedLandedCostTable from './LocatedLandedCostTable';
import JournalEntriesTable from '../../JournalEntriesTable/JournalEntriesTable';
import BillGLEntriesTable from './BillGLEntriesTable';
import BillPaymentTransactionTable from './BillPaymentTransactions/BillPaymentTransactionTable';
import { useBillDrawerContext } from './BillDrawerProvider';
import BillDrawerCls from 'style/components/Drawers/BillDrawer.module.scss';
import BillDetailActionsBar from './BillDetailActionsBar';
/**
* Bill view details.
* Bill details tabs.
*/
export default function BillDrawerDetails() {
const {
data: { transactions },
} = useBillDrawerContext();
function BillDetailsTabs() {
return (
<div className={clsx(BillDrawerCls.root)}>
<DrawerMainTabs
renderActiveTabPanelOnly={true}
defaultSelectedTabId="details"
>
<Tab
title={intl.get('details')}
id={'details'}
panel={<BillDetailTab />}
/>
<Tab
title={intl.get('journal_entries')}
id={'journal_entries'}
panel={<JournalEntriesTable transactions={transactions} />}
/>
<Tab
title={intl.get('payment_transactions')}
id={'payment_transactions'}
panel={<BillPaymentTransactionTable />}
/>
<Tab
title={intl.get('located_landed_cost')}
id={'landed_cost'}
panel={<LocatedLandedCostTable />}
/>
</DrawerMainTabs>
</div>
<DrawerMainTabs
renderActiveTabPanelOnly={true}
defaultSelectedTabId="details"
>
<Tab
title={intl.get('overview')}
id={'details'}
panel={<BillDetailTab />}
/>
<Tab
title={intl.get('journal_entries')}
id={'journal_entries'}
panel={<BillGLEntriesTable />}
/>
<Tab
title={intl.get('payment_transactions')}
id={'payment_transactions'}
panel={<BillPaymentTransactionTable />}
/>
<Tab
title={intl.get('located_landed_cost')}
id={'landed_cost'}
panel={<LocatedLandedCostTable />}
/>
</DrawerMainTabs>
);
}
/**
* Bill view detail.
*/
export default function BillDetails() {
return (
<BillDetailsRoot>
<BillDetailActionsBar />
<BillDetailsTabs />
</BillDetailsRoot>
);
}
export const BillDetailsRoot = styled.div``;

View File

@@ -1,11 +1,7 @@
import React from 'react';
import intl from 'react-intl-universal';
import { DrawerHeaderContent, DrawerLoading } from 'components';
import {
useBill,
useTransactionsByReference,
useBillLocatedLandedCost,
} from 'hooks/query';
import { useBill, useBillLocatedLandedCost } from 'hooks/query';
const BillDrawerContext = React.createContext();
@@ -18,15 +14,6 @@ function BillDrawerProvider({ billId, ...props }) {
enabled: !!billId,
});
// Handle fetch transaction by reference.
const { data, isLoading: isTransactionLoading } = useTransactionsByReference(
{
reference_id: billId,
reference_type: 'Bill',
},
{ enabled: !!billId },
);
// Handle fetch bill located landed cost transaction.
const { isLoading: isLandedCostLoading, data: transactions } =
useBillLocatedLandedCost(billId, {
@@ -35,13 +22,12 @@ function BillDrawerProvider({ billId, ...props }) {
//provider.
const provider = {
transactions,
billId,
data,
transactions,
bill,
};
const loading = isLandedCostLoading || isTransactionLoading || isBillLoading;
const loading = isLandedCostLoading || isBillLoading;
return (
<DrawerLoading loading={loading}>

View File

@@ -0,0 +1,49 @@
import React from 'react';
import styled from 'styled-components';
import { Card } from 'components';
import { useTransactionsByReference } from 'hooks/query';
import { useBillDrawerContext } from './BillDrawerProvider';
import JournalEntriesTable, {
AmountDisplayedBaseCurrencyMessage,
} from '../../JournalEntriesTable/JournalEntriesTable';
/**
* Bill GL entries table.
* @returns {React.JSX}
*/
export default function BillGLEntriesTable() {
const { billId } = useBillDrawerContext();
// Handle fetch transaction by reference.
const {
data: { transactions },
isLoading: isTransactionLoading,
} = useTransactionsByReference(
{
reference_id: billId,
reference_type: 'Bill',
},
{ enabled: !!billId },
);
return (
<BilleGLEntriesRoot>
<AmountDisplayedBaseCurrencyMessage />
<BillGLEntriesDatatable
loading={isTransactionLoading}
transactions={transactions}
/>
</BilleGLEntriesRoot>
);
}
const BilleGLEntriesRoot = styled(Card)``;
const BillGLEntriesDatatable = styled(JournalEntriesTable)`
.table .tbody .tr:last-child .td {
border-bottom: 0;
}
`;

View File

@@ -2,12 +2,13 @@ import React from 'react';
import { useHistory } from 'react-router-dom';
import { DataTable, Card } from 'components';
import 'style/pages/PaymentTransactions/List.scss';
import { useBillPaymentTransactionsColumns, ActionsMenu } from './components';
import { useBillDrawerContext } from '../BillDrawerProvider';
import { useBillPaymentTransactions } from 'hooks/query';
import { TableStyle } from '../../../../common';
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
@@ -59,12 +60,13 @@ function BillPaymentTransactionTable({
loading={isPaymentTransactionsLoading}
headerLoading={isPaymentTransactionsLoading}
progressBarLoading={isPaymentTransactionFetching}
TableLoadingRenderer={TableSkeletonRows}
styleName={TableStyle.Constrant}
ContextMenu={ActionsMenu}
payload={{
onDelete: handleDeleteBillPaymentTransactons,
onEdit: handleEditBillPaymentTransactions,
}}
className={'payment-transactions'}
/>
</Card>
);

View File

@@ -5,12 +5,13 @@ import { Button, Classes, NavbarGroup } from '@blueprintjs/core';
import { useLocatedLandedCostColumns, ActionsMenu } from './components';
import { useBillDrawerContext } from './BillDrawerProvider';
import '../../../style/pages/AllocateLandedCost/List.scss';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
import { TableStyle } from '../../../common';
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
import { compose } from 'utils';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import Icon from 'components/Icon';
@@ -75,11 +76,12 @@ function LocatedLandedCostTable({
columns={columns}
data={transactions}
ContextMenu={ActionsMenu}
TableLoadingRenderer={TableSkeletonRows}
styleName={TableStyle.Constrant}
payload={{
onDelete: handleDeleteTransaction,
onFromTranscationClick: handleFromTransactionClick,
}}
className={'datatable--landed-cost-transactions'}
/>
</Card>
</div>

View File

@@ -1,7 +1,13 @@
import React from 'react';
import intl from 'react-intl-universal';
import styled from 'styled-components';
import { Intent, Tag } from '@blueprintjs/core';
import { FormatNumberCell } from '../../../components';
import {
FormatNumberCell,
FormattedMessage as T,
Choose,
} from '../../../components';
/**
* Retrieve bill readonly details entries table columns.
@@ -49,3 +55,44 @@ export const useBillReadonlyEntriesTableColumns = () =>
],
[],
);
/**
* Bill details status.
* @returns {React.JSX}
*/
export function BillDetailsStatus({ bill }) {
return (
<Choose>
<Choose.When condition={bill.is_fully_paid && bill.is_open}>
<StatusTag intent={Intent.SUCCESS} round={true}>
<T id={'paid'} />
</StatusTag>
</Choose.When>
<Choose.When condition={bill.is_open}>
<Choose>
<Choose.When condition={bill.is_overdue}>
<StatusTag intent={Intent.WARNING} round={true}>
Overdue
</StatusTag>
</Choose.When>
<Choose.Otherwise>
<StatusTag intent={Intent.PRIMARY} round={true}>
Due
</StatusTag>
</Choose.Otherwise>
</Choose>
</Choose.When>
<Choose.Otherwise>
<StatusTag round={true} minimal={true}>
<T id={'draft'} />
</StatusTag>
</Choose.Otherwise>
</Choose>
);
}
const StatusTag = styled(Tag)`
min-width: 65px;
text-align: center;
`;

View File

@@ -7,7 +7,15 @@ const BillDeleteAlert = React.lazy(() =>
import('containers/Alerts/Bills/BillDeleteAlert'),
);
const BillLocatedLandedCostDeleteAlert = React.lazy(() =>
import('containers/Alerts/Bills/BillLocatedLandedCostDeleteAlert'),
);
export default [
{ name: 'bill-delete', component: BillDeleteAlert },
{ name: 'bill-open', component: BillOpenAlert },
{
name: 'bill-located-cost-delete',
component: BillLocatedLandedCostDeleteAlert,
},
];

View File

@@ -57,7 +57,7 @@ export function ActionsMenu({
<If condition={!original.is_open}>
<MenuItem
icon={<Icon icon={'check'} iconSize={18} />}
text={intl.get('mark_as_opened')}
text={intl.get('mark_as_open')}
onClick={safeCallback(onOpen, original)}
/>
</If>

View File

@@ -714,7 +714,6 @@
"mark_as_delivered": "Mark as delivered",
"deliver": "Deliver",
"mark_as_closed": "Mark as closed",
"mark_as_open": "Mark as open",
"save_close": "Save & Close",
"save_open": "Save & Open",
"close_and_new": "Close and new",
@@ -758,6 +757,7 @@
"inventory_adjustments": "Inventory adjustments",
"make_adjustment": "Make an adjustment",
"adjustment_type": "Adjustment type",
"mark_as_open":"Make as Open",
"decrement": "Decrement",
"new_quantity": "New quantity",
"reason": "Reason",
@@ -1219,6 +1219,7 @@
"bill.details.subtotal": "Subtotal",
"bill.details.payment_amount": "Payment amount",
"bill.details.due_amount": "Due amount",
"bill.drawer.bill_details":"Bill details ({billNumber})",
"expense.details.subtotal": "Subtotal",
"expense.details.total": "Total",
"manual_journal.details.subtotal": "Subtotal",