kupos-ui-components-lib 9.6.0 → 9.6.2

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.
@@ -111,9 +111,12 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
111
111
  : serviceItem.seat_types || [];
112
112
  const discountedSeats = seats.map((seat) => (Object.assign(Object.assign({}, seat), CommonService.calculateDiscountedPrice(seat.fare, serviceItem))));
113
113
  const hasDiscount = discountedSeats.some((seat) => seat.originalPrice !== seat.discountedPrice);
114
+ const dpDiscountEntry = Object.entries((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) || {})[0];
115
+ const dpDiscountPercent = dpDiscountEntry === null || dpDiscountEntry === void 0 ? void 0 : dpDiscountEntry[1];
116
+ const hasDpEnabled = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) === true;
114
117
  const offerGradient = `linear-gradient(90deg, ${colors.rightGradiantColor || "#ff5964"} 0%, ${colors.leftGradiantColor || "#ff8842"} 100%)`;
115
118
  const offerGradientWithOpacity = `linear-gradient(90deg, ${colors.rightGradiantColor || "#ff5964"}80 0%, ${colors.leftGradiantColor || "#ff8842"}80 100%)`;
116
- const serviceCardStyle = hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)
119
+ const serviceCardStyle = hasOfferText || hasDpEnabled
117
120
  ? {
118
121
  borderColor: "transparent",
119
122
  borderStyle: "solid",
@@ -236,22 +239,24 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
236
239
  },
237
240
  ];
238
241
  const otherItems = items.filter((i) => i.key !== "pet" && i.key !== "flexible" && !!i.condition);
239
- return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus })) : (React.createElement("div", { className: `relative hover:z-[150] ${hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) ? "mb-[55px]" : "mb-[10px]"} ${(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ||
242
+ return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus })) : (React.createElement("div", { className: `relative hover:z-[150] ${hasOfferText || hasDpEnabled ? "mb-[55px]" : "mb-[10px]"} ${(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ||
240
243
  (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" ||
241
244
  showTopLabel
242
245
  ? "mt-[24px]"
243
246
  : "mt-[20px]"} ` },
244
- ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)) && (React.createElement(OfferBanner, { offerGradient: offerGradient, isSoldOut: isSoldOut, serviceItem: serviceItem, renderIcon: renderIcon, isLoggedIn: isLoggedIn, showLoginModal: showLoginModal, viewersConfig: viewersConfig, getAnimationIcon: getAnimationIcon })),
245
- React.createElement("div", { id: `service-card-${serviceItem.id}`, className: `bg-white mx-auto relative ${hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)
247
+ ((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 })),
248
+ React.createElement("div", { id: `service-card-${serviceItem.id}`, className: `bg-white mx-auto relative ${(hasOfferText || hasDpEnabled) && !isSoldOut
246
249
  ? "z-[3] rounded-[18px]"
247
250
  : "rounded-[10px] border border-[#ccc]"}`, style: serviceCardStyle },
248
251
  React.createElement("div", { className: " pt-[20px]", style: {
249
- padding: (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text)
252
+ padding: hasDpEnabled || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text)
250
253
  ? "20px 15px 10px 15px"
251
254
  : coachKey
252
255
  ? "20px 15px 20px 15px"
253
256
  : "20px 15px 10px 15px",
254
- marginTop: hasDiscount || hasOfferText ? "14px" : "",
257
+ marginTop: hasDiscount || hasOfferText || dpDiscountPercent
258
+ ? "14px"
259
+ : "",
255
260
  } },
256
261
  React.createElement("div", { className: "grid text-[#464647] w-full [grid-template-columns:22%_28%_2.5%_24%_15.5%] gap-x-[2%] items-center" },
257
262
  React.createElement("div", { className: "flex flex-col gap-[5px]" },
@@ -280,11 +285,9 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
280
285
  gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
281
286
  transition: "grid-template-rows 0.3s ease-in-out, opacity 0.25s ease-in-out",
282
287
  position: "relative",
283
- zIndex: hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) ? 0 : -1,
288
+ zIndex: hasOfferText || hasDpEnabled ? 0 : -1,
284
289
  } },
285
- React.createElement("div", { style: Object.assign({ overflow: "hidden", minHeight: 0, marginTop: (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text)
286
- ? ""
287
- : "-10px" }, (hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)
290
+ 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
288
291
  ? {
289
292
  borderLeft: `3px solid ${isSoldOut ? "rgba(255, 89, 100, 0.5)" : "#ff5964"}`,
290
293
  borderRight: `3px solid ${isSoldOut ? "rgba(255, 136, 66, 0.5)" : "#ff8842"}`,
@@ -33,9 +33,9 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
33
33
  const offerGradientWithOpacity = `linear-gradient(90deg, ${colors.rightGradiantColor || "#ff5964"}80 0%, ${colors.leftGradiantColor || "#ff8842"}80 100%)`;
34
34
  const serviceCardStyle = hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)
35
35
  ? {
36
- borderColor: "transparent",
36
+ borderColor: isSoldOut ? "#ccc" : "transparent",
37
37
  borderStyle: "solid",
38
- borderWidth: "3px 3px 0 3px",
38
+ borderWidth: isSoldOut ? "1px" : "3px 3px 0 3px",
39
39
  borderRadius: "18px",
40
40
  background: `linear-gradient(#fff, #fff) padding-box, ${isSoldOut ? offerGradientWithOpacity : offerGradient} border-box`,
41
41
  }
@@ -93,7 +93,7 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
93
93
  showTopLabel
94
94
  ? "mt-[20px]"
95
95
  : "mt-[10px]"} `, style: { zIndex: 1 } },
96
- React.createElement("div", { className: `z-1 ${hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)
96
+ React.createElement("div", { className: `z-1 ${(hasOfferText || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)) && !isSoldOut
97
97
  ? "rounded-[18px]"
98
98
  : "rounded-[10px] border border-[#ccc]"}`, style: Object.assign(Object.assign({}, serviceCardStyle), { backgroundColor: "#fff" }) },
99
99
  React.createElement("div", { style: { padding: "12px 12px 8px 12px" } },
@@ -111,12 +111,18 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
111
111
  React.createElement("div", { className: "flex items-center cursor-pointer ", style: { color: isSoldOut ? "#bbb" : "text-[#464647]" } },
112
112
  React.createElement("span", { className: "ml-[3px] min-[420]:text-[13px] text-[12px] text-ellipsis overflow-hidden whitespace-nowrap max-w-[120px]" }, serviceItem.operator_details[2]))))) : null)),
113
113
  React.createElement(DateTimeSectionMobile, { onBookButtonPress: onBookButtonPress, isCiva: isCiva, isSoldOut: isSoldOut, isLinatal: isLinatal, isPeru: isPeru, orignLabel: orignLabel, destinationLabel: destinationLabel, originIcon: (_c = serviceItem.icons) === null || _c === void 0 ? void 0 : _c.origin, destinationIcon: (_d = serviceItem.icons) === null || _d === void 0 ? void 0 : _d.destination, travelDate: serviceItem.travel_date, arrivalDate: serviceItem.arrival_date, depTime: serviceItem.dep_time, arrTime: serviceItem.arr_time, seatTypes: serviceItem.seat_types, seatPriceColor: colors.seatPriceColor, tooltipBgColor: colors.tooltipBgColor, currencySign: currencySign, availableSeats: serviceItem.available_seats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, showLastSeats: showLastSeats }),
114
+ hasDiscount && (React.createElement("div", { className: "flex justify-end" }, isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)),
115
+ showLastSeats ? (React.createElement("div", { className: "flex justify-end " }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
116
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[10px] text-center", style: {
117
+ color: colors.tooltipBgColor,
118
+ } }, "\u00A1 \u00DAltimos Asientos!")))) : null,
114
119
  React.createElement("div", { className: "bg-[#E6E6E6] mt-[10px] mb-[8px] h-[1px]" }),
115
120
  React.createElement(BottomAmenitiesMobile, { isSoldOut: isSoldOut, amenitiesNodes: amenities(), hoursIcon: renderIcon("hours", "14px"), duration: (_e = serviceItem.duration) === null || _e === void 0 ? void 0 : _e.toString(), isDirectTrip: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip, directoColor: colors.directoColor, directoAnim: serviceItem.icons.directoAnim, isChangeTicket: serviceItem.is_change_ticket, isPetSeat: isPetSeat, petSeatInfo: serviceItem.pet_seat_info, petFriendlyAnim: serviceItem.icons.petFriendlyAnim, flexibleAnim: serviceItem.icons.flexibleAnim, isTrackingEnabled: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_tracking_enabled, locationAnim: serviceItem.icons.locationAnim, downArrowIcon: serviceItem.icons.downArrow, showDropdown: isItemExpanded, setShowDropdown: () => setIsExpanded(isItemExpanded ? null : serviceItem.id), onDropdownToggle: () => {
116
121
  setIsExpanded(isItemExpanded ? null : serviceItem.id);
117
122
  }, isPeru: isPeru })),
118
123
  React.createElement(ServiceBadgesMobile, { showTopLabel: showTopLabel, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, serviceItem: serviceItem, isConexion: isConexion })),
119
- ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)) && (React.createElement("div", { className: "px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]", style: {
124
+ ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled)) &&
125
+ !isSoldOut && (React.createElement("div", { className: "px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]", style: {
120
126
  background: isSoldOut ? offerGradientWithOpacity : offerGradient,
121
127
  // opacity: isSoldOut ? 0.5 : 1,
122
128
  borderRadius: "0 0 14px 14px",
@@ -39,6 +39,12 @@ export interface ServiceItemProps {
39
39
  offer_text?: string;
40
40
  is_direct_trip?: boolean;
41
41
  is_dp_enabled?: boolean;
42
+ dp_discount_percents?: Record<string, number | string> | Array<number | string>;
43
+ dp_discounted_seats?: Array<string | number>;
44
+ original_dp_price?: Record<string, number | string> | Array<number | string>;
45
+ discount_type?: string;
46
+ discount_value?: number;
47
+ max_discount?: number;
42
48
  is_transpordo?: boolean;
43
49
  is_train_type?: boolean;
44
50
  operator_service_name?: string;
@@ -55,7 +55,7 @@ function getNumberOfSeats(seatTypes) {
55
55
  return seatTypes.filter((val) => !SEAT_EXCEPTIONS.includes(val.label)).length;
56
56
  }
57
57
  function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, isPeru, serviceItem, renderIcon, dpSeatColor, }) {
58
- var _a, _b;
58
+ var _a, _b, _c;
59
59
  const uniqueSeats = getUniqueSeats(seatTypes);
60
60
  const sortedSeatTypes = getSortedSeatTypes(seatTypes);
61
61
  const numberOfSeats = getNumberOfSeats(seatTypes);
@@ -117,13 +117,50 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
117
117
  }
118
118
  return renderSeatNames();
119
119
  };
120
- const _dpSeatsFirstVal = Array.isArray(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats)
121
- ? serviceItem.dp_discounted_seats[0]
122
- : Object.values((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discounted_seats) || {})[0];
123
- const _dpPercentsFirstVal = Array.isArray(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents)
124
- ? serviceItem.dp_discount_percents[0]
125
- : Object.values((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) || {})[0];
126
- if ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) && !_dpSeatsFirstVal && !_dpPercentsFirstVal) {
120
+ // const dpDiscountEntry = Object.entries(
121
+ // serviceItem?.dp_discount_percents || {},
122
+ // ).find(([, percent]) => Number(percent));
123
+ const dpDiscountEntry = Object.entries((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dp_discount_percents) || {})[0];
124
+ const dpDiscountPercent = dpDiscountEntry === null || dpDiscountEntry === void 0 ? void 0 : dpDiscountEntry[1];
125
+ const getFirstDpValue = (source) => {
126
+ if (!source)
127
+ return undefined;
128
+ return Array.isArray(source) ? source[0] : Object.values(source)[0];
129
+ };
130
+ const renderDpDiscountUi = (originalDpPrice, seatTypeFare) => {
131
+ return (React.createElement("div", { className: "grid grid-cols-2 items-center text-[13.33px] relative" },
132
+ React.createElement("div", { className: "col-start-1 row-start-2 flex items-center" },
133
+ React.createElement("span", { className: "text-[13.33px] font-normal leading-[22px] text-[#ccc]" }, "Antes")),
134
+ React.createElement("div", { className: "col-start-1 row-start-3 flex h-[20px] items-end" },
135
+ React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#464647]" }, "Desde")),
136
+ 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)) &&
137
+ Number(dpDiscountPercent) > 0 && (React.createElement("span", { className: "rounded-[100px] bg-[#ff5964] px-[6px] text-[12px] bold-text leading-[20px] text-white", style: {
138
+ animation: "pulse-zoom 2s ease-in-out infinite",
139
+ whiteSpace: "nowrap",
140
+ } },
141
+ Math.round(Number(dpDiscountPercent)),
142
+ "% OFF"))),
143
+ React.createElement("div", { className: "col-start-2 row-start-2 flex items-center justify-center", style: { textAlign: "center" } },
144
+ React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative", style: { position: "relative" } },
145
+ formatPrice(Number(originalDpPrice)),
146
+ React.createElement("span", { style: {
147
+ position: "absolute",
148
+ left: "-2px",
149
+ top: "50%",
150
+ width: "calc(100% + 4px)",
151
+ height: "1px",
152
+ backgroundColor: "#9f9f9f",
153
+ transform: "rotate(-10deg)",
154
+ transformOrigin: "center",
155
+ } }))),
156
+ React.createElement("div", { className: "col-start-2 row-start-3 flex h-[30px] items-end justify-center relative" },
157
+ React.createElement("span", { className: "flex items-center gap-[6px] text-[22px] bold-text leading-[30px]", style: { color: isSoldOut ? "#c0c0c0" : "#ff5964" } },
158
+ React.createElement("div", { className: "absolute", style: { left: isPeru ? "-1px" : "-8px" } }, renderIcon("fireIcon", "16px")),
159
+ availableSeats <= 0
160
+ ? CommonService.currency(0, currencySign)
161
+ : CommonService.discountedCurrency(Number(seatTypeFare), currencySign)))));
162
+ };
163
+ if ((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_dp_enabled) && !dpDiscountEntry) {
127
164
  const dpSeats = (removeDuplicateSeats ? uniqueSeats : sortedSeatTypes).filter((s) => !SEAT_EXCEPTIONS.includes(s.label));
128
165
  const lowestFare = dpSeats.length > 0 ? Math.min(...dpSeats.map((s) => Number(s.price))) : 0;
129
166
  return (React.createElement("div", { className: "flex items-center justify-between text-[13.33px] ", style: {
@@ -148,50 +185,15 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
148
185
  ? CommonService.currency(0, currencySign)
149
186
  : CommonService.discountedCurrency(lowestFare, currencySign))))));
150
187
  }
151
- if (_dpSeatsFirstVal && _dpPercentsFirstVal) {
152
- const originalDpPrice = Array.isArray(serviceItem.original_dp_price)
153
- ? serviceItem.original_dp_price[0]
154
- : Object.values(serviceItem.original_dp_price || {})[0];
155
- const dpDiscountPercent = Array.isArray(serviceItem.dp_discount_percents)
156
- ? serviceItem.dp_discount_percents[0]
157
- : Object.values(serviceItem.dp_discount_percents || {})[0];
158
- const seatTypeFare = (_b = (_a = serviceItem.seat_types) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.fare;
188
+ if (dpDiscountEntry) {
189
+ const originalDpPrice = getFirstDpValue(serviceItem.original_dp_price);
190
+ const seatTypeFare = (_c = (_b = (_a = serviceItem.seat_types) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.fare) !== null && _c !== void 0 ? _c : originalDpPrice;
159
191
  if (originalDpPrice && seatTypeFare) {
160
- return (React.createElement("div", { className: "grid grid-cols-2 items-center text-[13.33px] relative" },
161
- React.createElement("div", { className: "col-start-1 row-start-2 flex items-center" },
162
- React.createElement("span", { className: "text-[13.33px] font-normal leading-[22px] text-[#ccc]" }, "Antes")),
163
- React.createElement("div", { className: "col-start-1 row-start-3 flex h-[20px] items-end" },
164
- React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#464647]" }, "Desde")),
165
- 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)) &&
166
- Number(dpDiscountPercent) > 0 && (React.createElement("span", { className: "rounded-[100px] bg-[#ff5964] px-[6px] text-[12px] bold-text leading-[20px] text-white", style: {
167
- animation: "pulse-zoom 2s ease-in-out infinite",
168
- whiteSpace: "nowrap",
169
- } },
170
- Math.round(Number(dpDiscountPercent)),
171
- "% OFF"))),
172
- React.createElement("div", { className: "col-start-2 row-start-2 flex items-center justify-center", style: { textAlign: "center" } },
173
- React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative", style: { position: "relative" } },
174
- formatPrice(Number(originalDpPrice)),
175
- React.createElement("span", { style: {
176
- position: "absolute",
177
- left: "-2px",
178
- top: "50%",
179
- width: "calc(100% + 4px)",
180
- height: "1px",
181
- backgroundColor: "#9f9f9f",
182
- transform: "rotate(-10deg)",
183
- transformOrigin: "center",
184
- } }))),
185
- React.createElement("div", { className: "col-start-2 row-start-3 flex h-[30px] items-end justify-center relative" },
186
- React.createElement("span", { className: "flex items-center gap-[6px] text-[22px] bold-text leading-[30px]", style: { color: isSoldOut ? "#c0c0c0" : "#ff5964" } },
187
- React.createElement("div", { className: "absolute", style: { left: isPeru ? "-1px" : "-8px" } }, renderIcon("fireIcon", "16px")),
188
- availableSeats <= 0
189
- ? CommonService.currency(0, currencySign)
190
- : CommonService.discountedCurrency(Number(seatTypeFare), currencySign)))));
192
+ return renderDpDiscountUi(originalDpPrice, seatTypeFare);
191
193
  }
192
194
  }
193
195
  if (hasDiscount && discountSeat) {
194
- return (React.createElement("div", { className: "grid grid-cols-2 items-center text-[13.33px] relative" },
196
+ return (React.createElement("div", { className: "grid grid-cols-2 items-center text-[13.33px] relative", style: { opacity: isSoldOut ? 0.5 : 1 } },
195
197
  React.createElement("div", { className: "col-start-1 row-start-2 flex items-center" },
196
198
  React.createElement("span", { className: "text-[13.33px] font-normal leading-[22px] text-[#ccc]" }, "Antes")),
197
199
  React.createElement("div", { className: "col-start-1 row-start-3 flex h-[20px] items-end" },
@@ -178,45 +178,42 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
178
178
  React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#ff5964" } },
179
179
  ((_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,
180
180
  commonService.discountedCurrency(Number(firstSeatFare), currencySign)),
181
- 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", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
182
- discountValue != null && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
183
- animation: "pulse-zoom 2s ease-in-out infinite",
184
- } },
185
- React.createElement("span", { className: "rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]", style: {
186
- backgroundColor: tooltipBgColor,
181
+ 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,
182
+ React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
183
+ discountValue != null && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
184
+ animation: "pulse-zoom 2s ease-in-out infinite",
185
+ opacity: isSoldOut ? 0.5 : 1,
187
186
  } },
188
- discountValue,
189
- "% OFF"))),
190
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]" }, "Antes"),
191
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f] text-right", style: {
192
- position: "relative",
193
- display: "inline-block",
194
- overflow: "hidden",
195
- } },
196
- commonService.currency(discountSeat.originalPrice, currencySign),
197
- React.createElement("span", { style: {
198
- position: "absolute",
199
- top: "35%",
200
- left: "50%",
201
- width: "80%",
202
- height: "1px",
203
- background: "#9f9f9f",
204
- transform: "rotate(-12deg)",
205
- transformOrigin: "center",
206
- } })),
207
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#464647" } }, "Desde"),
208
- React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#ff5964" } },
209
- ((_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: { filter: isSoldOut ? "grayscale" : "" } })) : null,
210
- commonService.discountedCurrency(discountSeat.discountedPrice, currencySign)),
211
- isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)) : (React.createElement("div", { className: "flex flex-col justify-between h-[2.5rem] ", style: {
187
+ React.createElement("span", { className: "rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]", style: {
188
+ backgroundColor: tooltipBgColor,
189
+ } },
190
+ discountValue,
191
+ "% OFF"))),
192
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]" }, "Antes"),
193
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f] text-right", style: {
194
+ position: "relative",
195
+ display: "inline-block",
196
+ overflow: "hidden",
197
+ } },
198
+ commonService.currency(discountSeat.originalPrice, currencySign),
199
+ React.createElement("span", { style: {
200
+ position: "absolute",
201
+ top: "35%",
202
+ left: "50%",
203
+ width: "80%",
204
+ height: "1px",
205
+ background: "#9f9f9f",
206
+ transform: "rotate(-12deg)",
207
+ transformOrigin: "center",
208
+ } })),
209
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#464647" } }, "Desde"),
210
+ React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#ff5964" } },
211
+ ((_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,
212
+ commonService.discountedCurrency(discountSeat.discountedPrice, currencySign))))) : (React.createElement("div", { className: "flex flex-col justify-between h-[2.5rem] ", style: {
212
213
  gap: isSoldOut ? "0px" : "5px",
213
214
  justifyContent: hasMultipleTypes ? "space-between" : "center",
214
215
  } },
215
216
  renderSeats(),
216
- showLastSeats ? (React.createElement("div", { className: "flex justify-end " }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
217
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[10px] text-center", style: {
218
- color: tooltipBgColor,
219
- } }, "\u00A1 \u00DAltimos Asientos!")))) : null,
220
217
  isSoldOut ? (React.createElement("div", { className: "flex justify-end" },
221
218
  React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] text-[#ccc]" }, "Agotado"))) : null))));
222
219
  }
@@ -312,6 +312,9 @@ const commonService = {
312
312
  startCountdown: (node, countdownSeconds = 599) => {
313
313
  if (!node)
314
314
  return;
315
+ if (node.dataset.timerStarted)
316
+ return;
317
+ node.dataset.timerStarted = "true";
315
318
  const prevId = node.dataset.countdownId;
316
319
  if (prevId)
317
320
  clearInterval(Number(prevId));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "9.6.0",
3
+ "version": "9.6.2",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -190,10 +190,16 @@ function ServiceItemPB({
190
190
  (seat) => seat.originalPrice !== seat.discountedPrice,
191
191
  );
192
192
 
193
+ const dpDiscountEntry = Object.entries(
194
+ serviceItem?.dp_discount_percents || {},
195
+ )[0];
196
+ const dpDiscountPercent = dpDiscountEntry?.[1];
197
+ const hasDpEnabled = serviceItem?.is_dp_enabled === true;
198
+
193
199
  const offerGradient = `linear-gradient(90deg, ${colors.rightGradiantColor || "#ff5964"} 0%, ${colors.leftGradiantColor || "#ff8842"} 100%)`;
194
200
  const offerGradientWithOpacity = `linear-gradient(90deg, ${colors.rightGradiantColor || "#ff5964"}80 0%, ${colors.leftGradiantColor || "#ff8842"}80 100%)`;
195
201
  const serviceCardStyle: React.CSSProperties =
196
- hasOfferText || serviceItem?.is_dp_enabled
202
+ hasOfferText || hasDpEnabled
197
203
  ? {
198
204
  borderColor: "transparent",
199
205
  borderStyle: "solid",
@@ -406,7 +412,7 @@ function ServiceItemPB({
406
412
  />
407
413
  ) : (
408
414
  <div
409
- className={`relative hover:z-[150] ${hasOfferText || serviceItem?.is_dp_enabled ? "mb-[55px]" : "mb-[10px]"} ${
415
+ className={`relative hover:z-[150] ${hasOfferText || hasDpEnabled ? "mb-[55px]" : "mb-[10px]"} ${
410
416
  serviceItem?.is_direct_trip ||
411
417
  serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
412
418
  showTopLabel
@@ -414,7 +420,7 @@ function ServiceItemPB({
414
420
  : "mt-[20px]"
415
421
  } `}
416
422
  >
417
- {(serviceItem?.offer_text || serviceItem?.is_dp_enabled) && (
423
+ {(serviceItem?.offer_text || hasDpEnabled) && !isSoldOut && (
418
424
  <OfferBanner
419
425
  offerGradient={offerGradient}
420
426
  isSoldOut={isSoldOut}
@@ -429,7 +435,7 @@ function ServiceItemPB({
429
435
  <div
430
436
  id={`service-card-${serviceItem.id}`}
431
437
  className={`bg-white mx-auto relative ${
432
- hasOfferText || serviceItem?.is_dp_enabled
438
+ (hasOfferText || hasDpEnabled) && !isSoldOut
433
439
  ? "z-[3] rounded-[18px]"
434
440
  : "rounded-[10px] border border-[#ccc]"
435
441
  }`}
@@ -439,13 +445,16 @@ function ServiceItemPB({
439
445
  className=" pt-[20px]"
440
446
  style={{
441
447
  padding:
442
- serviceItem?.is_dp_enabled || serviceItem?.offer_text
448
+ hasDpEnabled || serviceItem?.offer_text
443
449
  ? "20px 15px 10px 15px"
444
450
  : coachKey
445
451
  ? "20px 15px 20px 15px"
446
452
  : "20px 15px 10px 15px",
447
453
 
448
- marginTop: hasDiscount || hasOfferText ? "14px" : "",
454
+ marginTop:
455
+ hasDiscount || hasOfferText || dpDiscountPercent
456
+ ? "14px"
457
+ : "",
449
458
  }}
450
459
  >
451
460
  <div className="grid text-[#464647] w-full [grid-template-columns:22%_28%_2.5%_24%_15.5%] gap-x-[2%] items-center">
@@ -569,7 +578,7 @@ function ServiceItemPB({
569
578
  transition:
570
579
  "grid-template-rows 0.3s ease-in-out, opacity 0.25s ease-in-out",
571
580
  position: "relative",
572
- zIndex: hasOfferText || serviceItem?.is_dp_enabled ? 0 : -1,
581
+ zIndex: hasOfferText || hasDpEnabled ? 0 : -1,
573
582
  }}
574
583
  >
575
584
  <div
@@ -577,10 +586,8 @@ function ServiceItemPB({
577
586
  overflow: "hidden",
578
587
  minHeight: 0,
579
588
  marginTop:
580
- serviceItem?.is_dp_enabled || serviceItem?.offer_text
581
- ? ""
582
- : "-10px",
583
- ...(hasOfferText || serviceItem?.is_dp_enabled
589
+ hasDpEnabled || serviceItem?.offer_text ? "" : "-10px",
590
+ ...(hasOfferText || hasDpEnabled
584
591
  ? {
585
592
  borderLeft: `3px solid ${isSoldOut ? "rgba(255, 89, 100, 0.5)" : "#ff5964"}`,
586
593
  borderRight: `3px solid ${isSoldOut ? "rgba(255, 136, 66, 0.5)" : "#ff8842"}`,
@@ -74,9 +74,9 @@ function ServiceItemMobile({
74
74
  const serviceCardStyle: React.CSSProperties =
75
75
  hasOfferText || serviceItem?.is_dp_enabled
76
76
  ? {
77
- borderColor: "transparent",
77
+ borderColor: isSoldOut ? "#ccc" : "transparent",
78
78
  borderStyle: "solid",
79
- borderWidth: "3px 3px 0 3px",
79
+ borderWidth: isSoldOut ? "1px" : "3px 3px 0 3px",
80
80
  borderRadius: "18px",
81
81
  background: `linear-gradient(#fff, #fff) padding-box, ${isSoldOut ? offerGradientWithOpacity : offerGradient} border-box`,
82
82
  }
@@ -166,7 +166,7 @@ function ServiceItemMobile({
166
166
  >
167
167
  <div
168
168
  className={`z-1 ${
169
- hasOfferText || serviceItem?.is_dp_enabled
169
+ (hasOfferText || serviceItem?.is_dp_enabled) && !isSoldOut
170
170
  ? "rounded-[18px]"
171
171
  : "rounded-[10px] border border-[#ccc]"
172
172
  }`}
@@ -249,6 +249,32 @@ function ServiceItemMobile({
249
249
  showLastSeats={showLastSeats}
250
250
  />
251
251
 
252
+ {hasDiscount && (
253
+ <div className="flex justify-end">
254
+ {isSoldOut ? (
255
+ <span className="col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]">
256
+ Agotado
257
+ </span>
258
+ ) : null}
259
+ </div>
260
+ )}
261
+
262
+ {showLastSeats ? (
263
+ <div className="flex justify-end ">
264
+ {serviceItem?.available_seats < 10 &&
265
+ serviceItem?.available_seats > 0 && (
266
+ <div
267
+ className="text-[10px] text-center"
268
+ style={{
269
+ color: colors.tooltipBgColor,
270
+ }}
271
+ >
272
+ ¡ Últimos Asientos!
273
+ </div>
274
+ )}
275
+ </div>
276
+ ) : null}
277
+
252
278
  {/* <div className="bg-[#E6E6E6] -ml-[12px] -mr-[12px] mt-[10px] mb-[10px] h-[1px]"></div> */}
253
279
  <div className="bg-[#E6E6E6] mt-[10px] mb-[8px] h-[1px]"></div>
254
280
 
@@ -290,102 +316,105 @@ function ServiceItemMobile({
290
316
  </div>
291
317
 
292
318
  {/* 🔹 EXPANDABLE DROPDOWN (below the card) */}
293
- {(serviceItem?.offer_text || serviceItem?.is_dp_enabled) && (
294
- <div
295
- className="px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]"
296
- style={{
297
- background: isSoldOut ? offerGradientWithOpacity : offerGradient,
298
- // opacity: isSoldOut ? 0.5 : 1,
299
- borderRadius: "0 0 14px 14px",
300
- zIndex: -1,
301
- }}
302
- >
319
+ {(serviceItem?.offer_text || serviceItem?.is_dp_enabled) &&
320
+ !isSoldOut && (
303
321
  <div
304
- className="flex flex-col gap-[8px] text-[12px] min-[420px]:text-[12px] text-[#464647]"
305
- style={{ lineHeight: 1.6 }}
322
+ className="px-[12px] pt-[22px] pb-[8px] relative -z-9 -mt-[15px]"
323
+ style={{
324
+ background: isSoldOut ? offerGradientWithOpacity : offerGradient,
325
+ // opacity: isSoldOut ? 0.5 : 1,
326
+ borderRadius: "0 0 14px 14px",
327
+ zIndex: -1,
328
+ }}
306
329
  >
307
- <div className="flex justify-between items-center">
308
- {serviceItem?.is_dp_enabled ? (
309
- <div className="flex items-center gap-[6px]">
310
- {/* {renderIcon("whiteFireIcon", "14px")} */}
311
- <LottiePlayer
312
- animationData={serviceItem.icons.starAnimation}
313
- width="14px"
314
- height="14px"
315
- />
316
-
317
- <span className="text-[#fff]">Más elegido</span>
318
- </div>
319
- ) : (
320
- <div
321
- className={`flex ${(serviceItem?.offer_text || "").length > 10 ? "items-start" : "items-center"}`}
322
- >
323
- <div className={isLongOfferText ? "mt-[2px]" : ""}>
330
+ <div
331
+ className="flex flex-col gap-[8px] text-[12px] min-[420px]:text-[12px] text-[#464647]"
332
+ style={{ lineHeight: 1.6 }}
333
+ >
334
+ <div className="flex justify-between items-center">
335
+ {serviceItem?.is_dp_enabled ? (
336
+ <div className="flex items-center gap-[6px]">
337
+ {/* {renderIcon("whiteFireIcon", "14px")} */}
324
338
  <LottiePlayer
325
- animationData={serviceItem.icons.bombAnim}
339
+ animationData={serviceItem.icons.starAnimation}
326
340
  width="14px"
327
341
  height="14px"
328
342
  />
343
+
344
+ <span className="text-[#fff]">Más elegido</span>
329
345
  </div>
346
+ ) : (
330
347
  <div
331
- className={`ml-[4px] flex-1 outline-none ${isLongOfferText ? "mt-[2px]" : ""}`}
332
- style={{
333
- color: "#fff",
334
- lineHeight: 1.4,
335
- }}
348
+ className={`flex ${(serviceItem?.offer_text || "").length > 10 ? "items-start" : "items-center"}`}
336
349
  >
337
- <span className="whitespace-nowrap min-[380px]:text-[12px]">
338
- Termina en&nbsp;
339
- <span
340
- className="bold-text"
341
- ref={(node) => commonService.startCountdown(node, 599)}
342
- style={{
343
- fontVariantNumeric: "tabular-nums",
344
- display: "inline-block",
345
- }}
350
+ <div className={isLongOfferText ? "mt-[2px]" : ""}>
351
+ <LottiePlayer
352
+ animationData={serviceItem.icons.bombAnim}
353
+ width="14px"
354
+ height="14px"
346
355
  />
347
- </span>
348
- </div>
349
- </div>
350
- )}
351
- <div
352
- className="flex flex-col items-end"
353
- style={{
354
- color: "#fff",
355
- }}
356
- >
357
- <div className="flex items-center">
358
- <div className="mr-[4px]">
359
- {" "}
360
- <LottiePlayer
361
- animationData={serviceItem.icons.dotAnimation}
362
- width="12px"
363
- height="12px"
364
- />
356
+ </div>
357
+ <div
358
+ className={`ml-[4px] flex-1 outline-none ${isLongOfferText ? "mt-[2px]" : ""}`}
359
+ style={{
360
+ color: "#fff",
361
+ lineHeight: 1.4,
362
+ }}
363
+ >
364
+ <span className="whitespace-nowrap min-[380px]:text-[12px]">
365
+ Termina en&nbsp;
366
+ <span
367
+ className="bold-text"
368
+ ref={(node) =>
369
+ commonService.startCountdown(node, 599)
370
+ }
371
+ style={{
372
+ fontVariantNumeric: "tabular-nums",
373
+ display: "inline-block",
374
+ }}
375
+ />
376
+ </span>
377
+ </div>
365
378
  </div>
366
- <span className="flex-1" style={{ lineHeight: 1.4 }}>
367
- <span
368
- className="bold-text"
369
- ref={(node) =>
370
- commonService.startViewerCount(node, viewersConfig)
371
- }
372
- style={{ fontVariantNumeric: "tabular-nums" }}
373
- />{" "}
374
- <span> viendo</span> |{" "}
375
- <span className="whitespace-nowrap">
376
- {/* {serviceItem?.is_dp_enabled ? null : "Quedan pocos • "} */}
379
+ )}
380
+ <div
381
+ className="flex flex-col items-end"
382
+ style={{
383
+ color: "#fff",
384
+ }}
385
+ >
386
+ <div className="flex items-center">
387
+ <div className="mr-[4px]">
388
+ {" "}
389
+ <LottiePlayer
390
+ animationData={serviceItem.icons.dotAnimation}
391
+ width="12px"
392
+ height="12px"
393
+ />
394
+ </div>
395
+ <span className="flex-1" style={{ lineHeight: 1.4 }}>
377
396
  <span
378
397
  className="bold-text"
379
398
  ref={(node) =>
380
- commonService.startComprandoCount(node, 4, 16)
399
+ commonService.startViewerCount(node, viewersConfig)
381
400
  }
382
401
  style={{ fontVariantNumeric: "tabular-nums" }}
383
402
  />{" "}
384
- comprando
403
+ <span> viendo</span> |{" "}
404
+ <span className="whitespace-nowrap">
405
+ {/* {serviceItem?.is_dp_enabled ? null : "Quedan pocos • "} */}
406
+ <span
407
+ className="bold-text"
408
+ ref={(node) =>
409
+ commonService.startComprandoCount(node, 4, 16)
410
+ }
411
+ style={{ fontVariantNumeric: "tabular-nums" }}
412
+ />{" "}
413
+ comprando
414
+ </span>
385
415
  </span>
386
- </span>
387
- </div>
388
- {/* <div className="flex items-center">
416
+ </div>
417
+ {/* <div className="flex items-center">
389
418
  <span className="whitespace-nowrap">
390
419
  {serviceItem?.is_dp_enabled ? null : "Quedan pocos • "}
391
420
  <span
@@ -398,9 +427,9 @@ function ServiceItemMobile({
398
427
  comprando
399
428
  </span>
400
429
  </div> */}
430
+ </div>
401
431
  </div>
402
- </div>
403
- {/* <div className="flex flex-col gap-[4px]">
432
+ {/* <div className="flex flex-col gap-[4px]">
404
433
  <div
405
434
  className={`flex ${isLongOfferText ? "items-start" : "items-center"}`}
406
435
  >
@@ -456,9 +485,9 @@ function ServiceItemMobile({
456
485
  </span>
457
486
  </div>
458
487
  </div> */}
488
+ </div>
459
489
  </div>
460
- </div>
461
- )}
490
+ )}
462
491
  <div
463
492
  style={{
464
493
  display: "grid",
@@ -41,6 +41,12 @@ export interface ServiceItemProps {
41
41
  offer_text?: string;
42
42
  is_direct_trip?: boolean;
43
43
  is_dp_enabled?: boolean;
44
+ dp_discount_percents?: Record<string, number | string> | Array<number | string>;
45
+ dp_discounted_seats?: Array<string | number>;
46
+ original_dp_price?: Record<string, number | string> | Array<number | string>;
47
+ discount_type?: string;
48
+ discount_value?: number;
49
+ max_discount?: number;
44
50
  is_transpordo?: boolean;
45
51
  is_train_type?: boolean;
46
52
  operator_service_name?: string;
@@ -222,14 +222,102 @@ function SeatSection({
222
222
  return renderSeatNames();
223
223
  };
224
224
 
225
- const _dpSeatsFirstVal = Array.isArray(serviceItem?.dp_discounted_seats)
226
- ? serviceItem.dp_discounted_seats[0]
227
- : Object.values(serviceItem?.dp_discounted_seats || {})[0];
228
- const _dpPercentsFirstVal = Array.isArray(serviceItem?.dp_discount_percents)
229
- ? serviceItem.dp_discount_percents[0]
230
- : Object.values(serviceItem?.dp_discount_percents || {})[0];
231
-
232
- if (serviceItem?.is_dp_enabled && !_dpSeatsFirstVal && !_dpPercentsFirstVal) {
225
+ // const dpDiscountEntry = Object.entries(
226
+ // serviceItem?.dp_discount_percents || {},
227
+ // ).find(([, percent]) => Number(percent));
228
+ const dpDiscountEntry = Object.entries(
229
+ serviceItem?.dp_discount_percents || {},
230
+ )[0];
231
+ const dpDiscountPercent = dpDiscountEntry?.[1];
232
+ const getFirstDpValue = (source: any) => {
233
+ if (!source) return undefined;
234
+ return Array.isArray(source) ? source[0] : Object.values(source)[0];
235
+ };
236
+
237
+ const renderDpDiscountUi = (
238
+ originalDpPrice: number | string,
239
+ seatTypeFare: number | string,
240
+ ) => {
241
+ return (
242
+ <div className="grid grid-cols-2 items-center text-[13.33px] relative">
243
+ <div className="col-start-1 row-start-2 flex items-center">
244
+ <span className="text-[13.33px] font-normal leading-[22px] text-[#ccc]">
245
+ Antes
246
+ </span>
247
+ </div>
248
+
249
+ <div className="col-start-1 row-start-3 flex h-[20px] items-end">
250
+ <span className="text-[13.33px] font-normal leading-[20px] text-[#464647]">
251
+ Desde
252
+ </span>
253
+ </div>
254
+
255
+ <div
256
+ className="col-start-2 row-start-1 flex items-center justify-center absolute"
257
+ style={{ top: "-22px", left: "50%", transform: "translateX(-50%)" }}
258
+ >
259
+ {!isNaN(Number(dpDiscountPercent)) &&
260
+ Number(dpDiscountPercent) > 0 && (
261
+ <span
262
+ className="rounded-[100px] bg-[#ff5964] px-[6px] text-[12px] bold-text leading-[20px] text-white"
263
+ style={{
264
+ animation: "pulse-zoom 2s ease-in-out infinite",
265
+ whiteSpace: "nowrap",
266
+ }}
267
+ >
268
+ {Math.round(Number(dpDiscountPercent))}% OFF
269
+ </span>
270
+ )}
271
+ </div>
272
+
273
+ <div
274
+ className="col-start-2 row-start-2 flex items-center justify-center"
275
+ style={{ textAlign: "center" }}
276
+ >
277
+ <span
278
+ className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative"
279
+ style={{ position: "relative" }}
280
+ >
281
+ {formatPrice(Number(originalDpPrice))}
282
+ <span
283
+ style={{
284
+ position: "absolute",
285
+ left: "-2px",
286
+ top: "50%",
287
+ width: "calc(100% + 4px)",
288
+ height: "1px",
289
+ backgroundColor: "#9f9f9f",
290
+ transform: "rotate(-10deg)",
291
+ transformOrigin: "center",
292
+ }}
293
+ />
294
+ </span>
295
+ </div>
296
+
297
+ <div className="col-start-2 row-start-3 flex h-[30px] items-end justify-center relative">
298
+ <span
299
+ className="flex items-center gap-[6px] text-[22px] bold-text leading-[30px]"
300
+ style={{ color: isSoldOut ? "#c0c0c0" : "#ff5964" }}
301
+ >
302
+ <div
303
+ className="absolute"
304
+ style={{ left: isPeru ? "-1px" : "-8px" }}
305
+ >
306
+ {renderIcon("fireIcon", "16px")}
307
+ </div>
308
+ {availableSeats <= 0
309
+ ? CommonService.currency(0, currencySign)
310
+ : CommonService.discountedCurrency(
311
+ Number(seatTypeFare),
312
+ currencySign,
313
+ )}
314
+ </span>
315
+ </div>
316
+ </div>
317
+ );
318
+ };
319
+
320
+ if (serviceItem?.is_dp_enabled && !dpDiscountEntry) {
233
321
  const dpSeats = (
234
322
  removeDuplicateSeats ? uniqueSeats : sortedSeatTypes
235
323
  ).filter((s) => !SEAT_EXCEPTIONS.includes(s.label));
@@ -286,99 +374,21 @@ function SeatSection({
286
374
  );
287
375
  }
288
376
 
289
- if (_dpSeatsFirstVal && _dpPercentsFirstVal) {
290
- const originalDpPrice = Array.isArray(serviceItem.original_dp_price)
291
- ? serviceItem.original_dp_price[0]
292
- : Object.values(serviceItem.original_dp_price || {})[0];
293
- const dpDiscountPercent = Array.isArray(serviceItem.dp_discount_percents)
294
- ? serviceItem.dp_discount_percents[0]
295
- : Object.values(serviceItem.dp_discount_percents || {})[0];
296
- const seatTypeFare = serviceItem.seat_types?.[0]?.fare;
377
+ if (dpDiscountEntry) {
378
+ const originalDpPrice = getFirstDpValue(serviceItem.original_dp_price);
379
+ const seatTypeFare = serviceItem.seat_types?.[0]?.fare ?? originalDpPrice;
297
380
 
298
381
  if (originalDpPrice && seatTypeFare) {
299
- return (
300
- <div className="grid grid-cols-2 items-center text-[13.33px] relative">
301
- <div className="col-start-1 row-start-2 flex items-center">
302
- <span className="text-[13.33px] font-normal leading-[22px] text-[#ccc]">
303
- Antes
304
- </span>
305
- </div>
306
-
307
- <div className="col-start-1 row-start-3 flex h-[20px] items-end">
308
- <span className="text-[13.33px] font-normal leading-[20px] text-[#464647]">
309
- Desde
310
- </span>
311
- </div>
312
-
313
- <div
314
- className="col-start-2 row-start-1 flex items-center justify-center absolute"
315
- style={{ top: "-22px", left: "50%", transform: "translateX(-50%)" }}
316
- >
317
- {!isNaN(Number(dpDiscountPercent)) &&
318
- Number(dpDiscountPercent) > 0 && (
319
- <span
320
- className="rounded-[100px] bg-[#ff5964] px-[6px] text-[12px] bold-text leading-[20px] text-white"
321
- style={{
322
- animation: "pulse-zoom 2s ease-in-out infinite",
323
- whiteSpace: "nowrap",
324
- }}
325
- >
326
- {Math.round(Number(dpDiscountPercent))}% OFF
327
- </span>
328
- )}
329
- </div>
330
-
331
- <div
332
- className="col-start-2 row-start-2 flex items-center justify-center"
333
- style={{ textAlign: "center" }}
334
- >
335
- <span
336
- className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative"
337
- style={{ position: "relative" }}
338
- >
339
- {formatPrice(Number(originalDpPrice))}
340
- <span
341
- style={{
342
- position: "absolute",
343
- left: "-2px",
344
- top: "50%",
345
- width: "calc(100% + 4px)",
346
- height: "1px",
347
- backgroundColor: "#9f9f9f",
348
- transform: "rotate(-10deg)",
349
- transformOrigin: "center",
350
- }}
351
- />
352
- </span>
353
- </div>
354
-
355
- <div className="col-start-2 row-start-3 flex h-[30px] items-end justify-center relative">
356
- <span
357
- className="flex items-center gap-[6px] text-[22px] bold-text leading-[30px]"
358
- style={{ color: isSoldOut ? "#c0c0c0" : "#ff5964" }}
359
- >
360
- <div
361
- className="absolute"
362
- style={{ left: isPeru ? "-1px" : "-8px" }}
363
- >
364
- {renderIcon("fireIcon", "16px")}
365
- </div>
366
- {availableSeats <= 0
367
- ? CommonService.currency(0, currencySign)
368
- : CommonService.discountedCurrency(
369
- Number(seatTypeFare),
370
- currencySign,
371
- )}
372
- </span>
373
- </div>
374
- </div>
375
- );
382
+ return renderDpDiscountUi(originalDpPrice, seatTypeFare);
376
383
  }
377
384
  }
378
385
 
379
386
  if (hasDiscount && discountSeat) {
380
387
  return (
381
- <div className="grid grid-cols-2 items-center text-[13.33px] relative">
388
+ <div
389
+ className="grid grid-cols-2 items-center text-[13.33px] relative"
390
+ style={{ opacity: isSoldOut ? 0.5 : 1 }}
391
+ >
382
392
  <div className="col-start-1 row-start-2 flex items-center">
383
393
  <span className="text-[13.33px] font-normal leading-[22px] text-[#ccc]">
384
394
  Antes
@@ -455,81 +455,78 @@ function SeatSectionMobile({
455
455
  ) : null}
456
456
  </div>
457
457
  ) : hasDiscount && discountSeat ? (
458
- <div className="relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] ">
459
- {discountValue != null && (
460
- <div
461
- className="absolute -top-[18px] right-[0px]"
462
- style={{
463
- animation: "pulse-zoom 2s ease-in-out infinite",
464
- }}
465
- >
466
- <span
467
- className="rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]"
458
+ <div>
459
+ <div className="relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] ">
460
+ {discountValue != null && (
461
+ <div
462
+ className="absolute -top-[18px] right-[0px]"
468
463
  style={{
469
- backgroundColor: tooltipBgColor,
464
+ animation: "pulse-zoom 2s ease-in-out infinite",
465
+ opacity: isSoldOut ? 0.5 : 1,
470
466
  }}
471
467
  >
472
- {discountValue}% OFF
473
- </span>
474
- </div>
475
- )}
468
+ <span
469
+ className="rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]"
470
+ style={{
471
+ backgroundColor: tooltipBgColor,
472
+ }}
473
+ >
474
+ {discountValue}% OFF
475
+ </span>
476
+ </div>
477
+ )}
476
478
 
477
- <span className="min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]">
478
- Antes
479
- </span>
480
- <span
481
- className="min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f] text-right"
482
- style={{
483
- position: "relative",
484
- display: "inline-block",
485
- overflow: "hidden",
486
- }}
487
- >
488
- {commonService.currency(discountSeat.originalPrice, currencySign)}
479
+ <span className="min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]">
480
+ Antes
481
+ </span>
489
482
  <span
483
+ className="min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f] text-right"
490
484
  style={{
491
- position: "absolute",
492
- top: "35%",
493
- left: "50%",
494
- width: "80%",
495
- height: "1px",
496
- background: "#9f9f9f",
497
- transform: "rotate(-12deg)",
498
- transformOrigin: "center",
485
+ position: "relative",
486
+ display: "inline-block",
487
+ overflow: "hidden",
499
488
  }}
500
- />
501
- </span>
502
-
503
- <span
504
- className="min-[420]:text-[13px] text-[12px] leading-[24px]"
505
- style={{ color: isSoldOut ? "#bbb" : "#464647" }}
506
- >
507
- Desde
508
- </span>
509
- <span
510
- className="flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]"
511
- style={{ color: isSoldOut ? "#bbb" : "#ff5964" }}
512
- >
513
- {serviceItem?.icons?.fireIcon ? (
514
- <img
515
- src={serviceItem.icons.fireIcon}
516
- alt="discount"
517
- className="h-[16px] w-[16px] object-contain"
518
- style={{ filter: isSoldOut ? "grayscale" : "" }}
489
+ >
490
+ {commonService.currency(discountSeat.originalPrice, currencySign)}
491
+ <span
492
+ style={{
493
+ position: "absolute",
494
+ top: "35%",
495
+ left: "50%",
496
+ width: "80%",
497
+ height: "1px",
498
+ background: "#9f9f9f",
499
+ transform: "rotate(-12deg)",
500
+ transformOrigin: "center",
501
+ }}
519
502
  />
520
- ) : null}
521
- {/* {commonService.currency(discountSeat.discountedPrice, currencySign)} */}
522
- {commonService.discountedCurrency(
523
- discountSeat.discountedPrice,
524
- currencySign,
525
- )}
526
- </span>
503
+ </span>
527
504
 
528
- {isSoldOut ? (
529
- <span className="col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]">
530
- Agotado
505
+ <span
506
+ className="min-[420]:text-[13px] text-[12px] leading-[24px]"
507
+ style={{ color: isSoldOut ? "#bbb" : "#464647" }}
508
+ >
509
+ Desde
531
510
  </span>
532
- ) : null}
511
+ <span
512
+ className="flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]"
513
+ style={{ color: isSoldOut ? "#bbb" : "#ff5964" }}
514
+ >
515
+ {serviceItem?.icons?.fireIcon ? (
516
+ <img
517
+ src={serviceItem.icons.fireIcon}
518
+ alt="discount"
519
+ className="h-[16px] w-[16px] object-contain"
520
+ style={{ opacity: isSoldOut ? 0.5 : 1 }}
521
+ />
522
+ ) : null}
523
+ {/* {commonService.currency(discountSeat.discountedPrice, currencySign)} */}
524
+ {commonService.discountedCurrency(
525
+ discountSeat.discountedPrice,
526
+ currencySign,
527
+ )}
528
+ </span>
529
+ </div>
533
530
  </div>
534
531
  ) : (
535
532
  <div
@@ -540,21 +537,6 @@ function SeatSectionMobile({
540
537
  }}
541
538
  >
542
539
  {renderSeats()}
543
- {showLastSeats ? (
544
- <div className="flex justify-end ">
545
- {serviceItem?.available_seats < 10 &&
546
- serviceItem?.available_seats > 0 && (
547
- <div
548
- className="text-[10px] text-center"
549
- style={{
550
- color: tooltipBgColor,
551
- }}
552
- >
553
- ¡ Últimos Asientos!
554
- </div>
555
- )}
556
- </div>
557
- ) : null}
558
540
 
559
541
  {isSoldOut ? (
560
542
  <div className="flex justify-end">
@@ -349,6 +349,8 @@ const commonService = {
349
349
  countdownSeconds: number = 599,
350
350
  ) => {
351
351
  if (!node) return;
352
+ if (node.dataset.timerStarted) return;
353
+ node.dataset.timerStarted = "true";
352
354
 
353
355
  const prevId = node.dataset.countdownId;
354
356
  if (prevId) clearInterval(Number(prevId));