kupos-ui-components-lib 9.11.9 → 10.0.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/components/ServiceItem/PeruServiceItemDesktop.js +3 -3
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +20 -8
- package/dist/components/ServiceItem/mobileTypes.d.ts +2 -0
- package/dist/styles.css +3 -0
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +43 -8
- package/dist/ui/SeatSection/SeatSection.js +2 -1
- package/dist/ui/ServiceBadges/ServiceBadges.d.ts +3 -0
- package/dist/ui/ServiceBadges/ServiceBadges.js +9 -2
- package/dist/ui/mobileweb/ServiceBadgesMobile.d.ts +2 -0
- package/dist/ui/mobileweb/ServiceBadgesMobile.js +31 -2
- package/dist/utils/CommonService.d.ts +1 -0
- package/dist/utils/CommonService.js +35 -0
- package/package.json +1 -1
- package/src/components/ServiceItem/PeruServiceItemDesktop.tsx +5 -2
- package/src/components/ServiceItem/ServiceItemMobile.tsx +22 -1
- package/src/components/ServiceItem/mobileTypes.ts +2 -0
- package/src/ui/FeatureServiceUI/FeatureServiceUi.tsx +59 -10
- package/src/ui/SeatSection/SeatSection.tsx +2 -1
- package/src/ui/ServiceBadges/ServiceBadges.tsx +30 -0
- package/src/ui/mobileweb/ServiceBadgesMobile.tsx +49 -0
- package/src/utils/CommonService.ts +48 -0
|
@@ -461,12 +461,12 @@ function PeruServiceItemDesktop({ serviceItem, onBookButtonPress, colors, metaDa
|
|
|
461
461
|
React.createElement(SeatSection, { seatTypes: serviceItem.seat_types, serviceItem: serviceItem, availableSeats: serviceItem.available_seats, isSoldOut: isSoldOut, priceColor: colors.priceColor, currencySign: currencySign, removeDuplicateSeats: removeDuplicateSeats, isPeru: isPeru, renderIcon: renderIcon, discountSeatPriceColor: colors.discountSeatPriceColor })),
|
|
462
462
|
React.createElement("div", { className: "relative" },
|
|
463
463
|
React.createElement(KuposButton, { isSoldOut: isSoldOut, isLoading: serviceDetailsLoading, buttonColor: colors.kuposButtonColor, buyLabel: translation === null || translation === void 0 ? void 0 : translation.buyButton, soldOutLabel: translation === null || translation === void 0 ? void 0 : translation.soldOutButton, soldOutIcon: renderIcon("soldOutIcon", "14px"), onClick: checkMidnight }),
|
|
464
|
-
showLastSeats ? (React.createElement("div", { className: "flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[
|
|
465
|
-
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[
|
|
464
|
+
showLastSeats ? (React.createElement("div", { className: "flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[36px]" }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
|
|
465
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[11px] mt-1 text-center whitespace-nowrap", style: {
|
|
466
466
|
color: colors.seatPriceColor,
|
|
467
467
|
} }, "\u00A1\u00DAltimos Asientos!")))) : null)),
|
|
468
468
|
React.createElement(BottomAmenities, { otherItems: otherItems, serviceItem: serviceItem, grayscaleClass: grayscaleClass, isSoldOut: isSoldOut, isItemExpanded: isItemExpanded, colors: colors, translation: translation, getAnimationIcon: getAnimationIcon, downArrowIcon: renderIcon("downArrow", "10px"), onToggleExpand: () => setIsExpand && setIsExpand(isItemExpanded ? null : serviceItem.id), isPeru: isPeru }))),
|
|
469
469
|
children,
|
|
470
|
-
React.createElement(ServiceBadges, { showTopLabel: showTopLabel, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, translation: translation, serviceItem: serviceItem })));
|
|
470
|
+
React.createElement(ServiceBadges, { showTopLabel: showTopLabel, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, translation: translation, serviceItem: serviceItem, isAllinBus: isAllinBus, boardingName: boardingName, getAnimationIcon: getAnimationIcon })));
|
|
471
471
|
}
|
|
472
472
|
export default PeruServiceItemDesktop;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { MobileServiceItemProps } from "./mobileTypes";
|
|
3
|
-
declare function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, }: MobileServiceItemProps): React.ReactElement;
|
|
3
|
+
declare function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, isAllinBus, }: MobileServiceItemProps): React.ReactElement;
|
|
4
4
|
export default ServiceItemMobile;
|
|
@@ -18,8 +18,8 @@ const exceptions = [
|
|
|
18
18
|
"blanco",
|
|
19
19
|
"asiento_mascota",
|
|
20
20
|
];
|
|
21
|
-
function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, }) {
|
|
22
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
21
|
+
function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, isAllinBus, }) {
|
|
22
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
23
23
|
const isItemExpanded = serviceItem.id === isExpanded;
|
|
24
24
|
const isPetSeat = (Object.keys(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.pet_seat_info) || []).length > 0;
|
|
25
25
|
const isNewUiEnabled = ((_b = (_a = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discounts) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.new_ui_enabled) === true;
|
|
@@ -89,6 +89,17 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
89
89
|
if (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_transpordo) {
|
|
90
90
|
isConexion = true;
|
|
91
91
|
}
|
|
92
|
+
const extractStage = (stageArr, index) => {
|
|
93
|
+
const stageObj = stageArr[index];
|
|
94
|
+
const key = Object.keys(stageObj)[0];
|
|
95
|
+
return stageObj[key][0].split(", ")[0];
|
|
96
|
+
};
|
|
97
|
+
const boardingName = ((_e = serviceItem.stage_details_arr) === null || _e === void 0 ? void 0 : _e.length)
|
|
98
|
+
? extractStage(serviceItem.stage_details_arr, 0)
|
|
99
|
+
: null;
|
|
100
|
+
const dropoffName = ((_f = serviceItem.stage_details_arr) === null || _f === void 0 ? void 0 : _f.length)
|
|
101
|
+
? extractStage(serviceItem.stage_details_arr, 1)
|
|
102
|
+
: null;
|
|
92
103
|
return (React.createElement(React.Fragment, null, isNewUi ? (React.createElement(FeatureServiceUiMobile, { serviceItem: serviceItem, showTopLabel: showTopLabel, colors: colors, isSoldOut: isSoldOut, cityOrigin: cityOrigin, cityDestination: cityDestination, renderIcon: renderIcon, viewersConfig: viewersConfig, isFeatureDropDownExpand: isFeatureDropDownExpand, ticketQuantity: ticketQuantity, onIncreaseTicketQuantity: onIncreaseTicketQuantity, onDecreaseTicketQuantity: onDecreaseTicketQuantity, onBookButtonPress: onRemateUiButtonClick, onToggleExpand: () => setIsFeatureDropDownExpand &&
|
|
93
104
|
setIsFeatureDropDownExpand(isFeatureDropDownExpand === serviceItem.id ||
|
|
94
105
|
isFeatureDropDownExpand === true
|
|
@@ -96,7 +107,8 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
96
107
|
: serviceItem.id), selectedTimeSlot: selectedTimeSlot, onTimeSlotChange: onTimeSlotChange, isTimeDropdownOpen: isTimeDropdownOpen, onTimeDropdownToggle: onTimeDropdownToggle, wowDealData: wowDealData })) : (React.createElement("div", { className: `relative ${!serviceItem.offer_text || !(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) ? "mb-[14px]" : showTopLabel || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ? "mb-[20px]" : "mb-[12px]"} ${(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ||
|
|
97
108
|
isConexion ||
|
|
98
109
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" ||
|
|
99
|
-
showTopLabel
|
|
110
|
+
showTopLabel ||
|
|
111
|
+
boardingName
|
|
100
112
|
? "mt-[20px]"
|
|
101
113
|
: "mt-[10px]"} `, style: { zIndex: 1 } },
|
|
102
114
|
React.createElement("div", { className: `z-1 ${((hasOfferText && isNewUiEnabled) ||
|
|
@@ -125,17 +137,17 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
125
137
|
color: isSoldOut ? "#bbb" : "text-[#464647]",
|
|
126
138
|
} },
|
|
127
139
|
React.createElement("span", { className: "ml-[3px] min-[420]:text-[13px] text-[12px] text-ellipsis overflow-hidden whitespace-nowrap max-w-[120px]" }, serviceItem.operator_details[2]))))) : null)),
|
|
128
|
-
React.createElement(DateTimeSectionMobile, { onBookButtonPress: onBookButtonPress, isCiva: isCiva, isSoldOut: isSoldOut, isLinatal: isLinatal, isPeru: isPeru, orignLabel: orignLabel, destinationLabel: destinationLabel, originIcon: (
|
|
140
|
+
React.createElement(DateTimeSectionMobile, { onBookButtonPress: onBookButtonPress, isCiva: isCiva, isSoldOut: isSoldOut, isLinatal: isLinatal, isPeru: isPeru, orignLabel: orignLabel, destinationLabel: destinationLabel, originIcon: (_g = serviceItem.icons) === null || _g === void 0 ? void 0 : _g.origin, destinationIcon: (_h = serviceItem.icons) === null || _h === void 0 ? void 0 : _h.destination, travelDate: serviceItem.travel_date, arrivalDate: serviceItem.arrival_date, depTime: serviceItem.dep_time, arrTime: serviceItem.arr_time, seatTypes: serviceItem.seat_types, seatPriceColor: colors.seatPriceColor, tooltipBgColor: colors.tooltipBgColor, currencySign: currencySign, availableSeats: serviceItem.available_seats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, showLastSeats: showLastSeats, discountSeatPriceColor: colors.discountSeatPriceColor }),
|
|
129
141
|
hasDiscount && (React.createElement("div", { className: "flex justify-end" }, isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)),
|
|
130
142
|
showLastSeats ? (React.createElement("div", { className: "flex justify-end " }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
|
|
131
143
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[10px] text-center", style: {
|
|
132
144
|
color: colors.tooltipBgColor,
|
|
133
145
|
} }, "\u00A1\u00DAltimos Asientos!")))) : null,
|
|
134
146
|
React.createElement("div", { className: "bg-[#E6E6E6] mt-[10px] mb-[8px] h-[1px]" }),
|
|
135
|
-
React.createElement(BottomAmenitiesMobile, { isSoldOut: isSoldOut, amenitiesNodes: amenities(), hoursIcon: renderIcon("hours", "14px"), duration: (
|
|
147
|
+
React.createElement(BottomAmenitiesMobile, { isSoldOut: isSoldOut, amenitiesNodes: amenities(), hoursIcon: renderIcon("hours", "14px"), duration: (_j = serviceItem.duration) === null || _j === void 0 ? void 0 : _j.toString(), isDirectTrip: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip, directoColor: colors.directoColor, directoAnim: serviceItem.icons.directoAnim, isChangeTicket: serviceItem.is_change_ticket, isPetSeat: isPetSeat, petSeatInfo: serviceItem.pet_seat_info, petFriendlyAnim: serviceItem.icons.petFriendlyAnim, flexibleAnim: serviceItem.icons.flexibleAnim, isTrackingEnabled: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_tracking_enabled, locationAnim: serviceItem.icons.locationAnim, downArrowIcon: serviceItem.icons.downArrow, showDropdown: isItemExpanded, setShowDropdown: () => setIsExpanded(isItemExpanded ? null : serviceItem.id), onDropdownToggle: () => {
|
|
136
148
|
setIsExpanded(isItemExpanded ? null : serviceItem.id);
|
|
137
149
|
}, isPeru: isPeru, femaleAnim: serviceItem.icons.femaleAnim, ladiesBookedSeats: serviceItem.ladies_booked_seats, isDpEnabled: serviceItem.is_dp_enabled })),
|
|
138
|
-
React.createElement(ServiceBadgesMobile, { showTopLabel: showTopLabel, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, serviceItem: serviceItem, isConexion: isConexion })),
|
|
150
|
+
React.createElement(ServiceBadgesMobile, { showTopLabel: showTopLabel, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, serviceItem: serviceItem, isConexion: isConexion, isAllinBus: isAllinBus, boardingName: boardingName })),
|
|
139
151
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) &&
|
|
140
152
|
!isNewUiEnabled &&
|
|
141
153
|
!isSoldOut &&
|
|
@@ -167,9 +179,9 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
167
179
|
React.createElement("div", { className: "flex flex-col gap-[8px] text-[12px] min-[420px]:text-[12px] text-[#464647]", style: { lineHeight: 1.6 } },
|
|
168
180
|
React.createElement("div", { className: "flex justify-between items-center" },
|
|
169
181
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) &&
|
|
170
|
-
Object.keys((
|
|
182
|
+
Object.keys((_k = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) !== null && _k !== void 0 ? _k : {})
|
|
171
183
|
.length === 0 &&
|
|
172
|
-
((
|
|
184
|
+
((_l = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) !== null && _l !== void 0 ? _l : []).length === 0 ? (React.createElement("div", { className: "flex items-center gap-[6px]" },
|
|
173
185
|
React.createElement(LottiePlayer, { animationData: serviceItem.icons.starAnimation, width: "14px", height: "14px" }),
|
|
174
186
|
React.createElement("span", { className: "text-[#fff]" }, "M\u00E1s elegido"))) : (React.createElement("div", { className: `flex ${((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || "").length > 10 ? "items-start" : "items-center"}` },
|
|
175
187
|
React.createElement("div", { className: isLongOfferText ? "mt-[2px]" : "" },
|
|
@@ -158,6 +158,7 @@ export interface MobileServiceItemProps {
|
|
|
158
158
|
[key: string]: string | Record<string, string | undefined> | undefined;
|
|
159
159
|
};
|
|
160
160
|
useLottieFor?: string[];
|
|
161
|
+
stage_details_arr?: any;
|
|
161
162
|
};
|
|
162
163
|
onBookButtonPress?: () => void;
|
|
163
164
|
onRemateUiButtonClick?: () => void;
|
|
@@ -237,4 +238,5 @@ export interface MobileServiceItemProps {
|
|
|
237
238
|
wowDealData?: any;
|
|
238
239
|
isFlores?: boolean;
|
|
239
240
|
operatorLabel?: string;
|
|
241
|
+
isAllinBus?: any;
|
|
240
242
|
}
|
package/dist/styles.css
CHANGED
|
@@ -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",
|
|
@@ -309,7 +318,7 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
309
318
|
React.createElement("span", { style: { color: "#FF5C60" } }, "viendo"),
|
|
310
319
|
" |",
|
|
311
320
|
" ",
|
|
312
|
-
React.createElement("span", { className: "bold-text", ref: (node) => commonService.
|
|
321
|
+
React.createElement("span", { className: "bold-text", ref: (node) => commonService.startComprandoDealCount(node, 4, 16), style: { fontVariantNumeric: "tabular-nums" } }),
|
|
313
322
|
" ",
|
|
314
323
|
"han comprado"))),
|
|
315
324
|
React.createElement("div", { className: "flex flex-col justify-center gap-[12px] py-[2px] pl-[22px] pr-[10px] relative mb-[16px]" },
|
|
@@ -353,16 +362,42 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIc
|
|
|
353
362
|
"m\u00E1x. ",
|
|
354
363
|
maxSeatsPerBooking,
|
|
355
364
|
" pasajes"))),
|
|
356
|
-
React.createElement("button", { type: "button",
|
|
365
|
+
React.createElement("button", { type: "button", ref: (btn) => {
|
|
366
|
+
if (!btn)
|
|
367
|
+
return;
|
|
368
|
+
btn.onclick = () => {
|
|
369
|
+
if (btn.disabled)
|
|
370
|
+
return;
|
|
371
|
+
btn.disabled = true;
|
|
372
|
+
btn.style.cursor = "not-allowed";
|
|
373
|
+
btn.style.opacity = "0.85";
|
|
374
|
+
const normal = btn.querySelector('[data-btn-state="normal"]');
|
|
375
|
+
const loading = btn.querySelector('[data-btn-state="loading"]');
|
|
376
|
+
if (normal)
|
|
377
|
+
normal.style.display = "none";
|
|
378
|
+
if (loading)
|
|
379
|
+
loading.style.display = "flex";
|
|
380
|
+
onBookButtonPress === null || onBookButtonPress === void 0 ? void 0 : onBookButtonPress(ticketQuantity, serviceItem);
|
|
381
|
+
};
|
|
382
|
+
}, 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
383
|
backgroundColor: "#FF5C60",
|
|
358
384
|
whiteSpace: "nowrap",
|
|
385
|
+
minWidth: "120px",
|
|
359
386
|
} },
|
|
360
|
-
React.createElement(
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
387
|
+
React.createElement("span", { "data-btn-state": "normal", style: { display: "flex", alignItems: "center", gap: "6px" } },
|
|
388
|
+
React.createElement(LottiePlayer, { animationData: getAnimationIcon("thunderAnimation"), width: "16px", height: "16px" }),
|
|
389
|
+
React.createElement("span", { className: "whitespace-nowrap" }, "\u00A1Lo quiero!")),
|
|
390
|
+
React.createElement("span", { "data-btn-state": "loading", style: { display: "none", alignItems: "center", gap: "6px" } },
|
|
391
|
+
React.createElement("span", { style: {
|
|
392
|
+
display: "inline-block",
|
|
393
|
+
width: "16px",
|
|
394
|
+
height: "16px",
|
|
395
|
+
border: "2px solid rgba(255,255,255,0.4)",
|
|
396
|
+
borderTopColor: "#fff",
|
|
397
|
+
borderRadius: "50%",
|
|
398
|
+
animation: "feature-spin 0.7s linear infinite",
|
|
399
|
+
flexShrink: 0,
|
|
400
|
+
} })))),
|
|
366
401
|
React.createElement("div", { className: `absolute bottom-[11px] right-[18px] cursor-pointer transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`, onClick: onToggleExpand },
|
|
367
402
|
React.createElement("img", { src: (_f = serviceItem.icons) === null || _f === void 0 ? void 0 : _f.downArrow, alt: "down arrow", style: {
|
|
368
403
|
width: "14px",
|
|
@@ -187,7 +187,8 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
187
187
|
? CommonService.truncateSeatLabel(filteredSeats[0].label)
|
|
188
188
|
: filteredSeats[0].label
|
|
189
189
|
: null;
|
|
190
|
-
const operatorServiceName = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "MovilBus" ||
|
|
190
|
+
const operatorServiceName = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "MovilBus" ||
|
|
191
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "Movil Bus";
|
|
191
192
|
return (React.createElement(React.Fragment, null,
|
|
192
193
|
hasDiscount && (React.createElement("span", { className: "text-[13.33px]", style: {
|
|
193
194
|
color: "#999",
|
|
@@ -12,6 +12,9 @@ interface ServiceBadgesProps {
|
|
|
12
12
|
is_direct_trip?: boolean;
|
|
13
13
|
train_type_label?: string;
|
|
14
14
|
};
|
|
15
|
+
isAllinBus?: boolean;
|
|
16
|
+
boardingName?: string;
|
|
17
|
+
getAnimationIcon?: (iconKey: string) => any;
|
|
15
18
|
}
|
|
16
19
|
declare const ServiceBadges: React.FC<ServiceBadgesProps>;
|
|
17
20
|
export default ServiceBadges;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
|
|
2
|
+
import LottiePlayer from "../../assets/LottiePlayer";
|
|
3
|
+
const ServiceBadges = ({ showTopLabel, isSoldOut, colors, renderIcon, translation, serviceItem, isAllinBus = false, boardingName, getAnimationIcon, }) => {
|
|
3
4
|
return (React.createElement("div", { className: "absolute -top-[10px] left-0 w-full flex items-center justify-end gap-[12px] pr-[22px] z-10" },
|
|
4
5
|
showTopLabel && (React.createElement("div", { className: `flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-10`, style: {
|
|
5
6
|
backgroundColor: "#fff",
|
|
@@ -38,6 +39,12 @@ const ServiceBadges = ({ showTopLabel, isSoldOut, colors, renderIcon, translatio
|
|
|
38
39
|
color: isSoldOut ? "#ccc" : colors.topLabelColor,
|
|
39
40
|
} },
|
|
40
41
|
renderIcon("directo", "12px"),
|
|
41
|
-
React.createElement("div", null, "Tren Express")))
|
|
42
|
+
React.createElement("div", null, "Tren Express"))),
|
|
43
|
+
boardingName && isAllinBus && (React.createElement("div", { className: `flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`, style: {
|
|
44
|
+
backgroundColor: isSoldOut ? "#ddd" : colors.ratingBottomColor,
|
|
45
|
+
} },
|
|
46
|
+
React.createElement("div", { className: isSoldOut ? "grayscale" : "" },
|
|
47
|
+
React.createElement(LottiePlayer, { animationData: getAnimationIcon("priorityStageAnim"), width: "14px", height: "14px" })),
|
|
48
|
+
React.createElement("div", { className: isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]` }, boardingName)))));
|
|
42
49
|
};
|
|
43
50
|
export default ServiceBadges;
|
|
@@ -12,6 +12,8 @@ interface ServiceBadgesMobileProps {
|
|
|
12
12
|
train_type_label?: string;
|
|
13
13
|
};
|
|
14
14
|
isConexion?: boolean;
|
|
15
|
+
isAllinBus?: any;
|
|
16
|
+
boardingName?: string;
|
|
15
17
|
}
|
|
16
18
|
declare const ServiceBadgesMobile: React.FC<ServiceBadgesMobileProps>;
|
|
17
19
|
export default ServiceBadgesMobile;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
const ServiceBadgesMobile = ({ showTopLabel, isSoldOut, colors, renderIcon, serviceItem, isConexion, }) => {
|
|
2
|
+
const ServiceBadgesMobile = ({ showTopLabel, isSoldOut, colors, renderIcon, serviceItem, isConexion, isAllinBus = false, boardingName, }) => {
|
|
3
3
|
return (React.createElement("div", { className: "absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[17px] z-10" },
|
|
4
4
|
showTopLabel && (React.createElement("div", { className: `flex items-center gap-[2p x] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] h-[24px] z-20`, style: {
|
|
5
5
|
backgroundColor: "#fff",
|
|
@@ -38,6 +38,35 @@ const ServiceBadgesMobile = ({ showTopLabel, isSoldOut, colors, renderIcon, serv
|
|
|
38
38
|
color: isSoldOut ? "#ccc" : colors.topLabelColor,
|
|
39
39
|
} },
|
|
40
40
|
renderIcon("directo", "12px"),
|
|
41
|
-
React.createElement("div", null, "Tren Express")))
|
|
41
|
+
React.createElement("div", null, "Tren Express"))),
|
|
42
|
+
boardingName && isAllinBus && (React.createElement("div", { className: `flex items-center gap-[2p x] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] h-[24px] z-20`, style: {
|
|
43
|
+
backgroundColor: "#fff",
|
|
44
|
+
border: isSoldOut
|
|
45
|
+
? "1px solid #ccc"
|
|
46
|
+
: `1px solid ${colors.topLabelColor}`,
|
|
47
|
+
color: isSoldOut ? "#ccc" : colors.topLabelColor,
|
|
48
|
+
} },
|
|
49
|
+
React.createElement("div", { className: isSoldOut ? "grayscale" : "", style: { marginTop: "1px" } }, renderIcon("specialDeparture", "12px", { marginTop: "1px" })),
|
|
50
|
+
React.createElement("div", { style: {
|
|
51
|
+
color: isSoldOut ? "#ccc" : colors.topLabelColor,
|
|
52
|
+
} }, boardingName))
|
|
53
|
+
// <div
|
|
54
|
+
// className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
55
|
+
// style={{
|
|
56
|
+
// backgroundColor: isSoldOut ? "#ddd" : colors.ratingBottomColor,
|
|
57
|
+
// }}
|
|
58
|
+
// >
|
|
59
|
+
// <div className={isSoldOut ? "grayscale" : ""}>
|
|
60
|
+
// {renderIcon("specialDeparture", "12px", { marginTop: "1px" })}
|
|
61
|
+
// </div>
|
|
62
|
+
// <div
|
|
63
|
+
// className={
|
|
64
|
+
// isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
|
|
65
|
+
// }
|
|
66
|
+
// >
|
|
67
|
+
// {boardingName}
|
|
68
|
+
// </div>
|
|
69
|
+
// </div>
|
|
70
|
+
)));
|
|
42
71
|
};
|
|
43
72
|
export default ServiceBadgesMobile;
|
|
@@ -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
|
@@ -906,11 +906,11 @@ function PeruServiceItemDesktop({
|
|
|
906
906
|
onClick={checkMidnight}
|
|
907
907
|
/>
|
|
908
908
|
{showLastSeats ? (
|
|
909
|
-
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[
|
|
909
|
+
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[36px]">
|
|
910
910
|
{serviceItem?.available_seats < 10 &&
|
|
911
911
|
serviceItem?.available_seats > 0 && (
|
|
912
912
|
<div
|
|
913
|
-
className="text-[
|
|
913
|
+
className="text-[11px] mt-1 text-center whitespace-nowrap"
|
|
914
914
|
style={{
|
|
915
915
|
color: colors.seatPriceColor,
|
|
916
916
|
}}
|
|
@@ -1025,6 +1025,9 @@ function PeruServiceItemDesktop({
|
|
|
1025
1025
|
renderIcon={renderIcon}
|
|
1026
1026
|
translation={translation}
|
|
1027
1027
|
serviceItem={serviceItem}
|
|
1028
|
+
isAllinBus={isAllinBus}
|
|
1029
|
+
boardingName={boardingName}
|
|
1030
|
+
getAnimationIcon={getAnimationIcon}
|
|
1028
1031
|
/>
|
|
1029
1032
|
|
|
1030
1033
|
{/* <div className="absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[15px] z-10 ">
|
|
@@ -63,6 +63,7 @@ function ServiceItemMobile({
|
|
|
63
63
|
onTimeDropdownToggle,
|
|
64
64
|
wowDealData,
|
|
65
65
|
isFlores,
|
|
66
|
+
isAllinBus,
|
|
66
67
|
}: MobileServiceItemProps): React.ReactElement {
|
|
67
68
|
const isItemExpanded = serviceItem.id === isExpanded;
|
|
68
69
|
const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
|
|
@@ -174,6 +175,23 @@ function ServiceItemMobile({
|
|
|
174
175
|
isConexion = true;
|
|
175
176
|
}
|
|
176
177
|
|
|
178
|
+
const extractStage = (
|
|
179
|
+
stageArr: Record<string, string[]>[],
|
|
180
|
+
index: number,
|
|
181
|
+
) => {
|
|
182
|
+
const stageObj = stageArr[index];
|
|
183
|
+
const key = Object.keys(stageObj)[0];
|
|
184
|
+
return stageObj[key][0].split(", ")[0];
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const boardingName = serviceItem.stage_details_arr?.length
|
|
188
|
+
? extractStage(serviceItem.stage_details_arr, 0)
|
|
189
|
+
: null;
|
|
190
|
+
|
|
191
|
+
const dropoffName = serviceItem.stage_details_arr?.length
|
|
192
|
+
? extractStage(serviceItem.stage_details_arr, 1)
|
|
193
|
+
: null;
|
|
194
|
+
|
|
177
195
|
return (
|
|
178
196
|
<>
|
|
179
197
|
{isNewUi ? (
|
|
@@ -212,7 +230,8 @@ function ServiceItemMobile({
|
|
|
212
230
|
serviceItem?.is_direct_trip ||
|
|
213
231
|
isConexion ||
|
|
214
232
|
serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
|
|
215
|
-
showTopLabel
|
|
233
|
+
showTopLabel ||
|
|
234
|
+
boardingName
|
|
216
235
|
? "mt-[20px]"
|
|
217
236
|
: "mt-[10px]"
|
|
218
237
|
} `}
|
|
@@ -384,6 +403,8 @@ function ServiceItemMobile({
|
|
|
384
403
|
renderIcon={renderIcon}
|
|
385
404
|
serviceItem={serviceItem}
|
|
386
405
|
isConexion={isConexion}
|
|
406
|
+
isAllinBus={isAllinBus}
|
|
407
|
+
boardingName={boardingName}
|
|
387
408
|
/>
|
|
388
409
|
</div>
|
|
389
410
|
|
|
@@ -162,6 +162,7 @@ export interface MobileServiceItemProps {
|
|
|
162
162
|
[key: string]: string | Record<string, string | undefined> | undefined;
|
|
163
163
|
};
|
|
164
164
|
useLottieFor?: string[];
|
|
165
|
+
stage_details_arr?: any;
|
|
165
166
|
};
|
|
166
167
|
onBookButtonPress?: () => void;
|
|
167
168
|
onRemateUiButtonClick?: () => void;
|
|
@@ -249,4 +250,5 @@ export interface MobileServiceItemProps {
|
|
|
249
250
|
wowDealData?: any;
|
|
250
251
|
isFlores?: boolean;
|
|
251
252
|
operatorLabel?: string;
|
|
253
|
+
isAllinBus?: any;
|
|
252
254
|
}
|
|
@@ -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",
|
|
@@ -523,7 +533,7 @@ const FeatureServiceUi = ({
|
|
|
523
533
|
<span
|
|
524
534
|
className="bold-text"
|
|
525
535
|
ref={(node) =>
|
|
526
|
-
commonService.
|
|
536
|
+
commonService.startComprandoDealCount(node, 4, 16)
|
|
527
537
|
}
|
|
528
538
|
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
529
539
|
/>{" "}
|
|
@@ -628,20 +638,59 @@ const FeatureServiceUi = ({
|
|
|
628
638
|
|
|
629
639
|
<button
|
|
630
640
|
type="button"
|
|
631
|
-
|
|
632
|
-
|
|
641
|
+
ref={(btn) => {
|
|
642
|
+
if (!btn) return;
|
|
643
|
+
btn.onclick = () => {
|
|
644
|
+
if (btn.disabled) return;
|
|
645
|
+
btn.disabled = true;
|
|
646
|
+
btn.style.cursor = "not-allowed";
|
|
647
|
+
btn.style.opacity = "0.85";
|
|
648
|
+
const normal = btn.querySelector(
|
|
649
|
+
'[data-btn-state="normal"]',
|
|
650
|
+
) as HTMLElement | null;
|
|
651
|
+
const loading = btn.querySelector(
|
|
652
|
+
'[data-btn-state="loading"]',
|
|
653
|
+
) as HTMLElement | null;
|
|
654
|
+
if (normal) normal.style.display = "none";
|
|
655
|
+
if (loading) loading.style.display = "flex";
|
|
656
|
+
onBookButtonPress?.(ticketQuantity, serviceItem);
|
|
657
|
+
};
|
|
658
|
+
}}
|
|
659
|
+
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
660
|
style={{
|
|
634
661
|
backgroundColor: "#FF5C60",
|
|
635
662
|
whiteSpace: "nowrap",
|
|
663
|
+
minWidth: "120px",
|
|
636
664
|
}}
|
|
637
665
|
>
|
|
638
|
-
<
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
666
|
+
<span
|
|
667
|
+
data-btn-state="normal"
|
|
668
|
+
style={{ display: "flex", alignItems: "center", gap: "6px" }}
|
|
669
|
+
>
|
|
670
|
+
<LottiePlayer
|
|
671
|
+
animationData={getAnimationIcon("thunderAnimation")}
|
|
672
|
+
width="16px"
|
|
673
|
+
height="16px"
|
|
674
|
+
/>
|
|
675
|
+
<span className="whitespace-nowrap">¡Lo quiero!</span>
|
|
676
|
+
</span>
|
|
677
|
+
<span
|
|
678
|
+
data-btn-state="loading"
|
|
679
|
+
style={{ display: "none", alignItems: "center", gap: "6px" }}
|
|
680
|
+
>
|
|
681
|
+
<span
|
|
682
|
+
style={{
|
|
683
|
+
display: "inline-block",
|
|
684
|
+
width: "16px",
|
|
685
|
+
height: "16px",
|
|
686
|
+
border: "2px solid rgba(255,255,255,0.4)",
|
|
687
|
+
borderTopColor: "#fff",
|
|
688
|
+
borderRadius: "50%",
|
|
689
|
+
animation: "feature-spin 0.7s linear infinite",
|
|
690
|
+
flexShrink: 0,
|
|
691
|
+
}}
|
|
692
|
+
/>
|
|
693
|
+
</span>
|
|
645
694
|
</button>
|
|
646
695
|
</div>
|
|
647
696
|
|
|
@@ -358,7 +358,8 @@ function SeatSection({
|
|
|
358
358
|
: null;
|
|
359
359
|
|
|
360
360
|
const operatorServiceName =
|
|
361
|
-
serviceItem?.operator_service_name === "MovilBus" ||
|
|
361
|
+
serviceItem?.operator_service_name === "MovilBus" ||
|
|
362
|
+
serviceItem?.operator_service_name === "Movil Bus";
|
|
362
363
|
|
|
363
364
|
return (
|
|
364
365
|
<>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import LottiePlayer from "../../assets/LottiePlayer";
|
|
2
3
|
|
|
3
4
|
interface ServiceBadgesProps {
|
|
4
5
|
showTopLabel?: string;
|
|
@@ -13,6 +14,9 @@ interface ServiceBadgesProps {
|
|
|
13
14
|
is_direct_trip?: boolean;
|
|
14
15
|
train_type_label?: string;
|
|
15
16
|
};
|
|
17
|
+
isAllinBus?: boolean;
|
|
18
|
+
boardingName?: string;
|
|
19
|
+
getAnimationIcon?: (iconKey: string) => any;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
const ServiceBadges: React.FC<ServiceBadgesProps> = ({
|
|
@@ -22,6 +26,9 @@ const ServiceBadges: React.FC<ServiceBadgesProps> = ({
|
|
|
22
26
|
renderIcon,
|
|
23
27
|
translation,
|
|
24
28
|
serviceItem,
|
|
29
|
+
isAllinBus = false,
|
|
30
|
+
boardingName,
|
|
31
|
+
getAnimationIcon,
|
|
25
32
|
}) => {
|
|
26
33
|
return (
|
|
27
34
|
<div className="absolute -top-[10px] left-0 w-full flex items-center justify-end gap-[12px] pr-[22px] z-10">
|
|
@@ -89,6 +96,29 @@ const ServiceBadges: React.FC<ServiceBadgesProps> = ({
|
|
|
89
96
|
<div>{"Tren Express"}</div>
|
|
90
97
|
</div>
|
|
91
98
|
)}
|
|
99
|
+
{boardingName && isAllinBus && (
|
|
100
|
+
<div
|
|
101
|
+
className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
102
|
+
style={{
|
|
103
|
+
backgroundColor: isSoldOut ? "#ddd" : colors.ratingBottomColor,
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<div className={isSoldOut ? "grayscale" : ""}>
|
|
107
|
+
<LottiePlayer
|
|
108
|
+
animationData={getAnimationIcon("priorityStageAnim")}
|
|
109
|
+
width="14px"
|
|
110
|
+
height="14px"
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
113
|
+
<div
|
|
114
|
+
className={
|
|
115
|
+
isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
|
|
116
|
+
}
|
|
117
|
+
>
|
|
118
|
+
{boardingName}
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
92
122
|
</div>
|
|
93
123
|
);
|
|
94
124
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import LottiePlayer from "../../assets/LottiePlayer";
|
|
2
3
|
|
|
3
4
|
interface ServiceBadgesMobileProps {
|
|
4
5
|
showTopLabel?: string;
|
|
@@ -13,6 +14,8 @@ interface ServiceBadgesMobileProps {
|
|
|
13
14
|
train_type_label?: string;
|
|
14
15
|
};
|
|
15
16
|
isConexion?: boolean;
|
|
17
|
+
isAllinBus?: any;
|
|
18
|
+
boardingName?: string;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
const ServiceBadgesMobile: React.FC<ServiceBadgesMobileProps> = ({
|
|
@@ -22,6 +25,8 @@ const ServiceBadgesMobile: React.FC<ServiceBadgesMobileProps> = ({
|
|
|
22
25
|
renderIcon,
|
|
23
26
|
serviceItem,
|
|
24
27
|
isConexion,
|
|
28
|
+
isAllinBus = false,
|
|
29
|
+
boardingName,
|
|
25
30
|
}) => {
|
|
26
31
|
return (
|
|
27
32
|
<div className="absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[17px] z-10">
|
|
@@ -96,6 +101,50 @@ const ServiceBadgesMobile: React.FC<ServiceBadgesMobileProps> = ({
|
|
|
96
101
|
<div>{"Tren Express"}</div>
|
|
97
102
|
</div>
|
|
98
103
|
)}
|
|
104
|
+
{boardingName && isAllinBus && (
|
|
105
|
+
<div
|
|
106
|
+
className={`flex items-center gap-[2p x] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] h-[24px] z-20`}
|
|
107
|
+
style={{
|
|
108
|
+
backgroundColor: "#fff",
|
|
109
|
+
border: isSoldOut
|
|
110
|
+
? "1px solid #ccc"
|
|
111
|
+
: `1px solid ${colors.topLabelColor}`,
|
|
112
|
+
color: isSoldOut ? "#ccc" : colors.topLabelColor,
|
|
113
|
+
}}
|
|
114
|
+
>
|
|
115
|
+
<div
|
|
116
|
+
className={isSoldOut ? "grayscale" : ""}
|
|
117
|
+
style={{ marginTop: "1px" }}
|
|
118
|
+
>
|
|
119
|
+
{renderIcon("specialDeparture", "12px", { marginTop: "1px" })}
|
|
120
|
+
</div>
|
|
121
|
+
<div
|
|
122
|
+
style={{
|
|
123
|
+
color: isSoldOut ? "#ccc" : colors.topLabelColor,
|
|
124
|
+
}}
|
|
125
|
+
>
|
|
126
|
+
{boardingName}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
// <div
|
|
131
|
+
// className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
132
|
+
// style={{
|
|
133
|
+
// backgroundColor: isSoldOut ? "#ddd" : colors.ratingBottomColor,
|
|
134
|
+
// }}
|
|
135
|
+
// >
|
|
136
|
+
// <div className={isSoldOut ? "grayscale" : ""}>
|
|
137
|
+
// {renderIcon("specialDeparture", "12px", { marginTop: "1px" })}
|
|
138
|
+
// </div>
|
|
139
|
+
// <div
|
|
140
|
+
// className={
|
|
141
|
+
// isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
|
|
142
|
+
// }
|
|
143
|
+
// >
|
|
144
|
+
// {boardingName}
|
|
145
|
+
// </div>
|
|
146
|
+
// </div>
|
|
147
|
+
)}
|
|
99
148
|
</div>
|
|
100
149
|
);
|
|
101
150
|
};
|
|
@@ -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);
|