kupos-ui-components-lib 10.1.4 → 10.1.6

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.
Files changed (29) hide show
  1. package/dist/components/FilterBar/ServiceFilter.js +1 -1
  2. package/dist/components/PaymentSideBar/PaymentSideBarDesktop.js +1 -1
  3. package/dist/components/PaymentSideBar/PaymentSideBarMobile.js +1 -1
  4. package/dist/components/ServiceItem/PeruServiceItemDesktop.js +1 -1
  5. package/dist/components/ServiceItem/ServiceItemDesktop.js +2 -2
  6. package/dist/styles.css +8 -5
  7. package/dist/ui/AmenitiesBlock.js +43 -24
  8. package/dist/ui/DurationBlock.js +2 -1
  9. package/dist/ui/OfferBanner.js +4 -4
  10. package/dist/ui/SeatSection/SeatSection.js +3 -1
  11. package/dist/ui/ServiceBadges/ServiceBadges.js +1 -1
  12. package/dist/ui/mobileweb/BottomAmenitiesMobile.js +2 -1
  13. package/dist/ui/mobileweb/ServiceBadgesMobile.js +1 -1
  14. package/dist/utils/DateService.d.ts +4 -0
  15. package/dist/utils/DateService.js +18 -0
  16. package/package.json +1 -1
  17. package/src/components/FilterBar/ServiceFilter.tsx +1 -1
  18. package/src/components/PaymentSideBar/PaymentSideBarDesktop.tsx +1 -1
  19. package/src/components/PaymentSideBar/PaymentSideBarMobile.tsx +1 -1
  20. package/src/components/ServiceItem/PeruServiceItemDesktop.tsx +1 -1
  21. package/src/components/ServiceItem/ServiceItemDesktop.tsx +2 -2
  22. package/src/ui/AmenitiesBlock.tsx +32 -6
  23. package/src/ui/DurationBlock.tsx +2 -1
  24. package/src/ui/OfferBanner.tsx +6 -4
  25. package/src/ui/SeatSection/SeatSection.tsx +6 -1
  26. package/src/ui/ServiceBadges/ServiceBadges.tsx +1 -1
  27. package/src/ui/mobileweb/BottomAmenitiesMobile.tsx +2 -1
  28. package/src/ui/mobileweb/ServiceBadgesMobile.tsx +1 -1
  29. package/src/utils/DateService.ts +19 -0
@@ -147,7 +147,7 @@ class ServiceFilter extends React.Component {
147
147
  ((option === null || option === void 0 ? void 0 : option.type) === "tipo" && this.props.isTrain) ||
148
148
  !this.props.isTrain;
149
149
  return (React.createElement("div", { key: key },
150
- shouldShowHeader && (React.createElement("div", { onClick: () => this.toggleFilter(option.type), className: "bold-text flex items-center justify-between mt-[13px] mb-[5px]" },
150
+ shouldShowHeader && (React.createElement("div", { onClick: () => this.toggleFilter(option.type), className: "bold-text flex items-center justify-between mt-[20px] mb-[5px]" },
151
151
  this.props.t("RESULTS_PAGE." + option.title),
152
152
  React.createElement("img", { src: this.props.icons.downArrow, alt: "downArrow", className: `${isOpen ? "rotate-180" : ""} w-[auto] h-[9px] transition-all duration-300 cursor-pointer` }))),
153
153
  React.createElement("div", { className: ` transition-all duration-300 ease-in-out
@@ -174,7 +174,7 @@ const renderSummaryDetailsCard = ({ serviceName, date, source, dest, boardingSta
174
174
  React.createElement("img", { src: icons === null || icons === void 0 ? void 0 : icons.hours, className: "w-[16px] h-[16px] mr-[5px]" })),
175
175
  React.createElement("span", null,
176
176
  "Duraci\u00F3n : ",
177
- duration,
177
+ DateService.formatDuration(duration),
178
178
  " horas")))))));
179
179
  };
180
180
  const PaymentSideBarDesktop = ({ serviceNameOnward, serviceNameReturn, metaData, currencySign, dateOnward, dateReturn, sourceOnward, sourceReturn, destinationOnward, destinationReturn, boardingStageOnward, boardingStageReturn, droppingStageOnward, droppingStageReturn, boardingTimeOnward, boardingTimeReturn, droppingTimeOnward, droppingTimeReturn, durationOnward, durationReturn, selectSeatOnward, selectSeatReturn, journeyTypeActive, setJourneyTypeActive, translation, trainTypeOnward, trainTypeReturn, colors, trainType, icons, selectedOnward, selectedReturn, conexionChecked, conexionPassengers, returnConexionFare, conexionFare, loginData, checkWhatsappEligibility, removeDiscountAtomValue, netFare, promoCode, onPromoRemove, isAgency, agencyFee, walletMoney, virtualMoney, virtualLimit, showUsd, netFareInUsd, renderDiscount, discountAmount, walletLabel, creditosLabel, currency, customSideBarwidth, isLinatal, insuranceData, isPeru, serviceFeeDataStateValue, }) => {
@@ -71,7 +71,7 @@ const renderSummaryDetailsCard = ({ serviceName, date, source, dest, boardingSta
71
71
  " ",
72
72
  isTacna
73
73
  ? `${getRoundedHour(duration)}hrs aprox`
74
- : `${duration} horas`)))))));
74
+ : `${DateService.formatDuration(duration)} horas`)))))));
75
75
  };
76
76
  const PaymentSideBarMobile = ({ serviceNameOnward, serviceNameReturn, metaData, currencySign, dateOnward, dateReturn, sourceOnward, sourceReturn, destinationOnward, destinationReturn, boardingStageOnward, boardingStageReturn, droppingStageOnward, droppingStageReturn, boardingTimeOnward, boardingTimeReturn, droppingTimeOnward, droppingTimeReturn, durationOnward, durationReturn, selectSeatOnward, selectSeatReturn, journeyTypeActive, setJourneyTypeActive, translation, trainTypeOnward, trainTypeReturn, colors, trainType, icons, selectedOnward, selectedReturn, conexionChecked, conexionPassengers, returnConexionFare, conexionFare, loginData, checkWhatsappEligibility, removeDiscountAtomValue, netFare, promoCode, onPromoRemove, isAgency, agencyFee, walletMoney, virtualMoney, virtualLimit, showUsd, netFareInUsd, renderDiscount, discountAmount, currency, showWhatsappChargesInfo, setShowWhatsappChargesInfo, t, countdown, walletLabel, creditosLabel, isTacna, isLinatal, insuranceData, isPeru, setShowServicefeeModal, serviceFeeDataStateValue, }) => {
77
77
  var _a, _b, _c, _d, _e;
@@ -394,7 +394,7 @@ function PeruServiceItemDesktop({ serviceItem, onBookButtonPress, colors, metaDa
394
394
  return (React.createElement("div", { className: `relative hover:z-[150] ${(hasOfferText || hasDpEnabled || isNewUiEnabled) && !isSoldOut ? "mb-[65px]" : "mb-[20px]"} ${(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ||
395
395
  (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" ||
396
396
  showTopLabel
397
- ? "mt-[30px]"
397
+ ? "mt-[20px]"
398
398
  : "mt-[20px]"} ` },
399
399
  ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || hasDpEnabled) && !isSoldOut && (React.createElement(OfferBanner, { offerGradient: offerGradient, isSoldOut: isSoldOut, serviceItem: serviceItem, renderIcon: renderIcon, isLoggedIn: isLoggedIn, showLoginModal: showLoginModal, viewersConfig: viewersConfig, getAnimationIcon: getAnimationIcon, showLoginOption: showLoginOption, isNewUiEnabled: isNewUiEnabled, colors: colors })),
400
400
  React.createElement("div", { id: `service-card-${serviceItem.id}`, className: `bg-white mx-auto relative ${((hasOfferText && isNewUiEnabled) || hasDpEnabled) && !isSoldOut
@@ -296,14 +296,14 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
296
296
  : serviceItem.id), selectedTimeSlot: selectedTimeSlot, onTimeSlotChange: onTimeSlotChange, isTimeDropdownOpen: isTimeDropdownOpen, onTimeDropdownToggle: onTimeDropdownToggle, wowDealData: wowDealData })) : (React.createElement("div", { className: `relative hover:z-[150] ${(hasOfferText || hasDpEnabled || isNewUiEnabled) && !isSoldOut ? "mb-[65px]" : "mb-[20px]"} ${(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ||
297
297
  (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" ||
298
298
  showTopLabel
299
- ? "mt-[30px]"
299
+ ? "mt-[20px]"
300
300
  : "mt-[20px]"} ` },
301
301
  ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || hasDpEnabled) && !isSoldOut && (React.createElement(OfferBanner, { offerGradient: offerGradient, isSoldOut: isSoldOut, serviceItem: serviceItem, renderIcon: renderIcon, isLoggedIn: isLoggedIn, showLoginModal: showLoginModal, viewersConfig: viewersConfig, getAnimationIcon: getAnimationIcon, showLoginOption: showLoginOption, isNewUiEnabled: isNewUiEnabled, colors: colors, isLinatal: isLinatal })),
302
302
  React.createElement("div", { id: `service-card-${serviceItem.id}`, className: `bg-white mx-auto relative ${((hasOfferText && isNewUiEnabled) || hasDpEnabled) && !isSoldOut
303
303
  ? "z-[3] rounded-[18px]"
304
304
  : "rounded-[10px] border border-[#ccc]"}`, style: serviceCardStyle },
305
305
  React.createElement("div", { className: " pt-[20px]", style: {
306
- padding: hasDpEnabled || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text)
306
+ padding: hasDpEnabled || (isNewUiEnabled && !isSoldOut)
307
307
  ? "20px 15px 10px 15px"
308
308
  : coachKey
309
309
  ? "20px 15px 20px 15px"
package/dist/styles.css CHANGED
@@ -90,8 +90,8 @@
90
90
  .-bottom-\[36px\] {
91
91
  bottom: calc(36px * -1);
92
92
  }
93
- .-bottom-\[44px\] {
94
- bottom: calc(44px * -1);
93
+ .-bottom-\[40px\] {
94
+ bottom: calc(40px * -1);
95
95
  }
96
96
  .bottom-\[11px\] {
97
97
  bottom: 11px;
@@ -243,9 +243,6 @@
243
243
  .mt-\[24px\] {
244
244
  margin-top: 24px;
245
245
  }
246
- .mt-\[30px\] {
247
- margin-top: 30px;
248
- }
249
246
  .mt-\[50px\] {
250
247
  margin-top: 50px;
251
248
  }
@@ -396,6 +393,9 @@
396
393
  .h-\[30px\] {
397
394
  height: 30px;
398
395
  }
396
+ .h-\[44px\] {
397
+ height: 44px;
398
+ }
399
399
  .h-\[90px\] {
400
400
  height: 90px;
401
401
  }
@@ -626,6 +626,9 @@
626
626
  .justify-end {
627
627
  justify-content: flex-end;
628
628
  }
629
+ .justify-start {
630
+ justify-content: flex-start;
631
+ }
629
632
  .gap-\[1px\] {
630
633
  gap: 1px;
631
634
  }
@@ -7,33 +7,51 @@ const getAmenityBaseName = (amenityStr) => {
7
7
  };
8
8
  const isWater = (amenityStr) => { var _a; return ((_a = getAmenityBaseName(amenityStr)) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === "WATER"; };
9
9
  const TooltipArrow = ({ color }) => (React.createElement("div", { className: "tooltip-arrow absolute -top-[7px] left-1/2 -translate-x-1/2 w-0 h-0 border-l-8 border-r-8 border-b-8 border-l-transparent border-r-transparent", style: { borderBottomColor: color } }));
10
+ /*
10
11
  const getAmenitySplit = ({ isPeru, amenities, priorityIds }) => {
11
- const priority = amenities.filter((id) => priorityIds.includes(id));
12
- const nonPriority = amenities.filter((id) => !priorityIds.includes(id));
13
- const hasPriority = priority.length > 0;
14
- /* ============================
15
- 🇵🇪 PERU LOGIC
16
- ============================ */
17
- // if (isPeru) {
18
- // return hasPriority
19
- // ? { visible: priority, plus: nonPriority }
20
- // : { visible: [], plus: amenities };
21
- // }
22
- if (isPeru) {
23
- return hasPriority
24
- ? {
25
- visible: priority.slice(0, 2),
26
- plus: [...priority.slice(2), ...nonPriority],
27
- }
28
- : { visible: amenities.slice(0, 2), plus: amenities.slice(2) };
12
+ const priority = amenities.filter((id) => priorityIds.includes(id));
13
+ const nonPriority = amenities.filter((id) => !priorityIds.includes(id));
14
+ const hasPriority = priority.length > 0;
15
+
16
+ // if (isPeru) {
17
+ // return hasPriority
18
+ // ? { visible: priority, plus: nonPriority }
19
+ // : { visible: [], plus: amenities };
20
+ // }
21
+
22
+ if (isPeru) {
23
+ return hasPriority
24
+ ? {
25
+ visible: priority.slice(0, 2),
26
+ plus: [...priority.slice(2), ...nonPriority],
27
+ }
28
+ : { visible: amenities.slice(0, 2), plus: amenities.slice(2) };
29
+ }
30
+
31
+ const sorted = [...amenities].sort(
32
+ (a, b) => Number(priorityIds.includes(b)) - Number(priorityIds.includes(a)),
33
+ );
34
+
35
+ return {
36
+ visible: sorted.slice(0, 2),
37
+ plus: sorted.slice(2),
38
+ };
39
+ };
40
+ */
41
+ const getAmenitySplit = ({ isPeru, amenities, priorityIds }) => {
42
+ // The three important amenities: Mobile ticket ("3"), USB charger ("2"), WiFi ("13")
43
+ const IMPORTANT_AMENITY_IDS = ["2", "3", "13"];
44
+ const important = amenities.filter((id) => IMPORTANT_AMENITY_IDS.includes(id));
45
+ const nonImportant = amenities.filter((id) => !IMPORTANT_AMENITY_IDS.includes(id));
46
+ if (important.length > 0) {
47
+ return {
48
+ visible: important,
49
+ plus: nonImportant,
50
+ };
29
51
  }
30
- /* ============================
31
- 🌍 NON-PERU LOGIC
32
- ============================ */
33
- const sorted = [...amenities].sort((a, b) => Number(priorityIds.includes(b)) - Number(priorityIds.includes(a)));
34
52
  return {
35
- visible: sorted.slice(0, 2),
36
- plus: sorted.slice(2),
53
+ visible: [],
54
+ plus: amenities,
37
55
  };
38
56
  };
39
57
  const AmenitiesBlock = ({ serviceItem, metaData, isSoldOut, colors, isPeru, getAnimationIcon, getAmenityName, SvgAmenities, }) => {
@@ -53,6 +71,7 @@ const AmenitiesBlock = ({ serviceItem, metaData, isSoldOut, colors, isPeru, getA
53
71
  amenities,
54
72
  priorityIds,
55
73
  });
74
+ console.log("🚀 ~ AmenitiesBlock ~ visibleAmenities:", visibleAmenities, amenities);
56
75
  const shouldShowPlus = plusAmenities.length > 0;
57
76
  const grayscaleClass = isSoldOut ? "grayscale" : "";
58
77
  return (React.createElement("div", { className: "relative flex items-center gap-[6px]" },
@@ -1,9 +1,10 @@
1
1
  import React from "react";
2
+ import DateService from "../utils/DateService";
2
3
  const DurationBlock = ({ serviceItem, translation, renderIcon, isSoldOut, colors, }) => (React.createElement("div", { className: "flex items-baseline relative whitespace-nowrap " },
3
4
  React.createElement("div", { className: `w-[18px] mr-[4px] ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }, renderIcon("hours", "14px")),
4
5
  React.createElement("div", { className: "group text-[13.33px] cursor-pointer" },
5
6
  React.createElement("span", { style: { opacity: isSoldOut ? 0.5 : 1 } },
6
- serviceItem.duration,
7
+ DateService.formatDuration(serviceItem.duration),
7
8
  " ",
8
9
  translation.hours),
9
10
  React.createElement("div", { className: "hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-normal z-10 mt-2.5 w-[188px] text-center break-normal shadow-service text-[12px]", style: { backgroundColor: colors.bottomStripColor } },
@@ -72,13 +72,13 @@ const OfferBanner = ({ offerGradient, isSoldOut, serviceItem, isLoggedIn, showLo
72
72
  }
73
73
  return null;
74
74
  };
75
- return (React.createElement("div", { className: "text-white p-[10px_15px] text-left w-full flex items-center absolute -bottom-[44px] pt-[50px] rounded-b-[14px] text-[14px] mt-[10px]", style: {
75
+ return (React.createElement("div", { className: "text-white w-full absolute -bottom-[40px] pt-[20px] rounded-b-[14px] text-[14px] mt-[10px]", style: {
76
76
  background,
77
77
  opacity: isSoldOut ? 0.5 : 1,
78
- zIndex: isLinatal ? "-1" : "",
78
+ zIndex: isLinatal ? "-1" : "-1",
79
79
  } },
80
- React.createElement("div", { className: "flex justify-between items-center w-full" },
81
- React.createElement("div", { className: "flex items-center" }, renderLeftContent()),
80
+ React.createElement("div", { className: "flex justify-start items-center h-[44px] w-full gap-[20px] px-[15px]" },
81
+ React.createElement("div", { className: "flex items-center justify-start" }, renderLeftContent()),
82
82
  showViewers && (React.createElement(ViewersCount, { serviceItem: serviceItem, viewersConfig: viewersConfig, getAnimationIcon: getAnimationIcon })))));
83
83
  };
84
84
  export default OfferBanner;
@@ -217,7 +217,9 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
217
217
  hasDiscount && (React.createElement("span", { className: "text-[13.33px]", style: {
218
218
  color: "#999",
219
219
  } }, "Antes")),
220
- React.createElement("span", { className: "text-[13.33px] flex flex-col" }, !hasDiscount ? (React.createElement("span", { className: "text-[13.33px] whitespace-nowrap flex items-center" },
220
+ React.createElement("span", { className: "text-[13.33px] flex flex-col" }, !hasDiscount ? (React.createElement("span", { className: "text-[13.33px] whitespace-nowrap flex items-center", style: {
221
+ opacity: isSoldOut ? 0.5 : 1,
222
+ } },
221
223
  isSeatIcon && !hasDiscount && (React.createElement("img", { src: getSeatTypeIcon(seatLabel, serviceItem), alt: "seattype", style: {
222
224
  width: "20px",
223
225
  height: "20px",
@@ -4,7 +4,7 @@ import CommonService from "../../utils/CommonService";
4
4
  const ServiceBadges = ({ showTopLabel, isSoldOut, colors, renderIcon, translation, serviceItem, isAllinBus = false, boardingName, getAnimationIcon, }) => {
5
5
  return (React.createElement("div", { className: "absolute -top-[10px] left-0 w-full flex items-center justify-end gap-[12px] pr-[22px] z-10" },
6
6
  showTopLabel && (React.createElement("div", { className: `flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-10`, style: {
7
- backgroundColor: colors.topLabelBgColor || "rgb(255, 242, 235)",
7
+ backgroundColor: colors.topLabelBgColor || "#fff",
8
8
  border: isSoldOut
9
9
  ? "1px solid #ccc"
10
10
  : `1px solid ${colors.topLabelColor}`,
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import LottiePlayer from "../../assets/LottiePlayer";
3
+ import DateService from "../../utils/DateService";
3
4
  function BottomAmenitiesMobile({ isSoldOut, amenitiesNodes, hoursIcon, duration, isDirectTrip, directoColor, directoAnim, isChangeTicket, isPetSeat, petSeatInfo, petFriendlyAnim, flexibleAnim, isTrackingEnabled, locationAnim, downArrowIcon, showDropdown, setShowDropdown, onDropdownToggle, isItemExpanded, isPeru, femaleAnim, ladiesBookedSeats, isDpEnabled, }) {
4
5
  return (React.createElement("div", { className: `${"flex justify-between items-center items-center "}` },
5
6
  React.createElement("div", { className: "w-[55%] flex justify-between items-center" },
@@ -8,7 +9,7 @@ function BottomAmenitiesMobile({ isSoldOut, amenitiesNodes, hoursIcon, duration,
8
9
  React.createElement("div", { className: `w-[12px] h-auto mr-[2px] ${isSoldOut ? "grayscale" : ""}` }, hoursIcon),
9
10
  "\u00A0",
10
11
  React.createElement("div", { className: `cursor-default group min-[420]:text-[13px] text-[12px] ${isSoldOut ? "text-[#c0c0c0]" : ""}`, style: { lineHeight: "normal" } },
11
- duration,
12
+ DateService.formatDuration(duration),
12
13
  "hrs"))),
13
14
  React.createElement("div", { className: "flex items-center" },
14
15
  React.createElement("div", null, (isChangeTicket || isPetSeat) && (React.createElement("div", { className: "flex items-center" },
@@ -3,7 +3,7 @@ import CommonService from "../../utils/CommonService";
3
3
  const ServiceBadgesMobile = ({ showTopLabel, isSoldOut, colors, renderIcon, serviceItem, isConexion, isAllinBus = false, boardingName, }) => {
4
4
  return (React.createElement("div", { className: "absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[17px] z-10" },
5
5
  showTopLabel && (React.createElement("div", { className: `flex items-center gap-[2p x] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] h-[24px] z-20`, style: {
6
- backgroundColor: "#fff",
6
+ backgroundColor: colors.topLabelBgColor || "#fff",
7
7
  border: isSoldOut
8
8
  ? "1px solid #ccc"
9
9
  : `1px solid ${colors.topLabelColor}`,
@@ -14,5 +14,9 @@ declare const DateService: {
14
14
  * Format time string (HH:MM) to AM/PM format
15
15
  */
16
16
  formatTime: (time: string) => string;
17
+ /**
18
+ * Format duration string (HH:MM:SS) to HH:MM format
19
+ */
20
+ formatDuration: (duration: string | number | undefined | null) => string;
17
21
  };
18
22
  export default DateService;
@@ -168,5 +168,23 @@ const DateService = {
168
168
  return time;
169
169
  }
170
170
  },
171
+ /**
172
+ * Format duration string (HH:MM:SS) to HH:MM format
173
+ */
174
+ formatDuration: (duration) => {
175
+ if (duration === null || duration === undefined) {
176
+ return "";
177
+ }
178
+ const durationStr = duration.toString().trim();
179
+ if (durationStr.includes(":")) {
180
+ const parts = durationStr.split(":");
181
+ if (parts.length >= 2) {
182
+ const hours = parts[0].trim().padStart(2, "0");
183
+ const minutes = parts[1].trim();
184
+ return `${hours}:${minutes}`;
185
+ }
186
+ }
187
+ return durationStr;
188
+ },
171
189
  };
172
190
  export default DateService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "10.1.4",
3
+ "version": "10.1.6",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -223,7 +223,7 @@ class ServiceFilter extends React.Component<
223
223
  {shouldShowHeader && (
224
224
  <div
225
225
  onClick={() => this.toggleFilter(option.type)}
226
- className="bold-text flex items-center justify-between mt-[13px] mb-[5px]"
226
+ className="bold-text flex items-center justify-between mt-[20px] mb-[5px]"
227
227
  >
228
228
  {this.props.t("RESULTS_PAGE." + option.title)}
229
229
  <img
@@ -266,7 +266,7 @@ const renderSummaryDetailsCard = ({
266
266
  className="w-[16px] h-[16px] mr-[5px]"
267
267
  />
268
268
  </div>
269
- <span>Duración : {duration} horas</span>
269
+ <span>Duración : {DateService.formatDuration(duration)} horas</span>
270
270
  </div>
271
271
  )}
272
272
  </div>
@@ -167,7 +167,7 @@ const renderSummaryDetailsCard = ({
167
167
  <span className="bold-text">Duración:</span>{" "}
168
168
  {isTacna
169
169
  ? `${getRoundedHour(duration)}hrs aprox`
170
- : `${duration} horas`}
170
+ : `${DateService.formatDuration(duration)} horas`}
171
171
  </span>
172
172
  </div>
173
173
  )}
@@ -609,7 +609,7 @@ function PeruServiceItemDesktop({
609
609
  serviceItem?.is_direct_trip ||
610
610
  serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
611
611
  showTopLabel
612
- ? "mt-[30px]"
612
+ ? "mt-[20px]"
613
613
  : "mt-[20px]"
614
614
  } `}
615
615
  >
@@ -539,7 +539,7 @@ function ServiceItemPB({
539
539
  serviceItem?.is_direct_trip ||
540
540
  serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
541
541
  showTopLabel
542
- ? "mt-[30px]"
542
+ ? "mt-[20px]"
543
543
  : "mt-[20px]"
544
544
  } `}
545
545
  >
@@ -572,7 +572,7 @@ function ServiceItemPB({
572
572
  className=" pt-[20px]"
573
573
  style={{
574
574
  padding:
575
- hasDpEnabled || serviceItem?.offer_text
575
+ hasDpEnabled || (isNewUiEnabled && !isSoldOut)
576
576
  ? "20px 15px 10px 15px"
577
577
  : coachKey
578
578
  ? "20px 15px 20px 15px"
@@ -20,14 +20,12 @@ const TooltipArrow = ({ color }) => (
20
20
  />
21
21
  );
22
22
 
23
+ /*
23
24
  const getAmenitySplit = ({ isPeru, amenities, priorityIds }) => {
24
25
  const priority = amenities.filter((id) => priorityIds.includes(id));
25
26
  const nonPriority = amenities.filter((id) => !priorityIds.includes(id));
26
27
  const hasPriority = priority.length > 0;
27
28
 
28
- /* ============================
29
- 🇵🇪 PERU LOGIC
30
- ============================ */
31
29
  // if (isPeru) {
32
30
  // return hasPriority
33
31
  // ? { visible: priority, plus: nonPriority }
@@ -43,9 +41,6 @@ const getAmenitySplit = ({ isPeru, amenities, priorityIds }) => {
43
41
  : { visible: amenities.slice(0, 2), plus: amenities.slice(2) };
44
42
  }
45
43
 
46
- /* ============================
47
- 🌍 NON-PERU LOGIC
48
- ============================ */
49
44
  const sorted = [...amenities].sort(
50
45
  (a, b) => Number(priorityIds.includes(b)) - Number(priorityIds.includes(a)),
51
46
  );
@@ -55,6 +50,32 @@ const getAmenitySplit = ({ isPeru, amenities, priorityIds }) => {
55
50
  plus: sorted.slice(2),
56
51
  };
57
52
  };
53
+ */
54
+
55
+ const getAmenitySplit = ({ isPeru, amenities, priorityIds }) => {
56
+ // The three important amenities: Mobile ticket ("3"), USB charger ("2"), WiFi ("13")
57
+ const IMPORTANT_AMENITY_IDS = ["2", "3", "13"];
58
+
59
+ const important = amenities.filter((id) =>
60
+ IMPORTANT_AMENITY_IDS.includes(id),
61
+ );
62
+
63
+ const nonImportant = amenities.filter(
64
+ (id) => !IMPORTANT_AMENITY_IDS.includes(id),
65
+ );
66
+
67
+ if (important.length > 0) {
68
+ return {
69
+ visible: important,
70
+ plus: nonImportant,
71
+ };
72
+ }
73
+
74
+ return {
75
+ visible: [],
76
+ plus: amenities,
77
+ };
78
+ };
58
79
 
59
80
  const AmenitiesBlock = ({
60
81
  serviceItem,
@@ -87,6 +108,11 @@ const AmenitiesBlock = ({
87
108
  amenities,
88
109
  priorityIds,
89
110
  });
111
+ console.log(
112
+ "🚀 ~ AmenitiesBlock ~ visibleAmenities:",
113
+ visibleAmenities,
114
+ amenities,
115
+ );
90
116
 
91
117
  const shouldShowPlus = plusAmenities.length > 0;
92
118
  const grayscaleClass = isSoldOut ? "grayscale" : "";
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import DateService from "../utils/DateService";
2
3
 
3
4
  const DurationBlock = ({
4
5
  serviceItem,
@@ -17,7 +18,7 @@ const DurationBlock = ({
17
18
 
18
19
  <div className="group text-[13.33px] cursor-pointer">
19
20
  <span style={{ opacity: isSoldOut ? 0.5 : 1 }}>
20
- {serviceItem.duration} {translation.hours}
21
+ {DateService.formatDuration(serviceItem.duration)} {translation.hours}
21
22
  </span>
22
23
  <div
23
24
  className="hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-normal z-10 mt-2.5 w-[188px] text-center break-normal shadow-service text-[12px]"
@@ -251,15 +251,17 @@ const OfferBanner: React.FC<OfferBannerProps> = ({
251
251
 
252
252
  return (
253
253
  <div
254
- className="text-white p-[10px_15px] text-left w-full flex items-center absolute -bottom-[44px] pt-[50px] rounded-b-[14px] text-[14px] mt-[10px]"
254
+ className="text-white w-full absolute -bottom-[40px] pt-[20px] rounded-b-[14px] text-[14px] mt-[10px]"
255
255
  style={{
256
256
  background,
257
257
  opacity: isSoldOut ? 0.5 : 1,
258
- zIndex: isLinatal ? "-1" : "",
258
+ zIndex: isLinatal ? "-1" : "-1",
259
259
  }}
260
260
  >
261
- <div className="flex justify-between items-center w-full">
262
- <div className="flex items-center">{renderLeftContent()}</div>
261
+ <div className="flex justify-start items-center h-[44px] w-full gap-[20px] px-[15px]">
262
+ <div className="flex items-center justify-start">
263
+ {renderLeftContent()}
264
+ </div>
263
265
  {showViewers && (
264
266
  <ViewersCount
265
267
  serviceItem={serviceItem}
@@ -411,7 +411,12 @@ function SeatSection({
411
411
 
412
412
  <span className="text-[13.33px] flex flex-col">
413
413
  {!hasDiscount ? (
414
- <span className="text-[13.33px] whitespace-nowrap flex items-center">
414
+ <span
415
+ className="text-[13.33px] whitespace-nowrap flex items-center"
416
+ style={{
417
+ opacity: isSoldOut ? 0.5 : 1,
418
+ }}
419
+ >
415
420
  {isSeatIcon && !hasDiscount && (
416
421
  <img
417
422
  src={
@@ -37,7 +37,7 @@ const ServiceBadges: React.FC<ServiceBadgesProps> = ({
37
37
  <div
38
38
  className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-10`}
39
39
  style={{
40
- backgroundColor: colors.topLabelBgColor || "rgb(255, 242, 235)",
40
+ backgroundColor: colors.topLabelBgColor || "#fff",
41
41
  border: isSoldOut
42
42
  ? "1px solid #ccc"
43
43
  : `1px solid ${colors.topLabelColor}`,
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import LottiePlayer from "../../assets/LottiePlayer";
3
+ import DateService from "../../utils/DateService";
3
4
 
4
5
  interface BottomAmenitiesMobileProps {
5
6
  isSoldOut: boolean;
@@ -75,7 +76,7 @@ function BottomAmenitiesMobile({
75
76
  }`}
76
77
  style={{ lineHeight: "normal" }}
77
78
  >
78
- {duration}hrs
79
+ {DateService.formatDuration(duration)}hrs
79
80
  </div>
80
81
  </div>
81
82
 
@@ -35,7 +35,7 @@ const ServiceBadgesMobile: React.FC<ServiceBadgesMobileProps> = ({
35
35
  <div
36
36
  className={`flex items-center gap-[2p x] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] h-[24px] z-20`}
37
37
  style={{
38
- backgroundColor: "#fff",
38
+ backgroundColor: colors.topLabelBgColor || "#fff",
39
39
  border: isSoldOut
40
40
  ? "1px solid #ccc"
41
41
  : `1px solid ${colors.topLabelColor}`,
@@ -206,6 +206,25 @@ const DateService = {
206
206
  return time;
207
207
  }
208
208
  },
209
+
210
+ /**
211
+ * Format duration string (HH:MM:SS) to HH:MM format
212
+ */
213
+ formatDuration: (duration: string | number | undefined | null): string => {
214
+ if (duration === null || duration === undefined) {
215
+ return "";
216
+ }
217
+ const durationStr = duration.toString().trim();
218
+ if (durationStr.includes(":")) {
219
+ const parts = durationStr.split(":");
220
+ if (parts.length >= 2) {
221
+ const hours = parts[0].trim().padStart(2, "0");
222
+ const minutes = parts[1].trim();
223
+ return `${hours}:${minutes}`;
224
+ }
225
+ }
226
+ return durationStr;
227
+ },
209
228
  };
210
229
 
211
230
  export default DateService;