kupos-ui-components-lib 9.3.5 → 9.3.7
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/ServiceItemDesktop.js +4 -3
- package/dist/components/ServiceItem/ServiceItemMobile.js +15 -8
- package/dist/components/ServiceItem/mobileTypes.d.ts +2 -0
- package/dist/ui/SeatSection/SeatSection.js +3 -2
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +2 -2
- package/dist/ui/mobileweb/SeatSectionMobile.js +27 -4
- package/dist/utils/CommonService.d.ts +1 -0
- package/dist/utils/CommonService.js +15 -9
- package/package.json +1 -1
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +5 -3
- package/src/components/ServiceItem/ServiceItemMobile.tsx +29 -7
- package/src/components/ServiceItem/mobileTypes.ts +2 -0
- package/src/ui/SeatSection/SeatSection.tsx +6 -2
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +10 -10
- package/src/ui/mobileweb/SeatSectionMobile.tsx +43 -8
- package/src/utils/CommonService.ts +17 -9
|
@@ -68,7 +68,6 @@ const ANIMATION_MAP = {
|
|
|
68
68
|
};
|
|
69
69
|
function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t = (key) => key, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, }) {
|
|
70
70
|
var _a;
|
|
71
|
-
console.log("🚀 ~ ServiceItemPB ~ serviceItem:", serviceItem);
|
|
72
71
|
const getAnimationIcon = (icon) => {
|
|
73
72
|
var _a;
|
|
74
73
|
const animation = ANIMATION_MAP[icon];
|
|
@@ -295,7 +294,9 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
295
294
|
React.createElement(LottiePlayer, { animationData: getAnimationIcon("bombAnimation"), width: "18px", height: "18px" }),
|
|
296
295
|
React.createElement("div", { className: "flex items-center mt-[2px]" },
|
|
297
296
|
React.createElement("span", { className: "bold-text ml-[6px]" },
|
|
298
|
-
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || ""
|
|
297
|
+
((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || "").length > 30
|
|
298
|
+
? ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || "").slice(0, 30) + "..."
|
|
299
|
+
: (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || "",
|
|
299
300
|
"\u00A0"),
|
|
300
301
|
" ",
|
|
301
302
|
"| Termina en\u00A0",
|
|
@@ -317,7 +318,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
317
318
|
" |",
|
|
318
319
|
" ",
|
|
319
320
|
React.createElement("span", { className: "" },
|
|
320
|
-
"
|
|
321
|
+
"Quedan pocos.",
|
|
321
322
|
" ",
|
|
322
323
|
React.createElement("span", { className: "bold-text", ref: (node) => CommonService.startComprandoCount(node, 4, 16), style: { fontVariantNumeric: "tabular-nums" } }),
|
|
323
324
|
" ",
|
|
@@ -18,13 +18,18 @@ const exceptions = [
|
|
|
18
18
|
"asiento_mascota",
|
|
19
19
|
];
|
|
20
20
|
function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, }) {
|
|
21
|
-
var _a, _b, _c, _d;
|
|
21
|
+
var _a, _b, _c, _d, _e;
|
|
22
22
|
const isItemExpanded = serviceItem.id === isExpanded;
|
|
23
23
|
const isPetSeat = (Object.keys(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.pet_seat_info) || []).length > 0;
|
|
24
24
|
let isSoldOut = serviceItem.available_seats <= 0;
|
|
25
|
-
const
|
|
25
|
+
const seats = removeDuplicateSeats
|
|
26
|
+
? ((_a = serviceItem.seat_types) === null || _a === void 0 ? void 0 : _a.filter((seat, index, self) => index === self.findIndex((s) => s.label === seat.label))) || []
|
|
27
|
+
: serviceItem.seat_types || [];
|
|
28
|
+
const discountedSeats = seats.map((seat) => (Object.assign(Object.assign({}, seat), commonService.calculateDiscountedPrice(seat.fare, serviceItem))));
|
|
29
|
+
const hasDiscount = discountedSeats.some((seat) => seat.originalPrice !== seat.discountedPrice);
|
|
30
|
+
const isLongOfferText = (((_b = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) === null || _b === void 0 ? void 0 : _b.length) || 0) > 35;
|
|
26
31
|
const hasOfferText = Boolean(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text);
|
|
27
|
-
const offerGradient =
|
|
32
|
+
const offerGradient = `linear-gradient(90deg, ${colors.rightGradiantColor || "#ff5964"} 0%, ${colors.leftGradiantColor || "#ff8842"} 100%)`;
|
|
28
33
|
const serviceCardStyle = hasOfferText
|
|
29
34
|
? {
|
|
30
35
|
borderColor: "transparent",
|
|
@@ -92,7 +97,9 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
92
97
|
: "rounded-[10px] border border-[#ccc]"}`, style: serviceCardStyle },
|
|
93
98
|
React.createElement("div", { style: { padding: "12px 12px 8px 12px" } },
|
|
94
99
|
React.createElement("div", { className: "flex justify-between items-center mb-[10px]" },
|
|
95
|
-
React.createElement("div", { className: "flex items-center justify-between", style: {
|
|
100
|
+
React.createElement("div", { className: "flex items-center justify-between", style: {
|
|
101
|
+
marginBottom: (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || hasDiscount ? "10px" : "",
|
|
102
|
+
} },
|
|
96
103
|
React.createElement("div", { className: "w-[120px] overflow-y-hidden" },
|
|
97
104
|
React.createElement("img", { src: serviceItem.operator_details[0], alt: "service logo", className: `w-[100px] h-auto object-contain ${isSoldOut ? "grayscale" : ""}` })),
|
|
98
105
|
isCiva ? (React.createElement("div", { className: "black-text min-[420]:text-[12px] text-[12px]" }, serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_details[2])) : showRating ? (React.createElement("div", { className: "flex min-[420]:text-[13px] text-[12px] items-center" },
|
|
@@ -104,9 +111,9 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
104
111
|
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),
|
|
105
112
|
showLastSeats ? (React.createElement("div", { className: "flex justify-end " }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
|
|
106
113
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[10px] text-[#464647] text-center" }, "\u00A1 \u00DAltimos Asientos!")))) : null),
|
|
107
|
-
React.createElement(DateTimeSectionMobile, { onBookButtonPress: onBookButtonPress, isCiva: isCiva, isSoldOut: isSoldOut, isLinatal: isLinatal, isPeru: isPeru, orignLabel: orignLabel, destinationLabel: destinationLabel, originIcon: (
|
|
114
|
+
React.createElement(DateTimeSectionMobile, { onBookButtonPress: onBookButtonPress, isCiva: isCiva, isSoldOut: isSoldOut, isLinatal: isLinatal, isPeru: isPeru, orignLabel: orignLabel, destinationLabel: destinationLabel, originIcon: (_c = serviceItem.icons) === null || _c === void 0 ? void 0 : _c.origin, destinationIcon: (_d = serviceItem.icons) === null || _d === void 0 ? void 0 : _d.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 }),
|
|
108
115
|
React.createElement("div", { className: "bg-[#E6E6E6] mt-[10px] mb-[10px] h-[1px]" }),
|
|
109
|
-
React.createElement(BottomAmenitiesMobile, { isSoldOut: isSoldOut, amenitiesNodes: amenities(), hoursIcon: renderIcon("hours", "14px"), duration: (
|
|
116
|
+
React.createElement(BottomAmenitiesMobile, { isSoldOut: isSoldOut, amenitiesNodes: amenities(), hoursIcon: renderIcon("hours", "14px"), duration: (_e = serviceItem.duration) === null || _e === void 0 ? void 0 : _e.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: () => {
|
|
110
117
|
setIsExpanded(isItemExpanded ? null : serviceItem.id);
|
|
111
118
|
}, isPeru: isPeru })),
|
|
112
119
|
React.createElement(ServiceBadgesMobile, { showTopLabel: showTopLabel, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, serviceItem: serviceItem, isConexion: isConexion })),
|
|
@@ -118,7 +125,7 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
118
125
|
} },
|
|
119
126
|
React.createElement("div", { className: "flex flex-col gap-[8px] text-[12px] min-[420px]:text-[12px] text-[#464647]", style: { lineHeight: 1.6 } },
|
|
120
127
|
React.createElement("div", { className: "flex justify-between items-start" },
|
|
121
|
-
React.createElement("div", { className: `flex ${
|
|
128
|
+
React.createElement("div", { className: `flex ${((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || "").length > 10 ? "items-start" : "items-center"}` },
|
|
122
129
|
React.createElement("div", { className: isLongOfferText ? "mt-[2px]" : "" },
|
|
123
130
|
React.createElement(LottiePlayer, { animationData: serviceItem.icons.bombAnim, width: "14px", height: "14px" })),
|
|
124
131
|
React.createElement("div", { className: `ml-[4px] flex-1 outline-none ${isLongOfferText ? "mt-[2px]" : ""}`, style: {
|
|
@@ -148,7 +155,7 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
148
155
|
"viendo"))),
|
|
149
156
|
React.createElement("div", { className: "flex items-center" },
|
|
150
157
|
React.createElement("span", { className: "whitespace-nowrap" },
|
|
151
|
-
"
|
|
158
|
+
"Quedan pocos.",
|
|
152
159
|
" ",
|
|
153
160
|
React.createElement("span", { className: "bold-text", ref: (node) => commonService.startComprandoCount(node, 4, 16), style: { fontVariantNumeric: "tabular-nums" } }),
|
|
154
161
|
" ",
|
|
@@ -145,8 +145,9 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
145
145
|
React.createElement("div", { className: "col-start-2 row-start-3 flex h-[30px] items-end justify-start" },
|
|
146
146
|
React.createElement("span", { className: "flex items-center gap-[6px] text-[22px] bold-text leading-[30px]", style: { color: isSoldOut ? "#c0c0c0" : "#ff5964" } },
|
|
147
147
|
renderIcon("fireIcon", "16px"),
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
availableSeats <= 0
|
|
149
|
+
? CommonService.currency(0, currencySign)
|
|
150
|
+
: CommonService.discountedCurrency(discountSeat.discountedPrice, currencySign)))));
|
|
150
151
|
}
|
|
151
152
|
return (React.createElement("div", { className: "relative flex gap-[10px] text-[13.33px] justify-between min-h-[2.2rem]", style: isCentered ? { alignItems: "center" } : {} },
|
|
152
153
|
React.createElement("div", { className: "flex flex-col justify-between", style: { gap: "10px" } }, renderLabels()),
|
|
@@ -46,12 +46,12 @@ function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal
|
|
|
46
46
|
React.createElement("div", { className: "min-h-[2.5rem] flex flex-col justify-between gap-[4px] w-[50%] ", style: { justifyContent: isCiva && "center" } },
|
|
47
47
|
React.createElement(TimeRow, { label: orignLabel, icon: originIcon, alt: "origin", date: travelDate, timeContent: depTimeContent, isSoldOut: isSoldOut }),
|
|
48
48
|
isCiva ? null : (React.createElement(TimeRow, { label: destinationLabel, icon: destinationIcon, alt: "destination", date: arrivalDate, timeContent: DateService.formatTime(arrTime), isSoldOut: isSoldOut }))),
|
|
49
|
-
|
|
49
|
+
React.createElement("div", { style: {
|
|
50
50
|
width: "1px",
|
|
51
51
|
height: "2.5rem",
|
|
52
52
|
backgroundColor: "#ccc",
|
|
53
53
|
margin: "auto",
|
|
54
|
-
} })
|
|
54
|
+
} }),
|
|
55
55
|
React.createElement(SeatSectionMobile, { seatTypes: seatTypes, isSoldOut: isSoldOut, isPeru: isPeru, seatPriceColor: seatPriceColor, currencySign: currencySign, availableSeats: availableSeats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, tooltipBgColor: tooltipBgColor })));
|
|
56
56
|
}
|
|
57
57
|
export default DateTimeSectionMobile;
|
|
@@ -88,8 +88,16 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
88
88
|
? getUniqueSeats(seatTypesData, 3)
|
|
89
89
|
: (_c = (_b = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.filter((item) => getFilteredSeats(item.label))) === null || _b === void 0 ? void 0 : _b.sort((a, b) => a.fare - b.fare)) === null || _c === void 0 ? void 0 : _c.slice(0, 2);
|
|
90
90
|
const discountedSeats = seats === null || seats === void 0 ? void 0 : seats.map((seat) => (Object.assign(Object.assign({}, seat), commonService.calculateDiscountedPrice(seat.fare, serviceItem))));
|
|
91
|
-
const
|
|
92
|
-
const
|
|
91
|
+
const peruLowestFare = isPeru ? getLowestFare() : null;
|
|
92
|
+
const peruDiscountCalc = isPeru && peruLowestFare != null
|
|
93
|
+
? commonService.calculateDiscountedPrice(peruLowestFare, serviceItem)
|
|
94
|
+
: null;
|
|
95
|
+
const hasDiscount = isPeru
|
|
96
|
+
? peruDiscountCalc != null &&
|
|
97
|
+
peruDiscountCalc.originalPrice !== peruDiscountCalc.discountedPrice
|
|
98
|
+
: discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.some((s) => s.originalPrice !== s.discountedPrice);
|
|
99
|
+
const discountSeat = isPeru && peruDiscountCalc
|
|
100
|
+
? Object.assign({ label: "", fare: peruLowestFare }, peruDiscountCalc) : (_d = discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.filter((seat) => !EXCEPTIONS.includes(seat.label))) === null || _d === void 0 ? void 0 : _d.sort((a, b) => a.discountedPrice - b.discountedPrice)[0];
|
|
93
101
|
const discountValue = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_type) === "percentage" &&
|
|
94
102
|
typeof (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_value) === "number"
|
|
95
103
|
? Math.round(serviceItem.discount_value)
|
|
@@ -104,11 +112,26 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
104
112
|
discountValue,
|
|
105
113
|
"% OFF"))),
|
|
106
114
|
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]" }, "Antes"),
|
|
107
|
-
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f]
|
|
115
|
+
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f] text-right", style: {
|
|
116
|
+
position: "relative",
|
|
117
|
+
display: "inline-block",
|
|
118
|
+
overflow: "hidden",
|
|
119
|
+
} },
|
|
120
|
+
commonService.currency(discountSeat.originalPrice, currencySign),
|
|
121
|
+
React.createElement("span", { style: {
|
|
122
|
+
position: "absolute",
|
|
123
|
+
top: "50%",
|
|
124
|
+
left: "25%",
|
|
125
|
+
width: "80%",
|
|
126
|
+
height: "1px",
|
|
127
|
+
background: "#9f9f9f",
|
|
128
|
+
transform: "rotate(-15deg)",
|
|
129
|
+
transformOrigin: "center",
|
|
130
|
+
} })),
|
|
108
131
|
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#464647" } }, "Desde"),
|
|
109
132
|
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#ff5964" } },
|
|
110
133
|
((_e = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _e === void 0 ? void 0 : _e.fireIcon) ? (React.createElement("img", { src: serviceItem.icons.fireIcon, alt: "discount", className: "h-[16px] w-[16px] object-contain", style: { filter: isSoldOut ? "grayscale" : "" } })) : null,
|
|
111
|
-
commonService.
|
|
134
|
+
commonService.discountedCurrency(discountSeat.discountedPrice, currencySign)),
|
|
112
135
|
isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)) : (React.createElement("div", { className: "flex flex-col justify-between h-[2.5rem] ", style: {
|
|
113
136
|
gap: isSoldOut ? "0px" : "5px",
|
|
114
137
|
justifyContent: hasMultipleTypes ? "space-between" : "center",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
declare const commonService: {
|
|
2
2
|
currency(amount: number, currencySign?: string): string;
|
|
3
|
+
discountedCurrency(amount: number, currencySign?: string): string;
|
|
3
4
|
copyObject: (ob: any) => any;
|
|
4
5
|
getServiceTypeLabelForFilters: (service_type: any) => "Tipo de servicio" | "Punto de embarque" | "Tipo de asiento" | "SERVICIOS" | "";
|
|
5
6
|
truncateSeatLabel: (label: string | number) => string;
|
|
@@ -6,6 +6,13 @@ const commonService = {
|
|
|
6
6
|
const sign = currencySign || "$";
|
|
7
7
|
return sign + formattedAmount;
|
|
8
8
|
},
|
|
9
|
+
discountedCurrency(amount, currencySign) {
|
|
10
|
+
const formattedAmount = Math.trunc(amount)
|
|
11
|
+
.toString()
|
|
12
|
+
.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
|
13
|
+
const sign = currencySign || "$";
|
|
14
|
+
return sign + formattedAmount;
|
|
15
|
+
},
|
|
9
16
|
copyObject: (ob) => {
|
|
10
17
|
if (!ob)
|
|
11
18
|
return {};
|
|
@@ -308,21 +315,20 @@ const commonService = {
|
|
|
308
315
|
const prevId = node.dataset.countdownId;
|
|
309
316
|
if (prevId)
|
|
310
317
|
clearInterval(Number(prevId));
|
|
311
|
-
let remaining = countdownSeconds
|
|
312
|
-
const formatTime = (
|
|
313
|
-
const m = Math.floor(
|
|
314
|
-
const s =
|
|
315
|
-
|
|
316
|
-
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}:${String(ms).padStart(2, "0")}`;
|
|
318
|
+
let remaining = countdownSeconds;
|
|
319
|
+
const formatTime = (totalSeconds) => {
|
|
320
|
+
const m = Math.floor(totalSeconds / 60);
|
|
321
|
+
const s = totalSeconds % 60;
|
|
322
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
317
323
|
};
|
|
318
324
|
node.textContent = formatTime(remaining);
|
|
319
325
|
const id = setInterval(() => {
|
|
320
|
-
remaining -=
|
|
326
|
+
remaining -= 1;
|
|
321
327
|
if (remaining <= 0) {
|
|
322
|
-
remaining = countdownSeconds
|
|
328
|
+
remaining = countdownSeconds;
|
|
323
329
|
}
|
|
324
330
|
node.textContent = formatTime(remaining);
|
|
325
|
-
},
|
|
331
|
+
}, 1000);
|
|
326
332
|
node.dataset.countdownId = String(id);
|
|
327
333
|
},
|
|
328
334
|
startComprandoCount: (node, min = 4, max = 16) => {
|
package/package.json
CHANGED
|
@@ -106,7 +106,6 @@ function ServiceItemPB({
|
|
|
106
106
|
coachKey,
|
|
107
107
|
viewersConfig,
|
|
108
108
|
}: ServiceItemProps & { currencySign?: string }): React.ReactElement {
|
|
109
|
-
console.log("🚀 ~ ServiceItemPB ~ serviceItem:", serviceItem);
|
|
110
109
|
const getAnimationIcon = (icon: string) => {
|
|
111
110
|
const animation = ANIMATION_MAP[icon];
|
|
112
111
|
if (!animation) return null;
|
|
@@ -615,7 +614,10 @@ function ServiceItemPB({
|
|
|
615
614
|
/>
|
|
616
615
|
<div className="flex items-center mt-[2px]">
|
|
617
616
|
<span className="bold-text ml-[6px]">
|
|
618
|
-
{serviceItem?.offer_text || ""
|
|
617
|
+
{(serviceItem?.offer_text || "").length > 30
|
|
618
|
+
? (serviceItem?.offer_text || "").slice(0, 30) + "..."
|
|
619
|
+
: serviceItem?.offer_text || ""}
|
|
620
|
+
|
|
619
621
|
</span>{" "}
|
|
620
622
|
| Termina en
|
|
621
623
|
<span
|
|
@@ -651,7 +653,7 @@ function ServiceItemPB({
|
|
|
651
653
|
{" "}
|
|
652
654
|
{viewersConfig?.label || " viendo"} |{" "}
|
|
653
655
|
<span className="">
|
|
654
|
-
|
|
656
|
+
Quedan pocos.{" "}
|
|
655
657
|
<span
|
|
656
658
|
className="bold-text"
|
|
657
659
|
ref={(node) =>
|
|
@@ -49,10 +49,27 @@ function ServiceItemMobile({
|
|
|
49
49
|
const isItemExpanded = serviceItem.id === isExpanded;
|
|
50
50
|
const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
|
|
51
51
|
let isSoldOut = serviceItem.available_seats <= 0;
|
|
52
|
+
|
|
53
|
+
const seats = removeDuplicateSeats
|
|
54
|
+
? serviceItem.seat_types?.filter(
|
|
55
|
+
(seat, index, self) =>
|
|
56
|
+
index === self.findIndex((s) => s.label === seat.label),
|
|
57
|
+
) || []
|
|
58
|
+
: serviceItem.seat_types || [];
|
|
59
|
+
|
|
60
|
+
const discountedSeats = seats.map((seat) => ({
|
|
61
|
+
...seat,
|
|
62
|
+
...commonService.calculateDiscountedPrice(seat.fare, serviceItem as any),
|
|
63
|
+
}));
|
|
64
|
+
|
|
65
|
+
const hasDiscount = discountedSeats.some(
|
|
66
|
+
(seat) => seat.originalPrice !== seat.discountedPrice,
|
|
67
|
+
);
|
|
68
|
+
|
|
52
69
|
const isLongOfferText = (serviceItem?.offer_text?.length || 0) > 35;
|
|
53
70
|
|
|
54
71
|
const hasOfferText = Boolean(serviceItem?.offer_text);
|
|
55
|
-
const offerGradient =
|
|
72
|
+
const offerGradient = `linear-gradient(90deg, ${colors.rightGradiantColor || "#ff5964"} 0%, ${colors.leftGradiantColor || "#ff8842"} 100%)`;
|
|
56
73
|
const serviceCardStyle: React.CSSProperties = hasOfferText
|
|
57
74
|
? {
|
|
58
75
|
borderColor: "transparent",
|
|
@@ -158,7 +175,10 @@ function ServiceItemMobile({
|
|
|
158
175
|
<div className="flex justify-between items-center mb-[10px]">
|
|
159
176
|
<div
|
|
160
177
|
className="flex items-center justify-between"
|
|
161
|
-
style={{
|
|
178
|
+
style={{
|
|
179
|
+
marginBottom:
|
|
180
|
+
serviceItem?.offer_text || hasDiscount ? "10px" : "",
|
|
181
|
+
}}
|
|
162
182
|
>
|
|
163
183
|
<div className="w-[120px] overflow-y-hidden">
|
|
164
184
|
<img
|
|
@@ -292,7 +312,7 @@ function ServiceItemMobile({
|
|
|
292
312
|
>
|
|
293
313
|
<div className="flex justify-between items-start">
|
|
294
314
|
<div
|
|
295
|
-
className={`flex ${
|
|
315
|
+
className={`flex ${(serviceItem?.offer_text || "").length > 10 ? "items-start" : "items-center"}`}
|
|
296
316
|
>
|
|
297
317
|
<div className={isLongOfferText ? "mt-[2px]" : ""}>
|
|
298
318
|
<LottiePlayer
|
|
@@ -309,9 +329,11 @@ function ServiceItemMobile({
|
|
|
309
329
|
}}
|
|
310
330
|
>
|
|
311
331
|
{/* <span className="min-[380px]:text-[12px] bold-text">
|
|
312
|
-
{serviceItem?.offer_text || ""
|
|
313
|
-
|
|
314
|
-
|
|
332
|
+
{(serviceItem?.offer_text || "").length > 30
|
|
333
|
+
? (serviceItem?.offer_text || "").slice(0, 30) + "..."
|
|
334
|
+
: serviceItem?.offer_text || ""}
|
|
335
|
+
</span>{" "}
|
|
336
|
+
<span className="min-[380px]:text-[12px]">|</span>{" "} */}
|
|
315
337
|
<span className="whitespace-nowrap min-[380px]:text-[12px]">
|
|
316
338
|
Termina en
|
|
317
339
|
<span
|
|
@@ -358,7 +380,7 @@ function ServiceItemMobile({
|
|
|
358
380
|
</div>
|
|
359
381
|
<div className="flex items-center">
|
|
360
382
|
<span className="whitespace-nowrap">
|
|
361
|
-
|
|
383
|
+
Quedan pocos.{" "}
|
|
362
384
|
<span
|
|
363
385
|
className="bold-text"
|
|
364
386
|
ref={(node) =>
|
|
@@ -284,8 +284,12 @@ function SeatSection({
|
|
|
284
284
|
>
|
|
285
285
|
{/* <span className="text-[18px] leading-[24px]">🔥</span> */}
|
|
286
286
|
{renderIcon("fireIcon", "16px")}
|
|
287
|
-
{
|
|
288
|
-
|
|
287
|
+
{availableSeats <= 0
|
|
288
|
+
? CommonService.currency(0, currencySign)
|
|
289
|
+
: CommonService.discountedCurrency(
|
|
290
|
+
discountSeat.discountedPrice,
|
|
291
|
+
currencySign,
|
|
292
|
+
)}
|
|
289
293
|
</span>
|
|
290
294
|
</div>
|
|
291
295
|
</div>
|
|
@@ -169,16 +169,16 @@ function DateTimeSectionMobile({
|
|
|
169
169
|
/>
|
|
170
170
|
)}
|
|
171
171
|
</div>
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
172
|
+
|
|
173
|
+
<div
|
|
174
|
+
style={{
|
|
175
|
+
width: "1px",
|
|
176
|
+
height: "2.5rem",
|
|
177
|
+
backgroundColor: "#ccc",
|
|
178
|
+
margin: "auto",
|
|
179
|
+
}}
|
|
180
|
+
></div>
|
|
181
|
+
|
|
182
182
|
{/* SEATS */}
|
|
183
183
|
<SeatSectionMobile
|
|
184
184
|
seatTypes={seatTypes}
|
|
@@ -236,12 +236,24 @@ function SeatSectionMobile({
|
|
|
236
236
|
...commonService.calculateDiscountedPrice(seat.fare, serviceItem),
|
|
237
237
|
}));
|
|
238
238
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
239
|
+
const peruLowestFare = isPeru ? getLowestFare() : null;
|
|
240
|
+
const peruDiscountCalc =
|
|
241
|
+
isPeru && peruLowestFare != null
|
|
242
|
+
? commonService.calculateDiscountedPrice(peruLowestFare, serviceItem)
|
|
243
|
+
: null;
|
|
244
|
+
|
|
245
|
+
const hasDiscount = isPeru
|
|
246
|
+
? peruDiscountCalc != null &&
|
|
247
|
+
peruDiscountCalc.originalPrice !== peruDiscountCalc.discountedPrice
|
|
248
|
+
: discountedSeats?.some((s) => s.originalPrice !== s.discountedPrice);
|
|
249
|
+
|
|
250
|
+
const discountSeat =
|
|
251
|
+
isPeru && peruDiscountCalc
|
|
252
|
+
? { label: "", fare: peruLowestFare as number, ...peruDiscountCalc }
|
|
253
|
+
: discountedSeats
|
|
254
|
+
?.filter((seat) => !EXCEPTIONS.includes(seat.label))
|
|
255
|
+
?.sort((a, b) => a.discountedPrice - b.discountedPrice)[0];
|
|
256
|
+
|
|
245
257
|
const discountValue =
|
|
246
258
|
serviceItem?.discount_type === "percentage" &&
|
|
247
259
|
typeof serviceItem?.discount_value === "number"
|
|
@@ -273,8 +285,27 @@ function SeatSectionMobile({
|
|
|
273
285
|
<span className="min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]">
|
|
274
286
|
Antes
|
|
275
287
|
</span>
|
|
276
|
-
<span
|
|
288
|
+
<span
|
|
289
|
+
className="min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f] text-right"
|
|
290
|
+
style={{
|
|
291
|
+
position: "relative",
|
|
292
|
+
display: "inline-block",
|
|
293
|
+
overflow: "hidden",
|
|
294
|
+
}}
|
|
295
|
+
>
|
|
277
296
|
{commonService.currency(discountSeat.originalPrice, currencySign)}
|
|
297
|
+
<span
|
|
298
|
+
style={{
|
|
299
|
+
position: "absolute",
|
|
300
|
+
top: "50%",
|
|
301
|
+
left: "25%",
|
|
302
|
+
width: "80%",
|
|
303
|
+
height: "1px",
|
|
304
|
+
background: "#9f9f9f",
|
|
305
|
+
transform: "rotate(-15deg)",
|
|
306
|
+
transformOrigin: "center",
|
|
307
|
+
}}
|
|
308
|
+
/>
|
|
278
309
|
</span>
|
|
279
310
|
|
|
280
311
|
<span
|
|
@@ -295,7 +326,11 @@ function SeatSectionMobile({
|
|
|
295
326
|
style={{ filter: isSoldOut ? "grayscale" : "" }}
|
|
296
327
|
/>
|
|
297
328
|
) : null}
|
|
298
|
-
{commonService.currency(discountSeat.discountedPrice, currencySign)}
|
|
329
|
+
{/* {commonService.currency(discountSeat.discountedPrice, currencySign)} */}
|
|
330
|
+
{commonService.discountedCurrency(
|
|
331
|
+
discountSeat.discountedPrice,
|
|
332
|
+
currencySign,
|
|
333
|
+
)}
|
|
299
334
|
</span>
|
|
300
335
|
|
|
301
336
|
{isSoldOut ? (
|
|
@@ -8,6 +8,15 @@ const commonService = {
|
|
|
8
8
|
return sign + formattedAmount;
|
|
9
9
|
},
|
|
10
10
|
|
|
11
|
+
discountedCurrency(amount: number, currencySign?: string) {
|
|
12
|
+
const formattedAmount = Math.trunc(amount)
|
|
13
|
+
.toString()
|
|
14
|
+
.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
|
15
|
+
|
|
16
|
+
const sign = currencySign || "$";
|
|
17
|
+
return sign + formattedAmount;
|
|
18
|
+
},
|
|
19
|
+
|
|
11
20
|
copyObject: (ob) => {
|
|
12
21
|
if (!ob) return {};
|
|
13
22
|
return JSON.parse(JSON.stringify(ob));
|
|
@@ -344,24 +353,23 @@ const commonService = {
|
|
|
344
353
|
const prevId = node.dataset.countdownId;
|
|
345
354
|
if (prevId) clearInterval(Number(prevId));
|
|
346
355
|
|
|
347
|
-
let remaining = countdownSeconds
|
|
356
|
+
let remaining = countdownSeconds;
|
|
348
357
|
|
|
349
|
-
const formatTime = (
|
|
350
|
-
const m = Math.floor(
|
|
351
|
-
const s =
|
|
352
|
-
|
|
353
|
-
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}:${String(ms).padStart(2, "0")}`;
|
|
358
|
+
const formatTime = (totalSeconds: number) => {
|
|
359
|
+
const m = Math.floor(totalSeconds / 60);
|
|
360
|
+
const s = totalSeconds % 60;
|
|
361
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
354
362
|
};
|
|
355
363
|
|
|
356
364
|
node.textContent = formatTime(remaining);
|
|
357
365
|
|
|
358
366
|
const id = setInterval(() => {
|
|
359
|
-
remaining -=
|
|
367
|
+
remaining -= 1;
|
|
360
368
|
if (remaining <= 0) {
|
|
361
|
-
remaining = countdownSeconds
|
|
369
|
+
remaining = countdownSeconds;
|
|
362
370
|
}
|
|
363
371
|
node.textContent = formatTime(remaining);
|
|
364
|
-
},
|
|
372
|
+
}, 1000);
|
|
365
373
|
|
|
366
374
|
node.dataset.countdownId = String(id);
|
|
367
375
|
},
|