kupos-ui-components-lib 3.0.9 → 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.
@@ -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, "_");
@@ -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
@@ -308,8 +334,9 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
308
334
  React.createElement("div", { className: "flex flex-col gap-[10px]" },
309
335
  orignLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, orignLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
310
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" : ""}` }))),
311
- !isCiva && (destinationLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, destinationLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
312
- 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 } }))))),
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 } }))))),
313
340
  React.createElement("div", { className: "flex flex-col gap-[10px]" },
314
341
  React.createElement("div", { className: "h-[20px] flex items-center group relative" },
315
342
  React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.travel_date)),
@@ -322,8 +349,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
322
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: {
323
350
  borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor,
324
351
  } }),
325
- 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) ||
326
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType))))))))),
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))))))))),
327
353
  React.createElement("div", { className: "flex flex-col gap-[10px] items-center" },
328
354
  React.createElement("div", { className: "h-[20px] flex items-center justify-center" },
329
355
  React.createElement("div", null, "\u2022")),
@@ -344,8 +370,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
344
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: {
345
371
  borderRightColor: colors === null || colors === void 0 ? void 0 : colors.tooltipColor,
346
372
  } }),
347
- 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) ||
348
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.apiType)))))))))),
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)))))))))),
349
374
  React.createElement("div", { style: {
350
375
  width: "1px",
351
376
  height: "2.5rem",
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "3.0.9",
3
+ "version": "4.0.1",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -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 {
@@ -61,8 +62,9 @@ function ServiceItemPB({
61
62
  style={{
62
63
  filter: color === "white" ? "brightness(0) invert(1)" : "",
63
64
  }}
64
- className={`object-contain ${moreAnemities ? "w-[16px] h-[16px]" : "w-[16px] h-[16px]"
65
- }`}
65
+ className={`object-contain ${
66
+ moreAnemities ? "w-[16px] h-[16px]" : "w-[16px] h-[16px]"
67
+ }`}
66
68
  />
67
69
  );
68
70
  };
@@ -211,10 +213,10 @@ function ServiceItemPB({
211
213
  {hideTime
212
214
  ? item?.split("|")[0]
213
215
  : item
214
- .replace(/false/g, "")
215
- .replace("true", "")
216
- .replace("|", " |")
217
- .replace("||", " |")}
216
+ .replace(/false/g, "")
217
+ .replace("true", "")
218
+ .replace("|", " |")
219
+ .replace("||", " |")}
218
220
  </div>
219
221
  ))}
220
222
  </div>
@@ -267,6 +269,24 @@ function ServiceItemPB({
267
269
  return seatTypesWithPrices;
268
270
  };
269
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
+
270
290
  const getNumberOfSeats = () => {
271
291
  return serviceItem.seat_types.filter(
272
292
  (val) => !SEAT_EXCEPTIONS.includes(val.label)
@@ -274,13 +294,32 @@ function ServiceItemPB({
274
294
  };
275
295
 
276
296
  const getSeatNames = () => {
297
+ const sortedSeatTypesDuplicate = getUniqueSeatsWithLowestPrice();
277
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
+ }
278
316
  return sortedSeatTypes.map((val, key: number) =>
279
317
  SEAT_EXCEPTIONS.includes(val.label) ? null : (
280
318
  <span
281
319
  key={key}
282
- className={`flex items-center justify-between text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""
283
- }`}
320
+ className={`flex items-center justify-between text-[13.33px] ${
321
+ isSoldOut ? "text-[#c0c0c0]" : ""
322
+ }`}
284
323
  >
285
324
  {typeof val.label === "string" || typeof val.label === "number"
286
325
  ? val.label
@@ -292,6 +331,16 @@ function ServiceItemPB({
292
331
 
293
332
  const getSeatPrice = () => {
294
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
+ }
295
344
  return sortedSeatTypes.map((val, key: number) => {
296
345
  return SEAT_EXCEPTIONS.includes(val.label) ? null : (
297
346
  <span key={key} className="flex items-center text-[13.33px] bold-text">
@@ -300,10 +349,10 @@ function ServiceItemPB({
300
349
  ? CommonService.currency(0, currencySign)
301
350
  : CommonService.currency(val.price, currencySign)
302
351
  : typeof val.price === "number"
303
- ? serviceItem?.available_seats <= 0
304
- ? CommonService.currency(0, currencySign)
305
- : CommonService.currency(val.price, currencySign)
306
- : null}
352
+ ? serviceItem?.available_seats <= 0
353
+ ? CommonService.currency(0, currencySign)
354
+ : CommonService.currency(val.price, currencySign)
355
+ : null}
307
356
  </span>
308
357
  );
309
358
  });
@@ -403,13 +452,15 @@ function ServiceItemPB({
403
452
 
404
453
  return (
405
454
  <div
406
- className={`relative ${serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"
407
- } ${serviceItem?.is_direct_trip ||
408
- serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
409
- showTopLabel
455
+ className={`relative ${
456
+ serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"
457
+ } ${
458
+ serviceItem?.is_direct_trip ||
459
+ serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
460
+ showTopLabel
410
461
  ? "mt-[24px]"
411
462
  : "mt-[14px]"
412
- } `}
463
+ } `}
413
464
  >
414
465
  <div
415
466
  className={"bg-white rounded-[20px] shadow-service mx-auto relative"}
@@ -450,8 +501,9 @@ function ServiceItemPB({
450
501
  <img
451
502
  src={serviceItem.operator_details[0]}
452
503
  alt="service logo"
453
- className={` h-auto object-contain ${isSoldOut ? "grayscale" : ""
454
- }`}
504
+ className={` h-auto object-contain ${
505
+ isSoldOut ? "grayscale" : ""
506
+ }`}
455
507
  />
456
508
  </div>
457
509
  {isCiva ? (
@@ -463,8 +515,9 @@ function ServiceItemPB({
463
515
 
464
516
  {/* DATE AND TIME - Grid Layout */}
465
517
  <div
466
- className={`min-h-[2.5rem] grid grid-cols-[26px_auto_26%_1fr] gap-x-4 items-center text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""
467
- }`}
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
+ }`}
468
521
  style={{
469
522
  // gridTemplateRows: isCiva ? "1fr" : "1fr 1fr",
470
523
  gridTemplateRows: "1fr",
@@ -475,33 +528,38 @@ function ServiceItemPB({
475
528
  <div className="flex flex-col gap-[10px]">
476
529
  {/* Origin Icon */}
477
530
  {orignLabel ? (
478
- <div className="w-[60px] h-[20px] flex items-center">{orignLabel}</div>
531
+ <div className="w-[60px] h-[20px] flex items-center">
532
+ {orignLabel}
533
+ </div>
479
534
  ) : (
480
535
  <div className="h-[20px] flex items-center">
481
536
  <img
482
537
  src={serviceItem.icons?.origin}
483
538
  alt="origin"
484
- className={`w-[18px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""
485
- }`}
539
+ className={`w-[18px] h-auto mr-[8px] ${
540
+ isSoldOut ? "grayscale" : ""
541
+ }`}
486
542
  />
487
543
  </div>
488
544
  )}
489
545
 
490
546
  {/* Destination Icon */}
491
- {!isCiva && (
492
- destinationLabel ? (
493
- <div className="w-[60px] h-[20px] flex items-center">{destinationLabel}</div>
547
+ {!isCiva &&
548
+ (destinationLabel ? (
549
+ <div className="w-[60px] h-[20px] flex items-center">
550
+ {destinationLabel}
551
+ </div>
494
552
  ) : (
495
553
  <div className="h-[20px] flex items-center">
496
554
  <img
497
555
  src={serviceItem.icons?.destination}
498
- className={`w-[18px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""
499
- }`}
556
+ className={`w-[18px] h-auto mr-[8px] ${
557
+ isSoldOut ? "grayscale" : ""
558
+ }`}
500
559
  style={{ opacity: isSoldOut ? 0.5 : 1 }}
501
560
  />
502
561
  </div>
503
- )
504
- )}
562
+ ))}
505
563
  </div>
506
564
 
507
565
  {/* DATES COLUMN */}
@@ -522,7 +580,10 @@ function ServiceItemPB({
522
580
  border-t-transparent border-b-transparent"
523
581
  style={{ borderRightColor: colors?.tooltipColor }}
524
582
  ></div>
525
- <div className="text-center text-[14px] font-normal" style={{ fontWeight: 400 }}>
583
+ <div
584
+ className="text-center text-[14px] font-normal"
585
+ style={{ fontWeight: 400 }}
586
+ >
526
587
  {renderStages(
527
588
  serviceItem.boarding_stages,
528
589
  1,
@@ -555,14 +616,16 @@ function ServiceItemPB({
555
616
  borderRightColor: colors?.tooltipColor,
556
617
  }}
557
618
  ></div>
558
- <div className="text-center text-[14px] font-normal" style={{ fontWeight: 400 }}>
619
+ <div
620
+ className="text-center text-[14px] font-normal"
621
+ style={{ fontWeight: 400 }}
622
+ >
559
623
  {renderStages(
560
624
  serviceItem.dropoff_stages,
561
625
  2,
562
626
  busStage,
563
627
  hideBoardingTime(
564
- serviceItem?.api_type ||
565
- serviceItem?.apiType
628
+ serviceItem?.api_type || serviceItem?.apiType
566
629
  )
567
630
  )}
568
631
  </div>
@@ -607,7 +670,10 @@ function ServiceItemPB({
607
670
  border-t-transparent border-b-transparent"
608
671
  style={{ borderRightColor: colors?.tooltipColor }}
609
672
  ></div>
610
- <div className="text-center text-[14px] font-normal" style={{ fontWeight: 400 }}>
673
+ <div
674
+ className="text-center text-[14px] font-normal"
675
+ style={{ fontWeight: 400 }}
676
+ >
611
677
  {renderStages(
612
678
  serviceItem.boarding_stages,
613
679
  1,
@@ -628,8 +694,8 @@ function ServiceItemPB({
628
694
  {removeArrivalTime
629
695
  ? null
630
696
  : serviceItem.arr_time
631
- ? DateService.formatTime(serviceItem.arr_time)
632
- : null}
697
+ ? DateService.formatTime(serviceItem.arr_time)
698
+ : null}
633
699
  </div>
634
700
  {/* Dropping stage tooltip */}
635
701
  {serviceItem.dropoff_stages && (
@@ -645,14 +711,16 @@ function ServiceItemPB({
645
711
  borderRightColor: colors?.tooltipColor,
646
712
  }}
647
713
  ></div>
648
- <div className="text-center text-[14px] font-normal" style={{ fontWeight: 400 }}>
714
+ <div
715
+ className="text-center text-[14px] font-normal"
716
+ style={{ fontWeight: 400 }}
717
+ >
649
718
  {renderStages(
650
719
  serviceItem.dropoff_stages,
651
720
  2,
652
721
  busStage,
653
722
  hideBoardingTime(
654
- serviceItem?.api_type ||
655
- serviceItem?.apiType
723
+ serviceItem?.api_type || serviceItem?.apiType
656
724
  )
657
725
  )}
658
726
  </div>
@@ -673,8 +741,9 @@ function ServiceItemPB({
673
741
  {/* SEATS */}
674
742
  <div className="content-center">
675
743
  <div
676
- className={`relative flex gap-[10px] text-[13.33px] justify-between min-h-[2.5rem] ${getNumberOfSeats() < 3 ? "" : ""
677
- }`}
744
+ className={`relative flex gap-[10px] text-[13.33px] justify-between min-h-[2.5rem] ${
745
+ getNumberOfSeats() < 3 ? "" : ""
746
+ }`}
678
747
  style={getNumberOfSeats() < 2 ? { alignItems: "center" } : {}}
679
748
  >
680
749
  <div className="flex flex-col justify-between">
@@ -701,8 +770,9 @@ function ServiceItemPB({
701
770
  <button
702
771
  onClick={() => (!isSoldOut ? checkMidnight() : null)}
703
772
  disabled={serviceDetailsLoading}
704
- className={`w-full ${serviceDetailsLoading || isSoldOut ? "py-[12px]" : "py-[12px]"
705
- } text-[13.33px] font-bold text-white rounded-[10px] border-none px-[20px] flex items-center justify-center`}
773
+ className={`w-full ${
774
+ serviceDetailsLoading || isSoldOut ? "py-[12px]" : "py-[12px]"
775
+ } text-[13.33px] font-bold text-white rounded-[10px] border-none px-[20px] flex items-center justify-center`}
706
776
  style={{
707
777
  backgroundColor:
708
778
  serviceDetailsLoading || isSoldOut
@@ -745,8 +815,9 @@ function ServiceItemPB({
745
815
  {/* Rating */}
746
816
  <div className="flex items-center ">
747
817
  <div
748
- className={`flex items-center ${isSoldOut ? "grayscale" : ""} ${showRating ? "cursor-pointer" : ""
749
- }`}
818
+ className={`flex items-center ${isSoldOut ? "grayscale" : ""} ${
819
+ showRating ? "cursor-pointer" : ""
820
+ }`}
750
821
  style={{ color: isSoldOut ? "#c0c0c0" : "" }}
751
822
  >
752
823
  {showRating ? (
@@ -773,14 +844,16 @@ function ServiceItemPB({
773
844
  <div className="flex items-baseline relative text-[#464647]">
774
845
  {/* {renderIcon("duration", "14px")} */}
775
846
  <div
776
- className={`w-[18px] h-auto mr-[4px] ${isSoldOut ? "grayscale" : ""
777
- }`}
847
+ className={`w-[18px] h-auto mr-[4px] ${
848
+ isSoldOut ? "grayscale" : ""
849
+ }`}
778
850
  >
779
851
  {renderIcon("hours", "14px")}
780
852
  </div>
781
853
  <div
782
- className={`cursor-default group text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""
783
- }`}
854
+ className={`cursor-default group text-[13.33px] ${
855
+ isSoldOut ? "text-[#c0c0c0]" : ""
856
+ }`}
784
857
  >
785
858
  {serviceItem.duration} {translation.hours}
786
859
  <div
@@ -799,7 +872,7 @@ function ServiceItemPB({
799
872
  )}
800
873
 
801
874
  {serviceItem.pet_seat_info &&
802
- Object.keys(serviceItem.pet_seat_info).length > 0 ? (
875
+ Object.keys(serviceItem.pet_seat_info).length > 0 ? (
803
876
  <div className="flex items-center text-[13.33px]">
804
877
  <div className={`relative group cursor-default `}>
805
878
  <div className="flex items-center">
@@ -870,8 +943,9 @@ function ServiceItemPB({
870
943
  {serviceItem?.is_tracking_enabled && (
871
944
  <div className="flex items-center mr-[10px]">
872
945
  <div
873
- className={`h-auto mr-[4px] text-[13px] text-[#464647] ${isSoldOut ? "grayscale" : ""
874
- }`}
946
+ className={`h-auto mr-[4px] text-[13px] text-[#464647] ${
947
+ isSoldOut ? "grayscale" : ""
948
+ }`}
875
949
  >
876
950
  <LottiePlayer
877
951
  animationData={serviceItem.icons.locationAnim}
@@ -969,8 +1043,9 @@ function ServiceItemPB({
969
1043
  className="flex items-center gap-[5px] whitespace-nowrap text-[13.33px]"
970
1044
  >
971
1045
  <div
972
- className={`${isSoldOut ? "grayscale" : ""
973
- }`}
1046
+ className={`${
1047
+ isSoldOut ? "grayscale" : ""
1048
+ }`}
974
1049
  >
975
1050
  <SvgAmenities
976
1051
  moreAnemities={true}
@@ -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;