kupos-ui-components-lib 9.10.7 → 9.10.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 +26 -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 +3 -0
- package/dist/ui/SeatSection/SeatSection.d.ts +7 -1
- package/dist/ui/SeatSection/SeatSection.js +41 -11
- 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 +49 -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/SeatSection/SeatSection.tsx +89 -20
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +44 -35
- package/src/ui/mobileweb/SeatSectionMobile.tsx +26 -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, 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,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, 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
|
+
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, tooltipColor: colors.tooltipColor })),
|
|
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, tooltipColor: colors.tooltipColor })),
|
|
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,
|
|
@@ -312,8 +330,12 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
312
330
|
} },
|
|
313
331
|
React.createElement("div", { style: Object.assign({ overflow: "hidden", minHeight: 0, marginTop: hasDpEnabled || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) ? "" : "-10px" }, (hasOfferText || hasDpEnabled
|
|
314
332
|
? {
|
|
315
|
-
borderLeft: isSoldOut
|
|
316
|
-
|
|
333
|
+
borderLeft: isSoldOut
|
|
334
|
+
? ""
|
|
335
|
+
: `3px solid ${colors.leftGradiantColor || "#ff8842"}`,
|
|
336
|
+
borderRight: isSoldOut
|
|
337
|
+
? ""
|
|
338
|
+
: `3px solid ${colors.rightGradiantColor || "#ff8842"}`,
|
|
317
339
|
borderRadius: "0 0 18px 18px",
|
|
318
340
|
boxSizing: "border-box",
|
|
319
341
|
}
|
|
@@ -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
|
@@ -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,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, 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);
|
|
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(CommonService.capitalize(String(val.label)), 8)
|
|
99
|
+
: val.label
|
|
100
|
+
: null)));
|
|
101
|
+
});
|
|
73
102
|
};
|
|
74
103
|
const renderSeatPrices = () => {
|
|
75
104
|
if (isPeru) {
|
|
@@ -147,9 +176,10 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
147
176
|
React.createElement("div", { className: "col-start-1 row-start-3 flex h-[20px] items-end" },
|
|
148
177
|
React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#464647]" }, "Desde")),
|
|
149
178
|
React.createElement("div", { className: "col-start-2 row-start-1 flex items-center justify-center absolute", style: { top: "-22px", left: "50%", transform: "translateX(-50%)" } }, !isNaN(Number(dpDiscountPercent)) &&
|
|
150
|
-
Number(dpDiscountPercent) > 0 && (React.createElement("span", { className: `rounded-[100px]
|
|
179
|
+
Number(dpDiscountPercent) > 0 && (React.createElement("span", { className: `rounded-[100px] px-[6px] text-[12px] bold-text leading-[20px] text-white`, style: {
|
|
151
180
|
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
152
181
|
whiteSpace: "nowrap",
|
|
182
|
+
backgroundColor: discountSeatPriceColor || "#ff5964",
|
|
153
183
|
} },
|
|
154
184
|
Math.round(Number(dpDiscountPercent)),
|
|
155
185
|
"% OFF"))),
|
|
@@ -167,7 +197,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
|
|
|
167
197
|
transformOrigin: "center",
|
|
168
198
|
} }))),
|
|
169
199
|
React.createElement("div", { className: "col-start-2 row-start-3 flex h-[30px] items-end justify-center relative" },
|
|
170
|
-
React.createElement("span", { className: "flex items-center gap-[6px] text-[22px] bold-text leading-[30px]", style: { color: isSoldOut ? "#c0c0c0" : "#ff5964" } },
|
|
200
|
+
React.createElement("span", { className: "flex items-center gap-[6px] text-[22px] bold-text leading-[30px]", style: { color: isSoldOut ? "#c0c0c0" : dpSeatColor || "#ff5964" } },
|
|
171
201
|
React.createElement("div", { className: "absolute", style: { left: isPeru ? "-1px" : "-19px", bottom: "1px" } }, renderIcon("fireIcon", "16px")),
|
|
172
202
|
availableSeats <= 0
|
|
173
203
|
? CommonService.currency(0, currencySign)
|
|
@@ -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(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) {
|
|
@@ -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,
|
|
@@ -145,6 +152,15 @@ function ServiceItemPB({
|
|
|
145
152
|
isFlores,
|
|
146
153
|
operatorLabel,
|
|
147
154
|
}: ServiceItemProps & { currencySign?: string }): React.ReactElement {
|
|
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
|
+
};
|
|
148
164
|
const getAnimationIcon = (icon: string) => {
|
|
149
165
|
const animation = ANIMATION_MAP[icon];
|
|
150
166
|
if (!animation) return null;
|
|
@@ -345,6 +361,17 @@ function ServiceItemPB({
|
|
|
345
361
|
return;
|
|
346
362
|
}
|
|
347
363
|
|
|
364
|
+
if (isTrain) {
|
|
365
|
+
if (!selectedSeatKey) {
|
|
366
|
+
onShowSeatSelectionError?.(serviceItem.id);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (onTrainButtonClick) {
|
|
370
|
+
onTrainButtonClick();
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
348
375
|
onBookButtonPress();
|
|
349
376
|
};
|
|
350
377
|
|
|
@@ -598,6 +625,10 @@ function ServiceItemPB({
|
|
|
598
625
|
isPeru={isPeru}
|
|
599
626
|
renderIcon={renderIcon}
|
|
600
627
|
discountSeatPriceColor={colors.discountSeatPriceColor}
|
|
628
|
+
isTrain={isTrain}
|
|
629
|
+
selectedSeatKey={selectedSeatKey}
|
|
630
|
+
onSeatSelect={handleSeatSelect}
|
|
631
|
+
topLabelColor={colors.topLabelColor}
|
|
601
632
|
tooltipColor={colors.tooltipColor}
|
|
602
633
|
/>
|
|
603
634
|
</div>
|
|
@@ -614,6 +645,18 @@ function ServiceItemPB({
|
|
|
614
645
|
soldOutIcon={renderIcon("soldOutIcon", "14px")}
|
|
615
646
|
onClick={checkMidnight}
|
|
616
647
|
/>
|
|
648
|
+
{showSeatSelectionError === serviceItem.id && isTrain && (
|
|
649
|
+
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
|
|
650
|
+
<div
|
|
651
|
+
className="text-[9px] text-center whitespace-nowrap"
|
|
652
|
+
style={{
|
|
653
|
+
color: colors.seatPriceColor,
|
|
654
|
+
}}
|
|
655
|
+
>
|
|
656
|
+
Selecciona el tipo de servicio
|
|
657
|
+
</div>
|
|
658
|
+
</div>
|
|
659
|
+
)}
|
|
617
660
|
{showLastSeats ? (
|
|
618
661
|
<div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
|
|
619
662
|
{serviceItem?.available_seats < 10 &&
|
|
@@ -671,8 +714,12 @@ function ServiceItemPB({
|
|
|
671
714
|
hasDpEnabled || serviceItem?.offer_text ? "" : "-10px",
|
|
672
715
|
...(hasOfferText || hasDpEnabled
|
|
673
716
|
? {
|
|
674
|
-
borderLeft: isSoldOut
|
|
675
|
-
|
|
717
|
+
borderLeft: isSoldOut
|
|
718
|
+
? ""
|
|
719
|
+
: `3px solid ${colors.leftGradiantColor || "#ff8842"}`,
|
|
720
|
+
borderRight: isSoldOut
|
|
721
|
+
? ""
|
|
722
|
+
: `3px solid ${colors.rightGradiantColor || "#ff8842"}`,
|
|
676
723
|
borderRadius: "0 0 18px 18px",
|
|
677
724
|
boxSizing: "border-box",
|
|
678
725
|
}
|
|
@@ -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;
|
|
@@ -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,15 +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);
|
|
128
|
+
const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
|
|
110
129
|
const numberOfSeats = getNumberOfSeats(seatTypes);
|
|
111
130
|
const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
|
|
112
131
|
|
|
@@ -118,22 +137,71 @@ function SeatSection({
|
|
|
118
137
|
const renderSeatNames = () => {
|
|
119
138
|
const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
|
|
120
139
|
|
|
121
|
-
return seats.map((val, key: number) =>
|
|
122
|
-
SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
+
}
|
|
128
158
|
>
|
|
129
|
-
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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] ${
|
|
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.truncateSeatLabel(
|
|
196
|
+
CommonService.capitalize(String(val.label)),
|
|
197
|
+
8,
|
|
198
|
+
)
|
|
199
|
+
: val.label
|
|
200
|
+
: null}
|
|
201
|
+
</span>
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
});
|
|
137
205
|
};
|
|
138
206
|
|
|
139
207
|
const renderSeatPrices = () => {
|
|
@@ -279,10 +347,11 @@ function SeatSection({
|
|
|
279
347
|
{!isNaN(Number(dpDiscountPercent)) &&
|
|
280
348
|
Number(dpDiscountPercent) > 0 && (
|
|
281
349
|
<span
|
|
282
|
-
className={`rounded-[100px]
|
|
350
|
+
className={`rounded-[100px] px-[6px] text-[12px] bold-text leading-[20px] text-white`}
|
|
283
351
|
style={{
|
|
284
352
|
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
285
353
|
whiteSpace: "nowrap",
|
|
354
|
+
backgroundColor: discountSeatPriceColor || "#ff5964",
|
|
286
355
|
}}
|
|
287
356
|
>
|
|
288
357
|
{Math.round(Number(dpDiscountPercent))}% OFF
|
|
@@ -317,7 +386,7 @@ function SeatSection({
|
|
|
317
386
|
<div className="col-start-2 row-start-3 flex h-[30px] items-end justify-center relative">
|
|
318
387
|
<span
|
|
319
388
|
className="flex items-center gap-[6px] text-[22px] bold-text leading-[30px]"
|
|
320
|
-
style={{ color: isSoldOut ? "#c0c0c0" : "#ff5964" }}
|
|
389
|
+
style={{ color: isSoldOut ? "#c0c0c0" : dpSeatColor || "#ff5964" }}
|
|
321
390
|
>
|
|
322
391
|
<div
|
|
323
392
|
className="absolute"
|
|
@@ -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,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
|
|
|
@@ -278,15 +287,17 @@ function SeatSectionMobile({
|
|
|
278
287
|
seatPriceColor={seatPriceColor}
|
|
279
288
|
hasMultipleTypes={hasMultipleTypes}
|
|
280
289
|
textSize="text-[11px]"
|
|
290
|
+
isTrain={isTrain}
|
|
281
291
|
/>
|
|
282
292
|
));
|
|
283
293
|
}
|
|
284
294
|
|
|
285
|
-
|
|
295
|
+
const filteredSeats = seatTypesData
|
|
286
296
|
?.filter((item) => getFilteredSeats(item.label))
|
|
287
|
-
?.sort((a, b) => a.fare - b.fare)
|
|
288
|
-
|
|
289
|
-
|
|
297
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
298
|
+
|
|
299
|
+
return (isTrain ? filteredSeats : filteredSeats?.slice(0, 2))?.map(
|
|
300
|
+
(type, i) => (
|
|
290
301
|
<SeatRow
|
|
291
302
|
key={i}
|
|
292
303
|
type={type}
|
|
@@ -297,16 +308,20 @@ function SeatSectionMobile({
|
|
|
297
308
|
seatPriceColor={seatPriceColor}
|
|
298
309
|
hasMultipleTypes={hasMultipleTypes}
|
|
299
310
|
textSize="text-[12px]"
|
|
311
|
+
isTrain={isTrain}
|
|
300
312
|
/>
|
|
301
|
-
)
|
|
313
|
+
),
|
|
314
|
+
);
|
|
302
315
|
};
|
|
303
316
|
|
|
304
317
|
const seats = removeDuplicateSeats
|
|
305
318
|
? getUniqueSeats(seatTypesData, 3)
|
|
306
|
-
:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
319
|
+
: (() => {
|
|
320
|
+
const filtered = seatTypesData
|
|
321
|
+
?.filter((item) => getFilteredSeats(item.label))
|
|
322
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
323
|
+
return isTrain ? filtered : filtered?.slice(0, 2);
|
|
324
|
+
})();
|
|
310
325
|
|
|
311
326
|
const discountedSeats = seats?.map((seat) => ({
|
|
312
327
|
...seat,
|
|
@@ -541,7 +556,7 @@ function SeatSectionMobile({
|
|
|
541
556
|
</div>
|
|
542
557
|
) : (
|
|
543
558
|
<div
|
|
544
|
-
className=
|
|
559
|
+
className={`flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `}
|
|
545
560
|
style={{
|
|
546
561
|
gap: isSoldOut ? "0px" : "5px",
|
|
547
562
|
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) =>
|