mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
feat: optimize style of sale receipt details.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import { defaultTo } from 'lodash';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import {
|
||||
CommercialDocHeader,
|
||||
@@ -11,8 +12,10 @@ import {
|
||||
DetailItem,
|
||||
Row,
|
||||
Col,
|
||||
ButtonLink,
|
||||
} from 'components';
|
||||
import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
||||
import { EstimateDetailsStatus } from './components';
|
||||
|
||||
/**
|
||||
* Estimate read-only details drawer header.
|
||||
@@ -24,9 +27,13 @@ export default function EstimateDetailHeader() {
|
||||
<CommercialDocHeader>
|
||||
<CommercialDocTopHeader>
|
||||
<DetailsMenu>
|
||||
<DetailItem label={intl.get('amount')}>
|
||||
<AmountEstimateDetail label={intl.get('amount')}>
|
||||
<span class="big-number">{estimate.formatted_amount}</span>
|
||||
</DetailItem>
|
||||
</AmountEstimateDetail>
|
||||
|
||||
<EstimateStatusDetail>
|
||||
<EstimateDetailsStatus estimate={estimate} />
|
||||
</EstimateStatusDetail>
|
||||
</DetailsMenu>
|
||||
</CommercialDocTopHeader>
|
||||
|
||||
@@ -37,14 +44,16 @@ export default function EstimateDetailHeader() {
|
||||
label={intl.get('estimate.details.estimate_number')}
|
||||
children={defaultTo(estimate.estimate_number, '-')}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('customer_name')}
|
||||
children={estimate.customer?.display_name}
|
||||
/>
|
||||
|
||||
<DetailItem label={intl.get('customer_name')}>
|
||||
<ButtonLink>{estimate.customer?.display_name}</ButtonLink>
|
||||
</DetailItem>
|
||||
|
||||
<DetailItem
|
||||
label={intl.get('estimate_date')}
|
||||
children={estimate.formatted_estimate_date}
|
||||
/>
|
||||
|
||||
<DetailItem
|
||||
label={intl.get('expiration_date')}
|
||||
children={estimate.formatted_expiration_date}
|
||||
@@ -72,3 +81,11 @@ export default function EstimateDetailHeader() {
|
||||
</CommercialDocHeader>
|
||||
);
|
||||
}
|
||||
|
||||
const EstimateStatusDetail = styled(DetailItem)`
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
`;
|
||||
const AmountEstimateDetail = styled(DetailItem)`
|
||||
width: 50%;
|
||||
`;
|
||||
|
||||
41
src/containers/Drawers/EstimateDetailDrawer/components.js
Normal file
41
src/containers/Drawers/EstimateDetailDrawer/components.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import { Intent, Tag } from '@blueprintjs/core';
|
||||
|
||||
import { T, Choose } from 'components';
|
||||
|
||||
/**
|
||||
* Estimate details status.
|
||||
* @return {React.JSX}
|
||||
*/
|
||||
export function EstimateDetailsStatus({ estimate }) {
|
||||
return (
|
||||
<Choose>
|
||||
<Choose.When condition={estimate.is_delivered && estimate.is_approved}>
|
||||
<Tag intent={Intent.SUCCESS} round={true}>
|
||||
<T id={'approved'} />
|
||||
</Tag>
|
||||
</Choose.When>
|
||||
<Choose.When condition={estimate.is_delivered && estimate.is_rejected}>
|
||||
<Tag intent={Intent.DANGER} round={true}>
|
||||
<T id={'rejected'} />
|
||||
</Tag>
|
||||
</Choose.When>
|
||||
<Choose.When
|
||||
condition={
|
||||
estimate.is_delivered &&
|
||||
!estimate.is_rejected &&
|
||||
!estimate.is_approved
|
||||
}
|
||||
>
|
||||
<Tag intent={Intent.SUCCESS} round={true}>
|
||||
<T id={'delivered'} />
|
||||
</Tag>
|
||||
</Choose.When>
|
||||
<Choose.Otherwise>
|
||||
<Tag round={true} minimal={true}>
|
||||
<T id={'draft'} />
|
||||
</Tag>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
);
|
||||
}
|
||||
@@ -1,35 +1,45 @@
|
||||
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 JournalEntriesTable from '../../JournalEntriesTable/JournalEntriesTable';
|
||||
import ReceiptDetailTab from './ReceiptDetailTab';
|
||||
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
||||
|
||||
import ReceiptDrawerCls from 'style/components/Drawers/ReceiptDrawer.module.scss';
|
||||
import ReceiptDetailActionBar from './ReceiptDetailActionBar';
|
||||
import { ReceiptDetailsGLEntriesPanel } from './ReceiptDetailsGLEntriesPanel';
|
||||
|
||||
/**
|
||||
* Receipt view detail.
|
||||
* @returns {React.JSX}
|
||||
*/
|
||||
export default function ReceiptDetail() {
|
||||
const { transactions } = useReceiptDetailDrawerContext();
|
||||
|
||||
return (
|
||||
<div className={clsx(ReceiptDrawerCls.root)}>
|
||||
<DrawerMainTabs defaultSelectedTabId="details">
|
||||
<Tab
|
||||
title={intl.get('details')}
|
||||
id={'details'}
|
||||
panel={<ReceiptDetailTab />}
|
||||
/>
|
||||
<Tab
|
||||
title={intl.get('journal_entries')}
|
||||
id={'journal_entries'}
|
||||
panel={<JournalEntriesTable transactions={transactions} />}
|
||||
/>
|
||||
</DrawerMainTabs>
|
||||
</div>
|
||||
<ReceiptDetailsRoot>
|
||||
<ReceiptDetailActionBar />
|
||||
<ReceiptDetailsTabs />
|
||||
</ReceiptDetailsRoot>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receipt details tabs bar.
|
||||
* @returns {React.JSX}
|
||||
*/
|
||||
function ReceiptDetailsTabs() {
|
||||
return (
|
||||
<DrawerMainTabs defaultSelectedTabId="details">
|
||||
<Tab
|
||||
title={intl.get('details')}
|
||||
id={'details'}
|
||||
panel={<ReceiptDetailTab />}
|
||||
/>
|
||||
<Tab
|
||||
title={intl.get('journal_entries')}
|
||||
id={'journal_entries'}
|
||||
panel={<ReceiptDetailsGLEntriesPanel />}
|
||||
/>
|
||||
</DrawerMainTabs>
|
||||
);
|
||||
}
|
||||
|
||||
const ReceiptDetailsRoot = styled.div``;
|
||||
|
||||
@@ -8,13 +8,18 @@ import {
|
||||
NavbarDivider,
|
||||
Intent,
|
||||
} from '@blueprintjs/core';
|
||||
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 { Can, Icon, FormattedMessage as T, MoreMenuItems } from 'components';
|
||||
import {
|
||||
Can,
|
||||
Icon,
|
||||
FormattedMessage as T,
|
||||
MoreMenuItems,
|
||||
DrawerActionsBar,
|
||||
} from 'components';
|
||||
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
||||
import {
|
||||
SaleReceiptAction,
|
||||
@@ -23,6 +28,10 @@ import {
|
||||
|
||||
import { safeCallback, compose } from 'utils';
|
||||
|
||||
/**
|
||||
* Receipt details actions bar.
|
||||
* @returns {React.JSX}
|
||||
*/
|
||||
function ReceiptDetailActionBar({
|
||||
// #withDialogActions
|
||||
openDialog,
|
||||
@@ -56,7 +65,7 @@ function ReceiptDetailActionBar({
|
||||
openDialog('notify-receipt-via-sms', { receiptId });
|
||||
};
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<DrawerActionsBar>
|
||||
<NavbarGroup>
|
||||
<Can I={SaleReceiptAction.Edit} a={AbilitySubject.Receipt}>
|
||||
<Button
|
||||
@@ -93,7 +102,7 @@ function ReceiptDetailActionBar({
|
||||
/>
|
||||
</Can>
|
||||
</NavbarGroup>
|
||||
</DashboardActionsBar>
|
||||
</DrawerActionsBar>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import { DrawerHeaderContent, DrawerLoading } from 'components';
|
||||
import { useTransactionsByReference, useReceipt } from 'hooks/query';
|
||||
import { useReceipt } from 'hooks/query';
|
||||
|
||||
// useTransactionsByReference
|
||||
const ReceiptDetailDrawerContext = React.createContext();
|
||||
@@ -18,29 +18,14 @@ function ReceiptDetailDrawerProvider({ receiptId, ...props }) {
|
||||
},
|
||||
);
|
||||
|
||||
// Handle fetch transaction by reference.
|
||||
const {
|
||||
data: { transactions },
|
||||
isLoading: isTransactionLoading,
|
||||
} = useTransactionsByReference(
|
||||
{
|
||||
reference_id: receiptId,
|
||||
reference_type: 'SaleReceipt',
|
||||
},
|
||||
{ enabled: !!receiptId },
|
||||
);
|
||||
|
||||
// Provider.
|
||||
const provider = {
|
||||
transactions,
|
||||
receiptId,
|
||||
receipt,
|
||||
};
|
||||
|
||||
const loading = isTransactionLoading || isReceiptLoading;
|
||||
|
||||
return (
|
||||
<DrawerLoading loading={loading}>
|
||||
<DrawerLoading loading={isReceiptLoading}>
|
||||
<DrawerHeaderContent
|
||||
name="receipt-detail-drawer"
|
||||
title={intl.get('receipt_details')}
|
||||
|
||||
@@ -1,58 +1,88 @@
|
||||
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 {
|
||||
ButtonLink,
|
||||
CommercialDocHeader,
|
||||
CommercialDocTopHeader,
|
||||
} from 'components';
|
||||
import { Row, Col, FormatDate, DetailsMenu, DetailItem } from 'components';
|
||||
|
||||
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
||||
|
||||
import ReceiptDrawerCls from 'style/components/Drawers/ReceiptDrawer.module.scss';
|
||||
import { ReceiptDetailsStatus } from './components';
|
||||
|
||||
/**
|
||||
* receipt detail content.
|
||||
* Receipt details header.
|
||||
*/
|
||||
export default function ReceiptDetailHeader() {
|
||||
const { receipt } = useReceiptDetailDrawerContext();
|
||||
|
||||
return (
|
||||
<div className={clsx(ReceiptDrawerCls.detail_panel_header)}>
|
||||
<DetailsMenu>
|
||||
<DetailItem label={intl.get('amount')}>
|
||||
<h3 class="big-number">{receipt.formatted_amount}</h3>
|
||||
</DetailItem>
|
||||
<DetailItem
|
||||
label={intl.get('receipt.details.receipt_number')}
|
||||
children={defaultTo(receipt.receipt_number, '-')}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('customer_name')}
|
||||
children={receipt.customer?.display_name}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('receipt_date')}
|
||||
children={<FormatDate value={receipt.receipt_date} />}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('closed_date')}
|
||||
children={<FormatDate value={receipt.closed_at_date} />}
|
||||
/>
|
||||
</DetailsMenu>
|
||||
<CommercialDocHeader>
|
||||
<CommercialDocTopHeader>
|
||||
<DetailsMenu>
|
||||
<AmountReceiptItem label={intl.get('amount')}>
|
||||
<h3 class="big-number">{receipt.formatted_amount}</h3>
|
||||
</AmountReceiptItem>
|
||||
|
||||
<DetailsMenu direction={'horizantal'}>
|
||||
<DetailItem
|
||||
label={intl.get('deposit_account')}
|
||||
children={receipt.deposit_account?.name}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('reference')}
|
||||
children={defaultTo(receipt.reference_no, '--')}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('receipt.details.created_at')}
|
||||
children={<FormatDate value={receipt.created_at} />}
|
||||
/>
|
||||
</DetailsMenu>
|
||||
</div>
|
||||
<StatusReceiptItem>
|
||||
<ReceiptDetailsStatus receipt={receipt} />
|
||||
</StatusReceiptItem>
|
||||
</DetailsMenu>
|
||||
</CommercialDocTopHeader>
|
||||
|
||||
<Row>
|
||||
<Col xs={6}>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<DetailItem
|
||||
label={intl.get('receipt.details.receipt_number')}
|
||||
children={defaultTo(receipt.receipt_number, '-')}
|
||||
/>
|
||||
<DetailItem label={intl.get('customer_name')}>
|
||||
<ButtonLink>{receipt.customer?.display_name} </ButtonLink>
|
||||
</DetailItem>
|
||||
<DetailItem
|
||||
label={intl.get('receipt_date')}
|
||||
children={<FormatDate value={receipt.receipt_date} />}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('closed_date')}
|
||||
children={<FormatDate value={receipt.closed_at_date} />}
|
||||
/>
|
||||
</DetailsMenu>
|
||||
</Col>
|
||||
<Col xs={6}>
|
||||
<DetailsMenu
|
||||
direction={'horizantal'}
|
||||
minLabelSize={'180px'}
|
||||
textAlign={'right'}
|
||||
>
|
||||
<DetailItem
|
||||
label={intl.get('deposit_account')}
|
||||
children={receipt.deposit_account?.name}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('reference')}
|
||||
children={defaultTo(receipt.reference_no, '--')}
|
||||
/>
|
||||
<DetailItem
|
||||
label={intl.get('receipt.details.created_at')}
|
||||
children={<FormatDate value={receipt.created_at} />}
|
||||
/>
|
||||
</DetailsMenu>
|
||||
</Col>
|
||||
</Row>
|
||||
</CommercialDocHeader>
|
||||
);
|
||||
}
|
||||
|
||||
const AmountReceiptItem = styled(DetailItem)`
|
||||
width: 50%;
|
||||
`;
|
||||
|
||||
const StatusReceiptItem = styled(DetailItem)`
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
`;
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
import React from 'react';
|
||||
import clsx from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Card } from 'components';
|
||||
import { CommercialDocBox } from 'components';
|
||||
|
||||
import ReceiptDetailActionBar from './ReceiptDetailActionBar';
|
||||
import ReceiptDetailHeader from './ReceiptDetailHeader';
|
||||
import ReceiptDetailTable from './ReceiptDetailTable';
|
||||
import { ReceiptDetailFooter } from './ReceiptDetailFooter';
|
||||
|
||||
import ReceiptDrawerCls from 'style/components/Drawers/ReceiptDrawer.module.scss';
|
||||
|
||||
export default function ReceiptDetailTab() {
|
||||
return (
|
||||
<div className={clsx(ReceiptDrawerCls.detail_panel)}>
|
||||
<ReceiptDetailActionBar />
|
||||
|
||||
<Card>
|
||||
<ReceiptDetailsOverviewRoot>
|
||||
<CommercialDocBox>
|
||||
<ReceiptDetailHeader />
|
||||
<ReceiptDetailTable />
|
||||
<ReceiptDetailFooter />
|
||||
</Card>
|
||||
</div>
|
||||
</CommercialDocBox>
|
||||
</ReceiptDetailsOverviewRoot>
|
||||
);
|
||||
}
|
||||
|
||||
const ReceiptDetailsOverviewRoot = styled.div``;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import React from 'react';
|
||||
import clsx from 'classnames';
|
||||
|
||||
import { DataTable } from 'components';
|
||||
import { CommercialDocEntriesTable } from 'components';
|
||||
|
||||
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
||||
import { useReceiptReadonlyEntriesTableColumns } from './utils';
|
||||
|
||||
import ReceiptDrawerCls from 'style/components/Drawers/ReceiptDrawer.module.scss';
|
||||
import { TableStyle } from '../../../common';
|
||||
|
||||
/**
|
||||
* Receipt readonly details table columns.
|
||||
*/
|
||||
export default function ReceiptDetailTable() {
|
||||
// Receipt details drawer context.
|
||||
const {
|
||||
receipt: { entries },
|
||||
} = useReceiptDetailDrawerContext();
|
||||
@@ -20,12 +20,10 @@ export default function ReceiptDetailTable() {
|
||||
const columns = useReceiptReadonlyEntriesTableColumns();
|
||||
|
||||
return (
|
||||
<div className={clsx(ReceiptDrawerCls.detail_panel_table)}>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={entries}
|
||||
className={'table-constrant'}
|
||||
/>
|
||||
</div>
|
||||
<CommercialDocEntriesTable
|
||||
columns={columns}
|
||||
data={entries}
|
||||
styleName={TableStyle.Constrant}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Card } from 'components';
|
||||
import { useTransactionsByReference } from 'hooks/query';
|
||||
import { useReceiptDetailDrawerContext } from './ReceiptDetailDrawerProvider';
|
||||
|
||||
import JournalEntriesTable, {
|
||||
AmountDisplayedBaseCurrencyMessage,
|
||||
} from '../../JournalEntriesTable/JournalEntriesTable';
|
||||
|
||||
/**
|
||||
* Receipt details GL entries panel.
|
||||
* @returns {React.JSX}
|
||||
*/
|
||||
export function ReceiptDetailsGLEntriesPanel() {
|
||||
// Receipt details drawer context.
|
||||
const { receiptId } = useReceiptDetailDrawerContext();
|
||||
|
||||
// Handle fetch transaction by reference.
|
||||
const {
|
||||
data: { transactions },
|
||||
isLoading: isTransactionLoading,
|
||||
} = useTransactionsByReference(
|
||||
{
|
||||
reference_id: receiptId,
|
||||
reference_type: 'SaleReceipt',
|
||||
},
|
||||
{ enabled: !!receiptId },
|
||||
);
|
||||
|
||||
return (
|
||||
<ReceiptGLEntriesRoot>
|
||||
<AmountDisplayedBaseCurrencyMessage />
|
||||
<JournalEntriesTable
|
||||
loading={isTransactionLoading}
|
||||
transactions={transactions}
|
||||
/>
|
||||
</ReceiptGLEntriesRoot>
|
||||
);
|
||||
}
|
||||
|
||||
const ReceiptGLEntriesRoot = styled(Card)``;
|
||||
26
src/containers/Drawers/ReceiptDetailDrawer/components.js
Normal file
26
src/containers/Drawers/ReceiptDetailDrawer/components.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import { Intent, Tag } from '@blueprintjs/core';
|
||||
|
||||
import { Choose, T } from 'components';
|
||||
|
||||
/**
|
||||
* Receipt details status.
|
||||
* @returns {React.JSX}
|
||||
*/
|
||||
export function ReceiptDetailsStatus({ receipt }) {
|
||||
return (
|
||||
<Choose>
|
||||
<Choose.When condition={receipt.is_closed}>
|
||||
<Tag round={true} intent={Intent.SUCCESS}>
|
||||
<T id={'closed'} />
|
||||
</Tag>
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<Tag intent={Intent.WARNING} round={true}>
|
||||
<T id={'draft'} />
|
||||
</Tag>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user