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.
- package/dist/components/FilterBar/FilterBarDesktop.js +10 -0
- package/dist/components/FilterBar/ServiceFilter.d.ts +1 -0
- package/dist/components/FilterBar/ServiceFilter.js +10 -4
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +4 -4
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +4 -4
- package/dist/components/ServiceItem/mobileTypes.d.ts +2 -0
- package/dist/components/ServiceItem/types.d.ts +2 -0
- package/dist/styles.css +3 -0
- package/dist/ui/RatingBlock.d.ts +1 -1
- package/dist/ui/RatingBlock.js +7 -3
- package/dist/ui/SeatSection/SeatSection.d.ts +2 -1
- package/dist/ui/SeatSection/SeatSection.js +28 -11
- package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +2 -2
- package/dist/ui/mobileweb/SeatSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/SeatSectionMobile.js +5 -4
- package/package.json +1 -1
- package/src/components/FilterBar/FilterBarDesktop.tsx +16 -0
- package/src/components/FilterBar/ServiceFilter.tsx +12 -2
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +7 -1
- package/src/components/ServiceItem/ServiceItemMobile.tsx +15 -1
- package/src/components/ServiceItem/mobileTypes.ts +3 -0
- package/src/components/ServiceItem/types.ts +3 -0
- package/src/ui/RatingBlock.tsx +7 -2
- package/src/ui/SeatSection/SeatSection.tsx +50 -15
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +3 -0
- 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 })),
|
package/dist/styles.css
CHANGED
package/dist/ui/RatingBlock.d.ts
CHANGED
|
@@ -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;
|
package/dist/ui/RatingBlock.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import RatingHover from "../components/ServiceItem/RatingHover";
|
|
3
|
-
|
|
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" : ""}` },
|
|
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
|
-
|
|
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
|
-
|
|
150
|
-
|
|
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
|
-
|
|
219
|
-
|
|
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
|
-
|
|
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
|
-
} },
|
|
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
|
-
|
|
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
|
@@ -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={
|
|
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={
|
|
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
|
}
|
package/src/ui/RatingBlock.tsx
CHANGED
|
@@ -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
|
-
{
|
|
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
|
-
{
|
|
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
|
-
|
|
258
|
-
|
|
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
|
-
|
|
380
|
-
|
|
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
|
-
{
|
|
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
|
-
{
|
|
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 ?? "")
|
|
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(
|
|
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 }}
|