kupos-ui-components-lib 3.0.8 → 4.0.1

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.
@@ -396,7 +396,6 @@ const FilterBarDesktop = ({ t, serviceList, setServiceList, allSchedules, showRe
396
396
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
397
397
  if (activeOptions && activeOptions.length)
398
398
  for (let f of activeOptions) {
399
- console.log("🚀 ~ filterBy ~ f:", f);
400
399
  if (f.active) {
401
400
  if (f.value.toLowerCase().indexOf("salon cama low") > -1) {
402
401
  for (let bt of it.seat_types) {
@@ -135,7 +135,7 @@ class ServiceFilter extends React.Component {
135
135
  option.type !== "special_departure" &&
136
136
  option.type !== "train_type")) &&
137
137
  option.options.map((val, i) => {
138
- var _a, _b, _c, _d, _e, _f, _g;
138
+ var _a, _b, _c, _d, _e, _f, _g, _h;
139
139
  let iconKey = "";
140
140
  if (val.icon === "sunrise") {
141
141
  iconKey = val.active
@@ -185,6 +185,9 @@ class ServiceFilter extends React.Component {
185
185
  else if (val.label === "Expreso") {
186
186
  label = "Tren express";
187
187
  }
188
+ else if (val.label === "PET_FRIENDLY") {
189
+ label = (_h = this.props.translation) === null || _h === void 0 ? void 0 : _h.petFriendly;
190
+ }
188
191
  else {
189
192
  // Use translation if available, otherwise use the label
190
193
  label = val.trText
@@ -55,7 +55,7 @@ const RatingHover = ({ serviceItem, isSoldOut, colors, t = (key) => key, transla
55
55
  React.createElement("div", { className: "px-1 py-2 text-center text-[12px] text-[#ff8f45] font9", style: {
56
56
  backgroundColor: colors.ratingBottomColor,
57
57
  } }, `${translation === null || translation === void 0 ? void 0 : translation.ratingMouseOverCalculationText} ${Object.values(serviceItem.operator_details)[5]} ${translation === null || translation === void 0 ? void 0 : translation.ratingMouseOverCalculationUsers}`))),
58
- React.createElement("span", { className: "text-[#464647] bold-text text-[13.33px]" }, typeof serviceItem.operator_details[1] === "number"
58
+ React.createElement("span", { className: "text-[#464647] text-[13.33px]" }, typeof serviceItem.operator_details[1] === "number"
59
59
  ? serviceItem.operator_details[1].toFixed(1)
60
60
  : serviceItem.operator_details[1])));
61
61
  };
@@ -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, originIconStyle, t, }: ServiceItemProps & {
3
+ declare function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, originIconStyle, t, }: ServiceItemProps & {
4
4
  currencySign?: string;
5
5
  }): React.ReactElement;
6
6
  export default ServiceItemPB;
@@ -6,7 +6,7 @@ import ModalEventManager from "../../utils/ModalEventManager";
6
6
  import InternationalServicePopupBody from "../InternationalServicePopupBody";
7
7
  import LottiePlayer from "../../assets/LottiePlayer";
8
8
  const SEAT_EXCEPTIONS = ["Asiento mascota"];
9
- function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, originIconStyle, t = (key) => key, }) {
9
+ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, originIconStyle, t = (key) => key, }) {
10
10
  var _a, _b, _c, _d, _e, _f, _g;
11
11
  const SvgAmenities = ({ moreAnemities, name, color, }) => {
12
12
  const amenityKey = name.toLowerCase().replace(/\s/g, "_");
@@ -143,7 +143,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
143
143
  const sortedStages = hideTime
144
144
  ? [...formattedStages].sort()
145
145
  : [...formattedStages].sort(compareTimings);
146
- return (React.createElement("div", { className: "flex flex-col space-y-3 text-justify gap-[4px]" }, sortedStages.map((item, key) => (React.createElement("div", { key: key }, hideTime
146
+ return (React.createElement("div", { className: "flex flex-col space-y-3 text-justify gap-[4px]" }, sortedStages.map((item, key) => (React.createElement("div", { key: key, className: "font-normal", style: { fontWeight: 400 } }, hideTime
147
147
  ? item === null || item === void 0 ? void 0 : item.split("|")[0]
148
148
  : item
149
149
  .replace(/false/g, "")
@@ -183,17 +183,43 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
183
183
  seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
184
184
  return seatTypesWithPrices;
185
185
  };
186
+ const getUniqueSeatsWithLowestPrice = () => {
187
+ const sortedSeatTypes = getSortedSeatTypes();
188
+ const seatMap = new Map();
189
+ sortedSeatTypes.forEach((seat) => {
190
+ if (SEAT_EXCEPTIONS.includes(seat.label))
191
+ return;
192
+ const currentLowest = seatMap.get(seat.label);
193
+ const seatPrice = parseFloat(seat.price);
194
+ if (!currentLowest || seatPrice < parseFloat(currentLowest.price)) {
195
+ seatMap.set(seat.label, seat);
196
+ }
197
+ });
198
+ return Array.from(seatMap.values());
199
+ };
186
200
  const getNumberOfSeats = () => {
187
201
  return serviceItem.seat_types.filter((val) => !SEAT_EXCEPTIONS.includes(val.label)).length;
188
202
  };
189
203
  const getSeatNames = () => {
204
+ const sortedSeatTypesDuplicate = getUniqueSeatsWithLowestPrice();
190
205
  const sortedSeatTypes = getSortedSeatTypes();
206
+ if (removeDuplicateSeats) {
207
+ return sortedSeatTypesDuplicate.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"
208
+ ? val.label
209
+ : null)));
210
+ }
191
211
  return sortedSeatTypes.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"
192
212
  ? val.label
193
213
  : null)));
194
214
  };
195
215
  const getSeatPrice = () => {
196
216
  const sortedSeatTypes = getSortedSeatTypes();
217
+ const uniqueSeats = getUniqueSeatsWithLowestPrice();
218
+ if (removeDuplicateSeats) {
219
+ return uniqueSeats.map((val, key) => (React.createElement("span", { key: key }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) <= 0
220
+ ? CommonService.currency(0, currencySign)
221
+ : CommonService.currency(val.price, currencySign))));
222
+ }
197
223
  return sortedSeatTypes.map((val, key) => {
198
224
  return SEAT_EXCEPTIONS.includes(val.label) ? null : (React.createElement("span", { key: key, className: "flex items-center text-[13.33px] bold-text" }, typeof val.price === "string"
199
225
  ? (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) <= 0
@@ -294,47 +320,57 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
294
320
  ? "mt-[24px]"
295
321
  : "mt-[14px]"} ` },
296
322
  React.createElement("div", { className: "bg-white rounded-[20px] shadow-service mx-auto relative" },
297
- React.createElement("div", { className: "p-[15px]" },
298
- React.createElement("div", { className: "grid text-[#464647] w-full [grid-template-columns:12%_28%_minmax(0,0.2fr)_29%_15%] gap-x-[4%] items-center", style: { marginTop: showTopLabel ? "8px" : "" } },
323
+ React.createElement("div", { className: "p-[15px] pt-[20px]" },
324
+ React.createElement("div", { className: "grid text-[#464647] w-full [grid-template-columns:14%_32%_0.5%_24%_13.5%] gap-x-[4%] items-center", style: { marginTop: showTopLabel ? "8px" : "" } },
299
325
  React.createElement("div", { className: "flex items-center justify-center m-[auto]" },
300
326
  React.createElement("div", { className: " " },
301
327
  React.createElement("img", { src: serviceItem.operator_details[0], alt: "service logo", className: ` h-auto object-contain ${isSoldOut ? "grayscale" : ""}` })),
302
328
  isCiva ? (React.createElement("div", { className: "text-[13.33px] black-text ml-2" }, serviceItem.operator_details[2])) : null),
303
- React.createElement("div", { className: "min-h-[2.5rem] flex flex-col gap-[10px]", style: { justifyContent: isCiva ? "center" : "space-between" } },
304
- React.createElement("div", { className: `flex items-center text-[13.33px] justify-between relative ${isSoldOut ? "text-[#c0c0c0]" : ""}` },
305
- React.createElement("div", { className: "flex items-center", style: { flex: 1 } },
306
- " ",
307
- orignLabel ? (React.createElement("div", { className: "w-[60px]" }, orignLabel)) : (React.createElement("div", null,
308
- React.createElement("img", { src: (_a = serviceItem.icons) === null || _a === void 0 ? void 0 : _a.origin, alt: "origin", className: `w-[18px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}` }))),
309
- React.createElement("div", { className: "flex items-center capitalize relative group items-center justify-between ", style: { flex: 1 } },
310
- React.createElement("span", { className: "cursor-pointer bold-text" }, DateService.getServiceItemDate(serviceItem.travel_date)),
311
- React.createElement("div", { className: "absolute left-[40%] flex items-center w-[60%]" },
312
- React.createElement("div", null, "\u2022"),
313
- React.createElement("div", { className: "font-[900] bold-text group relative ml-[20%]" },
314
- DateService.formatTime(serviceItem.dep_time),
315
- serviceItem.boarding_stages && (React.createElement("div", { className: "hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service", style: { backgroundColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } },
316
- React.createElement("div", { className: "tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 \n border-t-8 border-b-8 border-r-8 \n border-t-transparent border-b-transparent", style: { borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } }),
317
- React.createElement("div", { className: "text-center text-[14px]" }, renderStages(serviceItem.boarding_stages, 1, busStage, hideBoardingTime((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.api_type) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType))))))))))),
318
- isCiva ? null : (React.createElement("div", { className: `flex items-center text-[13.33px] justify-between relative ${isSoldOut ? "text-[#c0c0c0]" : ""}` },
319
- React.createElement("div", { className: "flex items-center", style: { flex: 1 } },
320
- destinationLabel ? (React.createElement("div", { className: "w-[60px]" }, destinationLabel)) : (React.createElement("div", null,
321
- React.createElement("img", { src: (_b = serviceItem.icons) === null || _b === void 0 ? void 0 : _b.destination, className: `w-[18px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }))),
322
- React.createElement("div", { className: "flex items-center capitalize relative group items-center justify-between ", style: { flex: 1 } },
323
- React.createElement("span", { className: "cursor-pointer bold-text" }, DateService.getServiceItemDate(serviceItem.arrival_date)),
324
- React.createElement("div", { className: "absolute left-[40%] flex items-center w-[60%]" },
325
- removeArrivalTime ? null : serviceItem.arr_time ? (React.createElement("div", null, "\u2022")) : null,
326
- React.createElement("div", { className: "font-[900] bold-text group relative ml-[20%]" },
327
- removeArrivalTime
328
- ? null
329
- : serviceItem.arr_time
330
- ? DateService.formatTime(serviceItem.arr_time)
331
- : null,
332
- serviceItem.dropoff_stages && (React.createElement("div", { className: "hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service", style: { backgroundColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } },
333
- React.createElement("div", { className: "tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 \n border-t-8 border-b-8 border-r-8 \n border-t-transparent border-b-transparent", style: {
334
- borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor,
335
- } }),
336
- React.createElement("div", { className: "text-center text-[14px]" }, renderStages(serviceItem.dropoff_stages, 2, busStage, hideBoardingTime((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.api_type) ||
337
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType))))))))))))),
329
+ React.createElement("div", { className: `min-h-[2.5rem] grid grid-cols-[26px_auto_26%_1fr] gap-x-4 items-center text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""}`, style: {
330
+ // gridTemplateRows: isCiva ? "1fr" : "1fr 1fr",
331
+ gridTemplateRows: "1fr",
332
+ // gap: isCiva ? "0" : "10px 16px"
333
+ } },
334
+ React.createElement("div", { className: "flex flex-col gap-[10px]" },
335
+ orignLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, orignLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
336
+ React.createElement("img", { src: (_a = serviceItem.icons) === null || _a === void 0 ? void 0 : _a.origin, alt: "origin", className: `w-[18px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}` }))),
337
+ !isCiva &&
338
+ (destinationLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, destinationLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
339
+ React.createElement("img", { src: (_b = serviceItem.icons) === null || _b === void 0 ? void 0 : _b.destination, className: `w-[18px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }))))),
340
+ React.createElement("div", { className: "flex flex-col gap-[10px]" },
341
+ React.createElement("div", { className: "h-[20px] flex items-center group relative" },
342
+ React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.travel_date)),
343
+ serviceItem.boarding_stages && (React.createElement("div", { className: "hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service", style: { backgroundColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } },
344
+ React.createElement("div", { className: "tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 \n border-t-8 border-b-8 border-r-8 \n border-t-transparent border-b-transparent", style: { borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } }),
345
+ React.createElement("div", { className: "text-center text-[14px] font-normal", style: { fontWeight: 400 } }, renderStages(serviceItem.boarding_stages, 1, busStage, hideBoardingTime((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.api_type) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType))))))),
346
+ !isCiva && (React.createElement("div", { className: "h-[20px] flex items-center group relative" },
347
+ React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.arrival_date)),
348
+ serviceItem.dropoff_stages && (React.createElement("div", { className: "hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service", style: { backgroundColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } },
349
+ React.createElement("div", { className: "tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 \n border-t-8 border-b-8 border-r-8 \n border-t-transparent border-b-transparent", style: {
350
+ borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor,
351
+ } }),
352
+ React.createElement("div", { className: "text-center text-[14px] font-normal", style: { fontWeight: 400 } }, renderStages(serviceItem.dropoff_stages, 2, busStage, hideBoardingTime((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.api_type) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType))))))))),
353
+ React.createElement("div", { className: "flex flex-col gap-[10px] items-center" },
354
+ React.createElement("div", { className: "h-[20px] flex items-center justify-center" },
355
+ React.createElement("div", null, "\u2022")),
356
+ !isCiva && (React.createElement("div", { className: "h-[20px] flex items-center justify-center" }, removeArrivalTime ? null : serviceItem.arr_time ? (React.createElement("div", null, "\u2022")) : null))),
357
+ React.createElement("div", { className: "flex flex-col gap-[10px]" },
358
+ React.createElement("div", { className: "h-[20px] flex items-center group relative" },
359
+ React.createElement("div", { className: "font-[900] bold-text" }, DateService.formatTime(serviceItem.dep_time)),
360
+ serviceItem.boarding_stages && (React.createElement("div", { className: "hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service", style: { backgroundColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } },
361
+ React.createElement("div", { className: "tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 \n border-t-8 border-b-8 border-r-8 \n border-t-transparent border-b-transparent", style: { borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } }),
362
+ React.createElement("div", { className: "text-center text-[14px] font-normal", style: { fontWeight: 400 } }, renderStages(serviceItem.boarding_stages, 1, busStage, hideBoardingTime((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.api_type) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType))))))),
363
+ !isCiva && (React.createElement("div", { className: "h-[20px] flex items-center group relative" },
364
+ React.createElement("div", { className: "font-[900] bold-text" }, removeArrivalTime
365
+ ? null
366
+ : serviceItem.arr_time
367
+ ? DateService.formatTime(serviceItem.arr_time)
368
+ : null),
369
+ serviceItem.dropoff_stages && (React.createElement("div", { className: "hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service", style: { backgroundColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor } },
370
+ React.createElement("div", { className: "tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 \n border-t-8 border-b-8 border-r-8 \n border-t-transparent border-b-transparent", style: {
371
+ borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor,
372
+ } }),
373
+ React.createElement("div", { className: "text-center text-[14px] font-normal", style: { fontWeight: 400 } }, renderStages(serviceItem.dropoff_stages, 2, busStage, hideBoardingTime((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.api_type) || (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType)))))))))),
338
374
  React.createElement("div", { style: {
339
375
  width: "1px",
340
376
  height: "2.5rem",
@@ -348,7 +384,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
348
384
  color: isSoldOut ? "#c0c0c0" : colors.priceColor,
349
385
  top: 0,
350
386
  bottom: 0,
351
- left: "70%",
387
+ left: "68%",
352
388
  right: 0,
353
389
  justifyContent: getNumberOfSeats() < 2 ? "center" : "",
354
390
  } }, getSeatPrice()))),
@@ -361,7 +397,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
361
397
  ? "not-allowed"
362
398
  : "pointer",
363
399
  } },
364
- React.createElement("span", { className: "min-w-[75px] flex justify-center items-center bold-text" },
400
+ React.createElement("span", { className: "min-w-[75px] flex justify-center items-center bold-text uppercase" },
365
401
  isSoldOut ? renderIcon("soldOutIcon", "14px") : null,
366
402
  serviceDetailsLoading ? (React.createElement("span", { className: "loader-circle" })) : !isSoldOut ? (translation === null || translation === void 0 ? void 0 : translation.buyButton) : (translation === null || translation === void 0 ? void 0 : translation.soldOutButton))))),
367
403
  showLastSeats ? (React.createElement("div", { className: "flex justify-end mr-[11px]" }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
@@ -370,7 +406,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
370
406
  React.createElement("div", { className: "flex items-center " },
371
407
  React.createElement("div", { className: `flex items-center ${isSoldOut ? "grayscale" : ""} ${showRating ? "cursor-pointer" : ""}`, style: { color: isSoldOut ? "#c0c0c0" : "" } },
372
408
  showRating ? (React.createElement(RatingHover, { serviceItem: serviceItem, isSoldOut: isSoldOut, colors: colors, t: t, translation: translation })) : null,
373
- React.createElement("span", { className: "ml-[10px] text-[#464647] text-[13.33px] bold-text", style: { marginLeft: showRating ? "10px" : "0" } }, serviceItem.operator_details[2]))),
409
+ React.createElement("span", { className: "ml-[10px] text-[#464647] text-[13.33px]", style: { marginLeft: showRating ? "10px" : "0" } }, serviceItem.operator_details[2]))),
374
410
  serviceItem.duration && (React.createElement("div", { className: "flex items-baseline relative text-[#464647]" },
375
411
  React.createElement("div", { className: `w-[18px] h-auto mr-[4px] ${isSoldOut ? "grayscale" : ""}` }, renderIcon("hours", "14px")),
376
412
  React.createElement("div", { className: `cursor-default group text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""}` },
@@ -459,27 +495,27 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
459
495
  } },
460
496
  React.createElement(LottiePlayer, { animationData: serviceItem.icons.promoAnim, width: "18px", height: "18px" }),
461
497
  React.createElement("span", { className: "ml-[10px]" }, serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text))),
462
- React.createElement("div", { className: "absolute -top-[13px] left-0 w-full flex items-center justify-end gap-[12px] pr-[15px] z-10 " },
463
- showTopLabel && (React.createElement("div", { className: `flex items-center gap-[10px] py-[5px] px-[14px] rounded-[38px] text-[13.33px] z-20`, style: {
498
+ React.createElement("div", { className: "absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[15px] z-10 " },
499
+ showTopLabel && (React.createElement("div", { className: `flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`, style: {
464
500
  backgroundColor: isSoldOut ? "#ddd" : colors.ratingBottomColor,
465
501
  } },
466
502
  React.createElement("div", { className: isSoldOut ? "grayscale" : "" },
467
- React.createElement(LottiePlayer, { animationData: serviceItem.icons.priorityStageAnim, width: "16px", height: "16px" })),
503
+ React.createElement(LottiePlayer, { animationData: serviceItem.icons.priorityStageAnim, width: "14px", height: "14px" })),
468
504
  React.createElement("div", { className: isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]` }, showTopLabel))),
469
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_transpordo) && (React.createElement("div", { className: `flex items-center gap-[10px] py-[5px] text-white px-[14px] rounded-[38px] text-[13.33px] z-20`, style: {
505
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_transpordo) && (React.createElement("div", { className: `flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20`, style: {
470
506
  backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
471
507
  } },
472
- React.createElement(LottiePlayer, { animationData: serviceItem.icons.connectingServiceIcon, width: "16px", height: "16px" }),
508
+ React.createElement(LottiePlayer, { animationData: serviceItem.icons.connectingServiceIcon, width: "14px", height: "14px" }),
473
509
  React.createElement("div", null, "Conexión"))),
474
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) && (React.createElement("div", { className: `flex items-center gap-[10px] py-[5px] text-white px-[14px] rounded-[38px] text-[13.33px] z-20 `, style: {
510
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) && (React.createElement("div", { className: `flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20 `, style: {
475
511
  backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
476
512
  } },
477
- React.createElement(LottiePlayer, { animationData: serviceItem.icons.directoAnim, width: "16px", height: "16px" }),
513
+ React.createElement(LottiePlayer, { animationData: serviceItem.icons.directoAnim, width: "14px", height: "14px" }),
478
514
  React.createElement("div", null, translation === null || translation === void 0 ? void 0 : translation.directService))),
479
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" && (React.createElement("div", { className: `flex items-center gap-[10px] py-[5px] text-white px-[14px] rounded-[38px] text-[13.33px] z-20 `, style: {
515
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" && (React.createElement("div", { className: `flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20 `, style: {
480
516
  backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
481
517
  } },
482
- React.createElement(LottiePlayer, { animationData: serviceItem.icons.directoAnim, width: "16px", height: "16px" }),
518
+ React.createElement(LottiePlayer, { animationData: serviceItem.icons.directoAnim, width: "14px", height: "14px" }),
483
519
  React.createElement("div", null, "Tren Express"))))));
484
520
  }
485
521
  export default ServiceItemPB;
@@ -36,9 +36,21 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
36
36
  }
37
37
  };
38
38
  const seatTypes = () => {
39
- var _a, _b, _c, _d;
40
- let seatTypes = (_d = (_c = (_b = (_a = serviceItem.seat_types) === null || _a === void 0 ? void 0 : _a.filter((item) => getFilteredSeats(item.label))) === null || _b === void 0 ? void 0 : _b.sort((a, b) => a.fare - b.fare) // Add this line to sort by fare
41
- ) === null || _c === void 0 ? void 0 : _c.slice(0, 2)) === null || _d === void 0 ? void 0 : _d.map((type, i) => {
39
+ var _a, _b;
40
+ const seatMap = new Map();
41
+ (_b = (_a = serviceItem.seat_types) === null || _a === void 0 ? void 0 : _a.filter((item) => getFilteredSeats(item.label))) === null || _b === void 0 ? void 0 : _b.forEach((item) => {
42
+ if (exceptions.includes(item.key))
43
+ return;
44
+ const existing = seatMap.get(item.label);
45
+ if (!existing ||
46
+ parseFloat(item.fare) < parseFloat(existing.fare)) {
47
+ seatMap.set(item.label, item);
48
+ }
49
+ });
50
+ const uniqueSeats = Array.from(seatMap.values())
51
+ .sort((a, b) => a.fare - b.fare)
52
+ .slice(0, 3);
53
+ return uniqueSeats.map((type, i) => {
42
54
  var _a;
43
55
  return exceptions.includes(type.label) ? null : (React.createElement("div", { className: ((_a = serviceItem.seat_types) === null || _a === void 0 ? void 0 : _a.length) > 2
44
56
  ? "w-[100%] flex flex-row justify-between "
@@ -51,7 +63,6 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
51
63
  ? commonService.currency(0, currencySign)
52
64
  : commonService.currency(type.fare, currencySign))));
53
65
  });
54
- return seatTypes;
55
66
  };
56
67
  const getFilteredSeats = (item) => {
57
68
  return item;
@@ -25,6 +25,7 @@ export interface MobileServiceItemProps {
25
25
  seat_types: Array<{
26
26
  label: string;
27
27
  fare: number;
28
+ key: any;
28
29
  }>;
29
30
  boarding_stages?: string;
30
31
  dropoff_stages?: string;
@@ -26,6 +26,7 @@ export interface ServiceItemProps {
26
26
  seat_types: Array<{
27
27
  label: string;
28
28
  fare: number;
29
+ key: any;
29
30
  }>;
30
31
  boarding_stages?: string;
31
32
  dropoff_stages?: string;
@@ -159,4 +160,5 @@ export interface ServiceItemProps {
159
160
  showLastSeats?: boolean;
160
161
  removeArrivalTime?: boolean;
161
162
  originIconStyle?: boolean;
163
+ removeDuplicateSeats?: boolean;
162
164
  }
package/dist/styles.css CHANGED
@@ -18,6 +18,9 @@
18
18
  .-top-\[8px\] {
19
19
  top: calc(8px * -1);
20
20
  }
21
+ .-top-\[11px\] {
22
+ top: calc(11px * -1);
23
+ }
21
24
  .-top-\[13px\] {
22
25
  top: calc(13px * -1);
23
26
  }
@@ -78,9 +81,6 @@
78
81
  .left-\[36\%\] {
79
82
  left: 36%;
80
83
  }
81
- .left-\[40\%\] {
82
- left: 40%;
83
- }
84
84
  .left-\[40px\] {
85
85
  left: 40px;
86
86
  }
@@ -231,9 +231,6 @@
231
231
  .ml-\[10px\] {
232
232
  margin-left: 10px;
233
233
  }
234
- .ml-\[20\%\] {
235
- margin-left: 20%;
236
- }
237
234
  .ml-\[25px\] {
238
235
  margin-left: 25px;
239
236
  }
@@ -394,8 +391,8 @@
394
391
  .cursor-pointer {
395
392
  cursor: pointer;
396
393
  }
397
- .\[grid-template-columns\:12\%_28\%_minmax\(0\,0\.2fr\)_29\%_15\%\] {
398
- grid-template-columns: 12% 28% minmax(0,0.2fr) 29% 15%;
394
+ .\[grid-template-columns\:14\%_32\%_0\.5\%_24\%_13\.5\%\] {
395
+ grid-template-columns: 14% 32% 0.5% 24% 13.5%;
399
396
  }
400
397
  .\[grid-template-columns\:minmax\(0\,1\.4fr\)_minmax\(0\,0\.2fr\)_minmax\(0\,1fr\)_auto\] {
401
398
  grid-template-columns: minmax(0,1.4fr) minmax(0,0.2fr) minmax(0,1fr) auto;
@@ -409,6 +406,9 @@
409
406
  .grid-cols-\[3\.17fr_4\.8fr\] {
410
407
  grid-template-columns: 3.17fr 4.8fr;
411
408
  }
409
+ .grid-cols-\[26px_auto_26\%_1fr\] {
410
+ grid-template-columns: 26px auto 26% 1fr;
411
+ }
412
412
  .flex-col {
413
413
  flex-direction: column;
414
414
  }
@@ -621,6 +621,9 @@
621
621
  .px-\[20px\] {
622
622
  padding-inline: 20px;
623
623
  }
624
+ .py-\[4px\] {
625
+ padding-block: 4px;
626
+ }
624
627
  .py-\[5px\] {
625
628
  padding-block: 5px;
626
629
  }
@@ -690,6 +693,9 @@
690
693
  .text-\[11px\] {
691
694
  font-size: 11px;
692
695
  }
696
+ .text-\[12\.5px\] {
697
+ font-size: 12.5px;
698
+ }
693
699
  .text-\[12px\] {
694
700
  font-size: 12px;
695
701
  }
@@ -754,6 +760,9 @@
754
760
  .capitalize {
755
761
  text-transform: capitalize;
756
762
  }
763
+ .uppercase {
764
+ text-transform: uppercase;
765
+ }
757
766
  .grayscale {
758
767
  --tw-grayscale: grayscale(100%);
759
768
  filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "3.0.8",
3
+ "version": "4.0.1",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -454,7 +454,6 @@ const FilterBarDesktop = ({
454
454
  filteredRoutes = filteredRoutes.filter((it) => {
455
455
  if (activeOptions && activeOptions.length)
456
456
  for (let f of activeOptions) {
457
- console.log("🚀 ~ filterBy ~ f:", f);
458
457
  if (f.active) {
459
458
  if (f.value.toLowerCase().indexOf("salon cama low") > -1) {
460
459
  for (let bt of it.seat_types) {
@@ -254,6 +254,8 @@ class ServiceFilter extends React.Component<
254
254
  label = "Tren regular";
255
255
  } else if (val.label === "Expreso") {
256
256
  label = "Tren express";
257
+ } else if (val.label === "PET_FRIENDLY") {
258
+ label = this.props.translation?.petFriendly;
257
259
  } else {
258
260
  // Use translation if available, otherwise use the label
259
261
  label = val.trText
@@ -183,7 +183,7 @@ const RatingHover: React.FC<RatingHoverProps> = ({
183
183
  </div>
184
184
  </div>
185
185
  </div>
186
- <span className="text-[#464647] bold-text text-[13.33px]">
186
+ <span className="text-[#464647] text-[13.33px]">
187
187
  {typeof serviceItem.operator_details[1] === "number"
188
188
  ? serviceItem.operator_details[1].toFixed(1)
189
189
  : serviceItem.operator_details[1]}
@@ -27,6 +27,7 @@ function ServiceItemPB({
27
27
  showRating,
28
28
  showLastSeats,
29
29
  removeArrivalTime,
30
+ removeDuplicateSeats,
30
31
  originIconStyle,
31
32
  t = (key: string) => key,
32
33
  }: ServiceItemProps & { currencySign?: string }): React.ReactElement {
@@ -208,7 +209,7 @@ function ServiceItemPB({
208
209
  return (
209
210
  <div className="flex flex-col space-y-3 text-justify gap-[4px]">
210
211
  {sortedStages.map((item, key) => (
211
- <div key={key}>
212
+ <div key={key} className="font-normal" style={{ fontWeight: 400 }}>
212
213
  {hideTime
213
214
  ? item?.split("|")[0]
214
215
  : item
@@ -268,6 +269,24 @@ function ServiceItemPB({
268
269
  return seatTypesWithPrices;
269
270
  };
270
271
 
272
+ const getUniqueSeatsWithLowestPrice = () => {
273
+ const sortedSeatTypes = getSortedSeatTypes();
274
+ const seatMap = new Map();
275
+
276
+ sortedSeatTypes.forEach((seat) => {
277
+ if (SEAT_EXCEPTIONS.includes(seat.label)) return;
278
+
279
+ const currentLowest = seatMap.get(seat.label);
280
+ const seatPrice = parseFloat(seat.price as any);
281
+
282
+ if (!currentLowest || seatPrice < parseFloat(currentLowest.price)) {
283
+ seatMap.set(seat.label, seat);
284
+ }
285
+ });
286
+
287
+ return Array.from(seatMap.values());
288
+ };
289
+
271
290
  const getNumberOfSeats = () => {
272
291
  return serviceItem.seat_types.filter(
273
292
  (val) => !SEAT_EXCEPTIONS.includes(val.label)
@@ -275,7 +294,25 @@ function ServiceItemPB({
275
294
  };
276
295
 
277
296
  const getSeatNames = () => {
297
+ const sortedSeatTypesDuplicate = getUniqueSeatsWithLowestPrice();
278
298
  const sortedSeatTypes = getSortedSeatTypes();
299
+
300
+ if (removeDuplicateSeats) {
301
+ return sortedSeatTypesDuplicate.map((val, key: number) =>
302
+ SEAT_EXCEPTIONS.includes(val.label) ? null : (
303
+ <span
304
+ key={key}
305
+ className={`flex items-center justify-between text-[13.33px] ${
306
+ isSoldOut ? "text-[#c0c0c0]" : ""
307
+ }`}
308
+ >
309
+ {typeof val.label === "string" || typeof val.label === "number"
310
+ ? val.label
311
+ : null}
312
+ </span>
313
+ )
314
+ );
315
+ }
279
316
  return sortedSeatTypes.map((val, key: number) =>
280
317
  SEAT_EXCEPTIONS.includes(val.label) ? null : (
281
318
  <span
@@ -294,6 +331,16 @@ function ServiceItemPB({
294
331
 
295
332
  const getSeatPrice = () => {
296
333
  const sortedSeatTypes = getSortedSeatTypes();
334
+ const uniqueSeats = getUniqueSeatsWithLowestPrice();
335
+ if (removeDuplicateSeats) {
336
+ return uniqueSeats.map((val, key) => (
337
+ <span key={key}>
338
+ {serviceItem?.available_seats <= 0
339
+ ? CommonService.currency(0, currencySign)
340
+ : CommonService.currency(val.price, currencySign)}
341
+ </span>
342
+ ));
343
+ }
297
344
  return sortedSeatTypes.map((val, key: number) => {
298
345
  return SEAT_EXCEPTIONS.includes(val.label) ? null : (
299
346
  <span key={key} className="flex items-center text-[13.33px] bold-text">
@@ -418,7 +465,7 @@ function ServiceItemPB({
418
465
  <div
419
466
  className={"bg-white rounded-[20px] shadow-service mx-auto relative"}
420
467
  >
421
- <div className="p-[15px]">
468
+ <div className="p-[15px] pt-[20px]">
422
469
  {/* Header with operator info and favorite */}
423
470
  {/* <div className="flex justify-between items-center mb-[15px]">
424
471
  <div className="flex items-center justify-between w-[250px]">
@@ -445,7 +492,7 @@ function ServiceItemPB({
445
492
 
446
493
  {/* <div className="grid grid-cols-[1.5fr_1fr_auto] gap-[3rem] sm:gap-[4rem] md:gap-[5rem] lg:gap-[6rem] xl:gap-[5rem] 2xl:gap-[7rem] text-[#464647]"> */}
447
494
  <div
448
- className="grid text-[#464647] w-full [grid-template-columns:12%_28%_minmax(0,0.2fr)_29%_15%] gap-x-[4%] items-center"
495
+ className="grid text-[#464647] w-full [grid-template-columns:14%_32%_0.5%_24%_13.5%] gap-x-[4%] items-center"
449
496
  style={{ marginTop: showTopLabel ? "8px" : "" }}
450
497
  >
451
498
  {/* OPERATOR LOGO */}
@@ -466,148 +513,222 @@ function ServiceItemPB({
466
513
  ) : null}
467
514
  </div>
468
515
 
469
- {/* DATE AND TIME */}
516
+ {/* DATE AND TIME - Grid Layout */}
470
517
  <div
471
- className="min-h-[2.5rem] flex flex-col gap-[10px]"
472
- style={{ justifyContent: isCiva ? "center" : "space-between" }}
518
+ className={`min-h-[2.5rem] grid grid-cols-[26px_auto_26%_1fr] gap-x-4 items-center text-[13.33px] ${
519
+ isSoldOut ? "text-[#c0c0c0]" : ""
520
+ }`}
521
+ style={{
522
+ // gridTemplateRows: isCiva ? "1fr" : "1fr 1fr",
523
+ gridTemplateRows: "1fr",
524
+ // gap: isCiva ? "0" : "10px 16px"
525
+ }}
473
526
  >
474
- <div
475
- className={`flex items-center text-[13.33px] justify-between relative ${
476
- isSoldOut ? "text-[#c0c0c0]" : ""
477
- }`}
478
- >
479
- <div className="flex items-center" style={{ flex: 1 }}>
480
- {" "}
481
- {orignLabel ? (
482
- <div className="w-[60px]">{orignLabel}</div>
527
+ {/* ICONS COLUMN */}
528
+ <div className="flex flex-col gap-[10px]">
529
+ {/* Origin Icon */}
530
+ {orignLabel ? (
531
+ <div className="w-[60px] h-[20px] flex items-center">
532
+ {orignLabel}
533
+ </div>
534
+ ) : (
535
+ <div className="h-[20px] flex items-center">
536
+ <img
537
+ src={serviceItem.icons?.origin}
538
+ alt="origin"
539
+ className={`w-[18px] h-auto mr-[8px] ${
540
+ isSoldOut ? "grayscale" : ""
541
+ }`}
542
+ />
543
+ </div>
544
+ )}
545
+
546
+ {/* Destination Icon */}
547
+ {!isCiva &&
548
+ (destinationLabel ? (
549
+ <div className="w-[60px] h-[20px] flex items-center">
550
+ {destinationLabel}
551
+ </div>
483
552
  ) : (
484
- <div>
553
+ <div className="h-[20px] flex items-center">
485
554
  <img
486
- src={serviceItem.icons?.origin}
487
- alt="origin"
555
+ src={serviceItem.icons?.destination}
488
556
  className={`w-[18px] h-auto mr-[8px] ${
489
557
  isSoldOut ? "grayscale" : ""
490
558
  }`}
491
- // style={{ width: originIconStyle ? "16px" : "18px" }}
559
+ style={{ opacity: isSoldOut ? 0.5 : 1 }}
492
560
  />
493
561
  </div>
494
- )}
495
- <div
496
- className="flex items-center capitalize relative group items-center justify-between "
497
- style={{ flex: 1 }}
498
- >
499
- <span className="cursor-pointer bold-text">
500
- {DateService.getServiceItemDate(serviceItem.travel_date)}
501
- </span>
562
+ ))}
563
+ </div>
502
564
 
503
- <div className="absolute left-[40%] flex items-center w-[60%]">
504
- <div>•</div>
505
- <div className="font-[900] bold-text group relative ml-[20%]">
506
- {DateService.formatTime(serviceItem.dep_time)}
507
-
508
- {serviceItem.boarding_stages && (
509
- <div
510
- className="hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service"
511
- style={{ backgroundColor: colors?.tooltipColor }}
512
- >
513
- <div
514
- className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0
515
- border-t-8 border-b-8 border-r-8
516
- border-t-transparent border-b-transparent"
517
- style={{ borderRightColor: colors?.tooltipColor }}
518
- ></div>
519
- <div className="text-center text-[14px]">
520
- {renderStages(
521
- serviceItem.boarding_stages,
522
- 1,
523
- busStage,
524
- hideBoardingTime(
525
- serviceItem?.api_type || serviceItem?.apiType
526
- )
527
- )}
528
- </div>
529
- </div>
565
+ {/* DATES COLUMN */}
566
+ <div className="flex flex-col gap-[10px]">
567
+ {/* Departure Date */}
568
+ <div className="h-[20px] flex items-center group relative">
569
+ <span className="cursor-pointer bold-text capitalize">
570
+ {DateService.getServiceItemDate(serviceItem.travel_date)}
571
+ </span>
572
+ {serviceItem.boarding_stages && (
573
+ <div
574
+ className="hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service"
575
+ style={{ backgroundColor: colors?.tooltipColor }}
576
+ >
577
+ <div
578
+ className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0
579
+ border-t-8 border-b-8 border-r-8
580
+ border-t-transparent border-b-transparent"
581
+ style={{ borderRightColor: colors?.tooltipColor }}
582
+ ></div>
583
+ <div
584
+ className="text-center text-[14px] font-normal"
585
+ style={{ fontWeight: 400 }}
586
+ >
587
+ {renderStages(
588
+ serviceItem.boarding_stages,
589
+ 1,
590
+ busStage,
591
+ hideBoardingTime(
592
+ serviceItem?.api_type || serviceItem?.apiType
593
+ )
530
594
  )}
531
595
  </div>
532
596
  </div>
533
- </div>
597
+ )}
534
598
  </div>
535
- </div>
536
- {isCiva ? null : (
537
- <div
538
- className={`flex items-center text-[13.33px] justify-between relative ${
539
- isSoldOut ? "text-[#c0c0c0]" : ""
540
- }`}
541
- >
542
- <div className="flex items-center" style={{ flex: 1 }}>
543
- {destinationLabel ? (
544
- <div className="w-[60px]">{destinationLabel}</div>
545
- ) : (
546
- <div>
547
- <img
548
- src={serviceItem.icons?.destination}
549
- className={`w-[18px] h-auto mr-[8px] ${
550
- isSoldOut ? "grayscale" : ""
551
- }`}
552
- style={{ opacity: isSoldOut ? 0.5 : 1 }}
553
- />
599
+
600
+ {/* Arrival Date */}
601
+ {!isCiva && (
602
+ <div className="h-[20px] flex items-center group relative">
603
+ <span className="cursor-pointer bold-text capitalize">
604
+ {DateService.getServiceItemDate(serviceItem.arrival_date)}
605
+ </span>
606
+ {serviceItem.dropoff_stages && (
607
+ <div
608
+ className="hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service"
609
+ style={{ backgroundColor: colors?.tooltipColor }}
610
+ >
611
+ <div
612
+ className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0
613
+ border-t-8 border-b-8 border-r-8
614
+ border-t-transparent border-b-transparent"
615
+ style={{
616
+ borderRightColor: colors?.tooltipColor,
617
+ }}
618
+ ></div>
619
+ <div
620
+ className="text-center text-[14px] font-normal"
621
+ style={{ fontWeight: 400 }}
622
+ >
623
+ {renderStages(
624
+ serviceItem.dropoff_stages,
625
+ 2,
626
+ busStage,
627
+ hideBoardingTime(
628
+ serviceItem?.api_type || serviceItem?.apiType
629
+ )
630
+ )}
631
+ </div>
554
632
  </div>
555
633
  )}
634
+ </div>
635
+ )}
636
+ </div>
637
+
638
+ {/* DOTS COLUMN */}
639
+ <div className="flex flex-col gap-[10px] items-center">
640
+ {/* Departure Dot */}
641
+ <div className="h-[20px] flex items-center justify-center">
642
+ <div>•</div>
643
+ </div>
644
+
645
+ {/* Arrival Dot */}
646
+ {!isCiva && (
647
+ <div className="h-[20px] flex items-center justify-center">
648
+ {removeArrivalTime ? null : serviceItem.arr_time ? (
649
+ <div>•</div>
650
+ ) : null}
651
+ </div>
652
+ )}
653
+ </div>
654
+
655
+ {/* TIMES COLUMN */}
656
+ <div className="flex flex-col gap-[10px]">
657
+ {/* Departure Time */}
658
+ <div className="h-[20px] flex items-center group relative">
659
+ <div className="font-[900] bold-text">
660
+ {DateService.formatTime(serviceItem.dep_time)}
661
+ </div>
662
+ {serviceItem.boarding_stages && (
556
663
  <div
557
- className="flex items-center capitalize relative group items-center justify-between "
558
- style={{ flex: 1 }}
664
+ className="hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service"
665
+ style={{ backgroundColor: colors?.tooltipColor }}
559
666
  >
560
- <span className="cursor-pointer bold-text">
561
- {DateService.getServiceItemDate(
562
- serviceItem.arrival_date
667
+ <div
668
+ className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0
669
+ border-t-8 border-b-8 border-r-8
670
+ border-t-transparent border-b-transparent"
671
+ style={{ borderRightColor: colors?.tooltipColor }}
672
+ ></div>
673
+ <div
674
+ className="text-center text-[14px] font-normal"
675
+ style={{ fontWeight: 400 }}
676
+ >
677
+ {renderStages(
678
+ serviceItem.boarding_stages,
679
+ 1,
680
+ busStage,
681
+ hideBoardingTime(
682
+ serviceItem?.api_type || serviceItem?.apiType
683
+ )
563
684
  )}
564
- </span>
565
-
566
- <div className="absolute left-[40%] flex items-center w-[60%]">
567
- {removeArrivalTime ? null : serviceItem.arr_time ? (
568
- <div>•</div>
569
- ) : null}
570
- <div className="font-[900] bold-text group relative ml-[20%]">
571
- {removeArrivalTime
572
- ? null
573
- : serviceItem.arr_time
574
- ? DateService.formatTime(serviceItem.arr_time)
575
- : null}
576
-
577
- {/* Dropping stage tooltip */}
578
- {serviceItem.dropoff_stages && (
579
- <div
580
- className="hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service"
581
- style={{ backgroundColor: colors?.tooltipColor }}
582
- >
583
- {/* Tooltip arrow */}
584
- <div
585
- className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0
586
- border-t-8 border-b-8 border-r-8
587
- border-t-transparent border-b-transparent"
588
- style={{
589
- borderRightColor: colors?.tooltipColor,
590
- }}
591
- ></div>
592
- <div className="text-center text-[14px]">
593
- {renderStages(
594
- serviceItem.dropoff_stages,
595
- 2,
596
- busStage,
597
- hideBoardingTime(
598
- serviceItem?.api_type ||
599
- serviceItem?.apiType
600
- )
601
- )}
602
- </div>
603
- </div>
685
+ </div>
686
+ </div>
687
+ )}
688
+ </div>
689
+
690
+ {/* Arrival Time */}
691
+ {!isCiva && (
692
+ <div className="h-[20px] flex items-center group relative">
693
+ <div className="font-[900] bold-text">
694
+ {removeArrivalTime
695
+ ? null
696
+ : serviceItem.arr_time
697
+ ? DateService.formatTime(serviceItem.arr_time)
698
+ : null}
699
+ </div>
700
+ {/* Dropping stage tooltip */}
701
+ {serviceItem.dropoff_stages && (
702
+ <div
703
+ className="hidden group-hover:block absolute -top-[8px] left-[100%] ml-[25px] text-white px-3 py-2 rounded-[10px] whitespace-nowrap z-10 shadow-service"
704
+ style={{ backgroundColor: colors?.tooltipColor }}
705
+ >
706
+ <div
707
+ className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0
708
+ border-t-8 border-b-8 border-r-8
709
+ border-t-transparent border-b-transparent"
710
+ style={{
711
+ borderRightColor: colors?.tooltipColor,
712
+ }}
713
+ ></div>
714
+ <div
715
+ className="text-center text-[14px] font-normal"
716
+ style={{ fontWeight: 400 }}
717
+ >
718
+ {renderStages(
719
+ serviceItem.dropoff_stages,
720
+ 2,
721
+ busStage,
722
+ hideBoardingTime(
723
+ serviceItem?.api_type || serviceItem?.apiType
724
+ )
604
725
  )}
605
726
  </div>
606
727
  </div>
607
- </div>
728
+ )}
608
729
  </div>
609
- </div>
610
- )}
730
+ )}
731
+ </div>
611
732
  </div>
612
733
  <div
613
734
  style={{
@@ -634,7 +755,7 @@ function ServiceItemPB({
634
755
  color: isSoldOut ? "#c0c0c0" : colors.priceColor,
635
756
  top: 0,
636
757
  bottom: 0,
637
- left: "70%",
758
+ left: "68%",
638
759
  right: 0,
639
760
  justifyContent: getNumberOfSeats() < 2 ? "center" : "",
640
761
  }}
@@ -663,7 +784,7 @@ function ServiceItemPB({
663
784
  : "pointer",
664
785
  }}
665
786
  >
666
- <span className="min-w-[75px] flex justify-center items-center bold-text">
787
+ <span className="min-w-[75px] flex justify-center items-center bold-text uppercase">
667
788
  {isSoldOut ? renderIcon("soldOutIcon", "14px") : null}
668
789
 
669
790
  {serviceDetailsLoading ? (
@@ -709,7 +830,7 @@ function ServiceItemPB({
709
830
  />
710
831
  ) : null}
711
832
  <span
712
- className="ml-[10px] text-[#464647] text-[13.33px] bold-text"
833
+ className="ml-[10px] text-[#464647] text-[13.33px]"
713
834
  style={{ marginLeft: showRating ? "10px" : "0" }}
714
835
  >
715
836
  {serviceItem.operator_details[2]}
@@ -988,10 +1109,10 @@ function ServiceItemPB({
988
1109
  </div>
989
1110
  )}
990
1111
 
991
- <div className="absolute -top-[13px] left-0 w-full flex items-center justify-end gap-[12px] pr-[15px] z-10 ">
1112
+ <div className="absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[15px] z-10 ">
992
1113
  {showTopLabel && (
993
1114
  <div
994
- className={`flex items-center gap-[10px] py-[5px] px-[14px] rounded-[38px] text-[13.33px] z-20`}
1115
+ className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
995
1116
  style={{
996
1117
  backgroundColor: isSoldOut ? "#ddd" : colors.ratingBottomColor,
997
1118
  }}
@@ -999,8 +1120,8 @@ function ServiceItemPB({
999
1120
  <div className={isSoldOut ? "grayscale" : ""}>
1000
1121
  <LottiePlayer
1001
1122
  animationData={serviceItem.icons.priorityStageAnim}
1002
- width="16px"
1003
- height="16px"
1123
+ width="14px"
1124
+ height="14px"
1004
1125
  />
1005
1126
  </div>
1006
1127
  <div
@@ -1014,45 +1135,45 @@ function ServiceItemPB({
1014
1135
  )}
1015
1136
  {serviceItem?.is_transpordo && (
1016
1137
  <div
1017
- className={`flex items-center gap-[10px] py-[5px] text-white px-[14px] rounded-[38px] text-[13.33px] z-20`}
1138
+ className={`flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20`}
1018
1139
  style={{
1019
1140
  backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
1020
1141
  }}
1021
1142
  >
1022
1143
  <LottiePlayer
1023
1144
  animationData={serviceItem.icons.connectingServiceIcon}
1024
- width="16px"
1025
- height="16px"
1145
+ width="14px"
1146
+ height="14px"
1026
1147
  />
1027
1148
  <div>{"Conexión"}</div>
1028
1149
  </div>
1029
1150
  )}
1030
1151
  {serviceItem?.is_direct_trip && (
1031
1152
  <div
1032
- className={`flex items-center gap-[10px] py-[5px] text-white px-[14px] rounded-[38px] text-[13.33px] z-20 `}
1153
+ className={`flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20 `}
1033
1154
  style={{
1034
1155
  backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
1035
1156
  }}
1036
1157
  >
1037
1158
  <LottiePlayer
1038
1159
  animationData={serviceItem.icons.directoAnim}
1039
- width="16px"
1040
- height="16px"
1160
+ width="14px"
1161
+ height="14px"
1041
1162
  />
1042
1163
  <div>{translation?.directService}</div>
1043
1164
  </div>
1044
1165
  )}
1045
1166
  {serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
1046
1167
  <div
1047
- className={`flex items-center gap-[10px] py-[5px] text-white px-[14px] rounded-[38px] text-[13.33px] z-20 `}
1168
+ className={`flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20 `}
1048
1169
  style={{
1049
1170
  backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
1050
1171
  }}
1051
1172
  >
1052
1173
  <LottiePlayer
1053
1174
  animationData={serviceItem.icons.directoAnim}
1054
- width="16px"
1055
- height="16px"
1175
+ width="14px"
1176
+ height="14px"
1056
1177
  />
1057
1178
  <div>{"Tren Express"}</div>
1058
1179
  </div>
@@ -60,46 +60,59 @@ function ServiceItemMobile({
60
60
  };
61
61
 
62
62
  const seatTypes = () => {
63
- let seatTypes = serviceItem.seat_types
63
+ const seatMap = new Map();
64
+
65
+ serviceItem.seat_types
64
66
  ?.filter((item) => getFilteredSeats(item.label))
65
- ?.sort((a, b) => a.fare - b.fare) // Add this line to sort by fare
66
- ?.slice(0, 2)
67
- ?.map((type, i) =>
68
- exceptions.includes(type.label) ? null : (
69
- <div
70
- className={
71
- serviceItem.seat_types?.length > 2
72
- ? "w-[100%] flex flex-row justify-between "
73
- : "w-[100%] flex flex-row justify-between items-center"
74
- }
75
- key={i}
67
+ ?.forEach((item) => {
68
+ if (exceptions.includes(item.key as any)) return;
69
+ const existing = seatMap.get(item.label);
70
+ if (
71
+ !existing ||
72
+ parseFloat(item.fare as any) < parseFloat(existing.fare)
73
+ ) {
74
+ seatMap.set(item.label, item);
75
+ }
76
+ });
77
+
78
+ const uniqueSeats = Array.from(seatMap.values())
79
+ .sort((a, b) => a.fare - b.fare)
80
+ .slice(0, 3);
81
+ return uniqueSeats.map((type, i) =>
82
+ exceptions.includes(type.label) ? null : (
83
+ <div
84
+ className={
85
+ serviceItem.seat_types?.length > 2
86
+ ? "w-[100%] flex flex-row justify-between "
87
+ : "w-[100%] flex flex-row justify-between items-center"
88
+ }
89
+ key={i}
90
+ >
91
+ <span
92
+ className="min-[420]:text-[13px] text-[11px] "
93
+ style={{
94
+ // marginLeft: "10px",
95
+ color: isSoldOut ? "#bbb" : "#464647",
96
+ }}
76
97
  >
77
- <span
78
- className="min-[420]:text-[13px] text-[11px] "
79
- style={{
80
- // marginLeft: "10px",
81
- color: isSoldOut ? "#bbb" : "#464647",
82
- }}
83
- >
84
- {type.label}
85
- </span>
86
- <span
87
- className={"min-[420]:text-[13px] text-[11px] bold-text"}
88
- style={{ color: isSoldOut ? "#bbb" : colors.seatPriceColor }}
89
- >
90
- {/* {serviceItem?.operator_service_name === "Pullman San Andrés" &&
98
+ {type.label}
99
+ </span>
100
+ <span
101
+ className={"min-[420]:text-[13px] text-[11px] bold-text"}
102
+ style={{ color: isSoldOut ? "#bbb" : colors.seatPriceColor }}
103
+ >
104
+ {/* {serviceItem?.operator_service_name === "Pullman San Andrés" &&
91
105
  serviceItem?.available_seats <= 0
92
106
  ? null
93
107
  : commonService.currency(type.fare, currencySign)} */}
94
108
 
95
- {serviceItem?.available_seats <= 0 && !isPeru
96
- ? commonService.currency(0, currencySign)
97
- : commonService.currency(type.fare, currencySign)}
98
- </span>
99
- </div>
100
- )
101
- );
102
- return seatTypes;
109
+ {serviceItem?.available_seats <= 0 && !isPeru
110
+ ? commonService.currency(0, currencySign)
111
+ : commonService.currency(type.fare, currencySign)}
112
+ </span>
113
+ </div>
114
+ )
115
+ );
103
116
  };
104
117
 
105
118
  const getFilteredSeats = (item) => {
@@ -28,6 +28,7 @@ export interface MobileServiceItemProps {
28
28
  seat_types: Array<{
29
29
  label: string;
30
30
  fare: number;
31
+ key: any;
31
32
  }>;
32
33
  boarding_stages?: string;
33
34
  dropoff_stages?: string;
@@ -28,6 +28,7 @@ export interface ServiceItemProps {
28
28
  seat_types: Array<{
29
29
  label: string;
30
30
  fare: number;
31
+ key: any;
31
32
  }>;
32
33
  boarding_stages?: string;
33
34
  dropoff_stages?: string;
@@ -154,4 +155,5 @@ export interface ServiceItemProps {
154
155
  showLastSeats?: boolean
155
156
  removeArrivalTime?: boolean;
156
157
  originIconStyle?:boolean;
158
+ removeDuplicateSeats?: boolean
157
159
  }