@roomstay/frontend 2.6.104-3 → 2.6.105-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/211.bundle.js +1 -1
- package/dist/main.bundle.js +1 -1
- package/dist/src/components/steps/confirmation/StripePaymentOption/StripePaymentForm.js +23 -0
- package/dist/src/components/steps/confirmation/StripePaymentOption/StripePaymentForm.js.map +1 -1
- package/dist/src/components/steps/room/roomDetails/RoomDetailsPriceBlock.js.map +1 -1
- package/dist/src/components/summary/BESummaryAddonRow.js +10 -13
- package/dist/src/components/summary/BESummaryAddonRow.js.map +1 -1
- package/dist/src/contexts/BasketContext/BasketContextWrapper.js +17 -4
- package/dist/src/contexts/BasketContext/BasketContextWrapper.js.map +1 -1
- package/dist/src/contexts/CompanyContext/CompanyContextWrapper.js +1 -0
- package/dist/src/contexts/CompanyContext/CompanyContextWrapper.js.map +1 -1
- package/dist/src/models/Room/RoomRate.d.ts +7 -0
- package/dist/src/models/Room/RoomRate.js +22 -5
- package/dist/src/models/Room/RoomRate.js.map +1 -1
- package/dist/src/providers/CurrencyProvider.js +1 -1
- package/dist/src/providers/CurrencyProvider.js.map +1 -1
- package/dist/src/util/CurrencyHelper.js +1 -1
- package/dist/src/util/CurrencyHelper.js.map +1 -1
- package/dist/test.bundle.js +1 -1
- package/dist/vendors.bundle.js +1 -1
- package/package.json +3 -3
|
@@ -41,14 +41,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
41
41
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
44
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
48
|
exports.StripePaymentForm = void 0;
|
|
46
49
|
const react_stripe_js_1 = require("@stripe/react-stripe-js");
|
|
50
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
47
51
|
const react_1 = __importStar(require("react"));
|
|
52
|
+
const StripePaymentForm_module_scss_1 = __importDefault(require("./StripePaymentForm.module.scss"));
|
|
48
53
|
exports.StripePaymentForm = (0, react_1.forwardRef)((_props, ref) => {
|
|
49
54
|
const stripe = (0, react_stripe_js_1.useStripe)();
|
|
50
55
|
const elements = (0, react_stripe_js_1.useElements)();
|
|
51
56
|
const [message, setMessage] = (0, react_1.useState)();
|
|
57
|
+
const [cardholderName, setCardholderName] = (0, react_1.useState)('');
|
|
52
58
|
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
53
59
|
submitPayment: (redirectUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
60
|
var _a, _b;
|
|
@@ -56,10 +62,19 @@ exports.StripePaymentForm = (0, react_1.forwardRef)((_props, ref) => {
|
|
|
56
62
|
if (!stripe || !elements) {
|
|
57
63
|
return { success: false, message: 'Stripe has not loaded yet.' };
|
|
58
64
|
}
|
|
65
|
+
if (!cardholderName.trim()) {
|
|
66
|
+
setMessage('Cardholder name is required.');
|
|
67
|
+
return { success: false, message: 'Cardholder name is required.' };
|
|
68
|
+
}
|
|
59
69
|
const { error } = yield stripe.confirmPayment({
|
|
60
70
|
elements,
|
|
61
71
|
confirmParams: {
|
|
62
72
|
return_url: redirectUrl,
|
|
73
|
+
payment_method_data: {
|
|
74
|
+
billing_details: {
|
|
75
|
+
name: cardholderName,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
63
78
|
},
|
|
64
79
|
});
|
|
65
80
|
if (error) {
|
|
@@ -71,8 +86,16 @@ exports.StripePaymentForm = (0, react_1.forwardRef)((_props, ref) => {
|
|
|
71
86
|
}));
|
|
72
87
|
const paymentElementOptions = {
|
|
73
88
|
layout: 'accordion',
|
|
89
|
+
fields: {
|
|
90
|
+
billingDetails: {
|
|
91
|
+
name: 'never',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
74
94
|
};
|
|
75
95
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
96
|
+
react_1.default.createElement("div", { className: (0, classnames_1.default)(StripePaymentForm_module_scss_1.default['stripe-field-wrapper'], 'mb-3') },
|
|
97
|
+
react_1.default.createElement("label", { htmlFor: "cardholder-name", className: (0, classnames_1.default)(StripePaymentForm_module_scss_1.default['stripe-label'], { [StripePaymentForm_module_scss_1.default['stripe-label--empty']]: !cardholderName }) }, "Cardholder name"),
|
|
98
|
+
react_1.default.createElement("input", { type: "text", id: "cardholder-name", className: (0, classnames_1.default)(StripePaymentForm_module_scss_1.default['stripe-input'], { [StripePaymentForm_module_scss_1.default['stripe-input--empty']]: !cardholderName }), placeholder: "Full name on card", value: cardholderName, onChange: (e) => setCardholderName(e.target.value), autoComplete: "cc-name", required: true })),
|
|
76
99
|
react_1.default.createElement(react_stripe_js_1.PaymentElement, { id: "payment-element", options: paymentElementOptions }),
|
|
77
100
|
message && (react_1.default.createElement("div", { id: "payment-message", className: "alert alert-danger mt-3" }, message))));
|
|
78
101
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StripePaymentForm.js","sourceRoot":"/","sources":["src/components/steps/confirmation/StripePaymentOption/StripePaymentForm.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StripePaymentForm.js","sourceRoot":"/","sources":["src/components/steps/confirmation/StripePaymentOption/StripePaymentForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import { PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js';\nimport { StripePaymentElementOptions } from '@stripe/stripe-js';\nimport classNames from 'classnames';\nimport React, { forwardRef, useImperativeHandle, useState } from 'react';\n\nimport { PaymentHandlerElementRef } from '@/handlers/payment/PaymentHandler';\n\nimport styles from './StripePaymentForm.module.scss';\n\nexport const StripePaymentForm = forwardRef<PaymentHandlerElementRef>((_props, ref) => {\n const stripe = useStripe();\n const elements = useElements();\n\n const [message, setMessage] = useState<string>();\n const [cardholderName, setCardholderName] = useState<string>('');\n\n useImperativeHandle(ref, () => ({\n submitPayment: async (redirectUrl: string) => {\n setMessage(undefined);\n\n if (!stripe || !elements) {\n return { success: false, message: 'Stripe has not loaded yet.' };\n }\n\n if (!cardholderName.trim()) {\n setMessage('Cardholder name is required.');\n return { success: false, message: 'Cardholder name is required.' };\n }\n\n const { error } = await stripe.confirmPayment({\n elements,\n confirmParams: {\n return_url: redirectUrl,\n payment_method_data: {\n billing_details: {\n name: cardholderName,\n },\n },\n },\n });\n\n if (error) {\n setMessage(error.message ?? 'Something has gone wrong.');\n return { success: false, message: error.message ?? 'Something has gone wrong.' };\n }\n\n return { success: true, message: 'Payment successful' };\n },\n }));\n\n const paymentElementOptions: StripePaymentElementOptions = {\n layout: 'accordion' as const,\n fields: {\n billingDetails: {\n name: 'never',\n },\n },\n };\n\n return (\n <>\n <div className={classNames(styles['stripe-field-wrapper'], 'mb-3')}>\n <label htmlFor=\"cardholder-name\" className={classNames(styles['stripe-label'], { [styles['stripe-label--empty']]: !cardholderName })}>\n Cardholder name\n </label>\n <input\n type=\"text\"\n id=\"cardholder-name\"\n className={classNames(styles['stripe-input'], { [styles['stripe-input--empty']]: !cardholderName })}\n placeholder=\"Full name on card\"\n value={cardholderName}\n onChange={(e) => setCardholderName(e.target.value)}\n autoComplete=\"cc-name\"\n required\n />\n </div>\n <PaymentElement id=\"payment-element\" options={paymentElementOptions} />\n {message && (\n <div id=\"payment-message\" className=\"alert alert-danger mt-3\">\n {message}\n </div>\n )}\n </>\n );\n});\n\nStripePaymentForm.displayName = 'StripePaymentForm';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoomDetailsPriceBlock.js","sourceRoot":"/","sources":["src/components/steps/room/roomDetails/RoomDetailsPriceBlock.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"RoomDetailsPriceBlock.js","sourceRoot":"/","sources":["src/components/steps/room/roomDetails/RoomDetailsPriceBlock.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,wCAwDC;AA/ED,iDAA0D;AAC1D,4DAAoC;AACpC,kDAA0B;AAC1B,iDAA+C;AAC/C,0DAAuD;AAEvD,6EAAqD;AACrD,6EAAqD;AACrD,uEAAgE;AAChE,kEAA2D;AAC3D,mFAA2D;AAC3D,wCAAqC;AACrC,mEAA2C;AAW3C,SAAwB,qBAAqB,CAAC,KAAiC;IAC3E,MAAM,EAAE,CAAC,EAAE,GAAG,IAAA,8BAAc,GAAE,CAAC;IAE/B,MAAM,OAAO,GAAG,eAAK,CAAC,UAAU,CAAC,+BAAoB,CAAC,CAAC;IAEvD,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC;IAE7D,MAAM,eAAe,GAAG,kBAAkB,GAAG,YAAY,CAAC;IAE1D,MAAM,eAAe,GAAG,IAAA,oBAAU,EAAC,wCAAwC,EAAE;QACzE,mBAAmB,EAAE,eAAe,IAAI,CAAC,KAAK,CAAC,YAAY;QAC3D,kBAAkB,EAAE,KAAK,CAAC,YAAY;KACzC,CAAC,CAAC;IAEH,OAAO,CACH;QACI,uCACI,SAAS,EAAE,IAAA,oBAAU,EAAC,0FAA0F,EAAE;gBAC9G,UAAU,EAAE,QAAQ;aACvB,CAAC;YAED,CAAC,QAAQ,IAAI,eAAe,IAAI,CAC7B,wCAAM,SAAS,EAAC,kEAAkE;gBAC9E,8BAAC,cAAI,IAAC,KAAK,EAAE,aAAK,CAAC,QAAQ;oBACvB;wBACI,8BAAC,kBAAQ,QAAE,kBAAkB,CAAY,CACpC,CACN;gBACN,CAAC,KAAK,CAAC,YAAY,IAAI,CACpB,8BAAC,cAAI,IAAC,KAAK,EAAE,aAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,eAAQ,CAAC,OAAO;;oBAC7C,CAAC,CAAC,yBAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CACxB,CACV,CACE,CACV;YACD,wCAAM,SAAS,EAAE,eAAe;gBAC5B,8BAAC,kBAAQ,IACL,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,oBAAU,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EACjE,IAAI,QACJ,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAChD,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,aAAK,CAAC,IAAI,CAAC,CAAC,CAAC,aAAK,CAAC,QAAQ;oBAEvD,8BAAC,kBAAQ,IAAC,cAAc,QAAC,YAAY,UAChC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CACvB,CACJ;gBACV,CAAC,KAAK,CAAC,YAAY,IAAI,8BAAC,cAAI,IAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,aAAK,CAAC,IAAI,CAAC,CAAC,CAAC,aAAK,CAAC,QAAQ;;oBAAI,CAAC,CAAC,yBAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAQ,CACvH;YACP,8BAAC,iBAAO,IAAC,KAAK,EAAE,CAAC,CAAC,yBAAW,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC;gBACrE,wCAAM,SAAS,EAAC,kCAAkC;oBAC9C,8BAAC,cAAI,IAAC,IAAI,EAAE,eAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,aAAK,CAAC,OAAO,GAAI,CAChD,CACD,CACR,CACP,CACN,CAAC;AACN,CAAC","sourcesContent":["import { BookingEngineContext } from '@frontend/contexts';\nimport classNames from 'classnames';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Translation } from 'translations/Translation';\n\nimport Currency from '@/components/generic/Currency';\nimport Headline from '@/components/generic/Headline';\nimport Icon, { IconType } from '@/components/generic/Icon/Icon';\nimport Text, { TextType } from '@/components/generic/Text';\nimport Tooltip from '@/components/generic/Tooltip/Tooltip';\nimport { Color } from '@/util/Color';\nimport ScreenSize from '@/util/ScreenSize';\n\ninterface RoomDetailsPriceBlockProps {\n isLocked: boolean;\n averagePreDiscount: number;\n averagePrice: number;\n isMemberOnly?: boolean;\n hidePerNight?: boolean;\n useLightText?: boolean;\n}\n\nexport default function RoomDetailsPriceBlock(props: RoomDetailsPriceBlockProps) {\n const { t } = useTranslation();\n\n const context = React.useContext(BookingEngineContext);\n\n const { isLocked, averagePreDiscount, averagePrice } = props;\n\n const discountApplied = averagePreDiscount > averagePrice;\n\n const headlineClasses = classNames('room-details--content-price-protection', {\n '--accent-headline': discountApplied && !props.useLightText,\n '--accent-success': props.isMemberOnly,\n });\n\n return (\n <>\n <div\n className={classNames('room-details--content-price u-flex u-flex-direction-column justify-content-end flex-wrap', {\n '--locked': isLocked,\n })}\n >\n {!isLocked && discountApplied && (\n <span className=\"room-details--content-price-protection --original align-self-end\">\n <Text color={Color.DarkGrey}>\n <strong>\n <Currency>{averagePreDiscount}</Currency>\n </strong>\n </Text>\n {!props.hidePerNight && (\n <Text color={Color.DarkGrey} type={TextType.Caption}>\n /{t(Translation.Misc.Night)}\n </Text>\n )}\n </span>\n )}\n <span className={headlineClasses}>\n <Headline\n size={context.screenSize > ScreenSize.Medium ? 'large' : 'normal'}\n bold\n className={props.isMemberOnly ? '--success' : ''}\n color={props.useLightText ? Color.Snow : Color.Graphite}\n >\n <Currency disableLoading hideDecimals>\n {isLocked ? 321 : averagePrice}\n </Currency>\n </Headline>\n {!props.hidePerNight && <Text color={props.useLightText ? Color.Snow : Color.DarkGrey}>/{t(Translation.Misc.Night)}</Text>}\n </span>\n <Tooltip title={t(Translation.Step.Room.RoomInfo.MemberRateLockedTooltip)}>\n <span className=\"room-details--content-price-lock\">\n <Icon icon={IconType.Lock} color={Color.Success} />\n </span>\n </Tooltip>\n </div>\n </>\n );\n}\n"]}
|
|
@@ -50,7 +50,7 @@ const Tooltip_1 = __importDefault(require("../generic/Tooltip/Tooltip"));
|
|
|
50
50
|
const Addon_1 = require("../../models/Addon/Addon");
|
|
51
51
|
const Color_1 = require("../../util/Color");
|
|
52
52
|
function BESummaryAddonRow(props) {
|
|
53
|
-
var _a, _b, _c, _d, _e, _f
|
|
53
|
+
var _a, _b, _c, _d, _e, _f;
|
|
54
54
|
const { row } = props;
|
|
55
55
|
const { t } = (0, react_i18next_1.useTranslation)();
|
|
56
56
|
const { hotel } = (0, hooks_1.useCurrentHotel)();
|
|
@@ -76,18 +76,16 @@ function BESummaryAddonRow(props) {
|
|
|
76
76
|
};
|
|
77
77
|
const pricingType = addon.pricingType;
|
|
78
78
|
const totalFees = row.getTotalFees();
|
|
79
|
-
const itemisedFees = hotel && row.getItemisedFees(
|
|
79
|
+
// const itemisedFees = hotel && row.getItemisedFees(getFilteredBookingAddonFees(hotel.fees ?? []));
|
|
80
80
|
// Calculate discount if promo code is applied
|
|
81
|
-
const discount = row.getDiscountAmount((
|
|
81
|
+
const discount = row.getDiscountAmount((_a = props.promoCodeDetails) !== null && _a !== void 0 ? _a : undefined, props.remainingDiscount || 0);
|
|
82
82
|
const priceBeforeDiscount = row.getPriceBeforeDiscount();
|
|
83
83
|
let displayPrice = row.getTotalPrice();
|
|
84
84
|
if (discount > 0) {
|
|
85
|
-
displayPrice = row.getDiscountedTotalPrice((
|
|
86
|
-
}
|
|
87
|
-
if (itemisedFees === null || itemisedFees === void 0 ? void 0 : itemisedFees.length) {
|
|
88
|
-
// If we have itemised fees, we'll show the total price without fee.
|
|
89
|
-
displayPrice -= totalFees;
|
|
85
|
+
displayPrice = row.getDiscountedTotalPrice((_b = props.promoCodeDetails) !== null && _b !== void 0 ? _b : undefined, props.remainingDiscount || 0);
|
|
90
86
|
}
|
|
87
|
+
// we'll show the total price without fee.
|
|
88
|
+
displayPrice -= totalFees;
|
|
91
89
|
return (react_1.default.createElement(react_1.default.Fragment, null, priceInfo && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
92
90
|
react_1.default.createElement("div", { className: "u-marg-bottom--light u-marg-top" },
|
|
93
91
|
react_1.default.createElement(Text_1.default, { color: Color_1.Color.Navy },
|
|
@@ -97,18 +95,18 @@ function BESummaryAddonRow(props) {
|
|
|
97
95
|
price: priceInfo.price,
|
|
98
96
|
quantity: row.getQuantity(),
|
|
99
97
|
},
|
|
100
|
-
...(((
|
|
98
|
+
...(((_c = priceInfo.childPrice) !== null && _c !== void 0 ? _c : 0) > 0
|
|
101
99
|
? [
|
|
102
100
|
{
|
|
103
101
|
name: 'Adult',
|
|
104
|
-
price: (
|
|
102
|
+
price: (_d = priceInfo.adultPrice) !== null && _d !== void 0 ? _d : priceInfo.price,
|
|
105
103
|
quantity: row.getAdultQuantity(),
|
|
106
104
|
},
|
|
107
105
|
]
|
|
108
106
|
: []),
|
|
109
107
|
{
|
|
110
108
|
name: 'Child',
|
|
111
|
-
price: (
|
|
109
|
+
price: (_e = priceInfo.childPrice) !== null && _e !== void 0 ? _e : priceInfo.price,
|
|
112
110
|
quantity: row.getChildQuantity(),
|
|
113
111
|
},
|
|
114
112
|
].map(({ price, quantity, name }, index) => {
|
|
@@ -147,10 +145,9 @@ function BESummaryAddonRow(props) {
|
|
|
147
145
|
row.getChildQuantity() > 0 &&
|
|
148
146
|
printLine('Sub-total', react_1.default.createElement(Currency_1.default, null, row.getAddonSubtotal())),
|
|
149
147
|
core_1.ADDON_PER_NIGHT_TYPES.includes(pricingType) && printLine('Nights', row.getAddon().nights),
|
|
150
|
-
totalFees > 0 && !(itemisedFees === null || itemisedFees === void 0 ? void 0 : itemisedFees.length) && printLine('Fees', react_1.default.createElement(Currency_1.default, null, totalFees)),
|
|
151
148
|
discount > 0 && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
152
149
|
printLine(t(Translation_1.Translation.Misc.Rates), react_1.default.createElement(Currency_1.default, null, priceBeforeDiscount)),
|
|
153
|
-
((
|
|
150
|
+
((_f = props.promoCodeDetails) === null || _f === void 0 ? void 0 : _f.code) && printLine(t(Translation_1.Translation.Step.Date.PromoCode), props.promoCodeDetails.code),
|
|
154
151
|
printLine(t(Translation_1.Translation.Misc.Discount), react_1.default.createElement(react_1.default.Fragment, null,
|
|
155
152
|
react_1.default.createElement("span", { className: "u-ellip-overflow" }, "-"),
|
|
156
153
|
react_1.default.createElement(Currency_1.default, null, discount))))),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BESummaryAddonRow.js","sourceRoot":"/","sources":["src/components/summary/BESummaryAddonRow.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCurrentHotel } from '@frontend/hooks';\nimport { ADDON_PER_NIGHT_TYPES, EAddonPricingType, getFilteredBookingAddonFees, IPromoCodeDetails } from '@roomstay/core';\nimport dayjs, { Dayjs } from 'dayjs';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Translation } from 'translations/Translation';\n\nimport BEButton from '@/components/generic/BEButton';\nimport Currency from '@/components/generic/Currency';\nimport Text, { TextType } from '@/components/generic/Text';\nimport Tooltip from '@/components/generic/Tooltip/Tooltip';\nimport { ADDON_PER_PERSON_PER_NIGHT_TYPES } from '@/models/Addon/Addon';\nimport BasketAddonRow from '@/models/BasketAddonRow';\nimport { Color } from '@/util/Color';\n\ninterface BESummaryAddonRowProps {\n row: BasketAddonRow;\n onRemoveClick: () => void;\n promoCodeDetails?: IPromoCodeDetails | null;\n remainingDiscount?: number;\n}\n\nexport default function BESummaryAddonRow(props: BESummaryAddonRowProps) {\n const { row } = props;\n\n const { t } = useTranslation();\n const { hotel } = useCurrentHotel();\n\n const addon = row.getAddon();\n const date = row.getSelectedDate();\n const priceInfo = addon.availability[date];\n\n let selectedTime: Dayjs | undefined;\n if (row.getSelectedTime()) {\n const [hours, minutes, seconds] = row\n .getSelectedTime()\n .substr(1)\n .split(':')\n .map((it) => parseInt(it, 10));\n selectedTime = dayjs().hour(hours).minute(minutes).second(seconds);\n }\n\n const removeOnClickHandler = () => {\n props.onRemoveClick();\n };\n\n const printLine = (left: any, right: any) => {\n return (\n <div className=\"u-marg-top--light u-marg-bottom--light u-flex\">\n <Text type={TextType.Small}>{left}</Text>\n <Text type={TextType.Small} color={Color.DarkGrey}>\n {right}\n </Text>\n </div>\n );\n };\n\n const pricingType = addon.pricingType;\n const totalFees = row.getTotalFees();\n const itemisedFees = hotel && row.getItemisedFees(getFilteredBookingAddonFees(hotel.fees ?? []));\n\n // Calculate discount if promo code is applied\n const discount = row.getDiscountAmount(props.promoCodeDetails ?? undefined, props.remainingDiscount || 0);\n const priceBeforeDiscount = row.getPriceBeforeDiscount();\n\n let displayPrice = row.getTotalPrice();\n if (discount > 0) {\n displayPrice = row.getDiscountedTotalPrice(props.promoCodeDetails ?? undefined, props.remainingDiscount || 0);\n }\n if (itemisedFees?.length) {\n // If we have itemised fees, we'll show the total price without fee.\n displayPrice -= totalFees;\n }\n\n return (\n <>\n {priceInfo && (\n <>\n <div className=\"u-marg-bottom--light u-marg-top\">\n <Text color={Color.Navy}>\n <strong>{addon.name}</strong>\n </Text>\n </div>\n\n {[\n {\n price: priceInfo.price,\n quantity: row.getQuantity(),\n },\n ...((priceInfo.childPrice ?? 0) > 0\n ? [\n {\n name: 'Adult',\n price: priceInfo.adultPrice ?? priceInfo.price,\n quantity: row.getAdultQuantity(),\n },\n ]\n : []),\n {\n name: 'Child',\n price: priceInfo.childPrice ?? priceInfo.price,\n quantity: row.getChildQuantity(),\n },\n ].map(({ price, quantity, name }, index) => {\n let pluralName = name;\n\n if (quantity > 1) {\n switch (name) {\n case 'Adult':\n pluralName += 's';\n break;\n case 'Child':\n pluralName += 'ren';\n break;\n }\n }\n\n // If this is a per stay or per night addon, we only want to show the price once, if we show the name it will result in something like:\n // 2 x $100 = $200\n // 1 x Adult = $100\n // Total = $200\n if ((pricingType === EAddonPricingType.PER_STAY || pricingType === EAddonPricingType.PER_NIGHT) && name !== undefined) {\n return;\n }\n\n return (\n <React.Fragment key={index}>\n {price && quantity > 0 && (\n <div className=\"u-marg-top--light u-marg-bottom--light u-flex align-items-center\">\n <Text type={TextType.Small} inline>\n {quantity} {pluralName ? `${pluralName} ` : ''}× <Currency>{price}</Currency>\n </Text>\n <Text type={TextType.Small} color={Color.DarkGrey} inline>\n <Currency>{quantity * price}</Currency>\n </Text>\n </div>\n )}\n </React.Fragment>\n );\n })}\n\n {!row.getAddon().hideDatePicker && row.getSelectedDate() && printLine('Date', dayjs(row.getSelectedDate(), 'YYYY-MM-DD').format('D MMM'))}\n {selectedTime && printLine('Time', selectedTime.format('h:mma'))}\n\n {/* If this is a per person per night addon, and there are both children and adults added, show a sub-total. */}\n {ADDON_PER_PERSON_PER_NIGHT_TYPES.includes(pricingType) &&\n row.getAdultQuantity() > 0 &&\n row.getChildQuantity() > 0 &&\n printLine('Sub-total', <Currency>{row.getAddonSubtotal()}</Currency>)}\n\n {ADDON_PER_NIGHT_TYPES.includes(pricingType) && printLine('Nights', row.getAddon().nights)}\n\n {/*/ Only show fees if we don't have itemised fees. If we have itemised fees they will be shown later. */}\n {totalFees > 0 && !itemisedFees?.length && printLine('Fees', <Currency>{totalFees}</Currency>)}\n\n {/* Show discount information if promo code is applied */}\n {discount > 0 && (\n <>\n {printLine(t(Translation.Misc.Rates), <Currency>{priceBeforeDiscount}</Currency>)}\n {props.promoCodeDetails?.code && printLine(t(Translation.Step.Date.PromoCode), props.promoCodeDetails.code)}\n {printLine(\n t(Translation.Misc.Discount),\n <>\n <span className=\"u-ellip-overflow\">-</span>\n <Currency>{discount}</Currency>\n </>\n )}\n </>\n )}\n\n {printLine('Total', <Currency>{displayPrice}</Currency>)}\n\n <div className=\"u-marg-top--light u-marg-bottom--heavy u-flex justify-content-start\">\n <Tooltip title=\"Remove this addon\">\n <div>\n <BEButton isText size=\"tiny\" primary onClick={removeOnClickHandler}>\n {t(Translation.Misc.Remove)}\n </BEButton>\n </div>\n </Tooltip>\n </div>\n </>\n )}\n </>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BESummaryAddonRow.js","sourceRoot":"/","sources":["src/components/summary/BESummaryAddonRow.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCurrentHotel } from '@frontend/hooks';\nimport { ADDON_PER_NIGHT_TYPES, EAddonPricingType, IPromoCodeDetails } from '@roomstay/core';\nimport dayjs, { Dayjs } from 'dayjs';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Translation } from 'translations/Translation';\n\nimport BEButton from '@/components/generic/BEButton';\nimport Currency from '@/components/generic/Currency';\nimport Text, { TextType } from '@/components/generic/Text';\nimport Tooltip from '@/components/generic/Tooltip/Tooltip';\nimport { ADDON_PER_PERSON_PER_NIGHT_TYPES } from '@/models/Addon/Addon';\nimport BasketAddonRow from '@/models/BasketAddonRow';\nimport { Color } from '@/util/Color';\n\ninterface BESummaryAddonRowProps {\n row: BasketAddonRow;\n onRemoveClick: () => void;\n promoCodeDetails?: IPromoCodeDetails | null;\n remainingDiscount?: number;\n}\n\nexport default function BESummaryAddonRow(props: BESummaryAddonRowProps) {\n const { row } = props;\n\n const { t } = useTranslation();\n const { hotel } = useCurrentHotel();\n\n const addon = row.getAddon();\n const date = row.getSelectedDate();\n const priceInfo = addon.availability[date];\n\n let selectedTime: Dayjs | undefined;\n if (row.getSelectedTime()) {\n const [hours, minutes, seconds] = row\n .getSelectedTime()\n .substr(1)\n .split(':')\n .map((it) => parseInt(it, 10));\n selectedTime = dayjs().hour(hours).minute(minutes).second(seconds);\n }\n\n const removeOnClickHandler = () => {\n props.onRemoveClick();\n };\n\n const printLine = (left: any, right: any) => {\n return (\n <div className=\"u-marg-top--light u-marg-bottom--light u-flex\">\n <Text type={TextType.Small}>{left}</Text>\n <Text type={TextType.Small} color={Color.DarkGrey}>\n {right}\n </Text>\n </div>\n );\n };\n\n const pricingType = addon.pricingType;\n const totalFees = row.getTotalFees();\n // const itemisedFees = hotel && row.getItemisedFees(getFilteredBookingAddonFees(hotel.fees ?? []));\n\n // Calculate discount if promo code is applied\n const discount = row.getDiscountAmount(props.promoCodeDetails ?? undefined, props.remainingDiscount || 0);\n const priceBeforeDiscount = row.getPriceBeforeDiscount();\n\n let displayPrice = row.getTotalPrice();\n if (discount > 0) {\n displayPrice = row.getDiscountedTotalPrice(props.promoCodeDetails ?? undefined, props.remainingDiscount || 0);\n }\n // we'll show the total price without fee.\n displayPrice -= totalFees;\n\n return (\n <>\n {priceInfo && (\n <>\n <div className=\"u-marg-bottom--light u-marg-top\">\n <Text color={Color.Navy}>\n <strong>{addon.name}</strong>\n </Text>\n </div>\n\n {[\n {\n price: priceInfo.price,\n quantity: row.getQuantity(),\n },\n ...((priceInfo.childPrice ?? 0) > 0\n ? [\n {\n name: 'Adult',\n price: priceInfo.adultPrice ?? priceInfo.price,\n quantity: row.getAdultQuantity(),\n },\n ]\n : []),\n {\n name: 'Child',\n price: priceInfo.childPrice ?? priceInfo.price,\n quantity: row.getChildQuantity(),\n },\n ].map(({ price, quantity, name }, index) => {\n let pluralName = name;\n\n if (quantity > 1) {\n switch (name) {\n case 'Adult':\n pluralName += 's';\n break;\n case 'Child':\n pluralName += 'ren';\n break;\n }\n }\n\n // If this is a per stay or per night addon, we only want to show the price once, if we show the name it will result in something like:\n // 2 x $100 = $200\n // 1 x Adult = $100\n // Total = $200\n if ((pricingType === EAddonPricingType.PER_STAY || pricingType === EAddonPricingType.PER_NIGHT) && name !== undefined) {\n return;\n }\n\n return (\n <React.Fragment key={index}>\n {price && quantity > 0 && (\n <div className=\"u-marg-top--light u-marg-bottom--light u-flex align-items-center\">\n <Text type={TextType.Small} inline>\n {quantity} {pluralName ? `${pluralName} ` : ''}× <Currency>{price}</Currency>\n </Text>\n <Text type={TextType.Small} color={Color.DarkGrey} inline>\n <Currency>{quantity * price}</Currency>\n </Text>\n </div>\n )}\n </React.Fragment>\n );\n })}\n\n {!row.getAddon().hideDatePicker && row.getSelectedDate() && printLine('Date', dayjs(row.getSelectedDate(), 'YYYY-MM-DD').format('D MMM'))}\n {selectedTime && printLine('Time', selectedTime.format('h:mma'))}\n\n {/* If this is a per person per night addon, and there are both children and adults added, show a sub-total. */}\n {ADDON_PER_PERSON_PER_NIGHT_TYPES.includes(pricingType) &&\n row.getAdultQuantity() > 0 &&\n row.getChildQuantity() > 0 &&\n printLine('Sub-total', <Currency>{row.getAddonSubtotal()}</Currency>)}\n\n {ADDON_PER_NIGHT_TYPES.includes(pricingType) && printLine('Nights', row.getAddon().nights)}\n\n {/* Hide Add-on Fees Already Included in Card Surcharge or Itemised Fees */}\n {/* {totalFees > 0 && !itemisedFees?.length && printLine('Fees', <Currency>{totalFees}</Currency>)} */}\n\n {/* Show discount information if promo code is applied */}\n {discount > 0 && (\n <>\n {printLine(t(Translation.Misc.Rates), <Currency>{priceBeforeDiscount}</Currency>)}\n {props.promoCodeDetails?.code && printLine(t(Translation.Step.Date.PromoCode), props.promoCodeDetails.code)}\n {printLine(\n t(Translation.Misc.Discount),\n <>\n <span className=\"u-ellip-overflow\">-</span>\n <Currency>{discount}</Currency>\n </>\n )}\n </>\n )}\n\n {printLine('Total', <Currency>{displayPrice}</Currency>)}\n\n <div className=\"u-marg-top--light u-marg-bottom--heavy u-flex justify-content-start\">\n <Tooltip title=\"Remove this addon\">\n <div>\n <BEButton isText size=\"tiny\" primary onClick={removeOnClickHandler}>\n {t(Translation.Misc.Remove)}\n </BEButton>\n </div>\n </Tooltip>\n </div>\n </>\n )}\n </>\n );\n}\n"]}
|
|
@@ -611,6 +611,7 @@ function BasketContextWrapper(props) {
|
|
|
611
611
|
addRate: (rate_1, ...args_1) => __awaiter(this, [rate_1, ...args_1], void 0, function* (rate, notify = true) {
|
|
612
612
|
let basketRow = null;
|
|
613
613
|
let translationString;
|
|
614
|
+
const hasNoBasketRowSelected = !selectedBasketRow;
|
|
614
615
|
let addons = [];
|
|
615
616
|
if (selectedBasketRow) {
|
|
616
617
|
selectedBasketRow.setPreGuestsState();
|
|
@@ -627,6 +628,7 @@ function BasketContextWrapper(props) {
|
|
|
627
628
|
}
|
|
628
629
|
}
|
|
629
630
|
else {
|
|
631
|
+
// When no basket row is selected and the guest clicks "Book Now", create a new basket row using the selected room rate and dates.
|
|
630
632
|
if (!startDate || !endDate) {
|
|
631
633
|
console.error('room selected with no date values.');
|
|
632
634
|
return;
|
|
@@ -641,6 +643,10 @@ function BasketContextWrapper(props) {
|
|
|
641
643
|
addons = yield BookingAPI_1.default.Addons.findAddons([basketRow], hotel === null || hotel === void 0 ? void 0 : hotel.hotelID);
|
|
642
644
|
}
|
|
643
645
|
basketRow.setAuxiliaryFilter(beContext.currentGroupedRoomFilters);
|
|
646
|
+
if (hasNoBasketRowSelected) {
|
|
647
|
+
// When no basket row is currently selected, automatically select the newly created row so the guest can immediately review or edit it.
|
|
648
|
+
setSelectedBasketRow(basketRow);
|
|
649
|
+
}
|
|
644
650
|
beContext.setCurrentGroupedRoomFilters({});
|
|
645
651
|
basketRowReducer({ method: 'AddRate', rate, row: basketRow });
|
|
646
652
|
// Update promo code details from availability cache
|
|
@@ -676,9 +682,12 @@ function BasketContextWrapper(props) {
|
|
|
676
682
|
setSelectedBasketRow(nextAvailable);
|
|
677
683
|
}
|
|
678
684
|
else {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
685
|
+
/**
|
|
686
|
+
* If all rows already have a rate assigned. Set the selected basket row to null, ensuring that no row is selected for editing.
|
|
687
|
+
*/
|
|
688
|
+
if (!hasNoBasketRowSelected) {
|
|
689
|
+
workingContext.clearSelectedRates();
|
|
690
|
+
}
|
|
682
691
|
// Determine whether the next step is an add-on selection step.
|
|
683
692
|
const isNextStepAddon = StepManager_1.default.getNextStepUrl((0, GetStepRoom_1.default)()) === StepAddon_1.default.getStepUrl();
|
|
684
693
|
if (isNextStepAddon) {
|
|
@@ -1020,9 +1029,13 @@ function BasketContextWrapper(props) {
|
|
|
1020
1029
|
},
|
|
1021
1030
|
/**
|
|
1022
1031
|
* Set the selected basket row to null, ensuring that no row is selected for editing.
|
|
1032
|
+
* When the group booking limit is reached.
|
|
1033
|
+
* Ensure a basket row is always selected when navigating back to the Room step, allowing the guest to change the room rate directly.
|
|
1023
1034
|
*/
|
|
1024
1035
|
clearSelectedRates: () => {
|
|
1025
|
-
|
|
1036
|
+
if (canAddAnotherRoom) {
|
|
1037
|
+
setSelectedBasketRow(null);
|
|
1038
|
+
}
|
|
1026
1039
|
},
|
|
1027
1040
|
getRowForAddon: (selectedAddon) => {
|
|
1028
1041
|
if (selectedAddon === undefined) {
|