mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 07:40:32 +00:00
feat(bills): status accessor.
This commit is contained in:
@@ -8,10 +8,11 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Position,
|
Position,
|
||||||
Tag,
|
Tag,
|
||||||
|
ProgressBar,
|
||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { useIntl, FormattedMessage as T } from 'react-intl';
|
import { useIntl, FormattedMessage as T } from 'react-intl';
|
||||||
import { Icon, If, Choose, Money } from 'components';
|
import { Icon, If, Choose, Money } from 'components';
|
||||||
import { safeCallback, isBlank } from 'utils';
|
import { safeCallback, isBlank, calculateStatus } from 'utils';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,19 +78,58 @@ export function AmountAccessor(bill) {
|
|||||||
*/
|
*/
|
||||||
export function StatusAccessor(bill) {
|
export function StatusAccessor(bill) {
|
||||||
return (
|
return (
|
||||||
<Choose>
|
<div className={'status-accessor'}>
|
||||||
<Choose.When condition={bill.is_open}>
|
<Choose>
|
||||||
<Tag minimal={true} intent={Intent.SUCCESS}>
|
<Choose.When condition={bill.is_fully_paid && bill.is_open}>
|
||||||
<T id={'opened'} />
|
<span className={'fully-paid-icon'}>
|
||||||
</Tag>
|
<Icon icon="small-tick" iconSize={18} />
|
||||||
</Choose.When>
|
</span>
|
||||||
|
<span class="fully-paid-text">
|
||||||
<Choose.Otherwise>
|
<T id={'paid'} />
|
||||||
<Tag minimal={true}>
|
</span>
|
||||||
<T id={'draft'} />
|
</Choose.When>
|
||||||
</Tag>
|
<Choose.When condition={bill.is_open}>
|
||||||
</Choose.Otherwise>
|
<Choose>
|
||||||
</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',
|
id: 'bill_date',
|
||||||
Header: formatMessage({ id: 'bill_date' }),
|
Header: formatMessage({ id: 'bill_date' }),
|
||||||
accessor: (r) => moment(r.bill_date).format('YYYY MMM DD'),
|
accessor: (r) => moment(r.bill_date).format('YYYY MMM DD'),
|
||||||
width: 140,
|
width: 110,
|
||||||
className: 'bill_date',
|
className: 'bill_date',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'vendor',
|
id: 'vendor',
|
||||||
Header: formatMessage({ id: 'vendor_name' }),
|
Header: formatMessage({ id: 'vendor_name' }),
|
||||||
accessor: 'vendor.display_name',
|
accessor: 'vendor.display_name',
|
||||||
width: 140,
|
width: 180,
|
||||||
className: 'vendor',
|
className: 'vendor',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bill_number',
|
id: 'bill_number',
|
||||||
Header: formatMessage({ id: 'bill_number' }),
|
Header: formatMessage({ id: 'bill_number' }),
|
||||||
accessor: (row) => (row.bill_number ? `#${row.bill_number}` : null),
|
accessor: (row) => (row.bill_number ? `#${row.bill_number}` : null),
|
||||||
width: 140,
|
width: 100,
|
||||||
className: 'bill_number',
|
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',
|
id: 'amount',
|
||||||
Header: formatMessage({ id: 'amount' }),
|
Header: formatMessage({ id: 'amount' }),
|
||||||
accessor: AmountAccessor,
|
accessor: AmountAccessor,
|
||||||
width: 140,
|
width: 120,
|
||||||
className: 'amount',
|
className: 'amount',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'status',
|
id: 'status',
|
||||||
Header: formatMessage({ id: 'status' }),
|
Header: formatMessage({ id: 'status' }),
|
||||||
accessor: StatusAccessor,
|
accessor: StatusAccessor,
|
||||||
width: 140,
|
width: 160,
|
||||||
className: 'status',
|
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',
|
id: 'reference_no',
|
||||||
Header: formatMessage({ id: 'reference_no' }),
|
Header: formatMessage({ id: 'reference_no' }),
|
||||||
accessor: 'reference_no',
|
accessor: 'reference_no',
|
||||||
width: 140,
|
width: 90,
|
||||||
className: 'reference_no',
|
className: 'reference_no',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,15 +12,10 @@ import {
|
|||||||
} from '@blueprintjs/core';
|
} from '@blueprintjs/core';
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { round } from 'lodash';
|
|
||||||
import { Choose, If, Icon } from 'components';
|
import { Choose, If, Icon } from 'components';
|
||||||
import { Money, AppToaster } from 'components';
|
import { Money, AppToaster } from 'components';
|
||||||
import { formatMessage } from 'services/intl';
|
import { formatMessage } from 'services/intl';
|
||||||
import { safeCallback } from 'utils';
|
import { safeCallback, calculateStatus } from 'utils';
|
||||||
|
|
||||||
const calculateStatus = (paymentAmount, balanceAmount) => {
|
|
||||||
return round(paymentAmount / balanceAmount, 2);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const statusAccessor = (row) => {
|
export const statusAccessor = (row) => {
|
||||||
return (
|
return (
|
||||||
@@ -54,7 +49,12 @@ export const statusAccessor = (row) => {
|
|||||||
<T
|
<T
|
||||||
id={'day_partially_paid'}
|
id={'day_partially_paid'}
|
||||||
values={{
|
values={{
|
||||||
due: <Money amount={row.due_amount} currency={'USD'} />,
|
due: (
|
||||||
|
<Money
|
||||||
|
amount={row.due_amount}
|
||||||
|
currency={row.currency_code}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
@@ -183,15 +183,7 @@ export function useInvoicesTableColumns() {
|
|||||||
width: 180,
|
width: 180,
|
||||||
className: 'customer_id',
|
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',
|
id: 'invoice_no',
|
||||||
Header: formatMessage({ id: 'invoice_no__' }),
|
Header: formatMessage({ id: 'invoice_no__' }),
|
||||||
@@ -199,6 +191,15 @@ export function useInvoicesTableColumns() {
|
|||||||
width: 100,
|
width: 100,
|
||||||
className: 'invoice_no',
|
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',
|
id: 'status',
|
||||||
Header: formatMessage({ id: 'status' }),
|
Header: formatMessage({ id: 'status' }),
|
||||||
|
|||||||
@@ -1,18 +1,62 @@
|
|||||||
|
.dashboard__insider--bills {
|
||||||
.dashboard__insider--bills{
|
.bigcapital-datatable {
|
||||||
|
.tbody {
|
||||||
.bigcapital-datatable{
|
|
||||||
|
|
||||||
.tbody{
|
|
||||||
|
|
||||||
.td.amount {
|
.td.amount {
|
||||||
|
.cell-inner {
|
||||||
.cell-inner{
|
> span {
|
||||||
> span{
|
|
||||||
font-weight: 600;
|
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));
|
return _.mapKeys(data, (value, key) => _.snakeCase(key));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const calculateStatus = (paymentAmount, balanceAmount) => {
|
||||||
|
return _.round(paymentAmount / balanceAmount, 2);
|
||||||
|
};
|
||||||
|
|
||||||
const getCurrenciesOptions = () => {
|
const getCurrenciesOptions = () => {
|
||||||
return Object.keys(Currencies).map((currencyCode) => {
|
return Object.keys(Currencies).map((currencyCode) => {
|
||||||
const currency = Currencies[currencyCode];
|
const currency = Currencies[currencyCode];
|
||||||
|
|||||||
Reference in New Issue
Block a user