kupos-ui-components-lib 9.11.1 → 9.11.3
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.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +41 -5
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +1 -1
- package/dist/components/ServiceItem/mobileTypes.d.ts +1 -0
- package/dist/components/ServiceItem/types.d.ts +7 -0
- package/dist/styles.css +6 -0
- package/dist/ui/DateTimeSection/DateTimeSection.js +4 -4
- package/dist/ui/SeatSection/SeatSection.d.ts +7 -1
- package/dist/ui/SeatSection/SeatSection.js +59 -14
- package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +13 -7
- package/dist/ui/mobileweb/SeatSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/SeatSectionMobile.js +36 -16
- package/dist/utils/CommonService.d.ts +1 -1
- package/dist/utils/CommonService.js +5 -1
- package/package.json +1 -1
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +69 -3
- package/src/components/ServiceItem/ServiceItemMobile.tsx +2 -1
- package/src/components/ServiceItem/mobileTypes.ts +31 -26
- package/src/components/ServiceItem/types.ts +12 -0
- package/src/ui/DateTimeSection/DateTimeSection.tsx +4 -4
- package/src/ui/SeatSection/SeatSection.tsx +114 -24
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +47 -34
- package/src/ui/mobileweb/SeatSectionMobile.tsx +45 -13
- package/src/utils/CommonService.ts +7 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { ServiceItemProps } from "./types";
|
|
3
|
-
declare 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, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, }: ServiceItemProps & {
|
|
3
|
+
declare 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, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isTrain, selectedSeatKey, onSeatSelect, onTrainButtonClick, showSeatSelectionError, onShowSeatSelectionError, onClearSeatSelectionError, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, }: ServiceItemProps & {
|
|
4
4
|
currencySign?: string;
|
|
5
5
|
}): React.ReactElement;
|
|
6
6
|
export default ServiceItemPB;
|
|
@@ -87,9 +87,12 @@ const ANIMATION_MAP = {
|
|
|
87
87
|
kupos: flameAnimation,
|
|
88
88
|
},
|
|
89
89
|
};
|
|
90
|
-
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, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, }) {
|
|
90
|
+
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, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isTrain, selectedSeatKey, onSeatSelect, onTrainButtonClick, showSeatSelectionError, onShowSeatSelectionError, onClearSeatSelectionError, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, }) {
|
|
91
91
|
var _a, _b, _c;
|
|
92
|
-
|
|
92
|
+
const handleSeatSelect = (key, price, seatKey, apiSeatType) => {
|
|
93
|
+
onClearSeatSelectionError === null || onClearSeatSelectionError === void 0 ? void 0 : onClearSeatSelectionError();
|
|
94
|
+
onSeatSelect === null || onSeatSelect === void 0 ? void 0 : onSeatSelect(key, price, seatKey, apiSeatType);
|
|
95
|
+
};
|
|
93
96
|
const getAnimationIcon = (icon) => {
|
|
94
97
|
var _a;
|
|
95
98
|
const animation = ANIMATION_MAP[icon];
|
|
@@ -130,6 +133,24 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
130
133
|
: serviceItem.seat_types || [];
|
|
131
134
|
const discountedSeats = seats.map((seat) => (Object.assign(Object.assign({}, seat), CommonService.calculateDiscountedPrice(seat.fare, serviceItem))));
|
|
132
135
|
const hasDiscount = discountedSeats.some((seat) => seat.originalPrice !== seat.discountedPrice);
|
|
136
|
+
// Mirror the same check as SeatSection: hide badge (and its top margin) when
|
|
137
|
+
// both percentage and max_discount exist and the cap is being applied.
|
|
138
|
+
const isMaxDiscountApplied = (() => {
|
|
139
|
+
const { discount_type, discount_value, max_discount } = serviceItem;
|
|
140
|
+
if (discount_type === "percentage" &&
|
|
141
|
+
typeof discount_value === "number" &&
|
|
142
|
+
max_discount != null &&
|
|
143
|
+
max_discount > 0) {
|
|
144
|
+
const lowestFare = discountedSeats
|
|
145
|
+
.map((s) => s.originalPrice)
|
|
146
|
+
.filter((p) => p > 0)
|
|
147
|
+
.sort((a, b) => a - b)[0];
|
|
148
|
+
if (lowestFare != null) {
|
|
149
|
+
return (lowestFare * discount_value) / 100 > max_discount;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
})();
|
|
133
154
|
const dpDiscountEntry = Object.entries((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) || {})[0];
|
|
134
155
|
const dpDiscountPercent = dpDiscountEntry === null || dpDiscountEntry === void 0 ? void 0 : dpDiscountEntry[1];
|
|
135
156
|
const hasDpEnabled = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) === true;
|
|
@@ -228,6 +249,16 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
228
249
|
});
|
|
229
250
|
return;
|
|
230
251
|
}
|
|
252
|
+
if (isTrain) {
|
|
253
|
+
if (!selectedSeatKey) {
|
|
254
|
+
onShowSeatSelectionError === null || onShowSeatSelectionError === void 0 ? void 0 : onShowSeatSelectionError(serviceItem.id);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (onTrainButtonClick) {
|
|
258
|
+
onTrainButtonClick();
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
231
262
|
onBookButtonPress();
|
|
232
263
|
};
|
|
233
264
|
const items = [
|
|
@@ -277,11 +308,12 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
277
308
|
: coachKey
|
|
278
309
|
? "20px 15px 20px 15px"
|
|
279
310
|
: "20px 15px 10px 15px",
|
|
280
|
-
marginTop: hasDiscount || hasOfferText || dpDiscountPercent
|
|
311
|
+
marginTop: (hasDiscount || hasOfferText || dpDiscountPercent) &&
|
|
312
|
+
!isMaxDiscountApplied
|
|
281
313
|
? "14px"
|
|
282
314
|
: "",
|
|
283
315
|
} },
|
|
284
|
-
React.createElement("div", { className:
|
|
316
|
+
React.createElement("div", { className: `grid text-[#464647] w-full ${isTrain ? "[grid-template-columns:16%_30%_2.5%_28%_15.5%]" : "[grid-template-columns:20%_30%_2.5%_24%_15.5%]"} gap-x-[2%] items-center` },
|
|
285
317
|
React.createElement("div", { className: "flex flex-col gap-[5px]" },
|
|
286
318
|
React.createElement("div", null,
|
|
287
319
|
React.createElement("img", { src: serviceItem.operator_details[0], alt: "service logo", className: `h-[30px] w-[auto] ${isSoldOut ? "grayscale" : ""}` }),
|
|
@@ -294,9 +326,13 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
294
326
|
backgroundColor: "#ccc",
|
|
295
327
|
} }),
|
|
296
328
|
React.createElement("div", { className: "content-center" },
|
|
297
|
-
React.createElement(SeatSection, { seatTypes: serviceItem.seat_types, serviceItem: serviceItem, availableSeats: serviceItem.available_seats, isSoldOut: isSoldOut, priceColor: colors.priceColor, dpSeatColor: colors.seatPriceColor, currencySign: currencySign, removeDuplicateSeats: removeDuplicateSeats, isPeru: isPeru, renderIcon: renderIcon, discountSeatPriceColor: colors.discountSeatPriceColor, tooltipColor: colors.tooltipColor })),
|
|
329
|
+
React.createElement(SeatSection, { seatTypes: serviceItem.seat_types, serviceItem: serviceItem, availableSeats: serviceItem.available_seats, isSoldOut: isSoldOut, priceColor: colors.priceColor, dpSeatColor: colors.seatPriceColor, currencySign: currencySign, removeDuplicateSeats: removeDuplicateSeats, isPeru: isPeru, renderIcon: renderIcon, discountSeatPriceColor: colors.discountSeatPriceColor, isTrain: isTrain, selectedSeatKey: selectedSeatKey, onSeatSelect: handleSeatSelect, topLabelColor: colors.topLabelColor, tooltipColor: colors.tooltipColor })),
|
|
298
330
|
React.createElement("div", { className: "relative" },
|
|
299
331
|
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 }),
|
|
332
|
+
showSeatSelectionError === serviceItem.id && isTrain && (React.createElement("div", { className: "flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]" },
|
|
333
|
+
React.createElement("div", { className: "text-[9px] text-center whitespace-nowrap", style: {
|
|
334
|
+
color: colors.seatPriceColor,
|
|
335
|
+
} }, "Selecciona el tipo de servicio"))),
|
|
300
336
|
showLastSeats ? (React.createElement("div", { className: "flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]" }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
|
|
301
337
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[12px] mt-1 text-center", style: {
|
|
302
338
|
color: colors.seatPriceColor,
|
|
@@ -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, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores,
|
|
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;
|
|
4
4
|
export default ServiceItemMobile;
|
|
@@ -18,7 +18,7 @@ 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, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores,
|
|
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
22
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
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;
|
|
@@ -245,6 +245,13 @@ export interface ServiceItemProps {
|
|
|
245
245
|
showLoginModal?: any;
|
|
246
246
|
isLoggedIn?: any;
|
|
247
247
|
showLoginOption?: boolean;
|
|
248
|
+
isTrain?: boolean;
|
|
249
|
+
selectedSeatKey?: any;
|
|
250
|
+
onSeatSelect?: (key: any, price: number, seatKey: string, apiSeatType?: string) => void;
|
|
251
|
+
onTrainButtonClick?: any;
|
|
252
|
+
showSeatSelectionError?: string | null;
|
|
253
|
+
onShowSeatSelectionError?: (serviceId: string) => void;
|
|
254
|
+
onClearSeatSelectionError?: () => void;
|
|
248
255
|
selectedTimeSlot?: string;
|
|
249
256
|
onTimeSlotChange?: (slot: string) => void;
|
|
250
257
|
isTimeDropdownOpen?: string | number | null;
|
package/dist/styles.css
CHANGED
|
@@ -566,6 +566,9 @@
|
|
|
566
566
|
.\[grid-template-columns\:14\%_40\%_0\.5\%_24\%_13\.5\%\] {
|
|
567
567
|
grid-template-columns: 14% 40% 0.5% 24% 13.5%;
|
|
568
568
|
}
|
|
569
|
+
.\[grid-template-columns\:16\%_30\%_2\.5\%_28\%_15\.5\%\] {
|
|
570
|
+
grid-template-columns: 16% 30% 2.5% 28% 15.5%;
|
|
571
|
+
}
|
|
569
572
|
.\[grid-template-columns\:20\%_30\%_2\.5\%_24\%_15\.5\%\] {
|
|
570
573
|
grid-template-columns: 20% 30% 2.5% 24% 15.5%;
|
|
571
574
|
}
|
|
@@ -1023,6 +1026,9 @@
|
|
|
1023
1026
|
.text-right {
|
|
1024
1027
|
text-align: right;
|
|
1025
1028
|
}
|
|
1029
|
+
.text-\[9px\] {
|
|
1030
|
+
font-size: 9px;
|
|
1031
|
+
}
|
|
1026
1032
|
.text-\[10px\] {
|
|
1027
1033
|
font-size: 10px;
|
|
1028
1034
|
}
|
|
@@ -32,16 +32,16 @@ function DateTimeSection({ serviceItem, isSoldOut, isCiva, isLinatal, removeArri
|
|
|
32
32
|
React.createElement("img", { src: (_b = serviceItem.icons) === null || _b === void 0 ? void 0 : _b.destination, className: `w-[16px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }))))),
|
|
33
33
|
React.createElement("div", { className: "flex flex-col gap-[4px]" },
|
|
34
34
|
React.createElement(StageTooltip, { stageData: serviceItem.boarding_stages, direction: 1, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
|
|
35
|
-
React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.travel_date))),
|
|
35
|
+
React.createElement("span", { className: "cursor-pointer bold-text capitalize whitespace-nowrap" }, DateService.getServiceItemDate(serviceItem.travel_date))),
|
|
36
36
|
!isCiva && (React.createElement(StageTooltip, { stageData: serviceItem.dropoff_stages, direction: 2, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
|
|
37
|
-
React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.arrival_date))))),
|
|
37
|
+
React.createElement("span", { className: "cursor-pointer bold-text capitalize whitespace-nowrap" }, DateService.getServiceItemDate(serviceItem.arrival_date))))),
|
|
38
38
|
React.createElement("div", { className: "flex flex-col gap-[4px] items-center" },
|
|
39
39
|
React.createElement("div", { className: "h-[20px] flex items-center justify-center" },
|
|
40
40
|
React.createElement("div", null, "\u2022")),
|
|
41
41
|
!isCiva && (React.createElement("div", { className: "h-[20px] flex items-center justify-center" }, removeArrivalTime ? null : serviceItem.arr_time ? (React.createElement("div", null, "\u2022")) : null))),
|
|
42
42
|
React.createElement("div", { className: "flex flex-col gap-[4px]" },
|
|
43
43
|
React.createElement(StageTooltip, { stageData: serviceItem.boarding_stages, direction: 1, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
|
|
44
|
-
React.createElement("div", { className: "font-[900] bold-text" }, isLinatal ? (React.createElement(React.Fragment, null,
|
|
44
|
+
React.createElement("div", { className: "font-[900] bold-text whitespace-nowrap" }, isLinatal ? (React.createElement(React.Fragment, null,
|
|
45
45
|
cleanedDepTime,
|
|
46
46
|
" ",
|
|
47
47
|
React.createElement("span", null, hasPM ? "PM" : hasAM ? "AM" : ""),
|
|
@@ -49,7 +49,7 @@ function DateTimeSection({ serviceItem, isSoldOut, isCiva, isLinatal, removeArri
|
|
|
49
49
|
!(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dep_time.includes("PM")) &&
|
|
50
50
|
DateService.ampmOnly(serviceItem.dep_time))) : (DateService.formatTime(serviceItem.dep_time)))),
|
|
51
51
|
!isCiva && (React.createElement(StageTooltip, { stageData: serviceItem.dropoff_stages, direction: 2, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
|
|
52
|
-
React.createElement("div", { className: "font-[900] bold-text" }, removeArrivalTime
|
|
52
|
+
React.createElement("div", { className: "font-[900] bold-text whitespace-nowrap" }, removeArrivalTime
|
|
53
53
|
? "\u00A0"
|
|
54
54
|
: serviceItem.arr_time
|
|
55
55
|
? DateService.formatTime(serviceItem.arr_time)
|
|
@@ -3,6 +3,8 @@ interface SeatType {
|
|
|
3
3
|
label: string;
|
|
4
4
|
fare: number;
|
|
5
5
|
key: any;
|
|
6
|
+
apiSeatType?: string;
|
|
7
|
+
api_seat_type?: string;
|
|
6
8
|
}
|
|
7
9
|
interface SeatSectionProps {
|
|
8
10
|
seatTypes: SeatType[];
|
|
@@ -16,7 +18,11 @@ interface SeatSectionProps {
|
|
|
16
18
|
serviceItem?: any;
|
|
17
19
|
renderIcon?: (iconKey: string, size?: string) => React.ReactNode;
|
|
18
20
|
discountSeatPriceColor?: string;
|
|
21
|
+
isTrain?: boolean;
|
|
22
|
+
selectedSeatKey?: any;
|
|
23
|
+
onSeatSelect?: (key: any, price: number, seatKey: string, apiSeatType?: string) => void;
|
|
24
|
+
topLabelColor?: string;
|
|
19
25
|
tooltipColor?: string;
|
|
20
26
|
}
|
|
21
|
-
declare function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, tooltipColor, }: SeatSectionProps): React.ReactElement;
|
|
27
|
+
declare function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isTrain, topLabelColor, tooltipColor, }: SeatSectionProps): React.ReactElement;
|
|
22
28
|
export default SeatSection;
|
|
@@ -8,11 +8,13 @@ function getAllSeatTypes(seatTypes) {
|
|
|
8
8
|
let seatTypesWithPrices = seatTypes.filter(Boolean).map((val) => ({
|
|
9
9
|
label: val === null || val === void 0 ? void 0 : val.label,
|
|
10
10
|
price: val === null || val === void 0 ? void 0 : val.fare,
|
|
11
|
+
key: val === null || val === void 0 ? void 0 : val.key,
|
|
12
|
+
apiSeatType: (val === null || val === void 0 ? void 0 : val.apiSeatType) || (val === null || val === void 0 ? void 0 : val.api_seat_type),
|
|
11
13
|
}));
|
|
12
14
|
seatTypesWithPrices.sort((a, b) => a.price - b.price);
|
|
13
15
|
return seatTypesWithPrices;
|
|
14
16
|
}
|
|
15
|
-
function getSortedSeatTypes(seatTypes) {
|
|
17
|
+
function getSortedSeatTypes(seatTypes, isTrain) {
|
|
16
18
|
if (!(seatTypes === null || seatTypes === void 0 ? void 0 : seatTypes.length)) {
|
|
17
19
|
return [{ label: "Salon cama", price: 0 }];
|
|
18
20
|
}
|
|
@@ -21,7 +23,9 @@ function getSortedSeatTypes(seatTypes) {
|
|
|
21
23
|
if (premiumIndex >= 3) {
|
|
22
24
|
seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
|
|
23
25
|
}
|
|
24
|
-
|
|
26
|
+
if (!isTrain) {
|
|
27
|
+
seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
|
|
28
|
+
}
|
|
25
29
|
const seenPrices = new Set();
|
|
26
30
|
seatTypesWithPrices = seatTypesWithPrices.filter((seat) => {
|
|
27
31
|
if (seenPrices.has(seat.price))
|
|
@@ -54,11 +58,10 @@ function getUniqueSeats(seatTypes) {
|
|
|
54
58
|
function getNumberOfSeats(seatTypes) {
|
|
55
59
|
return seatTypes.filter((val) => !SEAT_EXCEPTIONS.includes(val.label)).length;
|
|
56
60
|
}
|
|
57
|
-
function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, tooltipColor, }) {
|
|
61
|
+
function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isTrain, topLabelColor, tooltipColor, }) {
|
|
58
62
|
var _a;
|
|
59
63
|
const uniqueSeats = getUniqueSeats(seatTypes);
|
|
60
|
-
const sortedSeatTypes = getSortedSeatTypes(seatTypes);
|
|
61
|
-
console.log("🚀 ~ SeatSection ~ sortedSeatTypes:", sortedSeatTypes);
|
|
64
|
+
const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
|
|
62
65
|
const numberOfSeats = getNumberOfSeats(seatTypes);
|
|
63
66
|
const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
|
|
64
67
|
const formatPrice = (price) => availableSeats <= 0
|
|
@@ -66,11 +69,36 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
66
69
|
: CommonService.currency(price, currencySign);
|
|
67
70
|
const renderSeatNames = () => {
|
|
68
71
|
const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
|
|
69
|
-
return seats.map((val, key) =>
|
|
70
|
-
?
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
return seats.map((val, key) => {
|
|
73
|
+
return SEAT_EXCEPTIONS.includes(val.label) ? null : (React.createElement("div", { className: "flex items-center", style: isTrain ? { cursor: "pointer" } : undefined, onClick: isTrain && !isSoldOut
|
|
74
|
+
? () => val.label === selectedSeatKey
|
|
75
|
+
? onSeatSelect === null || onSeatSelect === void 0 ? void 0 : onSeatSelect(null, 0, "", "")
|
|
76
|
+
: onSeatSelect === null || onSeatSelect === void 0 ? void 0 : onSeatSelect(val.label, val.price, val.key, val.apiSeatType)
|
|
77
|
+
: undefined },
|
|
78
|
+
isTrain && (React.createElement("div", { style: {
|
|
79
|
+
border: `1px solid ${val.label === selectedSeatKey ? topLabelColor : "#ccc"}`,
|
|
80
|
+
borderRadius: "50%",
|
|
81
|
+
width: "14px",
|
|
82
|
+
height: "14px",
|
|
83
|
+
minWidth: "14px",
|
|
84
|
+
marginRight: "10px",
|
|
85
|
+
display: "flex",
|
|
86
|
+
alignItems: "center",
|
|
87
|
+
justifyContent: "center",
|
|
88
|
+
} }, val.label === selectedSeatKey && (React.createElement("div", { style: {
|
|
89
|
+
backgroundColor: topLabelColor,
|
|
90
|
+
borderRadius: "50%",
|
|
91
|
+
width: "7px",
|
|
92
|
+
height: "7px",
|
|
93
|
+
} })))),
|
|
94
|
+
React.createElement("span", { key: key, className: `flex items-center justify-between text-[13.33px] whitespace-nowrap ${isSoldOut ? "text-[#c0c0c0]" : ""}` }, typeof val.label === "string" || typeof val.label === "number"
|
|
95
|
+
? removeDuplicateSeats && isPeru
|
|
96
|
+
? CommonService.truncateSeatLabel(val.label)
|
|
97
|
+
: isTrain
|
|
98
|
+
? CommonService.capitalize(String(val.label))
|
|
99
|
+
: val.label
|
|
100
|
+
: null)));
|
|
101
|
+
});
|
|
74
102
|
};
|
|
75
103
|
const renderSeatPrices = () => {
|
|
76
104
|
if (isPeru) {
|
|
@@ -126,6 +154,21 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
126
154
|
}
|
|
127
155
|
return null;
|
|
128
156
|
})();
|
|
157
|
+
console.log("🚀 ~ SeatSection ~ serviceItem:", serviceItem);
|
|
158
|
+
// Hide the % OFF badge when max_discount is capping the percentage discount
|
|
159
|
+
// (i.e. both percentage and max_discount exist, and the raw % amount exceeds the cap)
|
|
160
|
+
const isMaxDiscountApplied = (() => {
|
|
161
|
+
const { discount_type, discount_value, max_discount } = serviceItem !== null && serviceItem !== void 0 ? serviceItem : {};
|
|
162
|
+
if (discount_type === "percentage" &&
|
|
163
|
+
typeof discount_value === "number" &&
|
|
164
|
+
max_discount != null &&
|
|
165
|
+
max_discount > 0 &&
|
|
166
|
+
discountSeat) {
|
|
167
|
+
const rawPercentageDiscount = (discountSeat.originalPrice * discount_value) / 100;
|
|
168
|
+
return rawPercentageDiscount > max_discount;
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
})();
|
|
129
172
|
const renderLabels = () => {
|
|
130
173
|
if (isPeru) {
|
|
131
174
|
const isMovilBus = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "MovilBus";
|
|
@@ -148,7 +191,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
148
191
|
hasDiscount && (React.createElement("span", { className: "text-[13.33px]", style: {
|
|
149
192
|
color: "#999",
|
|
150
193
|
} }, "Antes")),
|
|
151
|
-
React.createElement("span", { className: "text-[13.33px] flex flex-col" }, operatorServiceName ? (React.createElement("span", { className: "text-[13.33px]" }, seatLabel)) : (React.createElement("span", { className: "text-[13.33px]" }, "Desde")))));
|
|
194
|
+
React.createElement("span", { className: "text-[13.33px] flex flex-col" }, operatorServiceName ? (React.createElement("span", { className: "text-[13.33px] whitespace-nowrap" }, seatLabel)) : (React.createElement("span", { className: "text-[13.33px]" }, "Desde")))));
|
|
152
195
|
}
|
|
153
196
|
return renderSeatNames();
|
|
154
197
|
};
|
|
@@ -242,7 +285,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
242
285
|
React.createElement("span", { className: "text-[13.33px] font-normal leading-[22px] text-[#ccc]" }, "Antes")),
|
|
243
286
|
React.createElement("div", { className: "col-start-1 row-start-3 flex h-[20px] items-end" },
|
|
244
287
|
React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#464647]" }, "Desde")),
|
|
245
|
-
React.createElement("div", { className: "col-start-2 row-start-1 flex items-center justify-center absolute", style: { top: "-22px", left: "50%", transform: "translateX(-50%)" } }, discountValue != null && (React.createElement("span", { className: "rounded-[100px] bg-[#ff5964] px-[6px] text-[12px] bold-text leading-[20px] text-white", style: {
|
|
288
|
+
React.createElement("div", { className: "col-start-2 row-start-1 flex items-center justify-center absolute", style: { top: "-22px", left: "50%", transform: "translateX(-50%)" } }, discountValue != null && !isMaxDiscountApplied && (React.createElement("span", { className: "rounded-[100px] bg-[#ff5964] px-[6px] text-[12px] bold-text leading-[20px] text-white", style: {
|
|
246
289
|
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
247
290
|
whiteSpace: "nowrap",
|
|
248
291
|
backgroundColor: discountSeatPriceColor,
|
|
@@ -250,7 +293,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
250
293
|
discountValue,
|
|
251
294
|
"% OFF"))),
|
|
252
295
|
React.createElement("div", { className: "col-start-2 row-start-2 flex items-center justify-center ", style: { textAlign: "center" } },
|
|
253
|
-
React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative", style: {
|
|
296
|
+
React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative whitespace-nowrap", style: {
|
|
254
297
|
position: "relative",
|
|
255
298
|
} },
|
|
256
299
|
formatPrice(discountSeat.originalPrice),
|
|
@@ -280,7 +323,9 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
280
323
|
color: isSoldOut ? "#c0c0c0" : priceColor,
|
|
281
324
|
top: 0,
|
|
282
325
|
bottom: 0,
|
|
283
|
-
left:
|
|
326
|
+
left: isTrain
|
|
327
|
+
? "73%"
|
|
328
|
+
: "clamp(60%, 65% + (100vw - 1300px) * 0.1, 65%)",
|
|
284
329
|
right: 0,
|
|
285
330
|
justifyContent: isCentered ? "center" : "",
|
|
286
331
|
gap: "10px",
|
|
@@ -22,6 +22,7 @@ interface DateTimeSectionMobileProps {
|
|
|
22
22
|
tooltipBgColor?: string;
|
|
23
23
|
showLastSeats?: boolean;
|
|
24
24
|
discountSeatPriceColor?: string;
|
|
25
|
+
isTrain?: boolean;
|
|
25
26
|
}
|
|
26
|
-
declare function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, }: DateTimeSectionMobileProps): React.ReactElement;
|
|
27
|
+
declare function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, }: DateTimeSectionMobileProps): React.ReactElement;
|
|
27
28
|
export default DateTimeSectionMobile;
|
|
@@ -23,19 +23,21 @@ const getCleanedDepTime = (raw) => {
|
|
|
23
23
|
};
|
|
24
24
|
const TimeRow = ({ label, icon, alt, date, timeContent, isSoldOut, }) => {
|
|
25
25
|
const formattedDate = DateService.getServiceItemDate(date);
|
|
26
|
-
const dotPositionClass = formattedDate.includes("dom")
|
|
27
|
-
|
|
26
|
+
const dotPositionClass = formattedDate.includes("dom")
|
|
27
|
+
? "max-[399px]:left-[53%]"
|
|
28
|
+
: "";
|
|
29
|
+
return (React.createElement("div", { className: `flex items-center min-[420]:text-[13px] text-[12px] justify-between ${isSoldOut ? "text-[#c0c0c0]" : ""}` },
|
|
28
30
|
React.createElement("div", { className: "flex items-center", style: { flex: 1 } },
|
|
29
31
|
React.createElement("div", null,
|
|
30
32
|
" ",
|
|
31
33
|
label ? (React.createElement("div", { className: "w-[60px]" }, label)) : (React.createElement("div", { className: "w-[12px] h-auto mr-[5px]" },
|
|
32
34
|
React.createElement("img", { src: icon, alt: alt, className: `w-[12px] h-auto mr-[5px] ${isSoldOut ? "grayscale" : ""}` })))),
|
|
33
35
|
React.createElement("div", { className: "flex items-center relative capitalize justify-between", style: { flex: 1 } },
|
|
34
|
-
React.createElement("span", { className: "cursor-pointer black-text" }, formattedDate),
|
|
36
|
+
React.createElement("span", { className: "cursor-pointer black-text whitespace-nowrap" }, formattedDate),
|
|
35
37
|
React.createElement("div", { className: `absolute left-[50%] ${dotPositionClass}` }, "\u2022"),
|
|
36
|
-
React.createElement("div", { className: "font-[900] relative black-text" }, timeContent))));
|
|
38
|
+
React.createElement("div", { className: "font-[900] relative black-text whitespace-nowrap" }, timeContent)))));
|
|
37
39
|
};
|
|
38
|
-
function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, }) {
|
|
40
|
+
function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, }) {
|
|
39
41
|
const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
|
|
40
42
|
const depTimeContent = isLinatal ? (React.createElement("div", null,
|
|
41
43
|
React.createElement("span", null,
|
|
@@ -47,7 +49,11 @@ function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal
|
|
|
47
49
|
? null
|
|
48
50
|
: DateService.ampmOnly(depTime)))) : (DateService.formatTime(depTime));
|
|
49
51
|
return (React.createElement("div", { className: "flex justify-between gap-[5px] w-full", onClick: onBookButtonPress },
|
|
50
|
-
React.createElement("div", { className:
|
|
52
|
+
React.createElement("div", { className: `flex flex-col gap-[4px] w-[50%] ${isTrain ? "justify-center" : "justify-between"}`, style: {
|
|
53
|
+
justifyContent: isCiva && "center",
|
|
54
|
+
minHeight: isTrain ? undefined : "2.5rem",
|
|
55
|
+
alignSelf: isTrain ? "stretch" : undefined,
|
|
56
|
+
} },
|
|
51
57
|
React.createElement(TimeRow, { label: orignLabel, icon: originIcon, alt: "origin", date: travelDate, timeContent: depTimeContent, isSoldOut: isSoldOut }),
|
|
52
58
|
isCiva ? null : (React.createElement(TimeRow, { label: destinationLabel, icon: destinationIcon, alt: "destination", date: arrivalDate, timeContent: DateService.formatTime(arrTime), isSoldOut: isSoldOut }))),
|
|
53
59
|
React.createElement("div", { style: {
|
|
@@ -56,6 +62,6 @@ function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal
|
|
|
56
62
|
backgroundColor: "#ccc",
|
|
57
63
|
margin: "auto",
|
|
58
64
|
} }),
|
|
59
|
-
React.createElement(SeatSectionMobile, { seatTypes: seatTypes, isSoldOut: isSoldOut, isPeru: isPeru, seatPriceColor: seatPriceColor, currencySign: currencySign, availableSeats: availableSeats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, tooltipBgColor: tooltipBgColor, showLastSeats: showLastSeats, discountSeatPriceColor: discountSeatPriceColor })));
|
|
65
|
+
React.createElement(SeatSectionMobile, { seatTypes: seatTypes, isSoldOut: isSoldOut, isPeru: isPeru, seatPriceColor: seatPriceColor, currencySign: currencySign, availableSeats: availableSeats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, tooltipBgColor: tooltipBgColor, showLastSeats: showLastSeats, discountSeatPriceColor: discountSeatPriceColor, isTrain: isTrain })));
|
|
60
66
|
}
|
|
61
67
|
export default DateTimeSectionMobile;
|
|
@@ -16,6 +16,7 @@ interface SeatSectionMobileProps {
|
|
|
16
16
|
tooltipBgColor?: string;
|
|
17
17
|
showLastSeats?: boolean;
|
|
18
18
|
discountSeatPriceColor?: string;
|
|
19
|
+
isTrain?: boolean;
|
|
19
20
|
}
|
|
20
|
-
declare function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, }: SeatSectionMobileProps): React.ReactElement;
|
|
21
|
+
declare function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, }: SeatSectionMobileProps): React.ReactElement;
|
|
21
22
|
export default SeatSectionMobile;
|
|
@@ -11,7 +11,7 @@ const EXCEPTIONS = [
|
|
|
11
11
|
"blanco",
|
|
12
12
|
"asiento_mascota",
|
|
13
13
|
];
|
|
14
|
-
const SeatRow = ({ type, index, displayLabel, fare, isSoldOut, seatPriceColor, hasMultipleTypes, textSize, }) => {
|
|
14
|
+
const SeatRow = ({ type, index, displayLabel, fare, isSoldOut, seatPriceColor, hasMultipleTypes, textSize, isTrain, }) => {
|
|
15
15
|
if (EXCEPTIONS.includes(type.label))
|
|
16
16
|
return null;
|
|
17
17
|
const rowClass = hasMultipleTypes
|
|
@@ -20,7 +20,9 @@ const SeatRow = ({ type, index, displayLabel, fare, isSoldOut, seatPriceColor, h
|
|
|
20
20
|
const labelColor = isSoldOut ? "#bbb" : "#464647";
|
|
21
21
|
const priceColor = isSoldOut ? "#bbb" : seatPriceColor;
|
|
22
22
|
return (React.createElement("div", { className: rowClass, key: index },
|
|
23
|
-
React.createElement("span", { className: `min-[420]:text-[13px] ${textSize} `, style: { color: labelColor } },
|
|
23
|
+
React.createElement("span", { className: `min-[420]:text-[13px] ${textSize} `, style: { color: labelColor } }, isTrain
|
|
24
|
+
? commonService.truncateSeatLabel(commonService.capitalize(displayLabel), 8)
|
|
25
|
+
: displayLabel),
|
|
24
26
|
React.createElement("span", { className: `min-[420]:text-[13px] ${textSize} bold-text`, style: { color: priceColor } }, fare)));
|
|
25
27
|
};
|
|
26
28
|
const getFilteredSeats = (item) => {
|
|
@@ -42,8 +44,8 @@ const getUniqueSeats = (data, limit) => {
|
|
|
42
44
|
.sort((a, b) => a.fare - b.fare)
|
|
43
45
|
.slice(0, limit);
|
|
44
46
|
};
|
|
45
|
-
function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, }) {
|
|
46
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
47
|
+
function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, }) {
|
|
48
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
47
49
|
const hasMultipleTypes = ((_a = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.length) !== null && _a !== void 0 ? _a : 0) > 2;
|
|
48
50
|
const getFare = (fare) => {
|
|
49
51
|
if (removeDuplicateSeats && availableSeats <= 0 && !isPeru) {
|
|
@@ -72,7 +74,7 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
72
74
|
return (React.createElement(React.Fragment, null, uniqueSeats.map((seat, key) => {
|
|
73
75
|
const { discountedPrice } = commonService.calculateDiscountedPrice(Number(seat.fare), serviceItem);
|
|
74
76
|
return (React.createElement("div", { key: key, className: "w-[100%] flex flex-row justify-between items-center" },
|
|
75
|
-
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text", style: { color: isSoldOut ? "#bbb" : "#464647" } }, commonService.truncateSeatLabel(seat.label)),
|
|
77
|
+
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text whitespace-nowrap", style: { color: isSoldOut ? "#bbb" : "#464647" } }, commonService.truncateSeatLabel(seat.label)),
|
|
76
78
|
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text", style: { color: priceColor } }, commonService.currency(discountedPrice, currencySign))));
|
|
77
79
|
})));
|
|
78
80
|
}
|
|
@@ -117,19 +119,24 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
117
119
|
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] text-[#464647]", style: { opacity: isSoldOut ? 0.5 : 1 } }, "Agotado"))) : null));
|
|
118
120
|
};
|
|
119
121
|
const renderSeats = () => {
|
|
120
|
-
var _a, _b
|
|
122
|
+
var _a, _b;
|
|
121
123
|
if (isPeru) {
|
|
122
124
|
return renderPeruSeats();
|
|
123
125
|
}
|
|
124
126
|
if (removeDuplicateSeats) {
|
|
125
127
|
const uniqueSeats = getUniqueSeats(seatTypesData, 3);
|
|
126
|
-
return uniqueSeats.map((type, i) => (React.createElement(SeatRow, { key: i, type: type, index: i, displayLabel: commonService.truncateSeatLabel(type.label), fare: getFare(type.fare), isSoldOut: isSoldOut, seatPriceColor: seatPriceColor, hasMultipleTypes: hasMultipleTypes, textSize: "text-[11px]" })));
|
|
128
|
+
return uniqueSeats.map((type, i) => (React.createElement(SeatRow, { key: i, type: type, index: i, displayLabel: commonService.truncateSeatLabel(type.label), fare: getFare(type.fare), isSoldOut: isSoldOut, seatPriceColor: seatPriceColor, hasMultipleTypes: hasMultipleTypes, textSize: "text-[11px]", isTrain: isTrain })));
|
|
127
129
|
}
|
|
128
|
-
|
|
130
|
+
const filteredSeats = (_a = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.filter((item) => getFilteredSeats(item.label))) === null || _a === void 0 ? void 0 : _a.sort((a, b) => a.fare - b.fare);
|
|
131
|
+
return (_b = (isTrain ? filteredSeats : filteredSeats === null || filteredSeats === void 0 ? void 0 : filteredSeats.slice(0, 2))) === null || _b === void 0 ? void 0 : _b.map((type, i) => (React.createElement(SeatRow, { key: i, type: type, index: i, displayLabel: type.label, fare: getFare(type.fare), isSoldOut: isSoldOut, seatPriceColor: seatPriceColor, hasMultipleTypes: hasMultipleTypes, textSize: "text-[12px]", isTrain: isTrain })));
|
|
129
132
|
};
|
|
130
133
|
const seats = removeDuplicateSeats
|
|
131
134
|
? getUniqueSeats(seatTypesData, 3)
|
|
132
|
-
: (
|
|
135
|
+
: (() => {
|
|
136
|
+
var _a;
|
|
137
|
+
const filtered = (_a = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.filter((item) => getFilteredSeats(item.label))) === null || _a === void 0 ? void 0 : _a.sort((a, b) => a.fare - b.fare);
|
|
138
|
+
return isTrain ? filtered : filtered === null || filtered === void 0 ? void 0 : filtered.slice(0, 2);
|
|
139
|
+
})();
|
|
133
140
|
const discountedSeats = seats === null || seats === void 0 ? void 0 : seats.map((seat) => (Object.assign(Object.assign({}, seat), commonService.calculateDiscountedPrice(seat.fare, serviceItem))));
|
|
134
141
|
const peruLowestFare = isPeru ? getLowestFare() : null;
|
|
135
142
|
const peruDiscountCalc = isPeru && peruLowestFare != null
|
|
@@ -140,7 +147,7 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
140
147
|
peruDiscountCalc.originalPrice !== peruDiscountCalc.discountedPrice
|
|
141
148
|
: discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.some((s) => s.originalPrice !== s.discountedPrice);
|
|
142
149
|
const discountSeat = isPeru && peruDiscountCalc
|
|
143
|
-
? Object.assign({ label: "", fare: peruLowestFare }, peruDiscountCalc) : (
|
|
150
|
+
? Object.assign({ label: "", fare: peruLowestFare }, peruDiscountCalc) : (_b = discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.filter((seat) => !EXCEPTIONS.includes(seat.label))) === null || _b === void 0 ? void 0 : _b.sort((a, b) => a.discountedPrice - b.discountedPrice)[0];
|
|
144
151
|
const discountValue = (() => {
|
|
145
152
|
if ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_type) === "percentage" &&
|
|
146
153
|
typeof (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_value) === "number") {
|
|
@@ -154,6 +161,19 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
154
161
|
}
|
|
155
162
|
return null;
|
|
156
163
|
})();
|
|
164
|
+
// Hide the % OFF badge when max_discount is capping the percentage discount
|
|
165
|
+
const isMaxDiscountApplied = (() => {
|
|
166
|
+
const { discount_type, discount_value, max_discount } = serviceItem !== null && serviceItem !== void 0 ? serviceItem : {};
|
|
167
|
+
if (discount_type === "percentage" &&
|
|
168
|
+
typeof discount_value === "number" &&
|
|
169
|
+
max_discount != null &&
|
|
170
|
+
max_discount > 0 &&
|
|
171
|
+
discountSeat) {
|
|
172
|
+
const rawPercentageDiscount = (discountSeat.originalPrice * discount_value) / 100;
|
|
173
|
+
return rawPercentageDiscount > max_discount;
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
176
|
+
})();
|
|
157
177
|
const getMinValue = (data) => {
|
|
158
178
|
const vals = (Array.isArray(data) ? data : Object.values(data || {})).map(Number);
|
|
159
179
|
if (!vals.length)
|
|
@@ -163,14 +183,14 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
163
183
|
};
|
|
164
184
|
const originalDpPrice = getMinValue(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.original_dp_price);
|
|
165
185
|
const dpDiscountPercent = getMinValue(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents);
|
|
166
|
-
const firstSeatFare = (
|
|
186
|
+
const firstSeatFare = (_d = (_c = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.filter((item) => getFilteredSeats(item.label) && !EXCEPTIONS.includes(item.label))) === null || _c === void 0 ? void 0 : _c.sort((a, b) => a.fare - b.fare)[0]) === null || _d === void 0 ? void 0 : _d.fare;
|
|
167
187
|
const hasDpDiscount = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) &&
|
|
168
188
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) &&
|
|
169
189
|
originalDpPrice != null &&
|
|
170
190
|
dpDiscountPercent != null &&
|
|
171
191
|
firstSeatFare != null;
|
|
172
192
|
return (React.createElement("div", { className: "content-center relative", style: { width: "40%" } }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) &&
|
|
173
|
-
!((
|
|
193
|
+
!((_e = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) === null || _e === void 0 ? void 0 : _e.length) &&
|
|
174
194
|
!dpDiscountPercent ? (React.createElement("div", { className: "flex flex-col justify-between h-[2.5rem]", style: { gap: isSoldOut ? "0px" : "5px" } }, renderDpSeats())) : hasDpDiscount ? (React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
|
|
175
195
|
!isNaN(Number(dpDiscountPercent)) &&
|
|
176
196
|
Number(dpDiscountPercent) > 0 && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
|
|
@@ -202,11 +222,11 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
202
222
|
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
|
|
203
223
|
color: isSoldOut ? "#bbb" : discountSeatPriceColor || "#ff5964",
|
|
204
224
|
} },
|
|
205
|
-
((
|
|
225
|
+
((_f = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _f === void 0 ? void 0 : _f.fireIcon) ? (React.createElement("img", { src: serviceItem.icons.fireIcon, alt: "discount", className: "h-[16px] w-[16px] object-contain", style: { filter: isSoldOut ? "grayscale" : "" } })) : null,
|
|
206
226
|
commonService.discountedCurrency(Number(firstSeatFare), currencySign)),
|
|
207
227
|
isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)) : hasDiscount && discountSeat ? (React.createElement("div", null,
|
|
208
228
|
React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
|
|
209
|
-
discountValue != null && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
|
|
229
|
+
discountValue != null && !isMaxDiscountApplied && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
|
|
210
230
|
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
211
231
|
opacity: isSoldOut ? 0.5 : 1,
|
|
212
232
|
} },
|
|
@@ -236,8 +256,8 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
236
256
|
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
|
|
237
257
|
color: isSoldOut ? "#bbb" : discountSeatPriceColor || "#ff5964",
|
|
238
258
|
} },
|
|
239
|
-
((
|
|
240
|
-
commonService.discountedCurrency(discountSeat.discountedPrice, currencySign))))) : (React.createElement("div", { className:
|
|
259
|
+
((_g = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _g === void 0 ? void 0 : _g.fireIcon) ? (React.createElement("img", { src: serviceItem.icons.fireIcon, alt: "discount", className: "h-[16px] w-[16px] object-contain", style: { opacity: isSoldOut ? 0.5 : 1 } })) : null,
|
|
260
|
+
commonService.discountedCurrency(discountSeat.discountedPrice, currencySign))))) : (React.createElement("div", { className: `flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `, style: {
|
|
241
261
|
gap: isSoldOut ? "0px" : "5px",
|
|
242
262
|
justifyContent: hasMultipleTypes ? "space-between" : "center",
|
|
243
263
|
} },
|
|
@@ -3,7 +3,7 @@ declare const commonService: {
|
|
|
3
3
|
discountedCurrency(amount: number, currencySign?: string): string;
|
|
4
4
|
copyObject: (ob: any) => any;
|
|
5
5
|
getServiceTypeLabelForFilters: (service_type: any) => "Tipo de servicio" | "Punto de embarque" | "Tipo de asiento" | "SERVICIOS" | "";
|
|
6
|
-
truncateSeatLabel: (label: string | number) => string;
|
|
6
|
+
truncateSeatLabel: (label: string | number, maxLength?: number) => string;
|
|
7
7
|
getAmenitiesImage: (name: string, serviceItem: any) => string;
|
|
8
8
|
getAmenityName: (rawAmenity: string) => string;
|
|
9
9
|
getSeatNameForFilters: (rawSeat: any) => any;
|
|
@@ -34,11 +34,15 @@ const commonService = {
|
|
|
34
34
|
return "";
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
|
-
truncateSeatLabel: (label) => {
|
|
37
|
+
truncateSeatLabel: (label, maxLength) => {
|
|
38
38
|
if (typeof label !== "string")
|
|
39
39
|
return String(label);
|
|
40
40
|
if (label.includes("("))
|
|
41
41
|
return label;
|
|
42
|
+
// If maxLength provided, hard-truncate regardless of word count
|
|
43
|
+
if (maxLength != null && label.length > maxLength) {
|
|
44
|
+
return label.slice(0, maxLength) + "...";
|
|
45
|
+
}
|
|
42
46
|
const words = label.trim().split(/\s+/);
|
|
43
47
|
const truncateWord = (word) => word.length > 5 ? word.slice(0, 3) + "..." : word;
|
|
44
48
|
if (words.length === 1)
|