kupos-ui-components-lib 9.9.8 → 9.9.9
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 +20 -2
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +7 -5
- package/dist/components/ServiceItem/mobileTypes.d.ts +2 -0
- package/dist/components/ServiceItem/types.d.ts +7 -0
- package/dist/styles.css +3 -0
- package/dist/ui/SeatSection/SeatSection.d.ts +7 -1
- package/dist/ui/SeatSection/SeatSection.js +38 -9
- package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +12 -6
- package/dist/ui/mobileweb/SeatSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/SeatSectionMobile.js +21 -14
- 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 +43 -0
- package/src/components/ServiceItem/ServiceItemMobile.tsx +45 -39
- package/src/components/ServiceItem/mobileTypes.ts +32 -26
- package/src/components/ServiceItem/types.ts +12 -0
- package/src/ui/SeatSection/SeatSection.tsx +83 -18
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +44 -35
- package/src/ui/mobileweb/SeatSectionMobile.tsx +23 -11
- 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, }: 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, }: ServiceItemProps & {
|
|
4
4
|
currencySign?: string;
|
|
5
5
|
}): React.ReactElement;
|
|
6
6
|
export default ServiceItemPB;
|
|
@@ -87,8 +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, }) {
|
|
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, }) {
|
|
91
91
|
var _a, _b, _c;
|
|
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
|
+
};
|
|
92
96
|
const getAnimationIcon = (icon) => {
|
|
93
97
|
var _a;
|
|
94
98
|
const animation = ANIMATION_MAP[icon];
|
|
@@ -227,6 +231,16 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
227
231
|
});
|
|
228
232
|
return;
|
|
229
233
|
}
|
|
234
|
+
if (isTrain) {
|
|
235
|
+
if (!selectedSeatKey) {
|
|
236
|
+
onShowSeatSelectionError === null || onShowSeatSelectionError === void 0 ? void 0 : onShowSeatSelectionError(serviceItem.id);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (onTrainButtonClick) {
|
|
240
|
+
onTrainButtonClick();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
230
244
|
onBookButtonPress();
|
|
231
245
|
};
|
|
232
246
|
const items = [
|
|
@@ -293,9 +307,13 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
293
307
|
backgroundColor: "#ccc",
|
|
294
308
|
} }),
|
|
295
309
|
React.createElement("div", { className: "content-center" },
|
|
296
|
-
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 })),
|
|
310
|
+
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 })),
|
|
297
311
|
React.createElement("div", { className: "relative" },
|
|
298
312
|
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 }),
|
|
313
|
+
showSeatSelectionError === serviceItem.id && isTrain && (React.createElement("div", { className: "flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]" },
|
|
314
|
+
React.createElement("div", { className: "text-[9px] text-center whitespace-nowrap", style: {
|
|
315
|
+
color: colors.seatPriceColor,
|
|
316
|
+
} }, "Selecciona el tipo de servicio"))),
|
|
299
317
|
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 &&
|
|
300
318
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[12px] mt-1 text-center", style: {
|
|
301
319
|
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, }: MobileServiceItemProps): React.ReactElement;
|
|
3
|
+
declare function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, }: 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;
|
|
@@ -99,7 +99,9 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
99
99
|
showTopLabel
|
|
100
100
|
? "mt-[20px]"
|
|
101
101
|
: "mt-[10px]"} `, style: { zIndex: 1 } },
|
|
102
|
-
React.createElement("div", { className: `z-1 ${((hasOfferText && isNewUiEnabled) ||
|
|
102
|
+
React.createElement("div", { className: `z-1 ${((hasOfferText && isNewUiEnabled) ||
|
|
103
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)) &&
|
|
104
|
+
!isSoldOut
|
|
103
105
|
? "rounded-[18px]"
|
|
104
106
|
: "rounded-[10px] border border-[#ccc]"}`, style: Object.assign(Object.assign({}, serviceCardStyle), { backgroundColor: "#fff" }) },
|
|
105
107
|
React.createElement("div", { style: { padding: "12px 12px 8px 12px" } },
|
|
@@ -129,8 +131,7 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
129
131
|
setIsExpanded(isItemExpanded ? null : serviceItem.id);
|
|
130
132
|
}, isPeru: isPeru, femaleAnim: serviceItem.icons.femaleAnim, ladiesBookedSeats: serviceItem.ladies_booked_seats, isDpEnabled: serviceItem.is_dp_enabled })),
|
|
131
133
|
React.createElement(ServiceBadgesMobile, { showTopLabel: showTopLabel, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, serviceItem: serviceItem, isConexion: isConexion })),
|
|
132
|
-
(
|
|
133
|
-
!isSoldOut && (React.createElement("div", { className: "px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]", style: {
|
|
134
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) && !isNewUiEnabled && !isSoldOut && (React.createElement("div", { className: "px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]", style: {
|
|
134
135
|
background: colors === null || colors === void 0 ? void 0 : colors.bottomStripColor,
|
|
135
136
|
borderRadius: "0 0 14px 14px",
|
|
136
137
|
zIndex: -1,
|
|
@@ -145,7 +146,8 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
|
|
|
145
146
|
lineHeight: 1.4,
|
|
146
147
|
} },
|
|
147
148
|
React.createElement("span", { className: "whitespace-nowrap min-[380px]:text-[12px]" }, serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text))))))),
|
|
148
|
-
(((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) && isNewUiEnabled) ||
|
|
149
|
+
(((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) && isNewUiEnabled) ||
|
|
150
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)) &&
|
|
149
151
|
!isSoldOut && (React.createElement("div", { className: "px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]", style: {
|
|
150
152
|
background: isSoldOut
|
|
151
153
|
? offerGradientWithOpacity
|
|
@@ -215,6 +215,8 @@ export interface MobileServiceItemProps {
|
|
|
215
215
|
label?: string;
|
|
216
216
|
icon?: string;
|
|
217
217
|
};
|
|
218
|
+
operatorLabel?: string;
|
|
219
|
+
isTrain?: boolean;
|
|
218
220
|
isFeatureDropDownExpand?: any;
|
|
219
221
|
setIsFeatureDropDownExpand?: (value: any) => void;
|
|
220
222
|
ticketQuantity?: number;
|
|
@@ -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
|
@@ -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,6 +18,10 @@ 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
|
}
|
|
20
|
-
declare function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, }: SeatSectionProps): React.ReactElement;
|
|
26
|
+
declare function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isTrain, topLabelColor, }: SeatSectionProps): React.ReactElement;
|
|
21
27
|
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,10 +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, }) {
|
|
61
|
+
function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isTrain, topLabelColor, }) {
|
|
58
62
|
var _a;
|
|
59
63
|
const uniqueSeats = getUniqueSeats(seatTypes);
|
|
60
|
-
const sortedSeatTypes = getSortedSeatTypes(seatTypes);
|
|
64
|
+
const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
|
|
61
65
|
const numberOfSeats = getNumberOfSeats(seatTypes);
|
|
62
66
|
const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
|
|
63
67
|
const formatPrice = (price) => availableSeats <= 0
|
|
@@ -65,11 +69,36 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
65
69
|
: CommonService.currency(price, currencySign);
|
|
66
70
|
const renderSeatNames = () => {
|
|
67
71
|
const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
|
|
68
|
-
return seats.map((val, key) =>
|
|
69
|
-
?
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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] ${isSoldOut ? "text-[#c0c0c0]" : ""}` }, typeof val.label === "string" || typeof val.label === "number"
|
|
95
|
+
? removeDuplicateSeats && isPeru
|
|
96
|
+
? CommonService.truncateSeatLabel(val.label)
|
|
97
|
+
: isTrain
|
|
98
|
+
? CommonService.truncateSeatLabel(val.label, 8)
|
|
99
|
+
: val.label
|
|
100
|
+
: null)));
|
|
101
|
+
});
|
|
73
102
|
};
|
|
74
103
|
const renderSeatPrices = () => {
|
|
75
104
|
if (isPeru) {
|
|
@@ -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,8 +23,10 @@ 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
|
" ",
|
|
@@ -33,9 +35,9 @@ const TimeRow = ({ label, icon, alt, date, timeContent, isSoldOut, }) => {
|
|
|
33
35
|
React.createElement("div", { className: "flex items-center relative capitalize justify-between", style: { flex: 1 } },
|
|
34
36
|
React.createElement("span", { className: "cursor-pointer black-text" }, 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" }, 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(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) {
|
|
@@ -101,19 +103,24 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
101
103
|
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] text-[#464647]", style: { opacity: isSoldOut ? 0.5 : 1 } }, "Agotado"))) : null));
|
|
102
104
|
};
|
|
103
105
|
const renderSeats = () => {
|
|
104
|
-
var _a, _b
|
|
106
|
+
var _a, _b;
|
|
105
107
|
if (isPeru) {
|
|
106
108
|
return renderPeruSeats();
|
|
107
109
|
}
|
|
108
110
|
if (removeDuplicateSeats) {
|
|
109
111
|
const uniqueSeats = getUniqueSeats(seatTypesData, 3);
|
|
110
|
-
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]" })));
|
|
112
|
+
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 })));
|
|
111
113
|
}
|
|
112
|
-
|
|
114
|
+
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);
|
|
115
|
+
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 })));
|
|
113
116
|
};
|
|
114
117
|
const seats = removeDuplicateSeats
|
|
115
118
|
? getUniqueSeats(seatTypesData, 3)
|
|
116
|
-
: (
|
|
119
|
+
: (() => {
|
|
120
|
+
var _a;
|
|
121
|
+
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);
|
|
122
|
+
return isTrain ? filtered : filtered === null || filtered === void 0 ? void 0 : filtered.slice(0, 2);
|
|
123
|
+
})();
|
|
117
124
|
const discountedSeats = seats === null || seats === void 0 ? void 0 : seats.map((seat) => (Object.assign(Object.assign({}, seat), commonService.calculateDiscountedPrice(seat.fare, serviceItem))));
|
|
118
125
|
const peruLowestFare = isPeru ? getLowestFare() : null;
|
|
119
126
|
const peruDiscountCalc = isPeru && peruLowestFare != null
|
|
@@ -124,7 +131,7 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
124
131
|
peruDiscountCalc.originalPrice !== peruDiscountCalc.discountedPrice
|
|
125
132
|
: discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.some((s) => s.originalPrice !== s.discountedPrice);
|
|
126
133
|
const discountSeat = isPeru && peruDiscountCalc
|
|
127
|
-
? Object.assign({ label: "", fare: peruLowestFare }, peruDiscountCalc) : (
|
|
134
|
+
? 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];
|
|
128
135
|
const discountValue = (() => {
|
|
129
136
|
if ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_type) === "percentage" &&
|
|
130
137
|
typeof (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_value) === "number") {
|
|
@@ -147,14 +154,14 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
147
154
|
};
|
|
148
155
|
const originalDpPrice = getMinValue(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.original_dp_price);
|
|
149
156
|
const dpDiscountPercent = getMinValue(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents);
|
|
150
|
-
const firstSeatFare = (
|
|
157
|
+
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;
|
|
151
158
|
const hasDpDiscount = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) &&
|
|
152
159
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) &&
|
|
153
160
|
originalDpPrice != null &&
|
|
154
161
|
dpDiscountPercent != null &&
|
|
155
162
|
firstSeatFare != null;
|
|
156
163
|
return (React.createElement("div", { className: "content-center relative", style: { width: "40%" } }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) &&
|
|
157
|
-
!((
|
|
164
|
+
!((_e = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) === null || _e === void 0 ? void 0 : _e.length) &&
|
|
158
165
|
!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] " },
|
|
159
166
|
!isNaN(Number(dpDiscountPercent)) &&
|
|
160
167
|
Number(dpDiscountPercent) > 0 && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
|
|
@@ -186,7 +193,7 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
186
193
|
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
|
|
187
194
|
color: isSoldOut ? "#bbb" : discountSeatPriceColor || "#ff5964",
|
|
188
195
|
} },
|
|
189
|
-
((
|
|
196
|
+
((_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,
|
|
190
197
|
commonService.discountedCurrency(Number(firstSeatFare), currencySign)),
|
|
191
198
|
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,
|
|
192
199
|
React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
|
|
@@ -220,8 +227,8 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
220
227
|
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
|
|
221
228
|
color: isSoldOut ? "#bbb" : discountSeatPriceColor || "#ff5964",
|
|
222
229
|
} },
|
|
223
|
-
((
|
|
224
|
-
commonService.discountedCurrency(discountSeat.discountedPrice, currencySign))))) : (React.createElement("div", { className:
|
|
230
|
+
((_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,
|
|
231
|
+
commonService.discountedCurrency(discountSeat.discountedPrice, currencySign))))) : (React.createElement("div", { className: `flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `, style: {
|
|
225
232
|
gap: isSoldOut ? "0px" : "5px",
|
|
226
233
|
justifyContent: hasMultipleTypes ? "space-between" : "center",
|
|
227
234
|
} },
|
|
@@ -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,
|
|
@@ -144,6 +151,15 @@ function ServiceItemPB({
|
|
|
144
151
|
wowDealData,
|
|
145
152
|
isFlores,
|
|
146
153
|
}: ServiceItemProps & { currencySign?: string }): React.ReactElement {
|
|
154
|
+
const handleSeatSelect = (
|
|
155
|
+
key: any,
|
|
156
|
+
price: number,
|
|
157
|
+
seatKey: string,
|
|
158
|
+
apiSeatType?: string,
|
|
159
|
+
) => {
|
|
160
|
+
onClearSeatSelectionError?.();
|
|
161
|
+
onSeatSelect?.(key, price, seatKey, apiSeatType);
|
|
162
|
+
};
|
|
147
163
|
const getAnimationIcon = (icon: string) => {
|
|
148
164
|
const animation = ANIMATION_MAP[icon];
|
|
149
165
|
if (!animation) return null;
|
|
@@ -341,6 +357,17 @@ function ServiceItemPB({
|
|
|
341
357
|
return;
|
|
342
358
|
}
|
|
343
359
|
|
|
360
|
+
if (isTrain) {
|
|
361
|
+
if (!selectedSeatKey) {
|
|
362
|
+
onShowSeatSelectionError?.(serviceItem.id);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (onTrainButtonClick) {
|
|
366
|
+
onTrainButtonClick();
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
344
371
|
onBookButtonPress();
|
|
345
372
|
};
|
|
346
373
|
|
|
@@ -594,6 +621,10 @@ function ServiceItemPB({
|
|
|
594
621
|
isPeru={isPeru}
|
|
595
622
|
renderIcon={renderIcon}
|
|
596
623
|
discountSeatPriceColor={colors.discountSeatPriceColor}
|
|
624
|
+
isTrain={isTrain}
|
|
625
|
+
selectedSeatKey={selectedSeatKey}
|
|
626
|
+
onSeatSelect={handleSeatSelect}
|
|
627
|
+
topLabelColor={colors.topLabelColor}
|
|
597
628
|
/>
|
|
598
629
|
</div>
|
|
599
630
|
|
|
@@ -609,6 +640,18 @@ function ServiceItemPB({
|
|
|
609
640
|
soldOutIcon={renderIcon("soldOutIcon", "14px")}
|
|
610
641
|
onClick={checkMidnight}
|
|
611
642
|
/>
|
|
643
|
+
{showSeatSelectionError === serviceItem.id && isTrain && (
|
|
644
|
+
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
|
|
645
|
+
<div
|
|
646
|
+
className="text-[9px] text-center whitespace-nowrap"
|
|
647
|
+
style={{
|
|
648
|
+
color: colors.seatPriceColor,
|
|
649
|
+
}}
|
|
650
|
+
>
|
|
651
|
+
Selecciona el tipo de servicio
|
|
652
|
+
</div>
|
|
653
|
+
</div>
|
|
654
|
+
)}
|
|
612
655
|
{showLastSeats ? (
|
|
613
656
|
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
|
|
614
657
|
{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,
|
|
@@ -215,7 +217,9 @@ function ServiceItemMobile({
|
|
|
215
217
|
>
|
|
216
218
|
<div
|
|
217
219
|
className={`z-1 ${
|
|
218
|
-
((hasOfferText && isNewUiEnabled) ||
|
|
220
|
+
((hasOfferText && isNewUiEnabled) ||
|
|
221
|
+
serviceItem?.is_dp_enabled) &&
|
|
222
|
+
!isSoldOut
|
|
219
223
|
? "rounded-[18px]"
|
|
220
224
|
: "rounded-[10px] border border-[#ccc]"
|
|
221
225
|
}`}
|
|
@@ -231,7 +235,9 @@ function ServiceItemMobile({
|
|
|
231
235
|
serviceItem?.offer_text || hasDiscount ? "10px" : "",
|
|
232
236
|
}}
|
|
233
237
|
>
|
|
234
|
-
<div
|
|
238
|
+
<div
|
|
239
|
+
className={`w-[115px] ${isFlores ? "" : "overflow-y-hidden"} h-[22px]`}
|
|
240
|
+
>
|
|
235
241
|
<img
|
|
236
242
|
src={serviceItem.operator_details[0]}
|
|
237
243
|
alt="service logo"
|
|
@@ -371,50 +377,50 @@ function ServiceItemMobile({
|
|
|
371
377
|
</div>
|
|
372
378
|
|
|
373
379
|
{/* 🔹 EXPANDABLE DROPDOWN (below the card) */}
|
|
374
|
-
{
|
|
375
|
-
|
|
380
|
+
{serviceItem?.offer_text && !isNewUiEnabled && !isSoldOut && (
|
|
381
|
+
<div
|
|
382
|
+
className="px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]"
|
|
383
|
+
style={{
|
|
384
|
+
background: colors?.bottomStripColor,
|
|
385
|
+
borderRadius: "0 0 14px 14px",
|
|
386
|
+
zIndex: -1,
|
|
387
|
+
}}
|
|
388
|
+
>
|
|
376
389
|
<div
|
|
377
|
-
className="
|
|
378
|
-
style={{
|
|
379
|
-
background: colors?.bottomStripColor,
|
|
380
|
-
borderRadius: "0 0 14px 14px",
|
|
381
|
-
zIndex: -1,
|
|
382
|
-
}}
|
|
390
|
+
className="flex flex-col gap-[8px] text-[12px] min-[420px]:text-[12px] text-[#464647]"
|
|
391
|
+
style={{ lineHeight: 1.6 }}
|
|
383
392
|
>
|
|
384
|
-
<div
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
<
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
<span className="whitespace-nowrap min-[380px]:text-[12px]">
|
|
407
|
-
{serviceItem?.offer_text}
|
|
408
|
-
</span>
|
|
409
|
-
</div>
|
|
410
|
-
</div>
|
|
393
|
+
<div className="flex justify-between items-center">
|
|
394
|
+
<div
|
|
395
|
+
className={`flex ${(serviceItem?.offer_text || "").length > 10 ? "items-start" : "items-center"}`}
|
|
396
|
+
>
|
|
397
|
+
<div className={isLongOfferText ? "mt-[2px]" : ""}>
|
|
398
|
+
<LottiePlayer
|
|
399
|
+
animationData={serviceItem.icons.promoAnim}
|
|
400
|
+
width="14px"
|
|
401
|
+
height="14px"
|
|
402
|
+
/>
|
|
403
|
+
</div>
|
|
404
|
+
<div
|
|
405
|
+
className={`ml-[4px] flex-1 outline-none ${isLongOfferText ? "mt-[2px]" : ""}`}
|
|
406
|
+
style={{
|
|
407
|
+
color: "#fff",
|
|
408
|
+
lineHeight: 1.4,
|
|
409
|
+
}}
|
|
410
|
+
>
|
|
411
|
+
<span className="whitespace-nowrap min-[380px]:text-[12px]">
|
|
412
|
+
{serviceItem?.offer_text}
|
|
413
|
+
</span>
|
|
414
|
+
</div>
|
|
411
415
|
</div>
|
|
412
416
|
</div>
|
|
413
417
|
</div>
|
|
414
|
-
|
|
418
|
+
</div>
|
|
419
|
+
)}
|
|
415
420
|
|
|
416
421
|
{/* 🔹 EXPANDABLE DROPDOWN (below the card) */}
|
|
417
|
-
{((serviceItem?.offer_text && isNewUiEnabled) ||
|
|
422
|
+
{((serviceItem?.offer_text && isNewUiEnabled) ||
|
|
423
|
+
serviceItem?.is_dp_enabled) &&
|
|
418
424
|
!isSoldOut && (
|
|
419
425
|
<div
|
|
420
426
|
className="px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]"
|
|
@@ -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,29 @@ 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
|
+
operatorLabel?: string;
|
|
232
|
+
isTrain?: boolean;
|
|
233
|
+
isFeatureDropDownExpand?: any;
|
|
232
234
|
setIsFeatureDropDownExpand?: (value: any) => void;
|
|
233
235
|
ticketQuantity?: number;
|
|
234
|
-
onIncreaseTicketQuantity?: (
|
|
235
|
-
|
|
236
|
+
onIncreaseTicketQuantity?: (
|
|
237
|
+
serviceItem: MobileServiceItemProps["serviceItem"],
|
|
238
|
+
) => void;
|
|
239
|
+
onDecreaseTicketQuantity?: (
|
|
240
|
+
serviceItem: MobileServiceItemProps["serviceItem"],
|
|
241
|
+
) => void;
|
|
236
242
|
cityOrigin?: { value: number; label: string };
|
|
237
243
|
cityDestination?: { value: number; label: string };
|
|
238
|
-
|
|
244
|
+
isNewUi?: boolean;
|
|
239
245
|
|
|
240
|
-
|
|
246
|
+
selectedTimeSlot?: string;
|
|
241
247
|
onTimeSlotChange?: (slot: string) => void;
|
|
242
248
|
isTimeDropdownOpen?: string | number | null;
|
|
243
249
|
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;
|
|
@@ -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
|
}
|
|
25
36
|
|
|
26
37
|
function getAllSeatTypes(seatTypes: SeatType[]) {
|
|
@@ -31,6 +42,8 @@ function getAllSeatTypes(seatTypes: SeatType[]) {
|
|
|
31
42
|
let seatTypesWithPrices = seatTypes.filter(Boolean).map((val) => ({
|
|
32
43
|
label: val?.label,
|
|
33
44
|
price: val?.fare,
|
|
45
|
+
key: val?.key,
|
|
46
|
+
apiSeatType: val?.apiSeatType || val?.api_seat_type,
|
|
34
47
|
}));
|
|
35
48
|
|
|
36
49
|
seatTypesWithPrices.sort((a, b) => a.price - b.price);
|
|
@@ -38,7 +51,7 @@ function getAllSeatTypes(seatTypes: SeatType[]) {
|
|
|
38
51
|
return seatTypesWithPrices;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
|
-
function getSortedSeatTypes(seatTypes: SeatType[]) {
|
|
54
|
+
function getSortedSeatTypes(seatTypes: SeatType[], isTrain: any) {
|
|
42
55
|
if (!seatTypes?.length) {
|
|
43
56
|
return [{ label: "Salon cama", price: 0 }];
|
|
44
57
|
}
|
|
@@ -52,7 +65,9 @@ function getSortedSeatTypes(seatTypes: SeatType[]) {
|
|
|
52
65
|
seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
|
|
53
66
|
}
|
|
54
67
|
|
|
55
|
-
|
|
68
|
+
if (!isTrain) {
|
|
69
|
+
seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
|
|
70
|
+
}
|
|
56
71
|
|
|
57
72
|
const seenPrices = new Set<number>();
|
|
58
73
|
seatTypesWithPrices = seatTypesWithPrices.filter((seat) => {
|
|
@@ -97,14 +112,18 @@ function SeatSection({
|
|
|
97
112
|
priceColor,
|
|
98
113
|
currencySign,
|
|
99
114
|
removeDuplicateSeats,
|
|
115
|
+
selectedSeatKey,
|
|
116
|
+
onSeatSelect,
|
|
100
117
|
isPeru,
|
|
101
118
|
serviceItem,
|
|
102
119
|
renderIcon,
|
|
103
120
|
dpSeatColor,
|
|
104
121
|
discountSeatPriceColor,
|
|
122
|
+
isTrain,
|
|
123
|
+
topLabelColor,
|
|
105
124
|
}: SeatSectionProps): React.ReactElement {
|
|
106
125
|
const uniqueSeats = getUniqueSeats(seatTypes);
|
|
107
|
-
const sortedSeatTypes = getSortedSeatTypes(seatTypes);
|
|
126
|
+
const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
|
|
108
127
|
const numberOfSeats = getNumberOfSeats(seatTypes);
|
|
109
128
|
const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
|
|
110
129
|
|
|
@@ -116,22 +135,68 @@ function SeatSection({
|
|
|
116
135
|
const renderSeatNames = () => {
|
|
117
136
|
const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
|
|
118
137
|
|
|
119
|
-
return seats.map((val, key: number) =>
|
|
120
|
-
SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
121
|
-
<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
138
|
+
return seats.map((val, key: number) => {
|
|
139
|
+
return SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
140
|
+
<div
|
|
141
|
+
className="flex items-center"
|
|
142
|
+
style={isTrain ? { cursor: "pointer" } : undefined}
|
|
143
|
+
onClick={
|
|
144
|
+
isTrain && !isSoldOut
|
|
145
|
+
? () =>
|
|
146
|
+
val.label === selectedSeatKey
|
|
147
|
+
? onSeatSelect?.(null, 0, "", "")
|
|
148
|
+
: onSeatSelect?.(
|
|
149
|
+
val.label,
|
|
150
|
+
val.price,
|
|
151
|
+
val.key,
|
|
152
|
+
(val as any).apiSeatType,
|
|
153
|
+
)
|
|
154
|
+
: undefined
|
|
155
|
+
}
|
|
126
156
|
>
|
|
127
|
-
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
157
|
+
{isTrain && (
|
|
158
|
+
<div
|
|
159
|
+
style={{
|
|
160
|
+
border: `1px solid ${val.label === selectedSeatKey ? topLabelColor : "#ccc"}`,
|
|
161
|
+
borderRadius: "50%",
|
|
162
|
+
width: "14px",
|
|
163
|
+
height: "14px",
|
|
164
|
+
minWidth: "14px",
|
|
165
|
+
marginRight: "10px",
|
|
166
|
+
display: "flex",
|
|
167
|
+
alignItems: "center",
|
|
168
|
+
justifyContent: "center",
|
|
169
|
+
}}
|
|
170
|
+
>
|
|
171
|
+
{val.label === selectedSeatKey && (
|
|
172
|
+
<div
|
|
173
|
+
style={{
|
|
174
|
+
backgroundColor: topLabelColor,
|
|
175
|
+
borderRadius: "50%",
|
|
176
|
+
width: "7px",
|
|
177
|
+
height: "7px",
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
)}
|
|
183
|
+
<span
|
|
184
|
+
key={key}
|
|
185
|
+
className={`flex items-center justify-between text-[13.33px] ${
|
|
186
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
187
|
+
}`}
|
|
188
|
+
>
|
|
189
|
+
{typeof val.label === "string" || typeof val.label === "number"
|
|
190
|
+
? removeDuplicateSeats && isPeru
|
|
191
|
+
? CommonService.truncateSeatLabel(val.label)
|
|
192
|
+
: isTrain
|
|
193
|
+
? CommonService.truncateSeatLabel(val.label, 8)
|
|
194
|
+
: val.label
|
|
195
|
+
: null}
|
|
196
|
+
</span>
|
|
197
|
+
</div>
|
|
198
|
+
);
|
|
199
|
+
});
|
|
135
200
|
};
|
|
136
201
|
|
|
137
202
|
const renderSeatPrices = () => {
|
|
@@ -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,43 @@ 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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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">{formattedDate}</span>
|
|
102
|
+
<div className={`absolute left-[50%] ${dotPositionClass}`}>•</div>
|
|
103
|
+
<div className="font-[900] relative black-text">{timeContent}</div>
|
|
104
|
+
</div>
|
|
102
105
|
</div>
|
|
103
106
|
</div>
|
|
104
|
-
|
|
107
|
+
);
|
|
105
108
|
};
|
|
106
109
|
|
|
107
110
|
function DateTimeSectionMobile({
|
|
@@ -127,6 +130,7 @@ function DateTimeSectionMobile({
|
|
|
127
130
|
tooltipBgColor,
|
|
128
131
|
showLastSeats,
|
|
129
132
|
discountSeatPriceColor,
|
|
133
|
+
isTrain,
|
|
130
134
|
}: DateTimeSectionMobileProps): React.ReactElement {
|
|
131
135
|
const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
|
|
132
136
|
|
|
@@ -153,8 +157,12 @@ function DateTimeSectionMobile({
|
|
|
153
157
|
>
|
|
154
158
|
{/* DATE AND TIME */}
|
|
155
159
|
<div
|
|
156
|
-
className=
|
|
157
|
-
style={{
|
|
160
|
+
className={`flex flex-col gap-[4px] w-[50%] ${isTrain ? "justify-center" : "justify-between"}`}
|
|
161
|
+
style={{
|
|
162
|
+
justifyContent: isCiva && "center",
|
|
163
|
+
minHeight: isTrain ? undefined : "2.5rem",
|
|
164
|
+
alignSelf: isTrain ? "stretch" : undefined,
|
|
165
|
+
}}
|
|
158
166
|
>
|
|
159
167
|
<TimeRow
|
|
160
168
|
label={orignLabel}
|
|
@@ -198,6 +206,7 @@ function DateTimeSectionMobile({
|
|
|
198
206
|
tooltipBgColor={tooltipBgColor}
|
|
199
207
|
showLastSeats={showLastSeats}
|
|
200
208
|
discountSeatPriceColor={discountSeatPriceColor}
|
|
209
|
+
isTrain={isTrain}
|
|
201
210
|
/>
|
|
202
211
|
</div>
|
|
203
212
|
);
|
|
@@ -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,9 @@ 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(displayLabel, 8)
|
|
77
|
+
: displayLabel}
|
|
73
78
|
</span>
|
|
74
79
|
<span
|
|
75
80
|
className={`min-[420]:text-[13px] ${textSize} bold-text`}
|
|
@@ -118,6 +123,7 @@ function SeatSectionMobile({
|
|
|
118
123
|
tooltipBgColor,
|
|
119
124
|
showLastSeats,
|
|
120
125
|
discountSeatPriceColor,
|
|
126
|
+
isTrain,
|
|
121
127
|
}: SeatSectionMobileProps): React.ReactElement {
|
|
122
128
|
const hasMultipleTypes = (seatTypesData?.length ?? 0) > 2;
|
|
123
129
|
|
|
@@ -278,15 +284,17 @@ function SeatSectionMobile({
|
|
|
278
284
|
seatPriceColor={seatPriceColor}
|
|
279
285
|
hasMultipleTypes={hasMultipleTypes}
|
|
280
286
|
textSize="text-[11px]"
|
|
287
|
+
isTrain={isTrain}
|
|
281
288
|
/>
|
|
282
289
|
));
|
|
283
290
|
}
|
|
284
291
|
|
|
285
|
-
|
|
292
|
+
const filteredSeats = seatTypesData
|
|
286
293
|
?.filter((item) => getFilteredSeats(item.label))
|
|
287
|
-
?.sort((a, b) => a.fare - b.fare)
|
|
288
|
-
|
|
289
|
-
|
|
294
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
295
|
+
|
|
296
|
+
return (isTrain ? filteredSeats : filteredSeats?.slice(0, 2))?.map(
|
|
297
|
+
(type, i) => (
|
|
290
298
|
<SeatRow
|
|
291
299
|
key={i}
|
|
292
300
|
type={type}
|
|
@@ -297,16 +305,20 @@ function SeatSectionMobile({
|
|
|
297
305
|
seatPriceColor={seatPriceColor}
|
|
298
306
|
hasMultipleTypes={hasMultipleTypes}
|
|
299
307
|
textSize="text-[12px]"
|
|
308
|
+
isTrain={isTrain}
|
|
300
309
|
/>
|
|
301
|
-
)
|
|
310
|
+
),
|
|
311
|
+
);
|
|
302
312
|
};
|
|
303
313
|
|
|
304
314
|
const seats = removeDuplicateSeats
|
|
305
315
|
? getUniqueSeats(seatTypesData, 3)
|
|
306
|
-
:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
316
|
+
: (() => {
|
|
317
|
+
const filtered = seatTypesData
|
|
318
|
+
?.filter((item) => getFilteredSeats(item.label))
|
|
319
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
320
|
+
return isTrain ? filtered : filtered?.slice(0, 2);
|
|
321
|
+
})();
|
|
310
322
|
|
|
311
323
|
const discountedSeats = seats?.map((seat) => ({
|
|
312
324
|
...seat,
|
|
@@ -541,7 +553,7 @@ function SeatSectionMobile({
|
|
|
541
553
|
</div>
|
|
542
554
|
) : (
|
|
543
555
|
<div
|
|
544
|
-
className=
|
|
556
|
+
className={`flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `}
|
|
545
557
|
style={{
|
|
546
558
|
gap: isSoldOut ? "0px" : "5px",
|
|
547
559
|
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) =>
|