kupos-ui-components-lib 10.4.61 → 10.4.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/components/FilterBar/FilterBarDesktop.js +10 -0
  2. package/dist/components/FilterBar/ServiceFilter.d.ts +1 -0
  3. package/dist/components/FilterBar/ServiceFilter.js +10 -4
  4. package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
  5. package/dist/components/ServiceItem/ServiceItemDesktop.js +4 -4
  6. package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
  7. package/dist/components/ServiceItem/ServiceItemMobile.js +4 -4
  8. package/dist/components/ServiceItem/mobileTypes.d.ts +2 -0
  9. package/dist/components/ServiceItem/types.d.ts +2 -0
  10. package/dist/styles.css +3 -0
  11. package/dist/ui/RatingBlock.d.ts +1 -1
  12. package/dist/ui/RatingBlock.js +7 -3
  13. package/dist/ui/SeatSection/SeatSection.d.ts +2 -1
  14. package/dist/ui/SeatSection/SeatSection.js +28 -11
  15. package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +2 -1
  16. package/dist/ui/mobileweb/DateTimeSectionMobile.js +2 -2
  17. package/dist/ui/mobileweb/SeatSectionMobile.d.ts +2 -1
  18. package/dist/ui/mobileweb/SeatSectionMobile.js +5 -4
  19. package/package.json +1 -1
  20. package/src/components/FilterBar/FilterBarDesktop.tsx +16 -0
  21. package/src/components/FilterBar/ServiceFilter.tsx +12 -2
  22. package/src/components/ServiceItem/ServiceItemDesktop.tsx +7 -1
  23. package/src/components/ServiceItem/ServiceItemMobile.tsx +15 -1
  24. package/src/components/ServiceItem/mobileTypes.ts +3 -0
  25. package/src/components/ServiceItem/types.ts +3 -0
  26. package/src/ui/RatingBlock.tsx +7 -2
  27. package/src/ui/SeatSection/SeatSection.tsx +50 -15
  28. package/src/ui/mobileweb/DateTimeSectionMobile.tsx +3 -0
  29. package/src/ui/mobileweb/SeatSectionMobile.tsx +9 -3
@@ -175,6 +175,16 @@ const FilterBarDesktop = ({ t, serviceList, setServiceList, allSchedules, showRe
175
175
  return true;
176
176
  });
177
177
  }
178
+ if (fil.type == "service_type") {
179
+ const activeOptions = fil.options.filter((it) => it.active);
180
+ if (activeOptions.length) {
181
+ filteredRoutes = filteredRoutes.filter((it) => activeOptions.some((f) => f.value ===
182
+ String(it.service_type || "")
183
+ .trim()
184
+ .replace(/\s+/g, " ")
185
+ .toLowerCase()));
186
+ }
187
+ }
178
188
  if (fil.type == "operator") {
179
189
  let activeOptions = fil.options.filter((it) => it.active);
180
190
  filteredRoutes = filteredRoutes.filter((it) => {
@@ -9,6 +9,7 @@ interface ServiceFilterBarDesktopState {
9
9
  showTrainType: boolean;
10
10
  addMargin: boolean;
11
11
  showAmenities: boolean;
12
+ showServiceType: boolean;
12
13
  sortedFilters: any[];
13
14
  }
14
15
  declare class ServiceFilter extends React.Component<ServiceFilterProps, ServiceFilterBarDesktopState> {
@@ -23,6 +23,7 @@ class ServiceFilter extends React.Component {
23
23
  showTrainType: ((_f = props.initialOpenFilters) === null || _f === void 0 ? void 0 : _f.includes("train_type")) || true,
24
24
  addMargin: false,
25
25
  showAmenities: ((_g = props.initialOpenFilters) === null || _g === void 0 ? void 0 : _g.includes("amenities")) || true,
26
+ showServiceType: true,
26
27
  sortedFilters: this.sortFilters(props.filtersArray),
27
28
  };
28
29
  this.handleScroll = this.handleScroll.bind(this);
@@ -53,6 +54,7 @@ class ServiceFilter extends React.Component {
53
54
  const FILTER_ORDER = [
54
55
  "time",
55
56
  "operator",
57
+ "service_type",
56
58
  "special_departure",
57
59
  "tipo",
58
60
  "seat_types",
@@ -120,18 +122,21 @@ class ServiceFilter extends React.Component {
120
122
  ? !prevState.showTrainType
121
123
  : prevState.showTrainType, showAmenities: type === "amenities"
122
124
  ? !prevState.showAmenities
123
- : prevState.showAmenities });
125
+ : prevState.showAmenities, showServiceType: type === "service_type"
126
+ ? !prevState.showServiceType
127
+ : prevState.showServiceType });
124
128
  });
125
129
  }
126
130
  renderFilterItem(option, onClick, key) {
127
- const { showOperators, showTimeOptions, showSeatOptions, showTypeOptions, showSpecialDeparture, showTrainType, showAmenities, } = this.state;
131
+ const { showOperators, showTimeOptions, showSeatOptions, showTypeOptions, showSpecialDeparture, showTrainType, showAmenities, showServiceType, } = this.state;
128
132
  const isOpen = (option.type === "operator" && showOperators) ||
129
133
  (option.type === "time" && showTimeOptions) ||
130
134
  (option.type === "seat_types" && showSeatOptions) ||
131
135
  (option.type === "tipo" && showTypeOptions) ||
132
136
  (option.type === "special_departure" && showSpecialDeparture) ||
133
137
  (option.type === "train_type" && showTrainType) ||
134
- (option.type === "amenities" && showAmenities);
138
+ (option.type === "amenities" && showAmenities) ||
139
+ (option.type === "service_type" && showServiceType);
135
140
  if ((option === null || option === void 0 ? void 0 : option.type) === "train_type" && !this.props.isTrain) {
136
141
  return null;
137
142
  }
@@ -159,7 +164,8 @@ class ServiceFilter extends React.Component {
159
164
  option.type !== "seat_types" &&
160
165
  option.type !== "tipo" &&
161
166
  option.type !== "special_departure" &&
162
- option.type !== "train_type")) &&
167
+ option.type !== "train_type" &&
168
+ option.type !== "service_type")) &&
163
169
  option.options.map((val, i) => {
164
170
  var _a, _b, _c, _d, _e, _f, _g, _h;
165
171
  let iconKey = "";
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { ServiceItemProps } from "./types";
3
- declare function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isTrain, selectedSeatKey, onSeatSelect, onTrainButtonClick, showSeatSelectionError, onShowSeatSelectionError, onClearSeatSelectionError, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, priority_stage_ids, isShowSeatIcon, }: ServiceItemProps & {
3
+ declare function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isTrain, selectedSeatKey, onSeatSelect, onTrainButtonClick, showSeatSelectionError, onShowSeatSelectionError, onClearSeatSelectionError, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, priority_stage_ids, isShowSeatIcon, showDesdeLabel, showServiceTypeUnderLogo, }: ServiceItemProps & {
4
4
  currencySign?: string;
5
5
  }): React.ReactElement;
6
6
  export default ServiceItemPB;
@@ -87,7 +87,7 @@ const ANIMATION_MAP = {
87
87
  kupos: flameAnimation,
88
88
  },
89
89
  };
90
- function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t = (key) => key, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isTrain, selectedSeatKey, onSeatSelect, onTrainButtonClick, showSeatSelectionError, onShowSeatSelectionError, onClearSeatSelectionError, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, priority_stage_ids, isShowSeatIcon = false, }) {
90
+ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t = (key) => key, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isTrain, selectedSeatKey, onSeatSelect, onTrainButtonClick, showSeatSelectionError, onShowSeatSelectionError, onClearSeatSelectionError, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, operatorLabel, priority_stage_ids, isShowSeatIcon = false, showDesdeLabel = false, showServiceTypeUnderLogo = false, }) {
91
91
  var _a, _b, _c;
92
92
  const handleSeatSelect = (key, price, seatKey, apiSeatType) => {
93
93
  onClearSeatSelectionError === null || onClearSeatSelectionError === void 0 ? void 0 : onClearSeatSelectionError();
@@ -356,7 +356,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
356
356
  React.createElement("div", null,
357
357
  React.createElement("img", { src: serviceItem.operator_details[0], alt: "service logo", className: `h-[30px] w-[auto] ${isSoldOut ? "grayscale" : ""}` }),
358
358
  isCiva ? (React.createElement("div", { className: "text-[13.33px] black-text ml-2" }, serviceItem.operator_details[2])) : null),
359
- React.createElement(RatingBlock, { showRating: showRating, serviceItem: serviceItem, isSoldOut: isSoldOut, colors: colors, t: t, translation: translation, isPeru: isPeru, isTrain: isTrain })),
359
+ React.createElement(RatingBlock, { showRating: showRating, serviceItem: serviceItem, isSoldOut: isSoldOut, colors: colors, t: t, translation: translation, isPeru: isPeru, isTrain: isTrain, showServiceTypeUnderLogo: showServiceTypeUnderLogo })),
360
360
  React.createElement(DateTimeSection, { serviceItem: serviceItem, isSoldOut: isSoldOut, isCiva: isCiva, isLinatal: isLinatal, removeArrivalTime: removeArrivalTime, orignLabel: orignLabel, destinationLabel: destinationLabel, busStage: busStage, metaData: metaData, colors: colors }),
361
361
  React.createElement("div", { style: {
362
362
  width: "1px",
@@ -364,7 +364,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
364
364
  backgroundColor: "#ccc",
365
365
  } }),
366
366
  React.createElement("div", { className: "content-center" },
367
- React.createElement(SeatSection, { seatTypes: serviceItem.seat_types, serviceItem: serviceItem, availableSeats: serviceItem.available_seats, isSoldOut: isSoldOut, priceColor: colors.priceColor, dpSeatColor: colors.seatPriceColor, currencySign: currencySign, removeDuplicateSeats: removeDuplicateSeats, isPeru: isPeru, renderIcon: renderIcon, discountSeatPriceColor: colors.discountSeatPriceColor, isSeatIcon: isSeatIcon, isTrain: isTrain, selectedSeatKey: selectedSeatKey, onSeatSelect: handleSeatSelect, topLabelColor: colors.topLabelColor, tooltipColor: colors.tooltipColor, discountSeatCrossPriceColor: colors.discountSeatCrossPriceColor, isShowSeatIcon: isShowSeatIcon })),
367
+ React.createElement(SeatSection, { seatTypes: serviceItem.seat_types, serviceItem: serviceItem, availableSeats: serviceItem.available_seats, isSoldOut: isSoldOut, priceColor: colors.priceColor, dpSeatColor: colors.seatPriceColor, currencySign: currencySign, removeDuplicateSeats: removeDuplicateSeats, isPeru: isPeru, renderIcon: renderIcon, discountSeatPriceColor: colors.discountSeatPriceColor, isSeatIcon: isSeatIcon, isTrain: isTrain, selectedSeatKey: selectedSeatKey, onSeatSelect: handleSeatSelect, topLabelColor: colors.topLabelColor, tooltipColor: colors.tooltipColor, discountSeatCrossPriceColor: colors.discountSeatCrossPriceColor, isShowSeatIcon: isShowSeatIcon, showDesdeLabel: showDesdeLabel })),
368
368
  React.createElement("div", { className: "relative" },
369
369
  React.createElement(KuposButton, { isSoldOut: isSoldOut, isLoading: serviceDetailsLoading, buttonColor: colors.kuposButtonColor, buyLabel: translation === null || translation === void 0 ? void 0 : translation.buyButton, soldOutLabel: translation === null || translation === void 0 ? void 0 : translation.soldOutButton, soldOutIcon: renderIcon("soldOutIcon", "14px"), onClick: checkMidnight }),
370
370
  showSeatSelectionError === serviceItem.id && isTrain && (React.createElement("div", { className: "flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]" },
@@ -376,7 +376,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
376
376
  color: colors.seatPriceColor,
377
377
  } }, "\u00A1\u00DAltimos Asientos!")))) : null)),
378
378
  React.createElement(BottomAmenities, { otherItems: otherItems, serviceItem: serviceItem, grayscaleClass: grayscaleClass, isSoldOut: isSoldOut, isItemExpanded: isItemExpanded, colors: colors, translation: translation, getAnimationIcon: getAnimationIcon, downArrowIcon: renderIcon("downArrow", "10px"), onToggleExpand: () => setIsExpand &&
379
- setIsExpand(isItemExpanded ? null : serviceItem.id), isPeru: isPeru, isTrain: isTrain, isDpEnabled: serviceItem.is_dp_enabled, serviceType: serviceItem.service_type, renderIcon: renderIcon }))),
379
+ setIsExpand(isItemExpanded ? null : serviceItem.id), isPeru: isPeru, isTrain: isTrain, isDpEnabled: serviceItem.is_dp_enabled, serviceType: showServiceTypeUnderLogo ? undefined : serviceItem.service_type, renderIcon: renderIcon }))),
380
380
  isPeru ? null : (React.createElement("div", { style: {
381
381
  display: "grid",
382
382
  gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
2
  import { MobileServiceItemProps } from "./mobileTypes";
3
- declare function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, isAllinBus, isPeruSite, priority_stage_ids, isShowSeatIcon, }: MobileServiceItemProps): React.ReactElement;
3
+ declare function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, isAllinBus, isPeruSite, priority_stage_ids, isShowSeatIcon, showDesdeLabel, showServiceTypeUnderLogo, }: MobileServiceItemProps): React.ReactElement;
4
4
  export default ServiceItemMobile;
@@ -19,7 +19,7 @@ const exceptions = [
19
19
  "blanco",
20
20
  "asiento_mascota",
21
21
  ];
22
- function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, isAllinBus, isPeruSite, priority_stage_ids, isShowSeatIcon = false, }) {
22
+ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, isAllinBus, isPeruSite, priority_stage_ids, isShowSeatIcon = false, showDesdeLabel = false, showServiceTypeUnderLogo = false, }) {
23
23
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
24
24
  const isItemExpanded = serviceItem.id === isExpanded;
25
25
  const isPetSeat = (Object.keys(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.pet_seat_info) || []).length > 0;
@@ -145,7 +145,7 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
145
145
  } },
146
146
  React.createElement("div", { className: `w-[115px] ${isFlores ? "" : "overflow-y-hidden"} h-[30px]` },
147
147
  React.createElement("img", { src: serviceItem.operator_details[0], alt: "service logo", className: `w-[100px] h-auto object-contain ${isSoldOut ? "grayscale" : ""}` })),
148
- isCiva ? (React.createElement("div", { className: "black-text min-[420]:text-[12px] text-[12px]" }, serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_details[2])) : showRating ? (React.createElement("div", { className: "flex min-[420]:text-[13px] text-[12px] h-[22px] items-center" },
148
+ isCiva ? (React.createElement("div", { className: "black-text min-[420]:text-[12px] text-[12px]" }, serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_details[2])) : showServiceTypeUnderLogo && (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.service_type) ? (React.createElement("div", { className: "min-[420]:text-[13px] text-[12px] text-ellipsis overflow-hidden whitespace-nowrap max-w-[150px]", style: { color: isSoldOut ? "#bbb" : "#464647" } }, commonService.capitalizeFirstLetter(serviceItem.service_type))) : showRating ? (React.createElement("div", { className: "flex min-[420]:text-[13px] text-[12px] h-[22px] items-center" },
149
149
  React.createElement("div", { className: "flex items-center" },
150
150
  React.createElement("div", { className: "flex items-center" },
151
151
  React.createElement("img", { src: serviceItem.icons.rating, alt: "origin", className: `w-[12px] h-[12px] mr-[4px] object-contain ${isSoldOut ? "grayscale" : ""}` }),
@@ -154,14 +154,14 @@ function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, o
154
154
  color: isSoldOut ? "#bbb" : "text-[#464647]",
155
155
  } },
156
156
  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)),
157
- React.createElement(DateTimeSectionMobile, { onBookButtonPress: onBookButtonPress, isCiva: isCiva, isSoldOut: isSoldOut, isLinatal: isLinatal, isPeru: isPeru, orignLabel: orignLabel, destinationLabel: destinationLabel, originIcon: (_g = serviceItem.icons) === null || _g === void 0 ? void 0 : _g.origin, destinationIcon: (_h = serviceItem.icons) === null || _h === void 0 ? void 0 : _h.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, discountSeatPriceColor: colors.discountSeatPriceColor, isTrain: isTrain, discountSeatCrossPriceColor: colors.discountSeatCrossPriceColor, isShowSeatIcon: isShowSeatIcon }),
157
+ React.createElement(DateTimeSectionMobile, { onBookButtonPress: onBookButtonPress, isCiva: isCiva, isSoldOut: isSoldOut, isLinatal: isLinatal, isPeru: isPeru, orignLabel: orignLabel, destinationLabel: destinationLabel, originIcon: (_g = serviceItem.icons) === null || _g === void 0 ? void 0 : _g.origin, destinationIcon: (_h = serviceItem.icons) === null || _h === void 0 ? void 0 : _h.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, discountSeatPriceColor: colors.discountSeatPriceColor, isTrain: isTrain, discountSeatCrossPriceColor: colors.discountSeatCrossPriceColor, isShowSeatIcon: isShowSeatIcon, showDesdeLabel: showDesdeLabel }),
158
158
  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)),
159
159
  showLastSeats ? (React.createElement("div", { className: "flex justify-end " }, (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) < 10 &&
160
160
  (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.available_seats) > 0 && (React.createElement("div", { className: "text-[10px] text-center", style: {
161
161
  color: colors.tooltipBgColor,
162
162
  } }, "\u00A1\u00DAltimos Asientos!")))) : null,
163
163
  React.createElement("div", { className: "bg-[#E6E6E6] mt-[10px] mb-[8px] h-[1px]" }),
164
- React.createElement(BottomAmenitiesMobile, { isSoldOut: isSoldOut, amenitiesNodes: amenities(), hoursIcon: renderIcon("hours", "14px"), duration: (_j = serviceItem.duration) === null || _j === void 0 ? void 0 : _j.toString(), isDirectTrip: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip, serviceType: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.service_type, 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: () => {
164
+ React.createElement(BottomAmenitiesMobile, { isSoldOut: isSoldOut, amenitiesNodes: amenities(), hoursIcon: renderIcon("hours", "14px"), duration: (_j = serviceItem.duration) === null || _j === void 0 ? void 0 : _j.toString(), isDirectTrip: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip, serviceType: showServiceTypeUnderLogo ? undefined : serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.service_type, 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: () => {
165
165
  setIsExpanded(isItemExpanded ? null : serviceItem.id);
166
166
  }, isPeru: isPeru, femaleAnim: serviceItem.icons.femaleAnim, ladiesBookedSeats: serviceItem.ladies_booked_seats, isDpEnabled: serviceItem.is_dp_enabled, isTrain: isTrain, renderIcon: renderIcon })),
167
167
  React.createElement(ServiceBadgesMobile, { showTopLabel: showTopLabel || undefined, isSoldOut: isSoldOut, colors: colors, renderIcon: renderIcon, serviceItem: serviceItem, isConexion: isConexion, isAllinBus: isAllinBus, boardingName: boardingName })),
@@ -253,4 +253,6 @@ export interface MobileServiceItemProps {
253
253
  isPeruSite?: boolean;
254
254
  priority_stage_ids?: string[];
255
255
  isShowSeatIcon?: boolean;
256
+ showDesdeLabel?: boolean;
257
+ showServiceTypeUnderLogo?: boolean;
256
258
  }
@@ -274,4 +274,6 @@ export interface ServiceItemProps {
274
274
  operatorLabel?: string;
275
275
  priority_stage_ids?: string[];
276
276
  isShowSeatIcon?: boolean;
277
+ showDesdeLabel?: boolean;
278
+ showServiceTypeUnderLogo?: boolean;
277
279
  }
package/dist/styles.css CHANGED
@@ -596,6 +596,9 @@
596
596
  .max-w-\[120px\] {
597
597
  max-width: 120px;
598
598
  }
599
+ .max-w-\[150px\] {
600
+ max-width: 150px;
601
+ }
599
602
  .max-w-\[165px\] {
600
603
  max-width: 165px;
601
604
  }
@@ -1,3 +1,3 @@
1
1
  import React from "react";
2
- declare const RatingBlock: ({ showRating, serviceItem, isSoldOut, colors, t, translation, isPeru, isTrain, }: any) => React.JSX.Element;
2
+ declare const RatingBlock: ({ showRating, serviceItem, isSoldOut, colors, t, translation, isPeru, isTrain, showServiceTypeUnderLogo, }: any) => React.JSX.Element;
3
3
  export default RatingBlock;
@@ -1,15 +1,19 @@
1
1
  import React from "react";
2
2
  import RatingHover from "../components/ServiceItem/RatingHover";
3
- const RatingBlock = ({ showRating, serviceItem, isSoldOut, colors, t, translation, isPeru = false, isTrain = false, }) => {
3
+ import commonService from "../utils/CommonService";
4
+ const RatingBlock = ({ showRating, serviceItem, isSoldOut, colors, t, translation, isPeru = false, isTrain = false, showServiceTypeUnderLogo = false, }) => {
5
+ const operatorLabel = showServiceTypeUnderLogo
6
+ ? commonService.capitalizeFirstLetter(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.service_type)
7
+ : serviceItem.operator_details[2];
4
8
  return (React.createElement("div", { className: "flex items-center whitespace-nowrap" },
5
9
  showRating && (React.createElement(RatingHover, { serviceItem: serviceItem, isSoldOut: isSoldOut, colors: colors, t: t, translation: translation, isPeru: isPeru })),
6
10
  React.createElement("div", { className: "group relative ml-[10px] text-[12px]", style: {
7
11
  marginLeft: showRating ? "6px" : "0",
8
12
  color: isSoldOut ? "#c0c0c0" : "#464647",
9
13
  } },
10
- React.createElement("span", { className: `block max-w-[120px] cursor-pointer text-[12px] ${isPeru || isTrain ? "overflow-hidden text-ellipsis whitespace-nowrap" : ""}` }, serviceItem.operator_details[2]),
14
+ React.createElement("span", { className: `block max-w-[120px] cursor-pointer text-[12px] ${isPeru || isTrain ? "overflow-hidden text-ellipsis whitespace-nowrap" : ""}` }, operatorLabel),
11
15
  React.createElement("div", { className: "hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-nowrap z-10 mt-2.5 w-max text-center shadow-service text-[12px]", style: { backgroundColor: colors.bottomStripColor, zIndex: "300" } },
12
16
  React.createElement("div", { className: "tooltip-arrow absolute -top-[7px] left-1/2 -translate-x-1/2 w-0 h-0 border-l-8 border-r-8 border-b-8 border-l-transparent border-r-transparent ", style: { borderBottomColor: colors.bottomStripColor } }),
13
- serviceItem.operator_details[2]))));
17
+ operatorLabel))));
14
18
  };
15
19
  export default RatingBlock;
@@ -15,6 +15,7 @@ interface SeatSectionProps {
15
15
  currencySign?: string;
16
16
  removeDuplicateSeats?: boolean;
17
17
  isPeru?: boolean;
18
+ showDesdeLabel?: boolean;
18
19
  serviceItem?: any;
19
20
  renderIcon?: (iconKey: string, size?: string) => React.ReactNode;
20
21
  discountSeatPriceColor?: string;
@@ -27,5 +28,5 @@ interface SeatSectionProps {
27
28
  discountSeatCrossPriceColor?: string;
28
29
  isShowSeatIcon?: boolean;
29
30
  }
30
- declare function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isSeatIcon, isTrain, topLabelColor, tooltipColor, discountSeatCrossPriceColor, isShowSeatIcon }: SeatSectionProps): React.ReactElement;
31
+ declare function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isSeatIcon, isTrain, topLabelColor, tooltipColor, discountSeatCrossPriceColor, isShowSeatIcon, showDesdeLabel, }: SeatSectionProps): React.ReactElement;
31
32
  export default SeatSection;
@@ -66,6 +66,10 @@ function getUniqueSeats(seatTypes, isTrain) {
66
66
  return true;
67
67
  });
68
68
  }
69
+ // Matches "160°" as well as a bare "160" label
70
+ function hasInclinationSeatTypes(seatTypes) {
71
+ return (seatTypes !== null && seatTypes !== void 0 ? seatTypes : []).some((seat) => { var _a; return /\b(120|140|160|180)\b/.test(String((_a = seat === null || seat === void 0 ? void 0 : seat.label) !== null && _a !== void 0 ? _a : "")); });
72
+ }
69
73
  function getNumberOfSeats(seatTypes) {
70
74
  return seatTypes.filter((val) => !SEAT_EXCEPTIONS.includes(val.label)).length;
71
75
  }
@@ -96,11 +100,17 @@ function addSeatDegree(label) {
96
100
  return label;
97
101
  return String(label).replace(/\b(120|140|160|180)\b(?!°)/g, "$1°");
98
102
  }
99
- function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isSeatIcon, isTrain, topLabelColor, tooltipColor, discountSeatCrossPriceColor, isShowSeatIcon }) {
103
+ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currencySign, removeDuplicateSeats, selectedSeatKey, onSeatSelect, isPeru, serviceItem, renderIcon, dpSeatColor, discountSeatPriceColor, isSeatIcon, isTrain, topLabelColor, tooltipColor, discountSeatCrossPriceColor, isShowSeatIcon, showDesdeLabel = false, }) {
100
104
  var _a;
101
105
  const uniqueSeats = getUniqueSeats(seatTypes, isTrain);
102
106
  const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
103
107
  const numberOfSeats = getNumberOfSeats(seatTypes);
108
+ const isMovilBus = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "MovilBus" ||
109
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "Movil Bus";
110
+ // Peru: list every seat type with its own fare (MovilBus, or inclination
111
+ // seats like 160° / 180°) instead of only the cheapest one.
112
+ const showSeatTypeRows = (isMovilBus || hasInclinationSeatTypes(seatTypes)) &&
113
+ uniqueSeats.length > 1;
104
114
  const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
105
115
  const formatPrice = (price) => availableSeats <= 0
106
116
  ? CommonService.currency(0, currencySign)
@@ -146,10 +156,8 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
146
156
  };
147
157
  const renderSeatPrices = () => {
148
158
  if (isPeru) {
149
- const isMovilBus = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "MovilBus" ||
150
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "Movil Bus";
151
- // Multiple unique seat types → show a price row for each (MovilBus only)
152
- if (isMovilBus && uniqueSeats.length > 1) {
159
+ // Multiple unique seat types → show a price row for each
160
+ if (showSeatTypeRows) {
153
161
  return uniqueSeats
154
162
  .filter((s) => !SEAT_EXCEPTIONS.includes(s.label))
155
163
  .map((val, key) => {
@@ -215,10 +223,8 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
215
223
  })();
216
224
  const renderLabels = () => {
217
225
  if (isPeru) {
218
- const isMovilBus = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "MovilBus" ||
219
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "Movil Bus";
220
- // Multiple unique seat types → show a label row for each (MovilBus only)
221
- if (isMovilBus && uniqueSeats.length > 1) {
226
+ // Multiple unique seat types → show a label row for each
227
+ if (showSeatTypeRows) {
222
228
  return uniqueSeats
223
229
  .filter((s) => !SEAT_EXCEPTIONS.includes(s.label))
224
230
  .map((val, key) => (React.createElement("span", { key: key, className: `flex items-center justify-between text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""}` },
@@ -227,7 +233,14 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
227
233
  height: "20px",
228
234
  marginRight: "5px",
229
235
  } })),
230
- CommonService.truncateSeatLabel(val.label))));
236
+ !isMovilBus && isShowSeatIcon && (React.createElement("img", { src: getSeatLabelIcon(val.label, serviceItem), alt: "seattype", style: {
237
+ width: "20px",
238
+ height: "20px",
239
+ marginRight: "5px",
240
+ } })),
241
+ isMovilBus
242
+ ? CommonService.truncateSeatLabel(val.label)
243
+ : CommonService.capitalize(addSeatDegree(val.label)))));
231
244
  }
232
245
  // Single seat type → original behaviour
233
246
  const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
@@ -426,6 +439,10 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
426
439
  right: 0,
427
440
  justifyContent: isCentered ? "center" : "",
428
441
  gap: "10px",
429
- } }, renderSeatPrices())));
442
+ } }, showDesdeLabel ? (
443
+ // "Desde" sits just above the price without shifting it
444
+ React.createElement("div", { className: "relative flex flex-col", style: { gap: "10px" } },
445
+ React.createElement("span", { className: "text-[12px] font-normal text-[#6a6a6a] absolute whitespace-nowrap", style: { top: "-15px" } }, "Desde"),
446
+ renderSeatPrices())) : (renderSeatPrices()))));
430
447
  }
431
448
  export default SeatSection;
@@ -25,6 +25,7 @@ interface DateTimeSectionMobileProps {
25
25
  isTrain?: boolean;
26
26
  discountSeatCrossPriceColor?: string;
27
27
  isShowSeatIcon?: boolean;
28
+ showDesdeLabel?: boolean;
28
29
  }
29
- declare function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, }: DateTimeSectionMobileProps): React.ReactElement;
30
+ declare function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, showDesdeLabel, }: DateTimeSectionMobileProps): React.ReactElement;
30
31
  export default DateTimeSectionMobile;
@@ -38,7 +38,7 @@ const TimeRow = ({ label, icon, alt, date, timeContent, isSoldOut, }) => {
38
38
  React.createElement("div", null, "\u2022"),
39
39
  React.createElement("div", { className: "font-[900] relative black-text", style: { fontVariantNumeric: "tabular-nums" } }, timeContent))))));
40
40
  };
41
- function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, }) {
41
+ function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, showDesdeLabel, }) {
42
42
  const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
43
43
  const depTimeContent = isLinatal ? (React.createElement("div", null,
44
44
  React.createElement("span", null,
@@ -66,6 +66,6 @@ function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal
66
66
  margin: "auto 6px",
67
67
  flexShrink: 0,
68
68
  } }),
69
- React.createElement(SeatSectionMobile, { seatTypes: seatTypes, isSoldOut: isSoldOut, isPeru: isPeru, seatPriceColor: seatPriceColor, currencySign: currencySign, availableSeats: availableSeats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, tooltipBgColor: tooltipBgColor, showLastSeats: showLastSeats, discountSeatPriceColor: discountSeatPriceColor, isTrain: isTrain, discountSeatCrossPriceColor: discountSeatCrossPriceColor, isShowSeatIcon: isShowSeatIcon })));
69
+ React.createElement(SeatSectionMobile, { seatTypes: seatTypes, isSoldOut: isSoldOut, isPeru: isPeru, seatPriceColor: seatPriceColor, currencySign: currencySign, availableSeats: availableSeats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, tooltipBgColor: tooltipBgColor, showLastSeats: showLastSeats, discountSeatPriceColor: discountSeatPriceColor, isTrain: isTrain, discountSeatCrossPriceColor: discountSeatCrossPriceColor, isShowSeatIcon: isShowSeatIcon, showDesdeLabel: showDesdeLabel })));
70
70
  }
71
71
  export default DateTimeSectionMobile;
@@ -20,6 +20,7 @@ interface SeatSectionMobileProps {
20
20
  isTrain?: boolean;
21
21
  discountSeatCrossPriceColor?: string;
22
22
  isShowSeatIcon?: boolean;
23
+ showDesdeLabel?: boolean;
23
24
  }
24
- declare function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, }: SeatSectionMobileProps): React.ReactElement;
25
+ declare function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, showDesdeLabel, }: SeatSectionMobileProps): React.ReactElement;
25
26
  export default SeatSectionMobile;
@@ -45,7 +45,8 @@ function addSeatDegree(label) {
45
45
  return String(label).replace(/\b(120|140|160|180)\b(?!°)/g, "$1°");
46
46
  }
47
47
  function hasInclinationSeatTypes(seatTypes) {
48
- return (seatTypes !== null && seatTypes !== void 0 ? seatTypes : []).some((seat) => { var _a; return String((_a = seat === null || seat === void 0 ? void 0 : seat.label) !== null && _a !== void 0 ? _a : "").includes("°"); });
48
+ // Matches "160°" as well as a bare "160" label
49
+ return (seatTypes !== null && seatTypes !== void 0 ? seatTypes : []).some((seat) => { var _a; return /\b(120|140|160|180)\b/.test(String((_a = seat === null || seat === void 0 ? void 0 : seat.label) !== null && _a !== void 0 ? _a : "")); });
49
50
  }
50
51
  const getUniqueSeats = (data, limit) => {
51
52
  var _a;
@@ -63,7 +64,7 @@ const getUniqueSeats = (data, limit) => {
63
64
  .sort((a, b) => a.fare - b.fare)
64
65
  .slice(0, limit);
65
66
  };
66
- function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, }) {
67
+ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, showLastSeats, discountSeatPriceColor, isTrain, discountSeatCrossPriceColor, isShowSeatIcon, showDesdeLabel = false, }) {
67
68
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
68
69
  const hasMultipleTypes = ((_a = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.length) !== null && _a !== void 0 ? _a : 0) > 2;
69
70
  const isMovilBus = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operator_service_name) === "MovilBus" ||
@@ -116,7 +117,7 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
116
117
  marginRight: "4px",
117
118
  filter: isSoldOut ? "grayscale(1)" : "",
118
119
  } })),
119
- commonService.truncateSeatLabel(seat.label)),
120
+ commonService.truncateSeatLabel(commonService.addSeatDegree(seat.label))),
120
121
  React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text", style: { color: priceColor } }, commonService.currency(showOriginalFare ? originalPrice : discountedPrice, currencySign))));
121
122
  })));
122
123
  }
@@ -134,7 +135,7 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
134
135
  React.createElement("span", { className: "min-[420]:text-[13px] text-[12px]", style: { color: "#bbb" } }, "Antes"),
135
136
  React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] line-through", style: { color: "#bbb" } }, commonService.currency(originalPrice, currencySign)))),
136
137
  React.createElement("div", { className: "relative w-[100%] flex flex-row justify-between items-center" },
137
- hasInclination && !hasStrikeOff && (React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] absolute", style: { color: "#6a6a6a", top: -20, right: 0 } }, "Desde")),
138
+ (hasInclination || showDesdeLabel) && !hasStrikeOff && (React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] absolute", style: { color: "#6a6a6a", top: -20, right: 0 } }, "Desde")),
138
139
  React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text flex items-center", style: { color: isSoldOut ? "#bbb" : "#464647" } },
139
140
  seatLabelIcon && (React.createElement("img", { src: seatLabelIcon, alt: "seattype", style: {
140
141
  width: "16px",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "10.4.61",
3
+ "version": "10.4.63",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -221,6 +221,22 @@ const FilterBarDesktop = ({
221
221
  });
222
222
  }
223
223
 
224
+ if (fil.type == "service_type") {
225
+ const activeOptions = fil.options.filter((it) => it.active);
226
+ if (activeOptions.length) {
227
+ filteredRoutes = filteredRoutes.filter((it) =>
228
+ activeOptions.some(
229
+ (f) =>
230
+ f.value ===
231
+ String(it.service_type || "")
232
+ .trim()
233
+ .replace(/\s+/g, " ")
234
+ .toLowerCase(),
235
+ ),
236
+ );
237
+ }
238
+ }
239
+
224
240
  if (fil.type == "operator") {
225
241
  let activeOptions = fil.options.filter((it) => it.active);
226
242
  filteredRoutes = filteredRoutes.filter((it) => {
@@ -23,6 +23,7 @@ interface ServiceFilterBarDesktopState {
23
23
  showTrainType: boolean;
24
24
  addMargin: boolean;
25
25
  showAmenities: boolean;
26
+ showServiceType: boolean;
26
27
  sortedFilters: any[];
27
28
  }
28
29
 
@@ -43,6 +44,7 @@ class ServiceFilter extends React.Component<
43
44
  showTrainType: props.initialOpenFilters?.includes("train_type") || true,
44
45
  addMargin: false,
45
46
  showAmenities: props.initialOpenFilters?.includes("amenities") || true,
47
+ showServiceType: true,
46
48
  sortedFilters: this.sortFilters(props.filtersArray),
47
49
  };
48
50
 
@@ -80,6 +82,7 @@ class ServiceFilter extends React.Component<
80
82
  const FILTER_ORDER = [
81
83
  "time",
82
84
  "operator",
85
+ "service_type",
83
86
  "special_departure",
84
87
  "tipo",
85
88
  "seat_types",
@@ -173,6 +176,10 @@ class ServiceFilter extends React.Component<
173
176
  type === "amenities"
174
177
  ? !prevState.showAmenities
175
178
  : prevState.showAmenities,
179
+ showServiceType:
180
+ type === "service_type"
181
+ ? !prevState.showServiceType
182
+ : prevState.showServiceType,
176
183
  };
177
184
  });
178
185
  }
@@ -186,6 +193,7 @@ class ServiceFilter extends React.Component<
186
193
  showSpecialDeparture,
187
194
  showTrainType,
188
195
  showAmenities,
196
+ showServiceType,
189
197
  } = this.state;
190
198
 
191
199
  const isOpen =
@@ -195,7 +203,8 @@ class ServiceFilter extends React.Component<
195
203
  (option.type === "tipo" && showTypeOptions) ||
196
204
  (option.type === "special_departure" && showSpecialDeparture) ||
197
205
  (option.type === "train_type" && showTrainType) ||
198
- (option.type === "amenities" && showAmenities);
206
+ (option.type === "amenities" && showAmenities) ||
207
+ (option.type === "service_type" && showServiceType);
199
208
 
200
209
  if (option?.type === "train_type" && !this.props.isTrain) {
201
210
  return null;
@@ -249,7 +258,8 @@ class ServiceFilter extends React.Component<
249
258
  option.type !== "seat_types" &&
250
259
  option.type !== "tipo" &&
251
260
  option.type !== "special_departure" &&
252
- option.type !== "train_type")) &&
261
+ option.type !== "train_type" &&
262
+ option.type !== "service_type")) &&
253
263
  option.options.map((val: any, i: number) => {
254
264
  let iconKey = "";
255
265
  if (val.icon === "sunrise") {
@@ -153,6 +153,8 @@ function ServiceItemPB({
153
153
  operatorLabel,
154
154
  priority_stage_ids,
155
155
  isShowSeatIcon = false,
156
+ showDesdeLabel = false,
157
+ showServiceTypeUnderLogo = false,
156
158
  }: ServiceItemProps & { currencySign?: string }): React.ReactElement {
157
159
  const handleSeatSelect = (
158
160
  key: any,
@@ -668,6 +670,7 @@ function ServiceItemPB({
668
670
  translation={translation}
669
671
  isPeru={isPeru}
670
672
  isTrain={isTrain}
673
+ showServiceTypeUnderLogo={showServiceTypeUnderLogo}
671
674
  />
672
675
  </div>
673
676
 
@@ -715,6 +718,7 @@ function ServiceItemPB({
715
718
  colors.discountSeatCrossPriceColor
716
719
  }
717
720
  isShowSeatIcon={isShowSeatIcon}
721
+ showDesdeLabel={showDesdeLabel}
718
722
  />
719
723
  </div>
720
724
 
@@ -776,7 +780,9 @@ function ServiceItemPB({
776
780
  isPeru={isPeru}
777
781
  isTrain={isTrain}
778
782
  isDpEnabled={serviceItem.is_dp_enabled}
779
- serviceType={serviceItem.service_type}
783
+ serviceType={
784
+ showServiceTypeUnderLogo ? undefined : serviceItem.service_type
785
+ }
780
786
  renderIcon={renderIcon}
781
787
  />
782
788
  </div>
@@ -68,6 +68,8 @@ function ServiceItemMobile({
68
68
  isPeruSite,
69
69
  priority_stage_ids,
70
70
  isShowSeatIcon = false,
71
+ showDesdeLabel = false,
72
+ showServiceTypeUnderLogo = false,
71
73
  }: MobileServiceItemProps): React.ReactElement {
72
74
  const isItemExpanded = serviceItem.id === isExpanded;
73
75
  const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
@@ -339,6 +341,15 @@ function ServiceItemMobile({
339
341
  <div className="black-text min-[420]:text-[12px] text-[12px]">
340
342
  {serviceItem?.operator_details[2]}
341
343
  </div>
344
+ ) : showServiceTypeUnderLogo && serviceItem?.service_type ? (
345
+ <div
346
+ className="min-[420]:text-[13px] text-[12px] text-ellipsis overflow-hidden whitespace-nowrap max-w-[150px]"
347
+ style={{ color: isSoldOut ? "#bbb" : "#464647" }}
348
+ >
349
+ {commonService.capitalizeFirstLetter(
350
+ serviceItem.service_type,
351
+ )}
352
+ </div>
342
353
  ) : showRating ? (
343
354
  <div className="flex min-[420]:text-[13px] text-[12px] h-[22px] items-center">
344
355
  <div className="flex items-center">
@@ -397,6 +408,7 @@ function ServiceItemMobile({
397
408
  isTrain={isTrain}
398
409
  discountSeatCrossPriceColor={colors.discountSeatCrossPriceColor}
399
410
  isShowSeatIcon={isShowSeatIcon}
411
+ showDesdeLabel={showDesdeLabel}
400
412
  />
401
413
 
402
414
  {hasDiscount && (
@@ -434,7 +446,9 @@ function ServiceItemMobile({
434
446
  hoursIcon={renderIcon("hours", "14px")}
435
447
  duration={serviceItem.duration?.toString()}
436
448
  isDirectTrip={serviceItem?.is_direct_trip}
437
- serviceType={serviceItem?.service_type}
449
+ serviceType={
450
+ showServiceTypeUnderLogo ? undefined : serviceItem?.service_type
451
+ }
438
452
  directoColor={colors.directoColor}
439
453
  directoAnim={serviceItem.icons.directoAnim}
440
454
  isChangeTicket={serviceItem.is_change_ticket}
@@ -265,4 +265,7 @@ export interface MobileServiceItemProps {
265
265
  isPeruSite?: boolean;
266
266
  priority_stage_ids?: string[];
267
267
  isShowSeatIcon?: boolean;
268
+ // shows a small "Desde" label above the price in the seat section
269
+ showDesdeLabel?: boolean;
270
+ showServiceTypeUnderLogo?: boolean;
268
271
  }
@@ -286,4 +286,7 @@ export interface ServiceItemProps {
286
286
  operatorLabel?: string;
287
287
  priority_stage_ids?: string[];
288
288
  isShowSeatIcon?: boolean;
289
+ // shows a small "Desde" label above the price in the seat section
290
+ showDesdeLabel?: boolean;
291
+ showServiceTypeUnderLogo?: boolean;
289
292
  }
@@ -11,7 +11,12 @@ const RatingBlock = ({
11
11
  translation,
12
12
  isPeru = false,
13
13
  isTrain = false,
14
+ showServiceTypeUnderLogo = false,
14
15
  }: any) => {
16
+ const operatorLabel = showServiceTypeUnderLogo
17
+ ? commonService.capitalizeFirstLetter(serviceItem?.service_type)
18
+ : serviceItem.operator_details[2];
19
+
15
20
  return (
16
21
  <div
17
22
  className="flex items-center whitespace-nowrap"
@@ -38,7 +43,7 @@ const RatingBlock = ({
38
43
  <span
39
44
  className={`block max-w-[120px] cursor-pointer text-[12px] ${isPeru || isTrain ? "overflow-hidden text-ellipsis whitespace-nowrap" : ""}`}
40
45
  >
41
- {serviceItem.operator_details[2]}
46
+ {operatorLabel}
42
47
  </span>
43
48
  <div
44
49
  className="hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-nowrap z-10 mt-2.5 w-max text-center shadow-service text-[12px]"
@@ -48,7 +53,7 @@ const RatingBlock = ({
48
53
  className="tooltip-arrow absolute -top-[7px] left-1/2 -translate-x-1/2 w-0 h-0 border-l-8 border-r-8 border-b-8 border-l-transparent border-r-transparent "
49
54
  style={{ borderBottomColor: colors.bottomStripColor }}
50
55
  ></div>
51
- {serviceItem.operator_details[2]}
56
+ {operatorLabel}
52
57
  </div>
53
58
  </div>
54
59
  </div>
@@ -20,6 +20,7 @@ interface SeatSectionProps {
20
20
  currencySign?: string;
21
21
  removeDuplicateSeats?: boolean;
22
22
  isPeru?: boolean;
23
+ showDesdeLabel?: boolean;
23
24
  serviceItem?: any;
24
25
  renderIcon?: (iconKey: string, size?: string) => React.ReactNode;
25
26
  discountSeatPriceColor?: string;
@@ -118,6 +119,13 @@ function getUniqueSeats(seatTypes: SeatType[], isTrain?: boolean) {
118
119
  });
119
120
  }
120
121
 
122
+ // Matches "160°" as well as a bare "160" label
123
+ function hasInclinationSeatTypes(seatTypes: SeatType[]) {
124
+ return (seatTypes ?? []).some((seat) =>
125
+ /\b(120|140|160|180)\b/.test(String(seat?.label ?? "")),
126
+ );
127
+ }
128
+
121
129
  function getNumberOfSeats(seatTypes: SeatType[]) {
122
130
  return seatTypes.filter((val) => !SEAT_EXCEPTIONS.includes(val.label)).length;
123
131
  }
@@ -162,11 +170,20 @@ function SeatSection({
162
170
  topLabelColor,
163
171
  tooltipColor,
164
172
  discountSeatCrossPriceColor,
165
- isShowSeatIcon
173
+ isShowSeatIcon,
174
+ showDesdeLabel = false,
166
175
  }: SeatSectionProps): React.ReactElement {
167
176
  const uniqueSeats = getUniqueSeats(seatTypes, isTrain);
168
177
  const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
169
178
  const numberOfSeats = getNumberOfSeats(seatTypes);
179
+ const isMovilBus =
180
+ serviceItem?.operator_service_name === "MovilBus" ||
181
+ serviceItem?.operator_service_name === "Movil Bus";
182
+ // Peru: list every seat type with its own fare (MovilBus, or inclination
183
+ // seats like 160° / 180°) instead of only the cheapest one.
184
+ const showSeatTypeRows =
185
+ (isMovilBus || hasInclinationSeatTypes(seatTypes)) &&
186
+ uniqueSeats.length > 1;
170
187
  const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
171
188
 
172
189
  const formatPrice = (price: number) =>
@@ -254,12 +271,8 @@ function SeatSection({
254
271
 
255
272
  const renderSeatPrices = () => {
256
273
  if (isPeru) {
257
- const isMovilBus =
258
- serviceItem?.operator_service_name === "MovilBus" ||
259
- serviceItem?.operator_service_name === "Movil Bus";
260
-
261
- // Multiple unique seat types → show a price row for each (MovilBus only)
262
- if (isMovilBus && uniqueSeats.length > 1) {
274
+ // Multiple unique seat types → show a price row for each
275
+ if (showSeatTypeRows) {
263
276
  return uniqueSeats
264
277
  .filter((s) => !SEAT_EXCEPTIONS.includes(s.label))
265
278
  .map((val, key) => {
@@ -376,12 +389,8 @@ function SeatSection({
376
389
 
377
390
  const renderLabels = () => {
378
391
  if (isPeru) {
379
- const isMovilBus =
380
- serviceItem?.operator_service_name === "MovilBus" ||
381
- serviceItem?.operator_service_name === "Movil Bus";
382
-
383
- // Multiple unique seat types → show a label row for each (MovilBus only)
384
- if (isMovilBus && uniqueSeats.length > 1) {
392
+ // Multiple unique seat types → show a label row for each
393
+ if (showSeatTypeRows) {
385
394
  return uniqueSeats
386
395
  .filter((s) => !SEAT_EXCEPTIONS.includes(s.label))
387
396
  .map((val, key) => (
@@ -402,7 +411,20 @@ function SeatSection({
402
411
  }}
403
412
  />
404
413
  )}
405
- {CommonService.truncateSeatLabel(val.label)}
414
+ {!isMovilBus && isShowSeatIcon && (
415
+ <img
416
+ src={getSeatLabelIcon(val.label, serviceItem)}
417
+ alt="seattype"
418
+ style={{
419
+ width: "20px",
420
+ height: "20px",
421
+ marginRight: "5px",
422
+ }}
423
+ />
424
+ )}
425
+ {isMovilBus
426
+ ? CommonService.truncateSeatLabel(val.label)
427
+ : CommonService.capitalize(addSeatDegree(val.label))}
406
428
  </span>
407
429
  ));
408
430
  }
@@ -824,7 +846,20 @@ function SeatSection({
824
846
  gap: "10px",
825
847
  }}
826
848
  >
827
- {renderSeatPrices()}
849
+ {showDesdeLabel ? (
850
+ // "Desde" sits just above the price without shifting it
851
+ <div className="relative flex flex-col" style={{ gap: "10px" }}>
852
+ <span
853
+ className="text-[12px] font-normal text-[#6a6a6a] absolute whitespace-nowrap"
854
+ style={{ top: "-15px" }}
855
+ >
856
+ Desde
857
+ </span>
858
+ {renderSeatPrices()}
859
+ </div>
860
+ ) : (
861
+ renderSeatPrices()
862
+ )}
828
863
  </div>
829
864
  </div>
830
865
  );
@@ -28,6 +28,7 @@ interface DateTimeSectionMobileProps {
28
28
  isTrain?: boolean;
29
29
  discountSeatCrossPriceColor?: string;
30
30
  isShowSeatIcon?: boolean;
31
+ showDesdeLabel?: boolean;
31
32
  }
32
33
 
33
34
  const pad = (n: number) => (n < 10 ? "0" + n : String(n));
@@ -149,6 +150,7 @@ function DateTimeSectionMobile({
149
150
  isTrain,
150
151
  discountSeatCrossPriceColor,
151
152
  isShowSeatIcon,
153
+ showDesdeLabel,
152
154
  }: DateTimeSectionMobileProps): React.ReactElement {
153
155
  const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
154
156
 
@@ -231,6 +233,7 @@ function DateTimeSectionMobile({
231
233
  isTrain={isTrain}
232
234
  discountSeatCrossPriceColor={discountSeatCrossPriceColor}
233
235
  isShowSeatIcon={isShowSeatIcon}
236
+ showDesdeLabel={showDesdeLabel}
234
237
  />
235
238
  </div>
236
239
  );
@@ -35,6 +35,8 @@ interface SeatSectionMobileProps {
35
35
  isTrain?: boolean;
36
36
  discountSeatCrossPriceColor?: string;
37
37
  isShowSeatIcon?: boolean;
38
+ // shows "Desde" above the price on every service, not only inclination ones
39
+ showDesdeLabel?: boolean;
38
40
  }
39
41
 
40
42
  interface SeatRowProps {
@@ -110,8 +112,9 @@ function addSeatDegree(label: string | null) {
110
112
  }
111
113
 
112
114
  function hasInclinationSeatTypes(seatTypes: SeatType[]): boolean {
115
+ // Matches "160°" as well as a bare "160" label
113
116
  return (seatTypes ?? []).some((seat) =>
114
- String(seat?.label ?? "").includes("°"),
117
+ /\b(120|140|160|180)\b/.test(String(seat?.label ?? "")),
115
118
  );
116
119
  }
117
120
 
@@ -151,6 +154,7 @@ function SeatSectionMobile({
151
154
  isTrain,
152
155
  discountSeatCrossPriceColor,
153
156
  isShowSeatIcon,
157
+ showDesdeLabel = false,
154
158
  }: SeatSectionMobileProps): React.ReactElement {
155
159
  const hasMultipleTypes = (seatTypesData?.length ?? 0) > 2;
156
160
 
@@ -244,7 +248,9 @@ function SeatSectionMobile({
244
248
  }}
245
249
  />
246
250
  )}
247
- {commonService.truncateSeatLabel(seat.label)}
251
+ {commonService.truncateSeatLabel(
252
+ commonService.addSeatDegree(seat.label),
253
+ )}
248
254
  </span>
249
255
  <span
250
256
  className="min-[420]:text-[13px] text-[12px] bold-text"
@@ -297,7 +303,7 @@ function SeatSectionMobile({
297
303
  )}
298
304
  <div className="relative w-[100%] flex flex-row justify-between items-center">
299
305
  {/* Inclination fares sit under "Desde", same as the stacked rows above. */}
300
- {hasInclination && !hasStrikeOff && (
306
+ {(hasInclination || showDesdeLabel) && !hasStrikeOff && (
301
307
  <span
302
308
  className="min-[420]:text-[13px] text-[12px] absolute"
303
309
  style={{ color: "#6a6a6a", top: -20, right: 0 }}