kupos-ui-components-lib 9.11.1 → 9.11.3

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