mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
BookingBreakdown can handle customer commission
This commit is contained in:
parent
7100a7421a
commit
08fcfac609
8 changed files with 164 additions and 14 deletions
|
|
@ -82,3 +82,20 @@
|
|||
margin: 2px 0 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.feeInfo {
|
||||
@apply --marketplaceTinyFontStyles;
|
||||
color: var(--matterColorAnti);
|
||||
margin: 0 0 20px 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin-top: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@media (--viewportLarge) {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,20 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { oneOf, string } from 'prop-types';
|
||||
import { intlShape, injectIntl } from 'react-intl';
|
||||
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { propTypes } from '../../util/types';
|
||||
import {
|
||||
propTypes,
|
||||
LINE_ITEM_CUSTOMER_COMMISSION,
|
||||
LINE_ITEM_PROVIDER_COMMISSION,
|
||||
} from '../../util/types';
|
||||
|
||||
import LineItemUnitPrice from './LineItemUnitPrice';
|
||||
import LineItemBookingPeriod from './LineItemBookingPeriod';
|
||||
import LineItemUnitsMaybe from './LineItemUnitsMaybe';
|
||||
import LineItemSubTotalMaybe from './LineItemSubTotalMaybe';
|
||||
import LineItemCommissionMaybe from './LineItemCommissionMaybe';
|
||||
import LineItemCustomerCommissionMaybe from './LineItemCustomerCommissionMaybe';
|
||||
import LineItemProviderCommissionMaybe from './LineItemProviderCommissionMaybe';
|
||||
import LineItemRefundMaybe from './LineItemRefundMaybe';
|
||||
import LineItemTotalPrice from './LineItemTotalPrice';
|
||||
import css from './BookingBreakdown.css';
|
||||
|
|
@ -20,7 +25,16 @@ import css from './BookingBreakdown.css';
|
|||
export const BookingBreakdownComponent = props => {
|
||||
const { rootClassName, className, userRole, unitType, transaction, booking, intl } = props;
|
||||
|
||||
const isCustomer = userRole === 'customer';
|
||||
const isProvider = userRole === 'provider';
|
||||
|
||||
const commissionLineItem = transaction.attributes.lineItems.find(
|
||||
item =>
|
||||
(item.code === LINE_ITEM_CUSTOMER_COMMISSION ||
|
||||
item.code === LINE_ITEM_PROVIDER_COMMISSION) &&
|
||||
!item.reversal
|
||||
);
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
return (
|
||||
|
|
@ -32,14 +46,28 @@ export const BookingBreakdownComponent = props => {
|
|||
<LineItemSubTotalMaybe
|
||||
transaction={transaction}
|
||||
unitType={unitType}
|
||||
userRole={userRole}
|
||||
intl={intl}
|
||||
/>
|
||||
<LineItemCustomerCommissionMaybe
|
||||
transaction={transaction}
|
||||
isCustomer={isCustomer}
|
||||
intl={intl}
|
||||
/>
|
||||
<LineItemProviderCommissionMaybe
|
||||
transaction={transaction}
|
||||
isProvider={isProvider}
|
||||
intl={intl}
|
||||
/>
|
||||
<LineItemCommissionMaybe transaction={transaction} isProvider={isProvider} intl={intl} />
|
||||
<LineItemRefundMaybe transaction={transaction} unitType={unitType} intl={intl} />
|
||||
|
||||
<hr className={css.totalDivider} />
|
||||
<LineItemTotalPrice transaction={transaction} isProvider={isProvider} intl={intl} />
|
||||
{commissionLineItem ? (
|
||||
<span className={css.feeInfo}>
|
||||
<FormattedMessage id="BookingBreakdown.commissionFeeNote" />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
import React from 'react';
|
||||
import { bool } from 'prop-types';
|
||||
import { FormattedMessage, intlShape } from 'react-intl';
|
||||
import { formatMoney } from '../../util/currency';
|
||||
import { types as sdkTypes } from '../../util/sdkLoader';
|
||||
import { LINE_ITEM_CUSTOMER_COMMISSION, propTypes } from '../../util/types';
|
||||
|
||||
import css from './BookingBreakdown.css';
|
||||
|
||||
const { Money } = sdkTypes;
|
||||
|
||||
// Validate the assumption that the commission exists and the amount
|
||||
// is zero or positive.
|
||||
const isValidCommission = commissionLineItem => {
|
||||
return commissionLineItem.lineTotal instanceof Money && commissionLineItem.lineTotal.amount >= 0;
|
||||
};
|
||||
|
||||
const LineItemStudioTimeCustomerCommissionMaybe = props => {
|
||||
const { transaction, isCustomer, intl } = props;
|
||||
|
||||
const customerCommissionLineItem = transaction.attributes.lineItems.find(
|
||||
item => item.code === LINE_ITEM_CUSTOMER_COMMISSION && !item.reversal
|
||||
);
|
||||
const commissionRefund = transaction.attributes.lineItems.find(
|
||||
item => item.code === LINE_ITEM_CUSTOMER_COMMISSION && item.reversal
|
||||
);
|
||||
|
||||
// If commission is passed it will be shown as a fee already reduces from the total price
|
||||
let commissionItem = null;
|
||||
|
||||
if (isCustomer && customerCommissionLineItem) {
|
||||
if (!isValidCommission(customerCommissionLineItem)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('invalid commission line item:', customerCommissionLineItem);
|
||||
throw new Error('Commission should be present and the value should be zero or positive');
|
||||
}
|
||||
|
||||
const commission = customerCommissionLineItem.lineTotal;
|
||||
const formattedCommission = commission ? formatMoney(intl, commission) : null;
|
||||
|
||||
commissionItem = commissionRefund ? null : (
|
||||
<div className={css.lineItem}>
|
||||
<span className={css.itemLabel}>
|
||||
<FormattedMessage id="BookingBreakdown.commission" />
|
||||
</span>
|
||||
<span className={css.itemValue}>{formattedCommission}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return commissionItem;
|
||||
};
|
||||
|
||||
LineItemStudioTimeCustomerCommissionMaybe.propTypes = {
|
||||
transaction: propTypes.transaction.isRequired,
|
||||
isCustomer: bool.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default LineItemStudioTimeCustomerCommissionMaybe;
|
||||
|
|
@ -19,7 +19,7 @@ const isValidCommission = commissionLineItem => {
|
|||
);
|
||||
};
|
||||
|
||||
const LineItemCommissionMaybe = props => {
|
||||
const LineItemProviderCommissionMaybe = props => {
|
||||
const { transaction, isProvider, intl } = props;
|
||||
|
||||
const providerCommissionLineItem = transaction.attributes.lineItems.find(
|
||||
|
|
@ -55,10 +55,10 @@ const LineItemCommissionMaybe = props => {
|
|||
return commissionItem;
|
||||
};
|
||||
|
||||
LineItemCommissionMaybe.propTypes = {
|
||||
LineItemProviderCommissionMaybe.propTypes = {
|
||||
transaction: propTypes.transaction.isRequired,
|
||||
isProvider: bool.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default LineItemCommissionMaybe;
|
||||
export default LineItemProviderCommissionMaybe;
|
||||
|
|
@ -1,13 +1,36 @@
|
|||
import React from 'react';
|
||||
import { bool } from 'prop-types';
|
||||
import { string } from 'prop-types';
|
||||
import { FormattedMessage, intlShape } from 'react-intl';
|
||||
import { formatMoney } from '../../util/currency';
|
||||
import { propTypes } from '../../util/types';
|
||||
import {
|
||||
propTypes,
|
||||
LINE_ITEM_CUSTOMER_COMMISSION,
|
||||
LINE_ITEM_PROVIDER_COMMISSION,
|
||||
} from '../../util/types';
|
||||
|
||||
import css from './BookingBreakdown.css';
|
||||
|
||||
/**
|
||||
* Checks if a transaction has a commission line-item for
|
||||
* a given user role.
|
||||
*/
|
||||
const txHasCommission = (transaction, userRole) => {
|
||||
let commissionLineItem = null;
|
||||
|
||||
if (userRole === 'customer') {
|
||||
commissionLineItem = transaction.attributes.lineItems.find(
|
||||
item => item.code === LINE_ITEM_CUSTOMER_COMMISSION
|
||||
);
|
||||
} else if (userRole === 'provider') {
|
||||
commissionLineItem = transaction.attributes.lineItems.find(
|
||||
item => item.code === LINE_ITEM_PROVIDER_COMMISSION
|
||||
);
|
||||
}
|
||||
return !!commissionLineItem;
|
||||
};
|
||||
|
||||
const LineItemSubTotalMaybe = props => {
|
||||
const { transaction, unitType, isProvider, intl } = props;
|
||||
const { transaction, unitType, userRole, intl } = props;
|
||||
|
||||
const refund = transaction.attributes.lineItems.find(
|
||||
item => item.code === unitType && item.reversal
|
||||
|
|
@ -16,7 +39,7 @@ const LineItemSubTotalMaybe = props => {
|
|||
// Show unit purchase line total (unit price * quantity) as a subtotal.
|
||||
// PLEASE NOTE that this assumes that the transaction doesn't have other
|
||||
// line item types than the defined unit type (e.g. week, month, year).
|
||||
const showSubTotal = isProvider || refund;
|
||||
const showSubTotal = txHasCommission(transaction, userRole) || refund;
|
||||
const unitPurchase = transaction.attributes.lineItems.find(
|
||||
item => item.code === unitType && !item.reversal
|
||||
);
|
||||
|
|
@ -34,7 +57,7 @@ const LineItemSubTotalMaybe = props => {
|
|||
|
||||
LineItemSubTotalMaybe.propTypes = {
|
||||
transaction: propTypes.transaction.isRequired,
|
||||
isProvider: bool.isRequired,
|
||||
userRole: string.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -221,6 +221,13 @@ exports[`BookingBreakdown provider canceled transaction data matches snapshot 1`
|
|||
0
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
className={undefined}
|
||||
>
|
||||
<span>
|
||||
BookingBreakdown.commissionFeeNote
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
|
@ -317,5 +324,12 @@ exports[`BookingBreakdown provider transaction data matches snapshot 1`] = `
|
|||
18
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
className={undefined}
|
||||
>
|
||||
<span>
|
||||
BookingBreakdown.commissionFeeNote
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@
|
|||
"AuthenticationPage.verifyEmailTitle": "{name}, check your inbox to verify your email",
|
||||
"Avatar.bannedUserDisplayName": "Banned user",
|
||||
"BookingBreakdown.bookingPeriod": "{bookingStart} – {bookingEnd}",
|
||||
"BookingBreakdown.commission": "Saunatime fee",
|
||||
"BookingBreakdown.commission": "Saunatime fee *",
|
||||
"BookingBreakdown.commissionFeeNote": "* The fee helps us run the platform and provide the best possible service to you!",
|
||||
"BookingBreakdown.dayCount": "{count, number} {count, plural, one {day} other {days}}",
|
||||
"BookingBreakdown.nightCount": "{count, number} {count, plural, one {night} other {nights}}",
|
||||
"BookingBreakdown.pricePerDay": "Price per day",
|
||||
|
|
|
|||
|
|
@ -329,9 +329,16 @@ propTypes.review = shape({
|
|||
export const LINE_ITEM_NIGHT = 'line-item/night';
|
||||
export const LINE_ITEM_DAY = 'line-item/day';
|
||||
export const LINE_ITEM_UNITS = 'line-item/units';
|
||||
export const LINE_ITEM_CUSTOMER_COMMISSION = 'line-item/customer-commission';
|
||||
export const LINE_ITEM_PROVIDER_COMMISSION = 'line-item/provider-commission';
|
||||
|
||||
const LINE_ITEMS = [LINE_ITEM_NIGHT, LINE_ITEM_DAY, LINE_ITEM_UNITS, LINE_ITEM_PROVIDER_COMMISSION];
|
||||
const LINE_ITEMS = [
|
||||
LINE_ITEM_NIGHT,
|
||||
LINE_ITEM_DAY,
|
||||
LINE_ITEM_UNITS,
|
||||
LINE_ITEM_CUSTOMER_COMMISSION,
|
||||
LINE_ITEM_PROVIDER_COMMISSION,
|
||||
];
|
||||
|
||||
propTypes.bookingUnitType = oneOf([LINE_ITEM_NIGHT, LINE_ITEM_DAY, LINE_ITEM_UNITS]);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue