kupos-ui-components-lib 9.11.2 → 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 +21 -4
- 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 +44 -13
- 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 +22 -15
- 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 +46 -2
- 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 +95 -23
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +47 -34
- package/src/ui/mobileweb/SeatSectionMobile.tsx +27 -12
- 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];
|
|
@@ -246,6 +249,16 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
246
249
|
});
|
|
247
250
|
return;
|
|
248
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
|
+
}
|
|
249
262
|
onBookButtonPress();
|
|
250
263
|
};
|
|
251
264
|
const items = [
|
|
@@ -300,7 +313,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
300
313
|
? "14px"
|
|
301
314
|
: "",
|
|
302
315
|
} },
|
|
303
|
-
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` },
|
|
304
317
|
React.createElement("div", { className: "flex flex-col gap-[5px]" },
|
|
305
318
|
React.createElement("div", null,
|
|
306
319
|
React.createElement("img", { src: serviceItem.operator_details[0], alt: "service logo", className: `h-[30px] w-[auto] ${isSoldOut ? "grayscale" : ""}` }),
|
|
@@ -313,9 +326,13 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
313
326
|
backgroundColor: "#ccc",
|
|
314
327
|
} }),
|
|
315
328
|
React.createElement("div", { className: "content-center" },
|
|
316
|
-
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 })),
|
|
317
330
|
React.createElement("div", { className: "relative" },
|
|
318
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"))),
|
|
319
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 &&
|
|
320
337
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[12px] mt-1 text-center", style: {
|
|
321
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,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
126
154
|
}
|
|
127
155
|
return null;
|
|
128
156
|
})();
|
|
157
|
+
console.log("🚀 ~ SeatSection ~ serviceItem:", serviceItem);
|
|
129
158
|
// Hide the % OFF badge when max_discount is capping the percentage discount
|
|
130
159
|
// (i.e. both percentage and max_discount exist, and the raw % amount exceeds the cap)
|
|
131
160
|
const isMaxDiscountApplied = (() => {
|
|
@@ -162,7 +191,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
162
191
|
hasDiscount && (React.createElement("span", { className: "text-[13.33px]", style: {
|
|
163
192
|
color: "#999",
|
|
164
193
|
} }, "Antes")),
|
|
165
|
-
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")))));
|
|
166
195
|
}
|
|
167
196
|
return renderSeatNames();
|
|
168
197
|
};
|
|
@@ -264,7 +293,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
264
293
|
discountValue,
|
|
265
294
|
"% OFF"))),
|
|
266
295
|
React.createElement("div", { className: "col-start-2 row-start-2 flex items-center justify-center ", style: { textAlign: "center" } },
|
|
267
|
-
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: {
|
|
268
297
|
position: "relative",
|
|
269
298
|
} },
|
|
270
299
|
formatPrice(discountSeat.originalPrice),
|
|
@@ -294,7 +323,9 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
294
323
|
color: isSoldOut ? "#c0c0c0" : priceColor,
|
|
295
324
|
top: 0,
|
|
296
325
|
bottom: 0,
|
|
297
|
-
left:
|
|
326
|
+
left: isTrain
|
|
327
|
+
? "73%"
|
|
328
|
+
: "clamp(60%, 65% + (100vw - 1300px) * 0.1, 65%)",
|
|
298
329
|
right: 0,
|
|
299
330
|
justifyContent: isCentered ? "center" : "",
|
|
300
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") {
|
|
@@ -176,14 +183,14 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
176
183
|
};
|
|
177
184
|
const originalDpPrice = getMinValue(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.original_dp_price);
|
|
178
185
|
const dpDiscountPercent = getMinValue(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents);
|
|
179
|
-
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;
|
|
180
187
|
const hasDpDiscount = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) &&
|
|
181
188
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) &&
|
|
182
189
|
originalDpPrice != null &&
|
|
183
190
|
dpDiscountPercent != null &&
|
|
184
191
|
firstSeatFare != null;
|
|
185
192
|
return (React.createElement("div", { className: "content-center relative", style: { width: "40%" } }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) &&
|
|
186
|
-
!((
|
|
193
|
+
!((_e = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) === null || _e === void 0 ? void 0 : _e.length) &&
|
|
187
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] " },
|
|
188
195
|
!isNaN(Number(dpDiscountPercent)) &&
|
|
189
196
|
Number(dpDiscountPercent) > 0 && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
|
|
@@ -215,7 +222,7 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
215
222
|
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
|
|
216
223
|
color: isSoldOut ? "#bbb" : discountSeatPriceColor || "#ff5964",
|
|
217
224
|
} },
|
|
218
|
-
((
|
|
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,
|
|
219
226
|
commonService.discountedCurrency(Number(firstSeatFare), currencySign)),
|
|
220
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,
|
|
221
228
|
React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
|
|
@@ -249,8 +256,8 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
249
256
|
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
|
|
250
257
|
color: isSoldOut ? "#bbb" : discountSeatPriceColor || "#ff5964",
|
|
251
258
|
} },
|
|
252
|
-
((
|
|
253
|
-
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: {
|
|
254
261
|
gap: isSoldOut ? "0px" : "5px",
|
|
255
262
|
justifyContent: hasMultipleTypes ? "space-between" : "center",
|
|
256
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)
|
package/package.json
CHANGED
|
@@ -131,6 +131,13 @@ function ServiceItemPB({
|
|
|
131
131
|
showLoginModal,
|
|
132
132
|
isLoggedIn,
|
|
133
133
|
showLoginOption,
|
|
134
|
+
isTrain,
|
|
135
|
+
selectedSeatKey,
|
|
136
|
+
onSeatSelect,
|
|
137
|
+
onTrainButtonClick,
|
|
138
|
+
showSeatSelectionError,
|
|
139
|
+
onShowSeatSelectionError,
|
|
140
|
+
onClearSeatSelectionError,
|
|
134
141
|
isFeatureDropDownExpand,
|
|
135
142
|
setIsFeatureDropDownExpand,
|
|
136
143
|
ticketQuantity,
|
|
@@ -145,7 +152,15 @@ function ServiceItemPB({
|
|
|
145
152
|
isFlores,
|
|
146
153
|
operatorLabel,
|
|
147
154
|
}: ServiceItemProps & { currencySign?: string }): React.ReactElement {
|
|
148
|
-
|
|
155
|
+
const handleSeatSelect = (
|
|
156
|
+
key: any,
|
|
157
|
+
price: number,
|
|
158
|
+
seatKey: string,
|
|
159
|
+
apiSeatType?: string,
|
|
160
|
+
) => {
|
|
161
|
+
onClearSeatSelectionError?.();
|
|
162
|
+
onSeatSelect?.(key, price, seatKey, apiSeatType);
|
|
163
|
+
};
|
|
149
164
|
const getAnimationIcon = (icon: string) => {
|
|
150
165
|
const animation = ANIMATION_MAP[icon];
|
|
151
166
|
if (!animation) return null;
|
|
@@ -367,6 +382,17 @@ function ServiceItemPB({
|
|
|
367
382
|
return;
|
|
368
383
|
}
|
|
369
384
|
|
|
385
|
+
if (isTrain) {
|
|
386
|
+
if (!selectedSeatKey) {
|
|
387
|
+
onShowSeatSelectionError?.(serviceItem.id);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (onTrainButtonClick) {
|
|
391
|
+
onTrainButtonClick();
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
370
396
|
onBookButtonPress();
|
|
371
397
|
};
|
|
372
398
|
|
|
@@ -559,7 +585,9 @@ function ServiceItemPB({
|
|
|
559
585
|
: "",
|
|
560
586
|
}}
|
|
561
587
|
>
|
|
562
|
-
<div
|
|
588
|
+
<div
|
|
589
|
+
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`}
|
|
590
|
+
>
|
|
563
591
|
{/* OPERATOR LOGO */}
|
|
564
592
|
<div className="flex flex-col gap-[5px]">
|
|
565
593
|
<div>
|
|
@@ -621,6 +649,10 @@ function ServiceItemPB({
|
|
|
621
649
|
isPeru={isPeru}
|
|
622
650
|
renderIcon={renderIcon}
|
|
623
651
|
discountSeatPriceColor={colors.discountSeatPriceColor}
|
|
652
|
+
isTrain={isTrain}
|
|
653
|
+
selectedSeatKey={selectedSeatKey}
|
|
654
|
+
onSeatSelect={handleSeatSelect}
|
|
655
|
+
topLabelColor={colors.topLabelColor}
|
|
624
656
|
tooltipColor={colors.tooltipColor}
|
|
625
657
|
/>
|
|
626
658
|
</div>
|
|
@@ -637,6 +669,18 @@ function ServiceItemPB({
|
|
|
637
669
|
soldOutIcon={renderIcon("soldOutIcon", "14px")}
|
|
638
670
|
onClick={checkMidnight}
|
|
639
671
|
/>
|
|
672
|
+
{showSeatSelectionError === serviceItem.id && isTrain && (
|
|
673
|
+
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
|
|
674
|
+
<div
|
|
675
|
+
className="text-[9px] text-center whitespace-nowrap"
|
|
676
|
+
style={{
|
|
677
|
+
color: colors.seatPriceColor,
|
|
678
|
+
}}
|
|
679
|
+
>
|
|
680
|
+
Selecciona el tipo de servicio
|
|
681
|
+
</div>
|
|
682
|
+
</div>
|
|
683
|
+
)}
|
|
640
684
|
{showLastSeats ? (
|
|
641
685
|
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
|
|
642
686
|
{serviceItem?.available_seats < 10 &&
|
|
@@ -46,6 +46,8 @@ function ServiceItemMobile({
|
|
|
46
46
|
removeDuplicateSeats,
|
|
47
47
|
isLinatal,
|
|
48
48
|
viewersConfig,
|
|
49
|
+
operatorLabel,
|
|
50
|
+
isTrain,
|
|
49
51
|
isFeatureDropDownExpand,
|
|
50
52
|
setIsFeatureDropDownExpand,
|
|
51
53
|
ticketQuantity,
|
|
@@ -61,7 +63,6 @@ function ServiceItemMobile({
|
|
|
61
63
|
onTimeDropdownToggle,
|
|
62
64
|
wowDealData,
|
|
63
65
|
isFlores,
|
|
64
|
-
operatorLabel
|
|
65
66
|
}: MobileServiceItemProps): React.ReactElement {
|
|
66
67
|
const isItemExpanded = serviceItem.id === isExpanded;
|
|
67
68
|
const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
|
|
@@ -135,36 +135,36 @@ export interface MobileServiceItemProps {
|
|
|
135
135
|
bombAnim?: string;
|
|
136
136
|
whiteBoardingIcon?: string;
|
|
137
137
|
downArrow?: string;
|
|
138
|
-
personIcon?: string
|
|
138
|
+
personIcon?: string;
|
|
139
139
|
specialDeparture?: string;
|
|
140
140
|
fireIcon?: string;
|
|
141
141
|
directoIcon?: string;
|
|
142
|
-
whiteFireIcon?: string
|
|
143
|
-
femaleAnim?:string
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
whiteDestination?: string
|
|
148
|
-
userIcon?: string
|
|
149
|
-
|
|
150
|
-
sheildIcon?: string
|
|
151
|
-
busIcon?: string
|
|
152
|
-
whiteDownArrow?: string
|
|
153
|
-
empressaIcon?: string
|
|
154
|
-
flexibleIcon?: string
|
|
155
|
-
listoIcon?: string
|
|
156
|
-
precioIcon?: string
|
|
157
|
-
confirmarIcon?: string
|
|
142
|
+
whiteFireIcon?: string;
|
|
143
|
+
femaleAnim?: string;
|
|
144
|
+
thunderAnim?: string;
|
|
145
|
+
personsAnim?: string;
|
|
146
|
+
whiteOrigin?: string;
|
|
147
|
+
whiteDestination?: string;
|
|
148
|
+
userIcon?: string;
|
|
149
|
+
|
|
150
|
+
sheildIcon?: string;
|
|
151
|
+
busIcon?: string;
|
|
152
|
+
whiteDownArrow?: string;
|
|
153
|
+
empressaIcon?: string;
|
|
154
|
+
flexibleIcon?: string;
|
|
155
|
+
listoIcon?: string;
|
|
156
|
+
precioIcon?: string;
|
|
157
|
+
confirmarIcon?: string;
|
|
158
158
|
cancelTicketIcon?: string;
|
|
159
159
|
changeTicketIcon?: string;
|
|
160
160
|
petFriendlyIcon?: string;
|
|
161
|
-
womenSeatIcon?: string
|
|
161
|
+
womenSeatIcon?: string;
|
|
162
162
|
[key: string]: string | Record<string, string | undefined> | undefined;
|
|
163
163
|
};
|
|
164
164
|
useLottieFor?: string[];
|
|
165
165
|
};
|
|
166
166
|
onBookButtonPress?: () => void;
|
|
167
|
-
onRemateUiButtonClick?: ()=> void;
|
|
167
|
+
onRemateUiButtonClick?: () => void;
|
|
168
168
|
terminals?: any[];
|
|
169
169
|
showDropdown?: boolean;
|
|
170
170
|
setShowDropdown?: (value: boolean) => void;
|
|
@@ -208,7 +208,7 @@ export interface MobileServiceItemProps {
|
|
|
208
208
|
seatPriceColor?: string;
|
|
209
209
|
rightGradiantColor?: string;
|
|
210
210
|
leftGradiantColor?: string;
|
|
211
|
-
discountSeatPriceColor?: string
|
|
211
|
+
discountSeatPriceColor?: string;
|
|
212
212
|
};
|
|
213
213
|
isCiva?: boolean;
|
|
214
214
|
currencySign?: string;
|
|
@@ -221,23 +221,28 @@ export interface MobileServiceItemProps {
|
|
|
221
221
|
showLastSeats?: boolean;
|
|
222
222
|
removeDuplicateSeats?: boolean;
|
|
223
223
|
isLinatal?: boolean;
|
|
224
|
-
|
|
224
|
+
viewersConfig?: {
|
|
225
225
|
min: number;
|
|
226
226
|
max: number;
|
|
227
227
|
interval?: number; // ms, default 5000
|
|
228
228
|
label?: string; // e.g. "personas están viendo este viaje"
|
|
229
229
|
icon?: string; // optional icon URL
|
|
230
230
|
};
|
|
231
|
-
|
|
231
|
+
isTrain?: boolean;
|
|
232
|
+
isFeatureDropDownExpand?: any;
|
|
232
233
|
setIsFeatureDropDownExpand?: (value: any) => void;
|
|
233
234
|
ticketQuantity?: number;
|
|
234
|
-
onIncreaseTicketQuantity?: (
|
|
235
|
-
|
|
235
|
+
onIncreaseTicketQuantity?: (
|
|
236
|
+
serviceItem: MobileServiceItemProps["serviceItem"],
|
|
237
|
+
) => void;
|
|
238
|
+
onDecreaseTicketQuantity?: (
|
|
239
|
+
serviceItem: MobileServiceItemProps["serviceItem"],
|
|
240
|
+
) => void;
|
|
236
241
|
cityOrigin?: { value: number; label: string };
|
|
237
242
|
cityDestination?: { value: number; label: string };
|
|
238
|
-
|
|
243
|
+
isNewUi?: boolean;
|
|
239
244
|
|
|
240
|
-
|
|
245
|
+
selectedTimeSlot?: string;
|
|
241
246
|
onTimeSlotChange?: (slot: string) => void;
|
|
242
247
|
isTimeDropdownOpen?: string | number | null;
|
|
243
248
|
onTimeDropdownToggle?: (id?: string | number | null) => void;
|
|
@@ -252,6 +252,18 @@ export interface ServiceItemProps {
|
|
|
252
252
|
showLoginModal?: any;
|
|
253
253
|
isLoggedIn?: any;
|
|
254
254
|
showLoginOption?: boolean;
|
|
255
|
+
isTrain?: boolean;
|
|
256
|
+
selectedSeatKey?: any;
|
|
257
|
+
onSeatSelect?: (
|
|
258
|
+
key: any,
|
|
259
|
+
price: number,
|
|
260
|
+
seatKey: string,
|
|
261
|
+
apiSeatType?: string,
|
|
262
|
+
) => void;
|
|
263
|
+
onTrainButtonClick?: any;
|
|
264
|
+
showSeatSelectionError?: string | null;
|
|
265
|
+
onShowSeatSelectionError?: (serviceId: string) => void;
|
|
266
|
+
onClearSeatSelectionError?: () => void;
|
|
255
267
|
selectedTimeSlot?: string;
|
|
256
268
|
onTimeSlotChange?: (slot: string) => void;
|
|
257
269
|
isTimeDropdownOpen?: string | number | null;
|
|
@@ -119,7 +119,7 @@ function DateTimeSection({
|
|
|
119
119
|
metaData={metaData}
|
|
120
120
|
colors={colors}
|
|
121
121
|
>
|
|
122
|
-
<span className="cursor-pointer bold-text capitalize">
|
|
122
|
+
<span className="cursor-pointer bold-text capitalize whitespace-nowrap">
|
|
123
123
|
{DateService.getServiceItemDate(serviceItem.travel_date)}
|
|
124
124
|
</span>
|
|
125
125
|
</StageTooltip>
|
|
@@ -134,7 +134,7 @@ function DateTimeSection({
|
|
|
134
134
|
metaData={metaData}
|
|
135
135
|
colors={colors}
|
|
136
136
|
>
|
|
137
|
-
<span className="cursor-pointer bold-text capitalize">
|
|
137
|
+
<span className="cursor-pointer bold-text capitalize whitespace-nowrap">
|
|
138
138
|
{DateService.getServiceItemDate(serviceItem.arrival_date)}
|
|
139
139
|
</span>
|
|
140
140
|
</StageTooltip>
|
|
@@ -169,7 +169,7 @@ function DateTimeSection({
|
|
|
169
169
|
metaData={metaData}
|
|
170
170
|
colors={colors}
|
|
171
171
|
>
|
|
172
|
-
<div className="font-[900] bold-text">
|
|
172
|
+
<div className="font-[900] bold-text whitespace-nowrap">
|
|
173
173
|
{isLinatal ? (
|
|
174
174
|
<>
|
|
175
175
|
{cleanedDepTime} <span>{hasPM ? "PM" : hasAM ? "AM" : ""}</span>
|
|
@@ -193,7 +193,7 @@ function DateTimeSection({
|
|
|
193
193
|
metaData={metaData}
|
|
194
194
|
colors={colors}
|
|
195
195
|
>
|
|
196
|
-
<div className="font-[900] bold-text">
|
|
196
|
+
<div className="font-[900] bold-text whitespace-nowrap">
|
|
197
197
|
{removeArrivalTime
|
|
198
198
|
? "\u00A0"
|
|
199
199
|
: serviceItem.arr_time
|
|
@@ -7,6 +7,8 @@ interface SeatType {
|
|
|
7
7
|
label: string;
|
|
8
8
|
fare: number;
|
|
9
9
|
key: any;
|
|
10
|
+
apiSeatType?: string;
|
|
11
|
+
api_seat_type?: string;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
interface SeatSectionProps {
|
|
@@ -21,6 +23,15 @@ interface SeatSectionProps {
|
|
|
21
23
|
serviceItem?: any;
|
|
22
24
|
renderIcon?: (iconKey: string, size?: string) => React.ReactNode;
|
|
23
25
|
discountSeatPriceColor?: string;
|
|
26
|
+
isTrain?: boolean;
|
|
27
|
+
selectedSeatKey?: any;
|
|
28
|
+
onSeatSelect?: (
|
|
29
|
+
key: any,
|
|
30
|
+
price: number,
|
|
31
|
+
seatKey: string,
|
|
32
|
+
apiSeatType?: string,
|
|
33
|
+
) => void;
|
|
34
|
+
topLabelColor?: string;
|
|
24
35
|
tooltipColor?: string;
|
|
25
36
|
}
|
|
26
37
|
|
|
@@ -32,6 +43,8 @@ function getAllSeatTypes(seatTypes: SeatType[]) {
|
|
|
32
43
|
let seatTypesWithPrices = seatTypes.filter(Boolean).map((val) => ({
|
|
33
44
|
label: val?.label,
|
|
34
45
|
price: val?.fare,
|
|
46
|
+
key: val?.key,
|
|
47
|
+
apiSeatType: val?.apiSeatType || val?.api_seat_type,
|
|
35
48
|
}));
|
|
36
49
|
|
|
37
50
|
seatTypesWithPrices.sort((a, b) => a.price - b.price);
|
|
@@ -39,7 +52,7 @@ function getAllSeatTypes(seatTypes: SeatType[]) {
|
|
|
39
52
|
return seatTypesWithPrices;
|
|
40
53
|
}
|
|
41
54
|
|
|
42
|
-
function getSortedSeatTypes(seatTypes: SeatType[]) {
|
|
55
|
+
function getSortedSeatTypes(seatTypes: SeatType[], isTrain: any) {
|
|
43
56
|
if (!seatTypes?.length) {
|
|
44
57
|
return [{ label: "Salon cama", price: 0 }];
|
|
45
58
|
}
|
|
@@ -53,7 +66,9 @@ function getSortedSeatTypes(seatTypes: SeatType[]) {
|
|
|
53
66
|
seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
|
|
54
67
|
}
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
if (!isTrain) {
|
|
70
|
+
seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
|
|
71
|
+
}
|
|
57
72
|
|
|
58
73
|
const seenPrices = new Set<number>();
|
|
59
74
|
seatTypesWithPrices = seatTypesWithPrices.filter((seat) => {
|
|
@@ -98,16 +113,19 @@ function SeatSection({
|
|
|
98
113
|
priceColor,
|
|
99
114
|
currencySign,
|
|
100
115
|
removeDuplicateSeats,
|
|
116
|
+
selectedSeatKey,
|
|
117
|
+
onSeatSelect,
|
|
101
118
|
isPeru,
|
|
102
119
|
serviceItem,
|
|
103
120
|
renderIcon,
|
|
104
121
|
dpSeatColor,
|
|
105
122
|
discountSeatPriceColor,
|
|
123
|
+
isTrain,
|
|
124
|
+
topLabelColor,
|
|
106
125
|
tooltipColor,
|
|
107
126
|
}: SeatSectionProps): React.ReactElement {
|
|
108
127
|
const uniqueSeats = getUniqueSeats(seatTypes);
|
|
109
|
-
const sortedSeatTypes = getSortedSeatTypes(seatTypes);
|
|
110
|
-
console.log("🚀 ~ SeatSection ~ sortedSeatTypes:", sortedSeatTypes);
|
|
128
|
+
const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
|
|
111
129
|
const numberOfSeats = getNumberOfSeats(seatTypes);
|
|
112
130
|
const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
|
|
113
131
|
|
|
@@ -119,22 +137,68 @@ function SeatSection({
|
|
|
119
137
|
const renderSeatNames = () => {
|
|
120
138
|
const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
|
|
121
139
|
|
|
122
|
-
return seats.map((val, key: number) =>
|
|
123
|
-
SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
140
|
+
return seats.map((val, key: number) => {
|
|
141
|
+
return SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
142
|
+
<div
|
|
143
|
+
className="flex items-center"
|
|
144
|
+
style={isTrain ? { cursor: "pointer" } : undefined}
|
|
145
|
+
onClick={
|
|
146
|
+
isTrain && !isSoldOut
|
|
147
|
+
? () =>
|
|
148
|
+
val.label === selectedSeatKey
|
|
149
|
+
? onSeatSelect?.(null, 0, "", "")
|
|
150
|
+
: onSeatSelect?.(
|
|
151
|
+
val.label,
|
|
152
|
+
val.price,
|
|
153
|
+
val.key,
|
|
154
|
+
(val as any).apiSeatType,
|
|
155
|
+
)
|
|
156
|
+
: undefined
|
|
157
|
+
}
|
|
129
158
|
>
|
|
130
|
-
{
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
159
|
+
{isTrain && (
|
|
160
|
+
<div
|
|
161
|
+
style={{
|
|
162
|
+
border: `1px solid ${val.label === selectedSeatKey ? topLabelColor : "#ccc"}`,
|
|
163
|
+
borderRadius: "50%",
|
|
164
|
+
width: "14px",
|
|
165
|
+
height: "14px",
|
|
166
|
+
minWidth: "14px",
|
|
167
|
+
marginRight: "10px",
|
|
168
|
+
display: "flex",
|
|
169
|
+
alignItems: "center",
|
|
170
|
+
justifyContent: "center",
|
|
171
|
+
}}
|
|
172
|
+
>
|
|
173
|
+
{val.label === selectedSeatKey && (
|
|
174
|
+
<div
|
|
175
|
+
style={{
|
|
176
|
+
backgroundColor: topLabelColor,
|
|
177
|
+
borderRadius: "50%",
|
|
178
|
+
width: "7px",
|
|
179
|
+
height: "7px",
|
|
180
|
+
}}
|
|
181
|
+
/>
|
|
182
|
+
)}
|
|
183
|
+
</div>
|
|
184
|
+
)}
|
|
185
|
+
<span
|
|
186
|
+
key={key}
|
|
187
|
+
className={`flex items-center justify-between text-[13.33px] whitespace-nowrap ${
|
|
188
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
189
|
+
}`}
|
|
190
|
+
>
|
|
191
|
+
{typeof val.label === "string" || typeof val.label === "number"
|
|
192
|
+
? removeDuplicateSeats && isPeru
|
|
193
|
+
? CommonService.truncateSeatLabel(val.label)
|
|
194
|
+
: isTrain
|
|
195
|
+
? CommonService.capitalize(String(val.label))
|
|
196
|
+
: val.label
|
|
197
|
+
: null}
|
|
198
|
+
</span>
|
|
199
|
+
</div>
|
|
200
|
+
);
|
|
201
|
+
});
|
|
138
202
|
};
|
|
139
203
|
|
|
140
204
|
const renderSeatPrices = () => {
|
|
@@ -151,7 +215,10 @@ function SeatSection({
|
|
|
151
215
|
serviceItem,
|
|
152
216
|
);
|
|
153
217
|
return (
|
|
154
|
-
<span
|
|
218
|
+
<span
|
|
219
|
+
key={key}
|
|
220
|
+
className="flex items-center text-[13.33px] bold-text"
|
|
221
|
+
>
|
|
155
222
|
{formatPrice(discountedPrice)}
|
|
156
223
|
</span>
|
|
157
224
|
);
|
|
@@ -235,6 +302,7 @@ function SeatSection({
|
|
|
235
302
|
}
|
|
236
303
|
return null;
|
|
237
304
|
})();
|
|
305
|
+
console.log("🚀 ~ SeatSection ~ serviceItem:", serviceItem);
|
|
238
306
|
|
|
239
307
|
// Hide the % OFF badge when max_discount is capping the percentage discount
|
|
240
308
|
// (i.e. both percentage and max_discount exist, and the raw % amount exceeds the cap)
|
|
@@ -304,7 +372,9 @@ function SeatSection({
|
|
|
304
372
|
|
|
305
373
|
<span className="text-[13.33px] flex flex-col">
|
|
306
374
|
{operatorServiceName ? (
|
|
307
|
-
<span className="text-[13.33px]">
|
|
375
|
+
<span className="text-[13.33px] whitespace-nowrap">
|
|
376
|
+
{seatLabel}
|
|
377
|
+
</span>
|
|
308
378
|
) : (
|
|
309
379
|
<span className="text-[13.33px]">Desde</span>
|
|
310
380
|
)}
|
|
@@ -527,7 +597,7 @@ function SeatSection({
|
|
|
527
597
|
style={{ textAlign: "center" }}
|
|
528
598
|
>
|
|
529
599
|
<span
|
|
530
|
-
className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative"
|
|
600
|
+
className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative whitespace-nowrap"
|
|
531
601
|
style={{
|
|
532
602
|
position: "relative",
|
|
533
603
|
}}
|
|
@@ -589,7 +659,9 @@ function SeatSection({
|
|
|
589
659
|
color: isSoldOut ? "#c0c0c0" : priceColor,
|
|
590
660
|
top: 0,
|
|
591
661
|
bottom: 0,
|
|
592
|
-
left:
|
|
662
|
+
left: isTrain
|
|
663
|
+
? "73%"
|
|
664
|
+
: "clamp(60%, 65% + (100vw - 1300px) * 0.1, 65%)",
|
|
593
665
|
right: 0,
|
|
594
666
|
justifyContent: isCentered ? "center" : "",
|
|
595
667
|
gap: "10px",
|
|
@@ -25,6 +25,7 @@ interface DateTimeSectionMobileProps {
|
|
|
25
25
|
tooltipBgColor?: string;
|
|
26
26
|
showLastSeats?: boolean;
|
|
27
27
|
discountSeatPriceColor?: string;
|
|
28
|
+
isTrain?: boolean;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
const pad = (n: number) => (n < 10 ? "0" + n : String(n));
|
|
@@ -67,41 +68,47 @@ const TimeRow: React.FC<TimeRowProps> = ({
|
|
|
67
68
|
isSoldOut,
|
|
68
69
|
}) => {
|
|
69
70
|
const formattedDate = DateService.getServiceItemDate(date);
|
|
70
|
-
const dotPositionClass = formattedDate.includes("dom")
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
71
|
+
const dotPositionClass = formattedDate.includes("dom")
|
|
72
|
+
? "max-[399px]:left-[53%]"
|
|
73
|
+
: "";
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
className={`flex items-center min-[420]:text-[13px] text-[12px] justify-between ${
|
|
77
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
78
|
+
}`}
|
|
79
|
+
>
|
|
80
|
+
<div className="flex items-center" style={{ flex: 1 }}>
|
|
81
|
+
<div>
|
|
82
|
+
{" "}
|
|
83
|
+
{label ? (
|
|
84
|
+
<div className="w-[60px]">{label}</div>
|
|
85
|
+
) : (
|
|
86
|
+
<div className="w-[12px] h-auto mr-[5px]">
|
|
87
|
+
<img
|
|
88
|
+
src={icon}
|
|
89
|
+
alt={alt}
|
|
90
|
+
className={`w-[12px] h-auto mr-[5px] ${
|
|
91
|
+
isSoldOut ? "grayscale" : ""
|
|
92
|
+
}`}
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
)}
|
|
96
|
+
</div>
|
|
97
|
+
<div
|
|
98
|
+
className="flex items-center relative capitalize justify-between"
|
|
99
|
+
style={{ flex: 1 }}
|
|
100
|
+
>
|
|
101
|
+
<span className="cursor-pointer black-text whitespace-nowrap">
|
|
102
|
+
{formattedDate}
|
|
103
|
+
</span>
|
|
104
|
+
<div className={`absolute left-[50%] ${dotPositionClass}`}>•</div>
|
|
105
|
+
<div className="font-[900] relative black-text whitespace-nowrap">
|
|
106
|
+
{timeContent}
|
|
90
107
|
</div>
|
|
91
|
-
|
|
92
|
-
</div>
|
|
93
|
-
<div
|
|
94
|
-
className="flex items-center relative capitalize justify-between"
|
|
95
|
-
style={{ flex: 1 }}
|
|
96
|
-
>
|
|
97
|
-
<span className="cursor-pointer black-text">
|
|
98
|
-
{formattedDate}
|
|
99
|
-
</span>
|
|
100
|
-
<div className={`absolute left-[50%] ${dotPositionClass}`}>•</div>
|
|
101
|
-
<div className="font-[900] relative black-text">{timeContent}</div>
|
|
108
|
+
</div>
|
|
102
109
|
</div>
|
|
103
110
|
</div>
|
|
104
|
-
|
|
111
|
+
);
|
|
105
112
|
};
|
|
106
113
|
|
|
107
114
|
function DateTimeSectionMobile({
|
|
@@ -127,6 +134,7 @@ function DateTimeSectionMobile({
|
|
|
127
134
|
tooltipBgColor,
|
|
128
135
|
showLastSeats,
|
|
129
136
|
discountSeatPriceColor,
|
|
137
|
+
isTrain,
|
|
130
138
|
}: DateTimeSectionMobileProps): React.ReactElement {
|
|
131
139
|
const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
|
|
132
140
|
|
|
@@ -153,8 +161,12 @@ function DateTimeSectionMobile({
|
|
|
153
161
|
>
|
|
154
162
|
{/* DATE AND TIME */}
|
|
155
163
|
<div
|
|
156
|
-
className=
|
|
157
|
-
style={{
|
|
164
|
+
className={`flex flex-col gap-[4px] w-[50%] ${isTrain ? "justify-center" : "justify-between"}`}
|
|
165
|
+
style={{
|
|
166
|
+
justifyContent: isCiva && "center",
|
|
167
|
+
minHeight: isTrain ? undefined : "2.5rem",
|
|
168
|
+
alignSelf: isTrain ? "stretch" : undefined,
|
|
169
|
+
}}
|
|
158
170
|
>
|
|
159
171
|
<TimeRow
|
|
160
172
|
label={orignLabel}
|
|
@@ -198,6 +210,7 @@ function DateTimeSectionMobile({
|
|
|
198
210
|
tooltipBgColor={tooltipBgColor}
|
|
199
211
|
showLastSeats={showLastSeats}
|
|
200
212
|
discountSeatPriceColor={discountSeatPriceColor}
|
|
213
|
+
isTrain={isTrain}
|
|
201
214
|
/>
|
|
202
215
|
</div>
|
|
203
216
|
);
|
|
@@ -31,6 +31,7 @@ interface SeatSectionMobileProps {
|
|
|
31
31
|
tooltipBgColor?: string;
|
|
32
32
|
showLastSeats?: boolean;
|
|
33
33
|
discountSeatPriceColor?: string;
|
|
34
|
+
isTrain?: boolean;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
interface SeatRowProps {
|
|
@@ -42,6 +43,7 @@ interface SeatRowProps {
|
|
|
42
43
|
seatPriceColor: string;
|
|
43
44
|
hasMultipleTypes: boolean;
|
|
44
45
|
textSize: string;
|
|
46
|
+
isTrain?: boolean;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
const SeatRow: React.FC<SeatRowProps> = ({
|
|
@@ -53,6 +55,7 @@ const SeatRow: React.FC<SeatRowProps> = ({
|
|
|
53
55
|
seatPriceColor,
|
|
54
56
|
hasMultipleTypes,
|
|
55
57
|
textSize,
|
|
58
|
+
isTrain,
|
|
56
59
|
}) => {
|
|
57
60
|
if (EXCEPTIONS.includes(type.label)) return null;
|
|
58
61
|
|
|
@@ -69,7 +72,12 @@ const SeatRow: React.FC<SeatRowProps> = ({
|
|
|
69
72
|
className={`min-[420]:text-[13px] ${textSize} `}
|
|
70
73
|
style={{ color: labelColor }}
|
|
71
74
|
>
|
|
72
|
-
{
|
|
75
|
+
{isTrain
|
|
76
|
+
? commonService.truncateSeatLabel(
|
|
77
|
+
commonService.capitalize(displayLabel),
|
|
78
|
+
8,
|
|
79
|
+
)
|
|
80
|
+
: displayLabel}
|
|
73
81
|
</span>
|
|
74
82
|
<span
|
|
75
83
|
className={`min-[420]:text-[13px] ${textSize} bold-text`}
|
|
@@ -118,6 +126,7 @@ function SeatSectionMobile({
|
|
|
118
126
|
tooltipBgColor,
|
|
119
127
|
showLastSeats,
|
|
120
128
|
discountSeatPriceColor,
|
|
129
|
+
isTrain,
|
|
121
130
|
}: SeatSectionMobileProps): React.ReactElement {
|
|
122
131
|
const hasMultipleTypes = (seatTypesData?.length ?? 0) > 2;
|
|
123
132
|
|
|
@@ -169,7 +178,7 @@ function SeatSectionMobile({
|
|
|
169
178
|
className="w-[100%] flex flex-row justify-between items-center"
|
|
170
179
|
>
|
|
171
180
|
<span
|
|
172
|
-
className="min-[420]:text-[13px] text-[12px] bold-text"
|
|
181
|
+
className="min-[420]:text-[13px] text-[12px] bold-text whitespace-nowrap"
|
|
173
182
|
style={{ color: isSoldOut ? "#bbb" : "#464647" }}
|
|
174
183
|
>
|
|
175
184
|
{commonService.truncateSeatLabel(seat.label)}
|
|
@@ -322,15 +331,17 @@ function SeatSectionMobile({
|
|
|
322
331
|
seatPriceColor={seatPriceColor}
|
|
323
332
|
hasMultipleTypes={hasMultipleTypes}
|
|
324
333
|
textSize="text-[11px]"
|
|
334
|
+
isTrain={isTrain}
|
|
325
335
|
/>
|
|
326
336
|
));
|
|
327
337
|
}
|
|
328
338
|
|
|
329
|
-
|
|
339
|
+
const filteredSeats = seatTypesData
|
|
330
340
|
?.filter((item) => getFilteredSeats(item.label))
|
|
331
|
-
?.sort((a, b) => a.fare - b.fare)
|
|
332
|
-
|
|
333
|
-
|
|
341
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
342
|
+
|
|
343
|
+
return (isTrain ? filteredSeats : filteredSeats?.slice(0, 2))?.map(
|
|
344
|
+
(type, i) => (
|
|
334
345
|
<SeatRow
|
|
335
346
|
key={i}
|
|
336
347
|
type={type}
|
|
@@ -341,16 +352,20 @@ function SeatSectionMobile({
|
|
|
341
352
|
seatPriceColor={seatPriceColor}
|
|
342
353
|
hasMultipleTypes={hasMultipleTypes}
|
|
343
354
|
textSize="text-[12px]"
|
|
355
|
+
isTrain={isTrain}
|
|
344
356
|
/>
|
|
345
|
-
)
|
|
357
|
+
),
|
|
358
|
+
);
|
|
346
359
|
};
|
|
347
360
|
|
|
348
361
|
const seats = removeDuplicateSeats
|
|
349
362
|
? getUniqueSeats(seatTypesData, 3)
|
|
350
|
-
:
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
363
|
+
: (() => {
|
|
364
|
+
const filtered = seatTypesData
|
|
365
|
+
?.filter((item) => getFilteredSeats(item.label))
|
|
366
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
367
|
+
return isTrain ? filtered : filtered?.slice(0, 2);
|
|
368
|
+
})();
|
|
354
369
|
|
|
355
370
|
const discountedSeats = seats?.map((seat) => ({
|
|
356
371
|
...seat,
|
|
@@ -602,7 +617,7 @@ function SeatSectionMobile({
|
|
|
602
617
|
</div>
|
|
603
618
|
) : (
|
|
604
619
|
<div
|
|
605
|
-
className=
|
|
620
|
+
className={`flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `}
|
|
606
621
|
style={{
|
|
607
622
|
gap: isSoldOut ? "0px" : "5px",
|
|
608
623
|
justifyContent: hasMultipleTypes ? "space-between" : "center",
|
|
@@ -39,9 +39,15 @@ const commonService = {
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
|
|
42
|
-
truncateSeatLabel: (label: string | number): string => {
|
|
42
|
+
truncateSeatLabel: (label: string | number, maxLength?: number): string => {
|
|
43
43
|
if (typeof label !== "string") return String(label);
|
|
44
44
|
if (label.includes("(")) return label;
|
|
45
|
+
|
|
46
|
+
// If maxLength provided, hard-truncate regardless of word count
|
|
47
|
+
if (maxLength != null && label.length > maxLength) {
|
|
48
|
+
return label.slice(0, maxLength) + "...";
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
const words = label.trim().split(/\s+/);
|
|
46
52
|
|
|
47
53
|
const truncateWord = (word: string) =>
|