diff --git a/src/components/BookingBreakdown/BookingBreakdown.css b/src/components/BookingBreakdown/BookingBreakdown.css
index 33e6fbc3..7ff45a13 100644
--- a/src/components/BookingBreakdown/BookingBreakdown.css
+++ b/src/components/BookingBreakdown/BookingBreakdown.css
@@ -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;
+ }
+}
diff --git a/src/components/BookingBreakdown/BookingBreakdown.js b/src/components/BookingBreakdown/BookingBreakdown.js
index 0913a1af..6c487ee4 100644
--- a/src/components/BookingBreakdown/BookingBreakdown.js
+++ b/src/components/BookingBreakdown/BookingBreakdown.js
@@ -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 => {
+
+
-
+ {commissionLineItem ? (
+
+
+
+ ) : null}
);
};
diff --git a/src/components/BookingBreakdown/LineItemCustomerCommissionMaybe.js b/src/components/BookingBreakdown/LineItemCustomerCommissionMaybe.js
new file mode 100644
index 00000000..522f53e3
--- /dev/null
+++ b/src/components/BookingBreakdown/LineItemCustomerCommissionMaybe.js
@@ -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 : (
+
+
+
+
+ {formattedCommission}
+
+ );
+ }
+
+ return commissionItem;
+};
+
+LineItemStudioTimeCustomerCommissionMaybe.propTypes = {
+ transaction: propTypes.transaction.isRequired,
+ isCustomer: bool.isRequired,
+ intl: intlShape.isRequired,
+};
+
+export default LineItemStudioTimeCustomerCommissionMaybe;
diff --git a/src/components/BookingBreakdown/LineItemCommissionMaybe.js b/src/components/BookingBreakdown/LineItemProviderCommissionMaybe.js
similarity index 93%
rename from src/components/BookingBreakdown/LineItemCommissionMaybe.js
rename to src/components/BookingBreakdown/LineItemProviderCommissionMaybe.js
index 67d373b0..b3da2052 100644
--- a/src/components/BookingBreakdown/LineItemCommissionMaybe.js
+++ b/src/components/BookingBreakdown/LineItemProviderCommissionMaybe.js
@@ -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;
diff --git a/src/components/BookingBreakdown/LineItemSubTotalMaybe.js b/src/components/BookingBreakdown/LineItemSubTotalMaybe.js
index 87ab9715..284e2650 100644
--- a/src/components/BookingBreakdown/LineItemSubTotalMaybe.js
+++ b/src/components/BookingBreakdown/LineItemSubTotalMaybe.js
@@ -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,
};
diff --git a/src/components/BookingBreakdown/__snapshots__/BookingBreakdown.test.js.snap b/src/components/BookingBreakdown/__snapshots__/BookingBreakdown.test.js.snap
index 2af3179a..45df5d77 100644
--- a/src/components/BookingBreakdown/__snapshots__/BookingBreakdown.test.js.snap
+++ b/src/components/BookingBreakdown/__snapshots__/BookingBreakdown.test.js.snap
@@ -221,6 +221,13 @@ exports[`BookingBreakdown provider canceled transaction data matches snapshot 1`
0
+
+
+ BookingBreakdown.commissionFeeNote
+
+
`;
@@ -317,5 +324,12 @@ exports[`BookingBreakdown provider transaction data matches snapshot 1`] = `
18
+
+
+ BookingBreakdown.commissionFeeNote
+
+
`;
diff --git a/src/translations/en.json b/src/translations/en.json
index 8437f301..cce0f477 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -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",
diff --git a/src/util/types.js b/src/util/types.js
index feec3558..92b8cb0d 100644
--- a/src/util/types.js
+++ b/src/util/types.js
@@ -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]);