mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 06:10:31 +00:00
feat(bills): status accessor.
This commit is contained in:
@@ -8,10 +8,11 @@ import {
|
||||
Button,
|
||||
Position,
|
||||
Tag,
|
||||
ProgressBar,
|
||||
} from '@blueprintjs/core';
|
||||
import { useIntl, FormattedMessage as T } from 'react-intl';
|
||||
import { Icon, If, Choose, Money } from 'components';
|
||||
import { safeCallback, isBlank } from 'utils';
|
||||
import { safeCallback, isBlank, calculateStatus } from 'utils';
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
@@ -77,19 +78,58 @@ export function AmountAccessor(bill) {
|
||||
*/
|
||||
export function StatusAccessor(bill) {
|
||||
return (
|
||||
<Choose>
|
||||
<Choose.When condition={bill.is_open}>
|
||||
<Tag minimal={true} intent={Intent.SUCCESS}>
|
||||
<T id={'opened'} />
|
||||
</Tag>
|
||||
</Choose.When>
|
||||
|
||||
<Choose.Otherwise>
|
||||
<Tag minimal={true}>
|
||||
<T id={'draft'} />
|
||||
</Tag>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
<div className={'status-accessor'}>
|
||||
<Choose>
|
||||
<Choose.When condition={bill.is_fully_paid && bill.is_open}>
|
||||
<span className={'fully-paid-icon'}>
|
||||
<Icon icon="small-tick" iconSize={18} />
|
||||
</span>
|
||||
<span class="fully-paid-text">
|
||||
<T id={'paid'} />
|
||||
</span>
|
||||
</Choose.When>
|
||||
<Choose.When condition={bill.is_open}>
|
||||
<Choose>
|
||||
<Choose.When condition={bill.is_overdue}>
|
||||
<span className={'overdue-status'}>
|
||||
<T id={'overdue_by'} values={{ overdue: bill.overdue_days }} />
|
||||
</span>
|
||||
</Choose.When>
|
||||
<Choose.Otherwise>
|
||||
<span className={'due-status'}>
|
||||
<T id={'due_in'} values={{ due: bill.remaining_days }} />
|
||||
</span>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
<If condition={bill.is_partially_paid}>
|
||||
<span className="partial-paid">
|
||||
<T
|
||||
id={'day_partially_paid'}
|
||||
values={{
|
||||
due: (
|
||||
<Money
|
||||
amount={bill.due_amount}
|
||||
currency={bill.currency_code}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
<ProgressBar
|
||||
animate={false}
|
||||
stripes={false}
|
||||
intent={Intent.PRIMARY}
|
||||
value={calculateStatus(bill.payment_amount, bill.amount)}
|
||||
/>
|
||||
</If>
|
||||
</Choose.When>
|
||||
<Choose.Otherwise>
|
||||
<Tag minimal={true}>
|
||||
<T id={'draft'} />
|
||||
</Tag>
|
||||
</Choose.Otherwise>
|
||||
</Choose>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -116,49 +156,49 @@ export function useBillsTableColumns() {
|
||||
id: 'bill_date',
|
||||
Header: formatMessage({ id: 'bill_date' }),
|
||||
accessor: (r) => moment(r.bill_date).format('YYYY MMM DD'),
|
||||
width: 140,
|
||||
width: 110,
|
||||
className: 'bill_date',
|
||||
},
|
||||
{
|
||||
id: 'vendor',
|
||||
Header: formatMessage({ id: 'vendor_name' }),
|
||||
accessor: 'vendor.display_name',
|
||||
width: 140,
|
||||
width: 180,
|
||||
className: 'vendor',
|
||||
},
|
||||
{
|
||||
id: 'bill_number',
|
||||
Header: formatMessage({ id: 'bill_number' }),
|
||||
accessor: (row) => (row.bill_number ? `#${row.bill_number}` : null),
|
||||
width: 140,
|
||||
width: 100,
|
||||
className: 'bill_number',
|
||||
},
|
||||
{
|
||||
id: 'due_date',
|
||||
Header: formatMessage({ id: 'due_date' }),
|
||||
accessor: (r) => moment(r.due_date).format('YYYY MMM DD'),
|
||||
width: 140,
|
||||
className: 'due_date',
|
||||
},
|
||||
{
|
||||
id: 'amount',
|
||||
Header: formatMessage({ id: 'amount' }),
|
||||
accessor: AmountAccessor,
|
||||
width: 140,
|
||||
width: 120,
|
||||
className: 'amount',
|
||||
},
|
||||
{
|
||||
id: 'status',
|
||||
Header: formatMessage({ id: 'status' }),
|
||||
accessor: StatusAccessor,
|
||||
width: 140,
|
||||
width: 160,
|
||||
className: 'status',
|
||||
},
|
||||
{
|
||||
id: 'due_date',
|
||||
Header: formatMessage({ id: 'due_date' }),
|
||||
accessor: (r) => moment(r.due_date).format('YYYY MMM DD'),
|
||||
width: 110,
|
||||
className: 'due_date',
|
||||
},
|
||||
{
|
||||
id: 'reference_no',
|
||||
Header: formatMessage({ id: 'reference_no' }),
|
||||
accessor: 'reference_no',
|
||||
width: 140,
|
||||
width: 90,
|
||||
className: 'reference_no',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -12,15 +12,10 @@ import {
|
||||
} from '@blueprintjs/core';
|
||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||
import moment from 'moment';
|
||||
import { round } from 'lodash';
|
||||
import { Choose, If, Icon } from 'components';
|
||||
import { Money, AppToaster } from 'components';
|
||||
import { formatMessage } from 'services/intl';
|
||||
import { safeCallback } from 'utils';
|
||||
|
||||
const calculateStatus = (paymentAmount, balanceAmount) => {
|
||||
return round(paymentAmount / balanceAmount, 2);
|
||||
};
|
||||
import { safeCallback, calculateStatus } from 'utils';
|
||||
|
||||
export const statusAccessor = (row) => {
|
||||
return (
|
||||
@@ -54,7 +49,12 @@ export const statusAccessor = (row) => {
|
||||
<T
|
||||
id={'day_partially_paid'}
|
||||
values={{
|
||||
due: <Money amount={row.due_amount} currency={'USD'} />,
|
||||
due: (
|
||||
<Money
|
||||
amount={row.due_amount}
|
||||
currency={row.currency_code}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
@@ -183,15 +183,7 @@ export function useInvoicesTableColumns() {
|
||||
width: 180,
|
||||
className: 'customer_id',
|
||||
},
|
||||
{
|
||||
id: 'balance',
|
||||
Header: formatMessage({ id: 'balance' }),
|
||||
accessor: (r) => (
|
||||
<Money amount={r.balance} currency={r.currency_code} />
|
||||
),
|
||||
width: 110,
|
||||
className: 'balance',
|
||||
},
|
||||
|
||||
{
|
||||
id: 'invoice_no',
|
||||
Header: formatMessage({ id: 'invoice_no__' }),
|
||||
@@ -199,6 +191,15 @@ export function useInvoicesTableColumns() {
|
||||
width: 100,
|
||||
className: 'invoice_no',
|
||||
},
|
||||
{
|
||||
id: 'balance',
|
||||
Header: formatMessage({ id: 'balance' }),
|
||||
accessor: (r) => (
|
||||
<Money amount={r.balance} currency={r.currency_code} />
|
||||
),
|
||||
width: 120,
|
||||
className: 'balance',
|
||||
},
|
||||
{
|
||||
id: 'status',
|
||||
Header: formatMessage({ id: 'status' }),
|
||||
|
||||
@@ -1,18 +1,62 @@
|
||||
|
||||
.dashboard__insider--bills{
|
||||
|
||||
.bigcapital-datatable{
|
||||
|
||||
.tbody{
|
||||
|
||||
.dashboard__insider--bills {
|
||||
.bigcapital-datatable {
|
||||
.tbody {
|
||||
.td.amount {
|
||||
|
||||
.cell-inner{
|
||||
> span{
|
||||
.cell-inner {
|
||||
> span {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
.status.td {
|
||||
.status-accessor {
|
||||
padding: 4px 0;
|
||||
}
|
||||
.overdue-status,
|
||||
.due-status {
|
||||
display: block;
|
||||
font-size: 13.5px;
|
||||
line-height: 1.4;
|
||||
|
||||
+ .partial-paid {
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
.overdue-status {
|
||||
color: #ec5b0a;
|
||||
}
|
||||
.due-status {
|
||||
color: #1652c8;
|
||||
}
|
||||
.partial-paid {
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.fully-paid-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 8px;
|
||||
|
||||
svg {
|
||||
fill: #2ba01d;
|
||||
}
|
||||
}
|
||||
.fully-paid-text {
|
||||
font-size: 13.5px;
|
||||
}
|
||||
.bp3-progress-bar {
|
||||
height: 4px;
|
||||
max-width: 180px;
|
||||
|
||||
&,
|
||||
.bp3-progress-meter {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,6 +623,10 @@ export const transformGeneralSettings = (data) => {
|
||||
return _.mapKeys(data, (value, key) => _.snakeCase(key));
|
||||
};
|
||||
|
||||
export const calculateStatus = (paymentAmount, balanceAmount) => {
|
||||
return _.round(paymentAmount / balanceAmount, 2);
|
||||
};
|
||||
|
||||
const getCurrenciesOptions = () => {
|
||||
return Object.keys(Currencies).map((currencyCode) => {
|
||||
const currency = Currencies[currencyCode];
|
||||
|
||||
Reference in New Issue
Block a user