kupos-ui-components-lib 9.11.10 → 10.0.1
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/components/PaymentSideBar/PaymentSideBarDesktop.js +11 -1
- package/dist/components/PaymentSideBar/PaymentSideBarMobile.js +9 -2
- package/dist/components/PaymentSideBar/types.d.ts +2 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.js +1 -1
- package/dist/styles.css +3 -11
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.d.ts +1 -2
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +53 -17
- package/dist/ui/SeatSection/SeatSection.js +3 -0
- package/dist/utils/CommonService.d.ts +1 -0
- package/dist/utils/CommonService.js +35 -0
- package/package.json +1 -1
- package/src/components/PaymentSideBar/PaymentSideBarDesktop.tsx +34 -0
- package/src/components/PaymentSideBar/PaymentSideBarMobile.tsx +41 -1
- package/src/components/PaymentSideBar/types.ts +2 -1
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +0 -1
- package/src/ui/FeatureServiceUI/FeatureServiceUi.tsx +66 -26
- package/src/ui/SeatSection/SeatSection.tsx +5 -0
- package/src/utils/CommonService.ts +48 -0
|
@@ -177,7 +177,7 @@ const renderSummaryDetailsCard = ({ serviceName, date, source, dest, boardingSta
|
|
|
177
177
|
duration,
|
|
178
178
|
" horas")))))));
|
|
179
179
|
};
|
|
180
|
-
const PaymentSideBarDesktop = ({ serviceNameOnward, serviceNameReturn, metaData, currencySign, dateOnward, dateReturn, sourceOnward, sourceReturn, destinationOnward, destinationReturn, boardingStageOnward, boardingStageReturn, droppingStageOnward, droppingStageReturn, boardingTimeOnward, boardingTimeReturn, droppingTimeOnward, droppingTimeReturn, durationOnward, durationReturn, selectSeatOnward, selectSeatReturn, journeyTypeActive, setJourneyTypeActive, translation, trainTypeOnward, trainTypeReturn, colors, trainType, icons, selectedOnward, selectedReturn, conexionChecked, conexionPassengers, returnConexionFare, conexionFare, loginData, checkWhatsappEligibility, removeDiscountAtomValue, netFare, promoCode, onPromoRemove, isAgency, agencyFee, walletMoney, virtualMoney, virtualLimit, showUsd, netFareInUsd, renderDiscount, discountAmount, walletLabel, creditosLabel, currency, customSideBarwidth, isLinatal, insuranceData, isPeru, }) => {
|
|
180
|
+
const PaymentSideBarDesktop = ({ serviceNameOnward, serviceNameReturn, metaData, currencySign, dateOnward, dateReturn, sourceOnward, sourceReturn, destinationOnward, destinationReturn, boardingStageOnward, boardingStageReturn, droppingStageOnward, droppingStageReturn, boardingTimeOnward, boardingTimeReturn, droppingTimeOnward, droppingTimeReturn, durationOnward, durationReturn, selectSeatOnward, selectSeatReturn, journeyTypeActive, setJourneyTypeActive, translation, trainTypeOnward, trainTypeReturn, colors, trainType, icons, selectedOnward, selectedReturn, conexionChecked, conexionPassengers, returnConexionFare, conexionFare, loginData, checkWhatsappEligibility, removeDiscountAtomValue, netFare, promoCode, onPromoRemove, isAgency, agencyFee, walletMoney, virtualMoney, virtualLimit, showUsd, netFareInUsd, renderDiscount, discountAmount, walletLabel, creditosLabel, currency, customSideBarwidth, isLinatal, insuranceData, isPeru, serviceFeeDataStateValue, }) => {
|
|
181
181
|
var _a, _b, _c, _d, _e;
|
|
182
182
|
// REMOVED AM/PM DUPLICATION AND ADDED 24 HOUR TIME FORMAT IN BOARDING STAGE
|
|
183
183
|
const depTime = droppingTimeOnward || "";
|
|
@@ -427,6 +427,16 @@ const PaymentSideBarDesktop = ({ serviceNameOnward, serviceNameReturn, metaData,
|
|
|
427
427
|
React.createElement("div", null, promoCode === null || promoCode === void 0 ? void 0 : promoCode.promoCode),
|
|
428
428
|
React.createElement("span", { className: "promo-remove", onClick: onPromoRemove },
|
|
429
429
|
React.createElement("img", { src: icons === null || icons === void 0 ? void 0 : icons.closeIcon, alt: "close", className: "w-[16px] h-[16px]" })))) : null,
|
|
430
|
+
(serviceFeeDataStateValue === null || serviceFeeDataStateValue === void 0 ? void 0 : serviceFeeDataStateValue.total_convenience_fee_amount) && (React.createElement(PaymentItem, { label: React.createElement("div", { style: { display: "flex", alignItems: "center" } },
|
|
431
|
+
React.createElement("div", { className: "font10" }, translation === null || translation === void 0 ? void 0 : translation.serviceFeeLabel),
|
|
432
|
+
React.createElement("div", { className: "img-hover" },
|
|
433
|
+
React.createElement("img", { src: icons === null || icons === void 0 ? void 0 : icons.whatsappInfoIcon, alt: "", style: {
|
|
434
|
+
marginLeft: "5px",
|
|
435
|
+
marginBottom: "3px",
|
|
436
|
+
width: "15px",
|
|
437
|
+
} }),
|
|
438
|
+
React.createElement("div", { className: "duration-mouseover font9", style: { lineHeight: "1.3" } },
|
|
439
|
+
React.createElement("span", null, translation === null || translation === void 0 ? void 0 : translation.serviceFeeHoverLabel)))), amount: CommonService.currency(serviceFeeDataStateValue === null || serviceFeeDataStateValue === void 0 ? void 0 : serviceFeeDataStateValue.total_convenience_fee_amount, currencySign), className: "font10", currency: currency, customStyle: { color: colors === null || colors === void 0 ? void 0 : colors.whatsappDeliveryChargesColor } })),
|
|
430
440
|
isAgency && (React.createElement(PaymentItem, { label: translation === null || translation === void 0 ? void 0 : translation.agencyFee, amount: CommonService.currency(agencyFee ? agencyFee : 0, currencySign), currency: "", customStyle: { color: colors === null || colors === void 0 ? void 0 : colors.agencyFeePriceColor } })),
|
|
431
441
|
walletMoney ? (React.createElement(PaymentItem, { label: walletLabel, amount: CommonService.currency(walletMoney, currencySign), currency: "" })) : null,
|
|
432
442
|
virtualMoney ? (React.createElement(PaymentItem, { label: React.createElement("span", { className: "secondary-text " }, `${creditosLabel}(${virtualLimit}%)`), amount: CommonService.currency(virtualMoney, currencySign), customStyle: { color: "var(--secondary-color)" }, currency: "" })) : null,
|
|
@@ -73,7 +73,7 @@ const renderSummaryDetailsCard = ({ serviceName, date, source, dest, boardingSta
|
|
|
73
73
|
? `${getRoundedHour(duration)}hrs aprox`
|
|
74
74
|
: `${duration} horas`)))))));
|
|
75
75
|
};
|
|
76
|
-
const PaymentSideBarMobile = ({ serviceNameOnward, serviceNameReturn, metaData, currencySign, dateOnward, dateReturn, sourceOnward, sourceReturn, destinationOnward, destinationReturn, boardingStageOnward, boardingStageReturn, droppingStageOnward, droppingStageReturn, boardingTimeOnward, boardingTimeReturn, droppingTimeOnward, droppingTimeReturn, durationOnward, durationReturn, selectSeatOnward, selectSeatReturn, journeyTypeActive, setJourneyTypeActive, translation, trainTypeOnward, trainTypeReturn, colors, trainType, icons, selectedOnward, selectedReturn, conexionChecked, conexionPassengers, returnConexionFare, conexionFare, loginData, checkWhatsappEligibility, removeDiscountAtomValue, netFare, promoCode, onPromoRemove, isAgency, agencyFee, walletMoney, virtualMoney, virtualLimit, showUsd, netFareInUsd, renderDiscount, discountAmount, currency, showWhatsappChargesInfo, setShowWhatsappChargesInfo, t, countdown, walletLabel, creditosLabel, isTacna, isLinatal, insuranceData, isPeru, }) => {
|
|
76
|
+
const PaymentSideBarMobile = ({ serviceNameOnward, serviceNameReturn, metaData, currencySign, dateOnward, dateReturn, sourceOnward, sourceReturn, destinationOnward, destinationReturn, boardingStageOnward, boardingStageReturn, droppingStageOnward, droppingStageReturn, boardingTimeOnward, boardingTimeReturn, droppingTimeOnward, droppingTimeReturn, durationOnward, durationReturn, selectSeatOnward, selectSeatReturn, journeyTypeActive, setJourneyTypeActive, translation, trainTypeOnward, trainTypeReturn, colors, trainType, icons, selectedOnward, selectedReturn, conexionChecked, conexionPassengers, returnConexionFare, conexionFare, loginData, checkWhatsappEligibility, removeDiscountAtomValue, netFare, promoCode, onPromoRemove, isAgency, agencyFee, walletMoney, virtualMoney, virtualLimit, showUsd, netFareInUsd, renderDiscount, discountAmount, currency, showWhatsappChargesInfo, setShowWhatsappChargesInfo, t, countdown, walletLabel, creditosLabel, isTacna, isLinatal, insuranceData, isPeru, setShowServicefeeModal, serviceFeeDataStateValue, }) => {
|
|
77
77
|
var _a, _b, _c, _d, _e;
|
|
78
78
|
return (React.createElement("div", { className: "pb-[10px]" },
|
|
79
79
|
React.createElement("div", { className: "border border-[#ccc] m-[20px] rounded-[20px] relative" },
|
|
@@ -211,6 +211,13 @@ const PaymentSideBarMobile = ({ serviceNameOnward, serviceNameReturn, metaData,
|
|
|
211
211
|
React.createElement("div", null, promoCode === null || promoCode === void 0 ? void 0 : promoCode.promoCode),
|
|
212
212
|
React.createElement("span", { className: "promo-remove", onClick: onPromoRemove },
|
|
213
213
|
React.createElement("img", { src: icons === null || icons === void 0 ? void 0 : icons.closeIcon, alt: "close", className: "w-[16px] h-[16px]" })))) : null,
|
|
214
|
+
(serviceFeeDataStateValue === null || serviceFeeDataStateValue === void 0 ? void 0 : serviceFeeDataStateValue.total_convenience_fee_amount) && (React.createElement(PaymentItem, { label: React.createElement("div", { style: { display: "flex", alignItems: "center" } },
|
|
215
|
+
React.createElement("div", { className: " font14 flex items-center gap-[5px]" }, translation === null || translation === void 0 ? void 0 : translation.serviceFeeLabel),
|
|
216
|
+
React.createElement("div", { className: "img-hover", onClick: () => setShowServicefeeModal(true) },
|
|
217
|
+
React.createElement("img", { src: icons === null || icons === void 0 ? void 0 : icons.whatsappInfoIcon, alt: "", style: {
|
|
218
|
+
marginLeft: "5px",
|
|
219
|
+
width: "15px",
|
|
220
|
+
} }))), amount: CommonService.currency(serviceFeeDataStateValue === null || serviceFeeDataStateValue === void 0 ? void 0 : serviceFeeDataStateValue.total_convenience_fee_amount, currencySign), className: "font14", currency: currency, customStyle: { color: colors === null || colors === void 0 ? void 0 : colors.whatsappDeliveryChargesColor } })),
|
|
214
221
|
conexionChecked && conexionFare && returnConexionFare ? (React.createElement(PaymentItem, { label: "Conexi\u00F3n Aeropuerto:", amount: CommonService.currency(dateReturn
|
|
215
222
|
? returnConexionFare * conexionPassengers
|
|
216
223
|
: conexionFare, currencySign), className: "subtotal-row text-[14px]", customStyle: { color: colors === null || colors === void 0 ? void 0 : colors.seatPriceColor } })) : null,
|
|
@@ -219,7 +226,7 @@ const PaymentSideBarMobile = ({ serviceNameOnward, serviceNameReturn, metaData,
|
|
|
219
226
|
walletMoney ? (React.createElement(PaymentItem, { label: walletLabel, amount: CommonService.currency(walletMoney, currencySign), className: "text-[14px]", customStyle: { color: "var(--secondary-color)" }, currency: "" })) : null,
|
|
220
227
|
virtualMoney ? (React.createElement(PaymentItem, { label: React.createElement("span", { className: "secondary-text", style: { color: "var(--secondary-color)" } }, `${creditosLabel}(${virtualLimit}%)`), amount: CommonService.currency(virtualMoney, currencySign), customStyle: { color: "var(--secondary-color)" }, className: "text-[14px]", currency: "" })) : null,
|
|
221
228
|
showUsd ? (React.createElement(PaymentItem, { label: React.createElement("span", { className: "primary-text" }, translation === null || translation === void 0 ? void 0 : translation.showUsd), amount: CommonService.currency(isAgency ? netFareInUsd + agencyFee : netFareInUsd, currencySign), currency: "USD", customStyle: { color: "var(--primary-color)" }, className: "text-[14px]" })) : null)),
|
|
222
|
-
React.createElement("div", { className: ` text-[#fff] p-[10px_15px] text-left w-full flex items-center absolute -bottom-[
|
|
229
|
+
React.createElement("div", { className: ` text-[#fff] p-[10px_15px] text-left w-full flex items-center absolute -bottom-[7%] pt-[50px] z-1 rounded-b-[14px] text-[14px]`, style: { backgroundColor: colors === null || colors === void 0 ? void 0 : colors.bottomStripColor } },
|
|
223
230
|
React.createElement("div", { className: "flex justify-between items-center w-full text-[#fff]" },
|
|
224
231
|
React.createElement("div", { className: "bold-text" }, "Total"),
|
|
225
232
|
React.createElement("div", { className: "bold-text text-[14px] text-[#fff]", style: {
|
|
@@ -91,6 +91,7 @@ export interface PaymentSideBarProps {
|
|
|
91
91
|
currency?: string;
|
|
92
92
|
t?: (key: string) => string;
|
|
93
93
|
setShowWhatsappChargesInfo?: (value: boolean) => void;
|
|
94
|
+
setShowServicefeeModal?: (value: boolean) => void;
|
|
94
95
|
showWhatsappChargesInfo?: boolean;
|
|
95
96
|
onButtonOneClick?: any;
|
|
96
97
|
onHide?: any;
|
|
@@ -103,4 +104,5 @@ export interface PaymentSideBarProps {
|
|
|
103
104
|
isTacna?: boolean;
|
|
104
105
|
insuranceData?: any;
|
|
105
106
|
isPeru?: boolean;
|
|
107
|
+
serviceFeeDataStateValue?: any;
|
|
106
108
|
}
|
|
@@ -289,7 +289,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
289
289
|
},
|
|
290
290
|
];
|
|
291
291
|
const otherItems = items.filter((i) => i.key !== "pet" && i.key !== "flexible" && !!i.condition);
|
|
292
|
-
return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus, viewersConfig: viewersConfig, isLoggedIn: isLoggedIn, showLoginModal: showLoginModal, isExpand: isExpand, setIsExpand: setIsExpand, coachKey: coachKey, isFlores: isFlores, isNewUiEnabled: isNewUiEnabled, showLoginOption: showLoginOption })) : isNewUi ? (React.createElement(FeatureServiceUi, { serviceItem: serviceItem, showTopLabel: showTopLabel,
|
|
292
|
+
return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus, viewersConfig: viewersConfig, isLoggedIn: isLoggedIn, showLoginModal: showLoginModal, isExpand: isExpand, setIsExpand: setIsExpand, coachKey: coachKey, isFlores: isFlores, isNewUiEnabled: isNewUiEnabled, showLoginOption: showLoginOption })) : isNewUi ? (React.createElement(FeatureServiceUi, { serviceItem: serviceItem, showTopLabel: showTopLabel, getAnimationIcon: getAnimationIcon, cityOrigin: cityOrigin, cityDestination: cityDestination, renderIcon: renderIcon, viewersConfig: viewersConfig, isFeatureDropDownExpand: isFeatureDropDownExpand, ticketQuantity: ticketQuantity, onIncreaseTicketQuantity: onIncreaseTicketQuantity, onDecreaseTicketQuantity: onDecreaseTicketQuantity, onBookButtonPress: onRemateUiButtonClick, onToggleExpand: () => setIsFeatureDropDownExpand &&
|
|
293
293
|
setIsFeatureDropDownExpand(isFeatureDropDownExpand === serviceItem.id ||
|
|
294
294
|
isFeatureDropDownExpand === true
|
|
295
295
|
? null
|
package/dist/styles.css
CHANGED
|
@@ -81,12 +81,12 @@
|
|
|
81
81
|
.right-\[25px\] {
|
|
82
82
|
right: 25px;
|
|
83
83
|
}
|
|
84
|
+
.-bottom-\[7\%\] {
|
|
85
|
+
bottom: calc(7% * -1);
|
|
86
|
+
}
|
|
84
87
|
.-bottom-\[9\%\] {
|
|
85
88
|
bottom: calc(9% * -1);
|
|
86
89
|
}
|
|
87
|
-
.-bottom-\[10\%\] {
|
|
88
|
-
bottom: calc(10% * -1);
|
|
89
|
-
}
|
|
90
90
|
.-bottom-\[30px\] {
|
|
91
91
|
bottom: calc(30px * -1);
|
|
92
92
|
}
|
|
@@ -1218,18 +1218,10 @@
|
|
|
1218
1218
|
outline-style: var(--tw-outline-style);
|
|
1219
1219
|
outline-width: 1px;
|
|
1220
1220
|
}
|
|
1221
|
-
.brightness-0 {
|
|
1222
|
-
--tw-brightness: brightness(0%);
|
|
1223
|
-
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1224
|
-
}
|
|
1225
1221
|
.grayscale {
|
|
1226
1222
|
--tw-grayscale: grayscale(100%);
|
|
1227
1223
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1228
1224
|
}
|
|
1229
|
-
.invert {
|
|
1230
|
-
--tw-invert: invert(100%);
|
|
1231
|
-
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1232
|
-
}
|
|
1233
1225
|
.filter {
|
|
1234
1226
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
1235
1227
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
declare const FeatureServiceUi: ({ serviceItem, showTopLabel,
|
|
2
|
+
declare const FeatureServiceUi: ({ serviceItem, showTopLabel, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, isFeatureDropDownExpand, onToggleExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onBookButtonPress, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, }: {
|
|
3
3
|
serviceItem: any;
|
|
4
4
|
showTopLabel: any;
|
|
5
|
-
isSoldOut: any;
|
|
6
5
|
getAnimationIcon: any;
|
|
7
6
|
cityOrigin: any;
|
|
8
7
|
cityDestination: any;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import LottiePlayer from "../../assets/LottiePlayer";
|
|
3
3
|
import commonService from "../../utils/CommonService";
|
|
4
|
+
if (typeof document !== "undefined") {
|
|
5
|
+
if (!document.getElementById("feature-spin-style")) {
|
|
6
|
+
const style = document.createElement("style");
|
|
7
|
+
style.id = "feature-spin-style";
|
|
8
|
+
style.textContent =
|
|
9
|
+
"@keyframes feature-spin { to { transform: rotate(360deg); } }";
|
|
10
|
+
document.head.appendChild(style);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
4
13
|
const HARDCODED_OPERATORS = [
|
|
5
14
|
{
|
|
6
15
|
logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Turbus_logo.svg/320px-Turbus_logo.svg.png",
|
|
@@ -21,8 +30,8 @@ const HARDCODED_OPERATORS = [
|
|
|
21
30
|
seatsAvailable: "3 disponibles",
|
|
22
31
|
},
|
|
23
32
|
];
|
|
24
|
-
const FeatureServiceUi = ({ serviceItem, showTopLabel,
|
|
25
|
-
var _a, _b, _c, _d, _e, _f;
|
|
33
|
+
const FeatureServiceUi = ({ serviceItem, showTopLabel, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, isFeatureDropDownExpand, onToggleExpand, ticketQuantity = 1, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onBookButtonPress, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData = undefined, }) => {
|
|
34
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
26
35
|
// Use wow_deal services if available, otherwise fall back to serviceItem operators or hardcoded
|
|
27
36
|
const operators = ((_a = wowDealData === null || wowDealData === void 0 ? void 0 : wowDealData.services) === null || _a === void 0 ? void 0 : _a.length) > 0
|
|
28
37
|
? wowDealData.services.slice(0, 3).map((service) => ({
|
|
@@ -97,7 +106,8 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
97
106
|
isFeatureDropDownExpand === true;
|
|
98
107
|
const isThisTimeDropdownOpen = isTimeDropdownOpen === serviceItem.id;
|
|
99
108
|
const canDecreaseTicketQuantity = ticketQuantity > 1;
|
|
100
|
-
const
|
|
109
|
+
const availableSeats = (_c = selectedSlotService === null || selectedSlotService === void 0 ? void 0 : selectedSlotService.available_seats) !== null && _c !== void 0 ? _c : maxSeatsPerBooking;
|
|
110
|
+
const canIncreaseTicketQuantity = ticketQuantity < availableSeats;
|
|
101
111
|
const HOW_IT_WORKS_STEPS = [
|
|
102
112
|
{
|
|
103
113
|
icon: "flexible",
|
|
@@ -185,10 +195,10 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
185
195
|
React.createElement("div", { className: "flex flex-col justify-between gap-[20px] mb-[16px] pr-[22px]" },
|
|
186
196
|
React.createElement("div", { className: "flex flex-col gap-[8px]" },
|
|
187
197
|
React.createElement("div", { className: "flex items-center gap-[8px]" },
|
|
188
|
-
React.createElement("img", { src: (
|
|
198
|
+
React.createElement("img", { src: (_d = serviceItem.icons) === null || _d === void 0 ? void 0 : _d.whiteOrigin, alt: "origin", className: `w-[14px] h-[14px] shrink-0` }),
|
|
189
199
|
React.createElement("span", { className: "text-[13px] bold-text" }, cityOrigin === null || cityOrigin === void 0 ? void 0 : cityOrigin.label.split(",")[0])),
|
|
190
200
|
React.createElement("div", { className: "flex items-center gap-[8px]" },
|
|
191
|
-
React.createElement("img", { src: (
|
|
201
|
+
React.createElement("img", { src: (_e = serviceItem.icons) === null || _e === void 0 ? void 0 : _e.whiteDestination, alt: "destination", className: `w-[14px] h-[14px] shrink-0` }),
|
|
192
202
|
React.createElement("span", { className: "text-[13px] bold-text" }, cityDestination === null || cityDestination === void 0 ? void 0 : cityDestination.label.split(",")[0]))),
|
|
193
203
|
React.createElement("div", { className: "flex flex-col gap-[10px]" },
|
|
194
204
|
React.createElement("div", { className: "text-[12px] bold-text" }, travelDate
|
|
@@ -205,7 +215,7 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
205
215
|
}, style: { outline: "none" } },
|
|
206
216
|
React.createElement("button", { type: "button", onClick: () => onTimeDropdownToggle === null || onTimeDropdownToggle === void 0 ? void 0 : onTimeDropdownToggle(isThisTimeDropdownOpen ? null : serviceItem.id), className: "flex whitespace-nowrap cursor-pointer select-none items-center gap-[6px] border-none bg-transparent p-0 bold-text text-[12px] text-[white]" },
|
|
207
217
|
React.createElement("span", null, departureRange),
|
|
208
|
-
React.createElement("img", { src: (
|
|
218
|
+
React.createElement("img", { src: (_f = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _f === void 0 ? void 0 : _f.downArrow, alt: "down arrow", className: `kupos-time-chevron transition-transform duration-200 ${isThisTimeDropdownOpen ? "rotate-180" : "rotate-0"}`, style: {
|
|
209
219
|
width: "12px",
|
|
210
220
|
height: "8px",
|
|
211
221
|
filter: "brightness(0) invert(1)",
|
|
@@ -282,7 +292,7 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
282
292
|
e.currentTarget.src =
|
|
283
293
|
((_a = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_details) === null || _a === void 0 ? void 0 : _a[0]) ||
|
|
284
294
|
"/images/service-list/bus-icon.svg";
|
|
285
|
-
}, className: `h-[24px] max-w-full object-contain
|
|
295
|
+
}, className: `h-[24px] max-w-full object-contain` }),
|
|
286
296
|
React.createElement("span", { className: "text-[11px] truncate w-full text-center text-[white] overflow-hidden" }, op.name),
|
|
287
297
|
React.createElement("div", { className: "bg-[#FF8F45] text-white text-[12px] font-bold px-[10px] py-[4px] rounded-[4px] bold-text whitespace-nowrap" },
|
|
288
298
|
React.createElement("span", null, op === null || op === void 0 ? void 0 : op.time)),
|
|
@@ -309,7 +319,7 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
309
319
|
React.createElement("span", { style: { color: "#FF5C60" } }, "viendo"),
|
|
310
320
|
" |",
|
|
311
321
|
" ",
|
|
312
|
-
React.createElement("span", { className: "bold-text", ref: (node) => commonService.
|
|
322
|
+
React.createElement("span", { className: "bold-text", ref: (node) => commonService.startComprandoDealCount(node, 4, 16), style: { fontVariantNumeric: "tabular-nums" } }),
|
|
313
323
|
" ",
|
|
314
324
|
"han comprado"))),
|
|
315
325
|
React.createElement("div", { className: "flex flex-col justify-center gap-[12px] py-[2px] pl-[22px] pr-[10px] relative mb-[16px]" },
|
|
@@ -351,20 +361,46 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
351
361
|
: "cursor-not-allowed bg-[#222b3d] opacity-50"}` }, "+")),
|
|
352
362
|
!canIncreaseTicketQuantity && (React.createElement("span", { className: "text-[10px] text-[#FF5C60]" },
|
|
353
363
|
"m\u00E1x. ",
|
|
354
|
-
|
|
364
|
+
availableSeats,
|
|
355
365
|
" pasajes"))),
|
|
356
|
-
React.createElement("button", { type: "button",
|
|
366
|
+
React.createElement("button", { type: "button", ref: (btn) => {
|
|
367
|
+
if (!btn)
|
|
368
|
+
return;
|
|
369
|
+
btn.onclick = () => {
|
|
370
|
+
if (btn.disabled)
|
|
371
|
+
return;
|
|
372
|
+
btn.disabled = true;
|
|
373
|
+
btn.style.cursor = "not-allowed";
|
|
374
|
+
btn.style.opacity = "0.85";
|
|
375
|
+
const normal = btn.querySelector('[data-btn-state="normal"]');
|
|
376
|
+
const loading = btn.querySelector('[data-btn-state="loading"]');
|
|
377
|
+
if (normal)
|
|
378
|
+
normal.style.display = "none";
|
|
379
|
+
if (loading)
|
|
380
|
+
loading.style.display = "flex";
|
|
381
|
+
onBookButtonPress === null || onBookButtonPress === void 0 ? void 0 : onBookButtonPress(ticketQuantity, serviceItem);
|
|
382
|
+
};
|
|
383
|
+
}, className: "flex items-center gap-[6px] px-[20px] py-[10px] rounded-[16px] text-white bold-text text-[13px] mt-[4px] justify-center border-none cursor-pointer text-center", style: {
|
|
357
384
|
backgroundColor: "#FF5C60",
|
|
358
385
|
whiteSpace: "nowrap",
|
|
386
|
+
minWidth: "120px",
|
|
359
387
|
} },
|
|
360
|
-
React.createElement(
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
388
|
+
React.createElement("span", { "data-btn-state": "normal", style: { display: "flex", alignItems: "center", gap: "6px" } },
|
|
389
|
+
React.createElement(LottiePlayer, { animationData: getAnimationIcon("thunderAnimation"), width: "16px", height: "16px" }),
|
|
390
|
+
React.createElement("span", { className: "whitespace-nowrap" }, "\u00A1Lo quiero!")),
|
|
391
|
+
React.createElement("span", { "data-btn-state": "loading", style: { display: "none", alignItems: "center", gap: "6px" } },
|
|
392
|
+
React.createElement("span", { style: {
|
|
393
|
+
display: "inline-block",
|
|
394
|
+
width: "16px",
|
|
395
|
+
height: "16px",
|
|
396
|
+
border: "2px solid rgba(255,255,255,0.4)",
|
|
397
|
+
borderTopColor: "#fff",
|
|
398
|
+
borderRadius: "50%",
|
|
399
|
+
animation: "feature-spin 0.7s linear infinite",
|
|
400
|
+
flexShrink: 0,
|
|
401
|
+
} })))),
|
|
366
402
|
React.createElement("div", { className: `absolute bottom-[11px] right-[18px] cursor-pointer transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`, onClick: onToggleExpand },
|
|
367
|
-
React.createElement("img", { src: (
|
|
403
|
+
React.createElement("img", { src: (_g = serviceItem.icons) === null || _g === void 0 ? void 0 : _g.downArrow, alt: "down arrow", style: {
|
|
368
404
|
width: "14px",
|
|
369
405
|
height: "8px",
|
|
370
406
|
filter: "brightness(0) invert(1)",
|
|
@@ -23,6 +23,9 @@ function getSortedSeatTypes(seatTypes, isTrain) {
|
|
|
23
23
|
if (premiumIndex >= 3) {
|
|
24
24
|
seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
|
|
25
25
|
}
|
|
26
|
+
if (isTrain) {
|
|
27
|
+
return seatTypesWithPrices;
|
|
28
|
+
}
|
|
26
29
|
if (!isTrain) {
|
|
27
30
|
seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
|
|
28
31
|
}
|
|
@@ -29,6 +29,7 @@ declare const commonService: {
|
|
|
29
29
|
startCountdown: (node: HTMLSpanElement | null, countdownSeconds?: number) => void;
|
|
30
30
|
startDealCountdown: (node: HTMLSpanElement | null, countdownSeconds: number) => void;
|
|
31
31
|
startComprandoCount: (node: HTMLSpanElement | null, min?: number, max?: number) => void;
|
|
32
|
+
startComprandoDealCount: (node: HTMLSpanElement | null, min?: number, max?: number) => void;
|
|
32
33
|
timeToMinutes: (time: string) => number;
|
|
33
34
|
minutesToTime: (minutes: number) => string;
|
|
34
35
|
generateTimeSlots: (from: string, to: string, windowHours: number) => Array<{
|
|
@@ -411,6 +411,41 @@ const commonService = {
|
|
|
411
411
|
node.dataset.comprandoId = String(id);
|
|
412
412
|
node.dataset.comprandoConfig = configKey;
|
|
413
413
|
},
|
|
414
|
+
startComprandoDealCount: (node, min = 4, max = 16) => {
|
|
415
|
+
if (!node)
|
|
416
|
+
return;
|
|
417
|
+
const configKey = `${min}-${max}`;
|
|
418
|
+
if (node.dataset.comprandoDealId &&
|
|
419
|
+
node.dataset.comprandoDealConfig === configKey) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
const prevId = node.dataset.comprandoDealId;
|
|
423
|
+
if (prevId)
|
|
424
|
+
clearInterval(Number(prevId));
|
|
425
|
+
const initialValue = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
426
|
+
node.textContent = String(initialValue);
|
|
427
|
+
const id = setInterval(() => {
|
|
428
|
+
const current = Number(node.textContent) || initialValue;
|
|
429
|
+
const changePercent = 0.05; // 5% change
|
|
430
|
+
const baseChange = Math.ceil(current * changePercent);
|
|
431
|
+
const rand = Math.random();
|
|
432
|
+
let change = baseChange;
|
|
433
|
+
if (baseChange <= 1) {
|
|
434
|
+
change = rand < 0.7 ? 1 : rand < 0.9 ? 2 : 3;
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
const variation = rand < 0.4 ? 0 : rand < 0.7 ? 1 : rand < 0.9 ? 2 : 3;
|
|
438
|
+
change = baseChange + variation;
|
|
439
|
+
}
|
|
440
|
+
// Only increase, never decrease
|
|
441
|
+
let next = current + change;
|
|
442
|
+
// Clamp within max
|
|
443
|
+
next = Math.min(max, next);
|
|
444
|
+
node.textContent = String(next);
|
|
445
|
+
}, 5000); // Update every 5 seconds
|
|
446
|
+
node.dataset.comprandoDealId = String(id);
|
|
447
|
+
node.dataset.comprandoDealConfig = configKey;
|
|
448
|
+
},
|
|
414
449
|
timeToMinutes: (time) => {
|
|
415
450
|
const [h, m] = time.split(":").map(Number);
|
|
416
451
|
return h * 60 + (m || 0);
|
package/package.json
CHANGED
|
@@ -334,6 +334,7 @@ const PaymentSideBarDesktop: React.FC<PaymentSideBarProps> = ({
|
|
|
334
334
|
isLinatal,
|
|
335
335
|
insuranceData,
|
|
336
336
|
isPeru,
|
|
337
|
+
serviceFeeDataStateValue,
|
|
337
338
|
}) => {
|
|
338
339
|
// REMOVED AM/PM DUPLICATION AND ADDED 24 HOUR TIME FORMAT IN BOARDING STAGE
|
|
339
340
|
const depTime = droppingTimeOnward || "";
|
|
@@ -757,6 +758,39 @@ const PaymentSideBarDesktop: React.FC<PaymentSideBarProps> = ({
|
|
|
757
758
|
</span>
|
|
758
759
|
</div>
|
|
759
760
|
) : null}
|
|
761
|
+
{serviceFeeDataStateValue?.total_convenience_fee_amount && (
|
|
762
|
+
<PaymentItem
|
|
763
|
+
label={
|
|
764
|
+
<div style={{ display: "flex", alignItems: "center" }}>
|
|
765
|
+
<div className="font10">{translation?.serviceFeeLabel}</div>
|
|
766
|
+
<div className="img-hover">
|
|
767
|
+
<img
|
|
768
|
+
src={icons?.whatsappInfoIcon}
|
|
769
|
+
alt=""
|
|
770
|
+
style={{
|
|
771
|
+
marginLeft: "5px",
|
|
772
|
+
marginBottom: "3px",
|
|
773
|
+
width: "15px",
|
|
774
|
+
}}
|
|
775
|
+
/>
|
|
776
|
+
<div
|
|
777
|
+
className="duration-mouseover font9"
|
|
778
|
+
style={{ lineHeight: "1.3" }}
|
|
779
|
+
>
|
|
780
|
+
<span>{translation?.serviceFeeHoverLabel}</span>
|
|
781
|
+
</div>
|
|
782
|
+
</div>
|
|
783
|
+
</div>
|
|
784
|
+
}
|
|
785
|
+
amount={CommonService.currency(
|
|
786
|
+
serviceFeeDataStateValue?.total_convenience_fee_amount,
|
|
787
|
+
currencySign,
|
|
788
|
+
)}
|
|
789
|
+
className="font10"
|
|
790
|
+
currency={currency}
|
|
791
|
+
customStyle={{ color: colors?.whatsappDeliveryChargesColor }}
|
|
792
|
+
/>
|
|
793
|
+
)}
|
|
760
794
|
|
|
761
795
|
{isAgency && (
|
|
762
796
|
<PaymentItem
|
|
@@ -240,6 +240,8 @@ const PaymentSideBarMobile: React.FC<PaymentSideBarProps> = ({
|
|
|
240
240
|
isLinatal,
|
|
241
241
|
insuranceData,
|
|
242
242
|
isPeru,
|
|
243
|
+
setShowServicefeeModal,
|
|
244
|
+
serviceFeeDataStateValue,
|
|
243
245
|
}) => {
|
|
244
246
|
return (
|
|
245
247
|
<div className="pb-[10px]">
|
|
@@ -526,6 +528,44 @@ const PaymentSideBarMobile: React.FC<PaymentSideBarProps> = ({
|
|
|
526
528
|
</div>
|
|
527
529
|
) : null}
|
|
528
530
|
|
|
531
|
+
{serviceFeeDataStateValue?.total_convenience_fee_amount && (
|
|
532
|
+
<PaymentItem
|
|
533
|
+
label={
|
|
534
|
+
<div style={{ display: "flex", alignItems: "center" }}>
|
|
535
|
+
<div className=" font14 flex items-center gap-[5px]">
|
|
536
|
+
{translation?.serviceFeeLabel}
|
|
537
|
+
</div>
|
|
538
|
+
<div
|
|
539
|
+
className="img-hover"
|
|
540
|
+
onClick={() => setShowServicefeeModal(true)}
|
|
541
|
+
>
|
|
542
|
+
<img
|
|
543
|
+
src={icons?.whatsappInfoIcon}
|
|
544
|
+
alt=""
|
|
545
|
+
style={{
|
|
546
|
+
marginLeft: "5px",
|
|
547
|
+
width: "15px",
|
|
548
|
+
}}
|
|
549
|
+
/>
|
|
550
|
+
{/* <div
|
|
551
|
+
className="duration-mouseover font9"
|
|
552
|
+
style={{ lineHeight: "1.3" }}
|
|
553
|
+
>
|
|
554
|
+
<span>{translation?.serviceFeeHoverLabel}</span>
|
|
555
|
+
</div> */}
|
|
556
|
+
</div>
|
|
557
|
+
</div>
|
|
558
|
+
}
|
|
559
|
+
amount={CommonService.currency(
|
|
560
|
+
serviceFeeDataStateValue?.total_convenience_fee_amount,
|
|
561
|
+
currencySign,
|
|
562
|
+
)}
|
|
563
|
+
className="font14"
|
|
564
|
+
currency={currency}
|
|
565
|
+
customStyle={{ color: colors?.whatsappDeliveryChargesColor }}
|
|
566
|
+
/>
|
|
567
|
+
)}
|
|
568
|
+
|
|
529
569
|
{conexionChecked && conexionFare && returnConexionFare ? (
|
|
530
570
|
<PaymentItem
|
|
531
571
|
label="Conexión Aeropuerto:"
|
|
@@ -604,7 +644,7 @@ const PaymentSideBarMobile: React.FC<PaymentSideBarProps> = ({
|
|
|
604
644
|
</div>
|
|
605
645
|
</div>
|
|
606
646
|
<div
|
|
607
|
-
className={` text-[#fff] p-[10px_15px] text-left w-full flex items-center absolute -bottom-[
|
|
647
|
+
className={` text-[#fff] p-[10px_15px] text-left w-full flex items-center absolute -bottom-[7%] pt-[50px] z-1 rounded-b-[14px] text-[14px]`}
|
|
608
648
|
style={{ backgroundColor: colors?.bottomStripColor }}
|
|
609
649
|
>
|
|
610
650
|
<div className="flex justify-between items-center w-full text-[#fff]">
|
|
@@ -90,6 +90,7 @@ export interface PaymentSideBarProps {
|
|
|
90
90
|
currency?: string;
|
|
91
91
|
t?: (key: string) => string;
|
|
92
92
|
setShowWhatsappChargesInfo?: (value: boolean) => void;
|
|
93
|
+
setShowServicefeeModal?: (value: boolean) => void;
|
|
93
94
|
showWhatsappChargesInfo?: boolean;
|
|
94
95
|
onButtonOneClick?: any;
|
|
95
96
|
onHide?: any;
|
|
@@ -102,5 +103,5 @@ export interface PaymentSideBarProps {
|
|
|
102
103
|
isTacna?: boolean;
|
|
103
104
|
insuranceData?: any;
|
|
104
105
|
isPeru?: boolean;
|
|
106
|
+
serviceFeeDataStateValue?: any;
|
|
105
107
|
}
|
|
106
|
-
|
|
@@ -2,6 +2,16 @@ import React from "react";
|
|
|
2
2
|
import LottiePlayer from "../../assets/LottiePlayer";
|
|
3
3
|
import commonService from "../../utils/CommonService";
|
|
4
4
|
|
|
5
|
+
if (typeof document !== "undefined") {
|
|
6
|
+
if (!document.getElementById("feature-spin-style")) {
|
|
7
|
+
const style = document.createElement("style");
|
|
8
|
+
style.id = "feature-spin-style";
|
|
9
|
+
style.textContent =
|
|
10
|
+
"@keyframes feature-spin { to { transform: rotate(360deg); } }";
|
|
11
|
+
document.head.appendChild(style);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
const HARDCODED_OPERATORS = [
|
|
6
16
|
{
|
|
7
17
|
logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Turbus_logo.svg/320px-Turbus_logo.svg.png",
|
|
@@ -26,7 +36,6 @@ const HARDCODED_OPERATORS = [
|
|
|
26
36
|
const FeatureServiceUi = ({
|
|
27
37
|
serviceItem,
|
|
28
38
|
showTopLabel,
|
|
29
|
-
isSoldOut,
|
|
30
39
|
getAnimationIcon,
|
|
31
40
|
cityOrigin,
|
|
32
41
|
cityDestination,
|
|
@@ -139,7 +148,9 @@ const FeatureServiceUi = ({
|
|
|
139
148
|
isFeatureDropDownExpand === true;
|
|
140
149
|
const isThisTimeDropdownOpen = isTimeDropdownOpen === serviceItem.id;
|
|
141
150
|
const canDecreaseTicketQuantity = ticketQuantity > 1;
|
|
142
|
-
const
|
|
151
|
+
const availableSeats =
|
|
152
|
+
selectedSlotService?.available_seats ?? maxSeatsPerBooking;
|
|
153
|
+
const canIncreaseTicketQuantity = ticketQuantity < availableSeats;
|
|
143
154
|
|
|
144
155
|
const HOW_IT_WORKS_STEPS = [
|
|
145
156
|
{
|
|
@@ -256,9 +267,7 @@ const FeatureServiceUi = ({
|
|
|
256
267
|
<img
|
|
257
268
|
src={serviceItem.icons?.whiteOrigin}
|
|
258
269
|
alt="origin"
|
|
259
|
-
className={`w-[14px] h-[14px] shrink-0
|
|
260
|
-
isSoldOut ? "grayscale" : ""
|
|
261
|
-
}`}
|
|
270
|
+
className={`w-[14px] h-[14px] shrink-0`}
|
|
262
271
|
/>
|
|
263
272
|
<span className="text-[13px] bold-text">
|
|
264
273
|
{cityOrigin?.label.split(",")[0]}
|
|
@@ -268,10 +277,7 @@ const FeatureServiceUi = ({
|
|
|
268
277
|
<img
|
|
269
278
|
src={serviceItem.icons?.whiteDestination}
|
|
270
279
|
alt="destination"
|
|
271
|
-
className={`w-[14px] h-[14px] shrink-0
|
|
272
|
-
isSoldOut ? "grayscale" : ""
|
|
273
|
-
}`}
|
|
274
|
-
style={{ opacity: isSoldOut ? 0.5 : 1 }}
|
|
280
|
+
className={`w-[14px] h-[14px] shrink-0`}
|
|
275
281
|
/>
|
|
276
282
|
<span className="text-[13px] bold-text">
|
|
277
283
|
{cityDestination?.label.split(",")[0]}
|
|
@@ -470,12 +476,7 @@ const FeatureServiceUi = ({
|
|
|
470
476
|
serviceItem?.operator_details?.[0] ||
|
|
471
477
|
"/images/service-list/bus-icon.svg";
|
|
472
478
|
}}
|
|
473
|
-
className={`h-[24px] max-w-full object-contain
|
|
474
|
-
isSoldOut ? "grayscale" : ""
|
|
475
|
-
}`}
|
|
476
|
-
// className={`h-[24px] max-w-full object-contain brightness-0 invert ${
|
|
477
|
-
// isSoldOut ? "grayscale" : ""
|
|
478
|
-
// }`}
|
|
479
|
+
className={`h-[24px] max-w-full object-contain`}
|
|
479
480
|
/>
|
|
480
481
|
<span className="text-[11px] truncate w-full text-center text-[white] overflow-hidden">
|
|
481
482
|
{op.name}
|
|
@@ -523,7 +524,7 @@ const FeatureServiceUi = ({
|
|
|
523
524
|
<span
|
|
524
525
|
className="bold-text"
|
|
525
526
|
ref={(node) =>
|
|
526
|
-
commonService.
|
|
527
|
+
commonService.startComprandoDealCount(node, 4, 16)
|
|
527
528
|
}
|
|
528
529
|
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
529
530
|
/>{" "}
|
|
@@ -621,27 +622,66 @@ const FeatureServiceUi = ({
|
|
|
621
622
|
</div>
|
|
622
623
|
{!canIncreaseTicketQuantity && (
|
|
623
624
|
<span className="text-[10px] text-[#FF5C60]">
|
|
624
|
-
máx. {
|
|
625
|
+
máx. {availableSeats} pasajes
|
|
625
626
|
</span>
|
|
626
627
|
)}
|
|
627
628
|
</div>
|
|
628
629
|
|
|
629
630
|
<button
|
|
630
631
|
type="button"
|
|
631
|
-
|
|
632
|
-
|
|
632
|
+
ref={(btn) => {
|
|
633
|
+
if (!btn) return;
|
|
634
|
+
btn.onclick = () => {
|
|
635
|
+
if (btn.disabled) return;
|
|
636
|
+
btn.disabled = true;
|
|
637
|
+
btn.style.cursor = "not-allowed";
|
|
638
|
+
btn.style.opacity = "0.85";
|
|
639
|
+
const normal = btn.querySelector(
|
|
640
|
+
'[data-btn-state="normal"]',
|
|
641
|
+
) as HTMLElement | null;
|
|
642
|
+
const loading = btn.querySelector(
|
|
643
|
+
'[data-btn-state="loading"]',
|
|
644
|
+
) as HTMLElement | null;
|
|
645
|
+
if (normal) normal.style.display = "none";
|
|
646
|
+
if (loading) loading.style.display = "flex";
|
|
647
|
+
onBookButtonPress?.(ticketQuantity, serviceItem);
|
|
648
|
+
};
|
|
649
|
+
}}
|
|
650
|
+
className="flex items-center gap-[6px] px-[20px] py-[10px] rounded-[16px] text-white bold-text text-[13px] mt-[4px] justify-center border-none cursor-pointer text-center"
|
|
633
651
|
style={{
|
|
634
652
|
backgroundColor: "#FF5C60",
|
|
635
653
|
whiteSpace: "nowrap",
|
|
654
|
+
minWidth: "120px",
|
|
636
655
|
}}
|
|
637
656
|
>
|
|
638
|
-
<
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
657
|
+
<span
|
|
658
|
+
data-btn-state="normal"
|
|
659
|
+
style={{ display: "flex", alignItems: "center", gap: "6px" }}
|
|
660
|
+
>
|
|
661
|
+
<LottiePlayer
|
|
662
|
+
animationData={getAnimationIcon("thunderAnimation")}
|
|
663
|
+
width="16px"
|
|
664
|
+
height="16px"
|
|
665
|
+
/>
|
|
666
|
+
<span className="whitespace-nowrap">¡Lo quiero!</span>
|
|
667
|
+
</span>
|
|
668
|
+
<span
|
|
669
|
+
data-btn-state="loading"
|
|
670
|
+
style={{ display: "none", alignItems: "center", gap: "6px" }}
|
|
671
|
+
>
|
|
672
|
+
<span
|
|
673
|
+
style={{
|
|
674
|
+
display: "inline-block",
|
|
675
|
+
width: "16px",
|
|
676
|
+
height: "16px",
|
|
677
|
+
border: "2px solid rgba(255,255,255,0.4)",
|
|
678
|
+
borderTopColor: "#fff",
|
|
679
|
+
borderRadius: "50%",
|
|
680
|
+
animation: "feature-spin 0.7s linear infinite",
|
|
681
|
+
flexShrink: 0,
|
|
682
|
+
}}
|
|
683
|
+
/>
|
|
684
|
+
</span>
|
|
645
685
|
</button>
|
|
646
686
|
</div>
|
|
647
687
|
|
|
@@ -58,6 +58,7 @@ function getSortedSeatTypes(seatTypes: SeatType[], isTrain: any) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
let seatTypesWithPrices = getAllSeatTypes(seatTypes);
|
|
61
|
+
|
|
61
62
|
const premiumIndex = seatTypesWithPrices.findIndex(
|
|
62
63
|
(item) => item.label === "Premium",
|
|
63
64
|
);
|
|
@@ -66,6 +67,10 @@ function getSortedSeatTypes(seatTypes: SeatType[], isTrain: any) {
|
|
|
66
67
|
seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
if (isTrain) {
|
|
71
|
+
return seatTypesWithPrices;
|
|
72
|
+
}
|
|
73
|
+
|
|
69
74
|
if (!isTrain) {
|
|
70
75
|
seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
|
|
71
76
|
}
|
|
@@ -482,6 +482,54 @@ const commonService = {
|
|
|
482
482
|
node.dataset.comprandoConfig = configKey;
|
|
483
483
|
},
|
|
484
484
|
|
|
485
|
+
startComprandoDealCount: (
|
|
486
|
+
node: HTMLSpanElement | null,
|
|
487
|
+
min: number = 4,
|
|
488
|
+
max: number = 16,
|
|
489
|
+
) => {
|
|
490
|
+
if (!node) return;
|
|
491
|
+
|
|
492
|
+
const configKey = `${min}-${max}`;
|
|
493
|
+
if (
|
|
494
|
+
node.dataset.comprandoDealId &&
|
|
495
|
+
node.dataset.comprandoDealConfig === configKey
|
|
496
|
+
) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const prevId = node.dataset.comprandoDealId;
|
|
501
|
+
if (prevId) clearInterval(Number(prevId));
|
|
502
|
+
|
|
503
|
+
const initialValue = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
504
|
+
node.textContent = String(initialValue);
|
|
505
|
+
|
|
506
|
+
const id = setInterval(() => {
|
|
507
|
+
const current = Number(node.textContent) || initialValue;
|
|
508
|
+
const changePercent = 0.05; // 5% change
|
|
509
|
+
const baseChange = Math.ceil(current * changePercent);
|
|
510
|
+
|
|
511
|
+
const rand = Math.random();
|
|
512
|
+
let change = baseChange;
|
|
513
|
+
if (baseChange <= 1) {
|
|
514
|
+
change = rand < 0.7 ? 1 : rand < 0.9 ? 2 : 3;
|
|
515
|
+
} else {
|
|
516
|
+
const variation = rand < 0.4 ? 0 : rand < 0.7 ? 1 : rand < 0.9 ? 2 : 3;
|
|
517
|
+
change = baseChange + variation;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Only increase, never decrease
|
|
521
|
+
let next = current + change;
|
|
522
|
+
|
|
523
|
+
// Clamp within max
|
|
524
|
+
next = Math.min(max, next);
|
|
525
|
+
|
|
526
|
+
node.textContent = String(next);
|
|
527
|
+
}, 5000); // Update every 5 seconds
|
|
528
|
+
|
|
529
|
+
node.dataset.comprandoDealId = String(id);
|
|
530
|
+
node.dataset.comprandoDealConfig = configKey;
|
|
531
|
+
},
|
|
532
|
+
|
|
485
533
|
timeToMinutes: (time: string): number => {
|
|
486
534
|
const [h, m] = time.split(":").map(Number);
|
|
487
535
|
return h * 60 + (m || 0);
|