kupos-ui-components-lib 1.0.0
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/README copy.md +125 -0
- package/README.md +125 -0
- package/build-css.js +28 -0
- package/copy-assets.js +45 -0
- package/dist/KuposUIComponent.d.ts +84 -0
- package/dist/KuposUIComponent.js +49 -0
- package/dist/ResponsiveServiceItem.d.ts +3 -0
- package/dist/ResponsiveServiceItem.js +10 -0
- package/dist/ServiceItemDesktop.d.ts +3 -0
- package/dist/ServiceItemDesktop.js +6 -0
- package/dist/ServiceItemMobile.d.ts +3 -0
- package/dist/ServiceItemMobile.js +5 -0
- package/dist/ServiceItemMobileView.d.ts +4 -0
- package/dist/ServiceItemMobileView.js +33 -0
- package/dist/ServiceItemPb.d.ts +4 -0
- package/dist/ServiceItemPb.js +486 -0
- package/dist/ServivceItemPbMobile.d.ts +4 -0
- package/dist/ServivceItemPbMobile.js +248 -0
- package/dist/assets/LottieIcon.d.ts +7 -0
- package/dist/assets/LottieIcon.js +8 -0
- package/dist/assets/LottieIcon.tsx +26 -0
- package/dist/assets/LottiePlayer.d.ts +20 -0
- package/dist/assets/LottiePlayer.js +24 -0
- package/dist/assets/LottiePlayer.tsx +63 -0
- package/dist/assets/PopupComponent.d.ts +12 -0
- package/dist/assets/PopupComponent.js +18 -0
- package/dist/assets/PopupComponent.tsx +65 -0
- package/dist/assets/images/amenities/Icon_More-Amenities.svg +1 -0
- package/dist/assets/images/amenities/Restrooms-white.svg +1 -0
- package/dist/assets/images/amenities/Restrooms.svg +1 -0
- package/dist/assets/images/amenities/air_condtion-white.svg +1 -0
- package/dist/assets/images/amenities/air_condtion.svg +1 -0
- package/dist/assets/images/amenities/amenity-cortina.png +0 -0
- package/dist/assets/images/amenities/baggage-white.svg +1 -0
- package/dist/assets/images/amenities/baggage.svg +1 -0
- package/dist/assets/images/amenities/charging_plug-white.svg +1 -0
- package/dist/assets/images/amenities/charging_plug.svg +17 -0
- package/dist/assets/images/amenities/coffee.svg +1 -0
- package/dist/assets/images/amenities/cortina_divisoria.svg +19 -0
- package/dist/assets/images/amenities/divider-curtain.svg +34 -0
- package/dist/assets/images/amenities/food_new_icon-white.svg +1 -0
- package/dist/assets/images/amenities/food_new_icon.svg +1 -0
- package/dist/assets/images/amenities/frazda_amenity.svg +11 -0
- package/dist/assets/images/amenities/handicap-white.svg +1 -0
- package/dist/assets/images/amenities/handicap.svg +1 -0
- package/dist/assets/images/amenities/icon-app-cortina.svg +19 -0
- package/dist/assets/images/amenities/mobile_ticket-white.svg +1 -0
- package/dist/assets/images/amenities/mobile_ticket.svg +29 -0
- package/dist/assets/images/amenities/movie-white.svg +1 -0
- package/dist/assets/images/amenities/movie.svg +1 -0
- package/dist/assets/images/amenities/music-white.svg +1 -0
- package/dist/assets/images/amenities/music.svg +1 -0
- package/dist/assets/images/amenities/snacks_new-white.svg +1 -0
- package/dist/assets/images/amenities/snacks_new.svg +27 -0
- package/dist/assets/images/amenities/whatsapp-charges-info-icon.svg +5 -0
- package/dist/assets/images/amenities/wifi-white.svg +1 -0
- package/dist/assets/images/amenities/wifi.svg +1 -0
- package/dist/assets/images/anims/service_list/flexible.json +391 -0
- package/dist/assets/images/anims/service_list/location.json +589 -0
- package/dist/assets/images/index.d.ts +32 -0
- package/dist/assets/images/index.js +35 -0
- package/dist/assets/images/index.ts +35 -0
- package/dist/components/InternationalServicePopupBody.d.ts +3 -0
- package/dist/components/InternationalServicePopupBody.js +21 -0
- package/dist/components/PaymentSideBar/PaymentSideBarDesktop.d.ts +4 -0
- package/dist/components/PaymentSideBar/PaymentSideBarDesktop.js +107 -0
- package/dist/components/PaymentSideBar/PaymentSideBarMobile.d.ts +4 -0
- package/dist/components/PaymentSideBar/PaymentSideBarMobile.js +115 -0
- package/dist/components/PaymentSideBar/ResponsivePaymentSideBar.d.ts +3 -0
- package/dist/components/PaymentSideBar/ResponsivePaymentSideBar.js +10 -0
- package/dist/components/PaymentSideBar/index.d.ts +5 -0
- package/dist/components/PaymentSideBar/index.js +4 -0
- package/dist/components/PaymentSideBar/types.d.ts +38 -0
- package/dist/components/PaymentSideBar/types.js +1 -0
- package/dist/components/ServiceItem/ResponsiveServiceItem.d.ts +3 -0
- package/dist/components/ServiceItem/ResponsiveServiceItem.js +10 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +4 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.js +486 -0
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +4 -0
- package/dist/components/ServiceItem/ServiceItemMobile.js +248 -0
- package/dist/components/ServiceItem/index.d.ts +5 -0
- package/dist/components/ServiceItem/index.js +4 -0
- package/dist/components/ServiceItem/mobileTypes.d.ts +141 -0
- package/dist/components/ServiceItem/mobileTypes.js +1 -0
- package/dist/components/ServiceItem/types.d.ts +164 -0
- package/dist/components/ServiceItem/types.js +1 -0
- package/dist/components/ServiceList/ResponsiveServiceList.d.ts +3 -0
- package/dist/components/ServiceList/ResponsiveServiceList.js +10 -0
- package/dist/components/ServiceList/ServiceListDesktop.d.ts +4 -0
- package/dist/components/ServiceList/ServiceListDesktop.js +164 -0
- package/dist/components/ServiceList/ServiceListMobile.d.ts +4 -0
- package/dist/components/ServiceList/ServiceListMobile.js +195 -0
- package/dist/components/ServiceList/index.d.ts +5 -0
- package/dist/components/ServiceList/index.js +4 -0
- package/dist/components/ServiceList/types.d.ts +35 -0
- package/dist/components/ServiceList/types.js +1 -0
- package/dist/example.d.ts +5 -0
- package/dist/example.js +240 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +15 -0
- package/dist/mobileTypes.d.ts +141 -0
- package/dist/mobileTypes.js +1 -0
- package/dist/styles.css +803 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.js +1 -0
- package/dist/utils/DateService.d.ts +16 -0
- package/dist/utils/DateService.js +160 -0
- package/dist/utils/ModalEventManager.d.ts +40 -0
- package/dist/utils/ModalEventManager.js +329 -0
- package/kupos-service-item-package-1.0.0.tgz +0 -0
- package/package.json +43 -0
- package/postcss.config.js +6 -0
- package/src/KuposUIComponent.tsx +152 -0
- package/src/ServiceItemPb.tsx +1048 -0
- package/src/assets/LottieIcon.tsx +26 -0
- package/src/assets/LottiePlayer.tsx +63 -0
- package/src/assets/PopupComponent.tsx +65 -0
- package/src/assets/images/amenities/Icon_More-Amenities.svg +1 -0
- package/src/assets/images/amenities/Restrooms-white.svg +1 -0
- package/src/assets/images/amenities/Restrooms.svg +1 -0
- package/src/assets/images/amenities/air_condtion-white.svg +1 -0
- package/src/assets/images/amenities/air_condtion.svg +1 -0
- package/src/assets/images/amenities/amenity-cortina.png +0 -0
- package/src/assets/images/amenities/baggage-white.svg +1 -0
- package/src/assets/images/amenities/baggage.svg +1 -0
- package/src/assets/images/amenities/charging_plug-white.svg +1 -0
- package/src/assets/images/amenities/charging_plug.svg +17 -0
- package/src/assets/images/amenities/coffee.svg +1 -0
- package/src/assets/images/amenities/cortina_divisoria.svg +19 -0
- package/src/assets/images/amenities/divider-curtain.svg +34 -0
- package/src/assets/images/amenities/food_new_icon-white.svg +1 -0
- package/src/assets/images/amenities/food_new_icon.svg +1 -0
- package/src/assets/images/amenities/frazda_amenity.svg +11 -0
- package/src/assets/images/amenities/handicap-white.svg +1 -0
- package/src/assets/images/amenities/handicap.svg +1 -0
- package/src/assets/images/amenities/icon-app-cortina.svg +19 -0
- package/src/assets/images/amenities/mobile_ticket-white.svg +1 -0
- package/src/assets/images/amenities/mobile_ticket.svg +29 -0
- package/src/assets/images/amenities/movie-white.svg +1 -0
- package/src/assets/images/amenities/movie.svg +1 -0
- package/src/assets/images/amenities/music-white.svg +1 -0
- package/src/assets/images/amenities/music.svg +1 -0
- package/src/assets/images/amenities/snacks_new-white.svg +1 -0
- package/src/assets/images/amenities/snacks_new.svg +27 -0
- package/src/assets/images/amenities/whatsapp-charges-info-icon.svg +5 -0
- package/src/assets/images/amenities/wifi-white.svg +1 -0
- package/src/assets/images/amenities/wifi.svg +1 -0
- package/src/assets/images/anims/service_list/flexible.json +391 -0
- package/src/assets/images/anims/service_list/location.json +589 -0
- package/src/assets/images/index.ts +35 -0
- package/src/components/InternationalServicePopupBody.tsx +40 -0
- package/src/components/PaymentSideBar/PaymentSideBarDesktop.tsx +183 -0
- package/src/components/PaymentSideBar/PaymentSideBarMobile.tsx +197 -0
- package/src/components/PaymentSideBar/ResponsivePaymentSideBar.tsx +14 -0
- package/src/components/PaymentSideBar/index.ts +5 -0
- package/src/components/PaymentSideBar/types.ts +44 -0
- package/src/components/ServiceItem/ResponsiveServiceItem.tsx +14 -0
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +1048 -0
- package/src/components/ServiceItem/ServiceItemMobile.tsx +544 -0
- package/src/components/ServiceItem/index.ts +5 -0
- package/src/components/ServiceItem/mobileTypes.ts +159 -0
- package/src/components/ServiceItem/types.ts +163 -0
- package/src/components/ServiceList/ResponsiveServiceList.tsx +14 -0
- package/src/components/ServiceList/ServiceListDesktop.tsx +353 -0
- package/src/components/ServiceList/ServiceListMobile.tsx +400 -0
- package/src/components/ServiceList/index.ts +5 -0
- package/src/components/ServiceList/types.ts +43 -0
- package/src/dummyData.json +73 -0
- package/src/example.tsx +348 -0
- package/src/index.ts +37 -0
- package/src/lottie-player.d.ts +0 -0
- package/src/styles.css +77 -0
- package/src/types.ts +150 -0
- package/src/utils/DateService.ts +197 -0
- package/src/utils/ModalEventManager.ts +405 -0
- package/tailwind.config.js +39 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,1048 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ServiceItemProps } from "./types";
|
|
3
|
+
import LottiePlayer from "./assets/LottiePlayer";
|
|
4
|
+
import DateService from "./utils/DateService";
|
|
5
|
+
import ModalEventManager from "./utils/ModalEventManager";
|
|
6
|
+
import InternationalServicePopupBody from "./components/InternationalServicePopupBody";
|
|
7
|
+
|
|
8
|
+
const SEAT_EXCEPTIONS = ["Asiento mascota"];
|
|
9
|
+
|
|
10
|
+
function ServiceItemPB({
|
|
11
|
+
serviceItem,
|
|
12
|
+
onBookButtonPress,
|
|
13
|
+
colors,
|
|
14
|
+
metaData,
|
|
15
|
+
children,
|
|
16
|
+
busStage,
|
|
17
|
+
serviceDetailsLoading,
|
|
18
|
+
cityOrigin,
|
|
19
|
+
cityDestination,
|
|
20
|
+
translation,
|
|
21
|
+
orignLabel,
|
|
22
|
+
destinationLabel,
|
|
23
|
+
t = (key: string) => key,
|
|
24
|
+
}: ServiceItemProps): React.ReactElement {
|
|
25
|
+
const SvgAmenities = ({
|
|
26
|
+
moreAnemities,
|
|
27
|
+
name,
|
|
28
|
+
color,
|
|
29
|
+
}: {
|
|
30
|
+
moreAnemities: boolean;
|
|
31
|
+
name: string;
|
|
32
|
+
color?: string;
|
|
33
|
+
}) => {
|
|
34
|
+
const amenityKey = name.toLowerCase().replace(/\s/g, "_");
|
|
35
|
+
|
|
36
|
+
const getIconPath = () => {
|
|
37
|
+
const amenityFileName = `${amenityKey}.png`;
|
|
38
|
+
const imagePath = getAmenitiesImage(amenityFileName);
|
|
39
|
+
|
|
40
|
+
if (!imagePath) {
|
|
41
|
+
return `/public/images/amenities/${amenityKey}.svg`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return imagePath;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const iconPath = getIconPath();
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<img
|
|
51
|
+
src={iconPath}
|
|
52
|
+
alt={name}
|
|
53
|
+
style={{
|
|
54
|
+
filter: color === "white" ? "brightness(0) invert(1)" : "",
|
|
55
|
+
}}
|
|
56
|
+
className={`object-contain ${
|
|
57
|
+
moreAnemities ? "w-[20px] h-[20px]" : "w-[16px] h-[16px]"
|
|
58
|
+
}`}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const getAmenitiesImage = (name: string): string => {
|
|
64
|
+
switch (name) {
|
|
65
|
+
case "air_condtion.png": {
|
|
66
|
+
return serviceItem?.icons?.airConditionIcon;
|
|
67
|
+
}
|
|
68
|
+
case "baggage.png": {
|
|
69
|
+
return serviceItem?.icons?.baggageIcon;
|
|
70
|
+
}
|
|
71
|
+
case "charging_plug.png": {
|
|
72
|
+
return serviceItem?.icons?.chargingIcon;
|
|
73
|
+
}
|
|
74
|
+
case "coffee.png": {
|
|
75
|
+
return serviceItem?.icons?.coffeeIcon;
|
|
76
|
+
}
|
|
77
|
+
case "food_new_icon.png": {
|
|
78
|
+
return serviceItem?.icons?.foodIcon;
|
|
79
|
+
}
|
|
80
|
+
case "gaming.png": {
|
|
81
|
+
return serviceItem?.icons?.gamingIcon;
|
|
82
|
+
}
|
|
83
|
+
case "handicap.png": {
|
|
84
|
+
return serviceItem?.icons?.handicapIcon;
|
|
85
|
+
}
|
|
86
|
+
case "mobile_ticket.png": {
|
|
87
|
+
return serviceItem?.icons?.mobileTicketIcon;
|
|
88
|
+
}
|
|
89
|
+
case "movie.png": {
|
|
90
|
+
return serviceItem?.icons?.movieIcon;
|
|
91
|
+
}
|
|
92
|
+
case "restrooms.png": {
|
|
93
|
+
return serviceItem?.icons?.restroomsIcon;
|
|
94
|
+
}
|
|
95
|
+
case "snacks_new.png": {
|
|
96
|
+
return serviceItem?.icons?.snackIcon;
|
|
97
|
+
}
|
|
98
|
+
case "wifi.png": {
|
|
99
|
+
return serviceItem?.icons?.wifiIcon;
|
|
100
|
+
}
|
|
101
|
+
case "cortina_divisoria.png": {
|
|
102
|
+
return serviceItem?.icons?.cortinaIcon;
|
|
103
|
+
}
|
|
104
|
+
case "frazada.png": {
|
|
105
|
+
return serviceItem?.icons?.frazaIcon;
|
|
106
|
+
}
|
|
107
|
+
default: {
|
|
108
|
+
return "";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const getAmenityName = (rawAmenity: string): string => {
|
|
114
|
+
switch (rawAmenity) {
|
|
115
|
+
case "mobile ticket":
|
|
116
|
+
return "Ticket móvil";
|
|
117
|
+
case "charging plug":
|
|
118
|
+
return "Cargador";
|
|
119
|
+
case "wifi":
|
|
120
|
+
return "WiFi";
|
|
121
|
+
case "movie":
|
|
122
|
+
return "Entretenimiento";
|
|
123
|
+
case "baggage":
|
|
124
|
+
return "Equipaje";
|
|
125
|
+
case "Restrooms":
|
|
126
|
+
return "Baños";
|
|
127
|
+
case "air condtion":
|
|
128
|
+
return "Aire acondicionado";
|
|
129
|
+
case "snacks new":
|
|
130
|
+
return "Snacks";
|
|
131
|
+
case "coffee":
|
|
132
|
+
return "Café";
|
|
133
|
+
case "cortina divisoria":
|
|
134
|
+
return "Cortina Divisoria";
|
|
135
|
+
case "frazada":
|
|
136
|
+
return "";
|
|
137
|
+
default:
|
|
138
|
+
return rawAmenity;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const currency = (amount: number) => {
|
|
143
|
+
const formattedAmount = amount
|
|
144
|
+
.toString()
|
|
145
|
+
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
146
|
+
return "$" + formattedAmount;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const labelId =
|
|
150
|
+
typeof serviceItem.boarding_stages === "string"
|
|
151
|
+
? serviceItem.boarding_stages.split("|")[0]
|
|
152
|
+
: "";
|
|
153
|
+
|
|
154
|
+
const showTopLabel =
|
|
155
|
+
busStage &&
|
|
156
|
+
busStage[labelId] &&
|
|
157
|
+
busStage[labelId].split("|")[1] === "true" &&
|
|
158
|
+
busStage[labelId].split("|")[0];
|
|
159
|
+
|
|
160
|
+
const renderStages = (stageData: any) => {
|
|
161
|
+
if (typeof stageData === "string") {
|
|
162
|
+
return (
|
|
163
|
+
<div className="flex flex-col space-y-1 text-justify gap-[4px]">
|
|
164
|
+
{stageData.split(",").map((stageInfo: string, index: number) => {
|
|
165
|
+
const parts = stageInfo.split("|");
|
|
166
|
+
const id = parts[0];
|
|
167
|
+
const time = parts[1];
|
|
168
|
+
const label = parts[3] || ""; // Skip empty part [2]
|
|
169
|
+
return (
|
|
170
|
+
<div key={index}>
|
|
171
|
+
{label} | {time}
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
})}
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
};
|
|
180
|
+
let isSoldOut = serviceItem.available_seats <= 0;
|
|
181
|
+
|
|
182
|
+
const renderIcon = (iconKey: string, size: string = "14px") => {
|
|
183
|
+
const iconValue = serviceItem.icons?.[iconKey];
|
|
184
|
+
if (iconValue) {
|
|
185
|
+
if (typeof iconValue === "string") {
|
|
186
|
+
return (
|
|
187
|
+
<img
|
|
188
|
+
src={iconValue}
|
|
189
|
+
alt={iconKey}
|
|
190
|
+
className={`${`w-[${size}] h-[${size}]`} mr-[5px]`}
|
|
191
|
+
/>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const getSortedSeatTypes = () => {
|
|
199
|
+
if (!serviceItem?.seat_types?.length) {
|
|
200
|
+
return [{ label: "Salon cama", price: 0 }];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
let seatTypesWithPrices = serviceItem.seat_types
|
|
204
|
+
.filter((item) => getFilteredSeats(item))
|
|
205
|
+
.map((val) => ({
|
|
206
|
+
label: val?.label,
|
|
207
|
+
price: val?.fare,
|
|
208
|
+
}));
|
|
209
|
+
|
|
210
|
+
seatTypesWithPrices.sort((a, b) => a.price - b.price);
|
|
211
|
+
const premiumIndex = seatTypesWithPrices.findIndex(
|
|
212
|
+
(item) => item.label === "Premium"
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
if (premiumIndex >= 3) {
|
|
216
|
+
seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
|
|
220
|
+
|
|
221
|
+
return seatTypesWithPrices;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const getNumberOfSeats = () => {
|
|
225
|
+
return serviceItem.seat_types.filter(
|
|
226
|
+
(val) => !SEAT_EXCEPTIONS.includes(val.label)
|
|
227
|
+
).length;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const getSeatNames = () => {
|
|
231
|
+
const sortedSeatTypes = getSortedSeatTypes();
|
|
232
|
+
return sortedSeatTypes.map((val, key: number) =>
|
|
233
|
+
SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
234
|
+
<span
|
|
235
|
+
key={key}
|
|
236
|
+
className={`flex items-center justify-between text-[13.33px] ${
|
|
237
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
238
|
+
}`}
|
|
239
|
+
>
|
|
240
|
+
{typeof val.label === "string" || typeof val.label === "number"
|
|
241
|
+
? val.label
|
|
242
|
+
: null}
|
|
243
|
+
</span>
|
|
244
|
+
)
|
|
245
|
+
);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const getSeatPrice = () => {
|
|
249
|
+
const sortedSeatTypes = getSortedSeatTypes();
|
|
250
|
+
return sortedSeatTypes.map((val, key: number) =>
|
|
251
|
+
SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
252
|
+
<span
|
|
253
|
+
key={key}
|
|
254
|
+
className="flex items-center justify-between text-[13.33px]"
|
|
255
|
+
>
|
|
256
|
+
{typeof val.price === "string"
|
|
257
|
+
? currency(val.price)
|
|
258
|
+
: typeof val.price === "number"
|
|
259
|
+
? currency(val.price)
|
|
260
|
+
: null}
|
|
261
|
+
</span>
|
|
262
|
+
)
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const getFilteredSeats = (item) => {
|
|
267
|
+
return item;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const checkMidnight = () => {
|
|
271
|
+
if (
|
|
272
|
+
cityOrigin?.label &&
|
|
273
|
+
cityDestination?.label &&
|
|
274
|
+
((cityOrigin.label.toLowerCase().includes("argentina") &&
|
|
275
|
+
!cityDestination.label.toLowerCase().includes("argentina")) ||
|
|
276
|
+
(!cityOrigin.label.toLowerCase().includes("argentina") &&
|
|
277
|
+
cityDestination.label.toLowerCase().includes("argentina")))
|
|
278
|
+
) {
|
|
279
|
+
ModalEventManager.showPopup({
|
|
280
|
+
modalIcon: serviceItem?.icons?.warningIcon,
|
|
281
|
+
title: translation?.title,
|
|
282
|
+
showPrimaryButton: false,
|
|
283
|
+
primaryButtonText: translation?.continueButton,
|
|
284
|
+
onSecondaryButtonClick: () => {
|
|
285
|
+
onBookButtonPress && onBookButtonPress();
|
|
286
|
+
},
|
|
287
|
+
secondaryButtonText: translation?.okContinueButton,
|
|
288
|
+
primaryButtonBgColor: colors?.kuposButtonColor,
|
|
289
|
+
primaryButtonTextColor: colors?.primaryButtonTextColor,
|
|
290
|
+
secondaryButtonBgColor: colors?.secondaryBgColor,
|
|
291
|
+
secondaryButtonTextColor: colors?.secondaryTextColor,
|
|
292
|
+
children: <InternationalServicePopupBody />,
|
|
293
|
+
});
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (serviceItem.dep_validation_text) {
|
|
298
|
+
ModalEventManager.showPopup({
|
|
299
|
+
body: serviceItem.dep_validation_text,
|
|
300
|
+
primaryButtonText: translation?.continueButton,
|
|
301
|
+
secondaryButtonText: translation?.chooseAnotherTripButton,
|
|
302
|
+
onPrimaryButtonClick: () => {
|
|
303
|
+
onBookButtonPress && onBookButtonPress();
|
|
304
|
+
},
|
|
305
|
+
primaryButtonBgColor: colors?.kuposButtonColor,
|
|
306
|
+
primaryButtonTextColor: colors?.primaryButtonTextColor,
|
|
307
|
+
secondaryButtonBgColor: colors?.secondaryBgColor,
|
|
308
|
+
secondaryButtonTextColor: colors?.secondaryTextColor,
|
|
309
|
+
});
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (
|
|
314
|
+
serviceItem.operator_service_name === "Classe Reale " &&
|
|
315
|
+
cityOrigin.label.toLowerCase() === "santiago,chile" &&
|
|
316
|
+
cityDestination.label.toLowerCase() === "portillo,chile"
|
|
317
|
+
) {
|
|
318
|
+
ModalEventManager.showPopup({
|
|
319
|
+
modalIcon: serviceItem?.icons?.warningIcon,
|
|
320
|
+
title: translation?.title,
|
|
321
|
+
primaryButtonText: translation?.okContinueButton,
|
|
322
|
+
secondaryButtonText: translation?.chooseAnotherTripButton,
|
|
323
|
+
onPrimaryButtonClick: () => {
|
|
324
|
+
onBookButtonPress && onBookButtonPress();
|
|
325
|
+
},
|
|
326
|
+
showSecondaryButton: false,
|
|
327
|
+
primaryButtonBgColor: colors?.kuposButtonColor,
|
|
328
|
+
primaryButtonTextColor: colors?.primaryButtonTextColor,
|
|
329
|
+
children: (
|
|
330
|
+
<>
|
|
331
|
+
<p className="mt-[5px] text-justify">
|
|
332
|
+
{translation.classeNormalText}
|
|
333
|
+
<span className="bold-text">
|
|
334
|
+
{translation.classeBoldText}
|
|
335
|
+
</span>
|
|
336
|
+
{translation.classeNormalText1}
|
|
337
|
+
</p>
|
|
338
|
+
<p className="mt-[10px] text-justify">
|
|
339
|
+
{translation.classeNormalText2}
|
|
340
|
+
<span className="bold-text">
|
|
341
|
+
{translation.classeBoldText1}
|
|
342
|
+
</span>{" "}
|
|
343
|
+
{translation.classeNormalText3}
|
|
344
|
+
</p>
|
|
345
|
+
</>
|
|
346
|
+
),
|
|
347
|
+
});
|
|
348
|
+
return;
|
|
349
|
+
} else {
|
|
350
|
+
onBookButtonPressHandler();
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const onBookButtonPressHandler = () => {
|
|
355
|
+
onBookButtonPress();
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
return (
|
|
359
|
+
<div
|
|
360
|
+
className={`relative ${
|
|
361
|
+
serviceItem.offer_text || serviceItem?.is_direct_trip
|
|
362
|
+
? "mb-[60px]"
|
|
363
|
+
: "mb-[20px]"
|
|
364
|
+
} ${
|
|
365
|
+
serviceItem?.is_direct_trip ||
|
|
366
|
+
serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
|
|
367
|
+
showTopLabel
|
|
368
|
+
? "mt-[30px]"
|
|
369
|
+
: "mt-[20px]"
|
|
370
|
+
} `}
|
|
371
|
+
// ${
|
|
372
|
+
// serviceItem?.is_direct_trip ||
|
|
373
|
+
// serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
|
|
374
|
+
// !showTopLabel
|
|
375
|
+
// ? "mb-[60px]"
|
|
376
|
+
// : ""
|
|
377
|
+
// }
|
|
378
|
+
>
|
|
379
|
+
<div
|
|
380
|
+
className={
|
|
381
|
+
"bg-white rounded-[20px] shadow-service mb-[10px] mx-auto relative"
|
|
382
|
+
}
|
|
383
|
+
>
|
|
384
|
+
<div className="p-[15px]">
|
|
385
|
+
{/* Header with operator info and favorite */}
|
|
386
|
+
<div className="flex justify-between items-center mb-[15px]">
|
|
387
|
+
<div className="w-[120px] overflow-y-hidden">
|
|
388
|
+
<img
|
|
389
|
+
src={serviceItem.operator_details[0]}
|
|
390
|
+
alt="service logo"
|
|
391
|
+
className={`w-[120px] h-auto object-contain ${
|
|
392
|
+
isSoldOut ? "grayscale" : ""
|
|
393
|
+
}`}
|
|
394
|
+
/>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
|
|
398
|
+
{/* <div className="grid grid-cols-[1.5fr_1fr_auto] gap-[3rem] sm:gap-[4rem] md:gap-[5rem] lg:gap-[6rem] xl:gap-[5rem] 2xl:gap-[7rem] text-[#464647]"> */}
|
|
399
|
+
<div className="grid text-[#464647] w-full [grid-template-columns:minmax(0,1.4fr)_minmax(0,0.2fr)_minmax(0,1fr)_auto] gap-x-[7rem] min-[640px]:gap-x-[6rem] min-[768px]:gap-x-[4rem] min-[1024px]:gap-x-[4rem] min-[1280px]:gap-x-[4rem] min-[1380px]:gap-x-[5rem]">
|
|
400
|
+
{/* DATE AND TIME */}
|
|
401
|
+
<div className="min-h-[2.5rem] flex flex-col justify-between gap-[10px]">
|
|
402
|
+
<div
|
|
403
|
+
className={`flex items-center text-[13.33px] justify-between ${
|
|
404
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
405
|
+
}`}
|
|
406
|
+
>
|
|
407
|
+
<div className="flex items-center bold-text capitalize group ">
|
|
408
|
+
{orignLabel ? (
|
|
409
|
+
<div className="w-[60px]">{orignLabel}</div>
|
|
410
|
+
) : (
|
|
411
|
+
<div className="w-[18px] h-auto mr-[8px]">
|
|
412
|
+
<img
|
|
413
|
+
src={serviceItem.icons?.origin}
|
|
414
|
+
alt="origin"
|
|
415
|
+
className={`w-[18px] h-auto mr-[8px] ${
|
|
416
|
+
isSoldOut ? "grayscale" : ""
|
|
417
|
+
}`}
|
|
418
|
+
/>
|
|
419
|
+
</div>
|
|
420
|
+
)}
|
|
421
|
+
<span className="cursor-pointer bold-text">
|
|
422
|
+
{DateService.getServiceItemDate(serviceItem.travel_date)}
|
|
423
|
+
</span>
|
|
424
|
+
|
|
425
|
+
{/* Boarding stage tooltip */}
|
|
426
|
+
{serviceItem.boarding_stages && (
|
|
427
|
+
<div
|
|
428
|
+
className="hidden group-hover:block absolute top-[29%] left-[35%] ml-2 text-white px-3 py-2 rounded-[10px] whitespace-normal z-10 shadow-service "
|
|
429
|
+
style={{ backgroundColor: colors?.tooltipColor }}
|
|
430
|
+
>
|
|
431
|
+
<div
|
|
432
|
+
className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 border-t-8 border-b-8 border-r-8 border-t-transparent border-b-transparent"
|
|
433
|
+
style={{ borderRightColor: colors?.tooltipColor }}
|
|
434
|
+
></div>
|
|
435
|
+
<div className="text-center text-[14px]">
|
|
436
|
+
{renderStages(serviceItem.boarding_stages)}
|
|
437
|
+
</div>
|
|
438
|
+
</div>
|
|
439
|
+
)}
|
|
440
|
+
</div>
|
|
441
|
+
<div className="mx-[8px]">•</div>
|
|
442
|
+
<div className="font-[900] relative">
|
|
443
|
+
{DateService.formatTime(serviceItem.dep_time)}
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
446
|
+
<div
|
|
447
|
+
className={`flex items-center text-[13.33px] justify-between ${
|
|
448
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
449
|
+
}`}
|
|
450
|
+
>
|
|
451
|
+
<div className="flex items-center bold-text capitalize group ">
|
|
452
|
+
{destinationLabel ? (
|
|
453
|
+
<div className="w-[60px]">{destinationLabel}</div>
|
|
454
|
+
) : (
|
|
455
|
+
<div className="w-[18px] h-auto mr-[8px]">
|
|
456
|
+
<img
|
|
457
|
+
src={serviceItem.icons?.destination}
|
|
458
|
+
className={`w-[18px] h-auto mr-[8px] ${
|
|
459
|
+
isSoldOut ? "grayscale" : ""
|
|
460
|
+
}`}
|
|
461
|
+
/>
|
|
462
|
+
</div>
|
|
463
|
+
)}
|
|
464
|
+
<span className="cursor-pointer bold-text">
|
|
465
|
+
{DateService.getServiceItemDate(serviceItem.arrival_date)}
|
|
466
|
+
</span>
|
|
467
|
+
|
|
468
|
+
{/* Dropping stage tooltip */}
|
|
469
|
+
{serviceItem.dropoff_stages && (
|
|
470
|
+
<div
|
|
471
|
+
className={`hidden group-hover:block absolute top-[46%] left-[35%] ml-2 text-white px-3 py-2 rounded-[10px] whitespace-normal z-10 shadow-service`}
|
|
472
|
+
style={{ backgroundColor: colors?.tooltipColor }}
|
|
473
|
+
>
|
|
474
|
+
{/* Tooltip arrow */}
|
|
475
|
+
<div
|
|
476
|
+
className="tooltip-arrow absolute top-2 -left-[7px] w-0 h-0 border-t-8 border-b-8 border-r-8 border-t-transparent border-b-transparent"
|
|
477
|
+
style={{ borderRightColor: colors?.tooltipColor }}
|
|
478
|
+
></div>
|
|
479
|
+
<div className="text-center text-[14px]">
|
|
480
|
+
{renderStages(serviceItem.dropoff_stages)}
|
|
481
|
+
</div>
|
|
482
|
+
</div>
|
|
483
|
+
)}
|
|
484
|
+
</div>
|
|
485
|
+
<div className="mx-[8px]">•</div>
|
|
486
|
+
<div className="font-[900]">
|
|
487
|
+
{DateService.formatTime(serviceItem.arr_time)}
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
490
|
+
</div>
|
|
491
|
+
<div
|
|
492
|
+
style={{
|
|
493
|
+
width: "1px",
|
|
494
|
+
height: "2.5rem",
|
|
495
|
+
backgroundColor: "#ccc",
|
|
496
|
+
margin: "auto",
|
|
497
|
+
}}
|
|
498
|
+
></div>
|
|
499
|
+
{/* SEATS */}
|
|
500
|
+
<div className="content-center">
|
|
501
|
+
<div
|
|
502
|
+
className={`flex gap-[10px] text-[13.33px] justify-between min-h-[2.5rem] ${
|
|
503
|
+
getNumberOfSeats() < 3 ? "" : ""
|
|
504
|
+
}`}
|
|
505
|
+
style={getNumberOfSeats() < 2 ? { alignItems: "center" } : {}}
|
|
506
|
+
>
|
|
507
|
+
<div
|
|
508
|
+
className="flex flex-col justify-between"
|
|
509
|
+
// className={`flex flex-col ${
|
|
510
|
+
// getNumberOfSeats() < 3 ? "justify-between" : ""
|
|
511
|
+
// }`}
|
|
512
|
+
>
|
|
513
|
+
{getSeatNames()}
|
|
514
|
+
</div>
|
|
515
|
+
<div
|
|
516
|
+
className="flex flex-col justify-between"
|
|
517
|
+
// className={`flex flex-col ${
|
|
518
|
+
// getNumberOfSeats() < 3 ? "justify-between" : ""
|
|
519
|
+
// }`}
|
|
520
|
+
style={{ color: isSoldOut ? "#c0c0c0" : colors.priceColor }}
|
|
521
|
+
>
|
|
522
|
+
{getSeatPrice()}
|
|
523
|
+
</div>
|
|
524
|
+
</div>
|
|
525
|
+
</div>
|
|
526
|
+
|
|
527
|
+
{/* BUTTON */}
|
|
528
|
+
<div>
|
|
529
|
+
<button
|
|
530
|
+
onClick={() => (!isSoldOut ? checkMidnight() : null)}
|
|
531
|
+
disabled={serviceDetailsLoading}
|
|
532
|
+
className={`w-full ${
|
|
533
|
+
serviceDetailsLoading || isSoldOut ? "py-[6px]" : "py-[12px]"
|
|
534
|
+
} text-[13.33px] font-bold text-white rounded-[10px] border-none px-[20px] flex items-center justify-center`}
|
|
535
|
+
style={{
|
|
536
|
+
backgroundColor:
|
|
537
|
+
serviceDetailsLoading || isSoldOut
|
|
538
|
+
? "lightgray"
|
|
539
|
+
: colors.kuposButtonColor,
|
|
540
|
+
cursor:
|
|
541
|
+
serviceDetailsLoading || isSoldOut
|
|
542
|
+
? "not-allowed"
|
|
543
|
+
: "pointer",
|
|
544
|
+
}}
|
|
545
|
+
>
|
|
546
|
+
<span className="min-w-[75px] flex justify-center items-center bold-text">
|
|
547
|
+
{isSoldOut ? renderIcon("soldOutIcon", "14px") : null}
|
|
548
|
+
|
|
549
|
+
{serviceDetailsLoading ? (
|
|
550
|
+
<span className="loader-circle"></span>
|
|
551
|
+
) : !isSoldOut ? (
|
|
552
|
+
translation?.buyButton
|
|
553
|
+
) : (
|
|
554
|
+
translation?.soldOutButton
|
|
555
|
+
)}
|
|
556
|
+
</span>
|
|
557
|
+
</button>
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
560
|
+
<div className="flex justify-end mr-[11px]">
|
|
561
|
+
{serviceItem?.available_seats < 10 &&
|
|
562
|
+
serviceItem?.available_seats > 0 && (
|
|
563
|
+
<div className="text-[12px] text-[red] mt-1 text-center">
|
|
564
|
+
¡ Últimos Asientos!
|
|
565
|
+
</div>
|
|
566
|
+
)}
|
|
567
|
+
</div>
|
|
568
|
+
|
|
569
|
+
<div
|
|
570
|
+
// className={`${
|
|
571
|
+
// serviceItem.is_change_ticket &&
|
|
572
|
+
// serviceItem.pet_seat_info &&
|
|
573
|
+
// serviceItem?.is_tracking_enabled &&
|
|
574
|
+
// Object.keys(serviceItem.pet_seat_info || {}).length > 0
|
|
575
|
+
// ? "grid grid-cols-[1.4fr_4.8fr] gap-[3.4rem] mt-[15px] text-[13px] items-center border-t border-[#eee] mt-[15px] pt-[12px]"
|
|
576
|
+
// : "grid grid-cols-[3.17fr_4.8fr] gap-[3rem] mt-[15px] text-[13px] items-center border-t border-[#eee] mt-[15px] pt-[12px]"
|
|
577
|
+
// }`}
|
|
578
|
+
className={`${"flex justify-between items-center mt-[15px] items-center border-t border-[#eee] mt-[15px] pt-[12px]"}`}
|
|
579
|
+
>
|
|
580
|
+
{/* Rating */}
|
|
581
|
+
<div>
|
|
582
|
+
<div className="flex items-center ">
|
|
583
|
+
<div
|
|
584
|
+
className="flex items-center cursor-pointer "
|
|
585
|
+
style={{ color: isSoldOut ? "#c0c0c0" : "" }}
|
|
586
|
+
>
|
|
587
|
+
<div className="flex items-center">
|
|
588
|
+
<div className="w-[18px] h-auto mr-[4px] relative">
|
|
589
|
+
<img
|
|
590
|
+
src={serviceItem.icons.rating}
|
|
591
|
+
alt="origin"
|
|
592
|
+
className={`w-[16px] h-[16px] mr-[4px] object-contain mb-[4px] ${
|
|
593
|
+
isSoldOut ? "grayscale" : ""
|
|
594
|
+
}`}
|
|
595
|
+
onMouseEnter={(e) => {
|
|
596
|
+
const tooltip = e.currentTarget
|
|
597
|
+
.nextElementSibling as HTMLElement;
|
|
598
|
+
if (tooltip) tooltip.style.display = "block";
|
|
599
|
+
}}
|
|
600
|
+
onMouseLeave={(e) => {
|
|
601
|
+
const tooltip = e.currentTarget
|
|
602
|
+
.nextElementSibling as HTMLElement;
|
|
603
|
+
if (tooltip) tooltip.style.display = "none";
|
|
604
|
+
}}
|
|
605
|
+
/>
|
|
606
|
+
<div
|
|
607
|
+
className="hidden group-hover:block absolute left-[80px] -bottom-[160px] z-20 mt-2 w-[280px] rounded-lg shadow-service-2 bg-white overflow-hidden rounded-[14px] border-[2px]"
|
|
608
|
+
style={{
|
|
609
|
+
borderColor: colors.ratingBorderColor,
|
|
610
|
+
color: isSoldOut ? "#c0c0c0" : "",
|
|
611
|
+
}}
|
|
612
|
+
>
|
|
613
|
+
<div className="pt-[20px] text-center">
|
|
614
|
+
<div className="text-[12px] bold-text text-[#464647]">
|
|
615
|
+
PUNTUACIÓN
|
|
616
|
+
</div>
|
|
617
|
+
<div className="text-[12px] font-light text-[#464647]">
|
|
618
|
+
{serviceItem.operator_service_name}
|
|
619
|
+
</div>
|
|
620
|
+
</div>
|
|
621
|
+
|
|
622
|
+
{/* Rating categories */}
|
|
623
|
+
<div className="px-3 py-2 flex flex-col gap-[10px]">
|
|
624
|
+
{[
|
|
625
|
+
{ key: "1", label: "Calidad del bus" },
|
|
626
|
+
{ key: "2", label: "Puntualidad" },
|
|
627
|
+
{
|
|
628
|
+
key: "3",
|
|
629
|
+
label: "Calidad del servicio",
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
key: "4",
|
|
633
|
+
label: "Recomendación del servicio",
|
|
634
|
+
},
|
|
635
|
+
].map((rating, index, array) => {
|
|
636
|
+
const isLast = index === array.length - 1;
|
|
637
|
+
// Use operator_details[6] for rating values
|
|
638
|
+
const ratingData =
|
|
639
|
+
serviceItem.operator_details[6] || {};
|
|
640
|
+
const value = ratingData?.[rating.key] || 0;
|
|
641
|
+
return (
|
|
642
|
+
<div
|
|
643
|
+
key={rating.key}
|
|
644
|
+
className={`flex items-center ${
|
|
645
|
+
isLast ? "mb-2" : ""
|
|
646
|
+
}`}
|
|
647
|
+
>
|
|
648
|
+
<div className="relative w-[3rem] h-[3rem]">
|
|
649
|
+
<div className="absolute inset-0 w-full h-full rounded-full">
|
|
650
|
+
<div className="w-full h-full rounded-full border-[2px] border-[lightgray]"></div>
|
|
651
|
+
</div>
|
|
652
|
+
|
|
653
|
+
{/* Colored progress arc based on value */}
|
|
654
|
+
<div className="absolute inset-0 w-full h-full">
|
|
655
|
+
<svg
|
|
656
|
+
className="w-full h-full"
|
|
657
|
+
viewBox="0 0 100 100"
|
|
658
|
+
>
|
|
659
|
+
<circle
|
|
660
|
+
cx="50"
|
|
661
|
+
cy="50"
|
|
662
|
+
r="48"
|
|
663
|
+
fill="none"
|
|
664
|
+
strokeWidth="4"
|
|
665
|
+
stroke={
|
|
666
|
+
value >= 4
|
|
667
|
+
? "#00A650"
|
|
668
|
+
: colors.ratingBorderColor
|
|
669
|
+
}
|
|
670
|
+
strokeDasharray={
|
|
671
|
+
value > 0
|
|
672
|
+
? `${value * 75.4} 301.6`
|
|
673
|
+
: "150.8 301.6"
|
|
674
|
+
}
|
|
675
|
+
strokeDashoffset="75.4"
|
|
676
|
+
transform="rotate(-90, 50, 50)"
|
|
677
|
+
/>
|
|
678
|
+
</svg>
|
|
679
|
+
</div>
|
|
680
|
+
|
|
681
|
+
{/* Center with value */}
|
|
682
|
+
<div className="absolute inset-0 flex items-center justify-center top-[40%] left-[36%]">
|
|
683
|
+
<span className="text-[#464647] font-medium text-[12px] ">
|
|
684
|
+
{value.toFixed(1)}
|
|
685
|
+
</span>
|
|
686
|
+
</div>
|
|
687
|
+
</div>
|
|
688
|
+
|
|
689
|
+
<span className="text-[#464647] text-[13.33px] ml-[10px]">
|
|
690
|
+
{rating.label}
|
|
691
|
+
</span>
|
|
692
|
+
</div>
|
|
693
|
+
);
|
|
694
|
+
})}
|
|
695
|
+
</div>
|
|
696
|
+
|
|
697
|
+
{/* Footer */}
|
|
698
|
+
<div
|
|
699
|
+
className="px-1 py-2 text-center text-[12px] text-[#ff8f45]"
|
|
700
|
+
style={{ backgroundColor: colors.ratingBottomColor }}
|
|
701
|
+
>
|
|
702
|
+
Esta puntuación se obtuvo de las opiniones de{" "}
|
|
703
|
+
{serviceItem.operator_details[5] || 0} usuarios.
|
|
704
|
+
</div>
|
|
705
|
+
</div>
|
|
706
|
+
</div>
|
|
707
|
+
<span className="text-[#464647] bold-text text-[13.33px]">
|
|
708
|
+
{typeof serviceItem.operator_details[1] === "number"
|
|
709
|
+
? serviceItem.operator_details[1].toFixed(1)
|
|
710
|
+
: serviceItem.operator_details[1]}
|
|
711
|
+
</span>
|
|
712
|
+
</div>
|
|
713
|
+
<span className="ml-[10px] text-[#464647] text-[13.33px]">
|
|
714
|
+
{serviceItem.operator_details[2]}
|
|
715
|
+
</span>
|
|
716
|
+
</div>
|
|
717
|
+
|
|
718
|
+
{/* Rating tooltip */}
|
|
719
|
+
</div>
|
|
720
|
+
</div>
|
|
721
|
+
|
|
722
|
+
{/* <div className="flex justify-between items-center gap-[10px]"> */}
|
|
723
|
+
{/* Duration */}
|
|
724
|
+
<div className="flex items-baseline relative text-[#464647]">
|
|
725
|
+
{/* {renderIcon("duration", "14px")} */}
|
|
726
|
+
<div
|
|
727
|
+
className={`w-[18px] h-auto mr-[4px] ${
|
|
728
|
+
isSoldOut ? "grayscale" : ""
|
|
729
|
+
}`}
|
|
730
|
+
>
|
|
731
|
+
{renderIcon("hours", "14px")}
|
|
732
|
+
</div>
|
|
733
|
+
<div
|
|
734
|
+
className={`cursor-default group text-[13.33px] ${
|
|
735
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
736
|
+
}`}
|
|
737
|
+
>
|
|
738
|
+
{serviceItem.duration} {translation.hours}
|
|
739
|
+
<div
|
|
740
|
+
className=" hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-normal z-10 mt-2.5 w-[230px] text-center break-normal shadow-service"
|
|
741
|
+
style={{ backgroundColor: colors.tooltipColor }}
|
|
742
|
+
>
|
|
743
|
+
{/* Tooltip arrow */}
|
|
744
|
+
<div
|
|
745
|
+
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"
|
|
746
|
+
style={{ borderBottomColor: colors.tooltipColor }}
|
|
747
|
+
></div>
|
|
748
|
+
Duración estimada del viaje
|
|
749
|
+
</div>
|
|
750
|
+
</div>
|
|
751
|
+
</div>
|
|
752
|
+
|
|
753
|
+
{serviceItem.pet_seat_info &&
|
|
754
|
+
Object.keys(serviceItem.pet_seat_info).length > 0 ? (
|
|
755
|
+
<div className="flex items-center">
|
|
756
|
+
<div className={`relative group cursor-default `}>
|
|
757
|
+
<div className="flex items-center">
|
|
758
|
+
<div className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}>
|
|
759
|
+
<LottiePlayer
|
|
760
|
+
animationData={serviceItem.icons.petFriendlyAnim}
|
|
761
|
+
width="20px"
|
|
762
|
+
height="20px"
|
|
763
|
+
/>
|
|
764
|
+
</div>
|
|
765
|
+
<div className="h-auto mr-[4px] text-[13px] text-[#464647]">
|
|
766
|
+
<span>{translation?.petFriendly}</span>
|
|
767
|
+
</div>
|
|
768
|
+
</div>
|
|
769
|
+
<div
|
|
770
|
+
className=" hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-normal z-10 mt-2.5 w-[230px] text-center break-normal shadow-service"
|
|
771
|
+
style={{ backgroundColor: colors?.tooltipColor }}
|
|
772
|
+
>
|
|
773
|
+
<div
|
|
774
|
+
className="tooltip-arrow absolute text-[13.33px] -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"
|
|
775
|
+
style={{ borderBottomColor: colors?.tooltipColor }}
|
|
776
|
+
></div>
|
|
777
|
+
Este servicio incluye asientos para mascotas.
|
|
778
|
+
</div>
|
|
779
|
+
</div>
|
|
780
|
+
</div>
|
|
781
|
+
) : null}
|
|
782
|
+
|
|
783
|
+
{/* Flexible ticket */}
|
|
784
|
+
{serviceItem.is_change_ticket && (
|
|
785
|
+
<div className="flex items-center">
|
|
786
|
+
<div className="relative group cursor-default">
|
|
787
|
+
<div className="flex items-center">
|
|
788
|
+
<div className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}>
|
|
789
|
+
<LottiePlayer
|
|
790
|
+
animationData={serviceItem.icons.flexibleAnim}
|
|
791
|
+
width="20px"
|
|
792
|
+
height="20px"
|
|
793
|
+
/>
|
|
794
|
+
</div>
|
|
795
|
+
<div className="h-auto mr-[4px] text-[13px] text-[#464647]">
|
|
796
|
+
<span>{translation?.flexible}</span>
|
|
797
|
+
</div>
|
|
798
|
+
</div>
|
|
799
|
+
<div
|
|
800
|
+
className="hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-normal z-10 mt-2.5 w-[230px] text-center break-normal shadow-service text-[13.33px]"
|
|
801
|
+
style={{ backgroundColor: colors.tooltipColor }}
|
|
802
|
+
>
|
|
803
|
+
{/* Tooltip arrow */}
|
|
804
|
+
<div
|
|
805
|
+
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 "
|
|
806
|
+
style={{ borderBottomColor: colors.tooltipColor }}
|
|
807
|
+
></div>
|
|
808
|
+
Esta empresa permite cambios sin costo hasta (
|
|
809
|
+
{serviceItem?.change_ticket_hours ?? 6}) horas antes del
|
|
810
|
+
viaje.
|
|
811
|
+
</div>
|
|
812
|
+
</div>
|
|
813
|
+
</div>
|
|
814
|
+
)}
|
|
815
|
+
|
|
816
|
+
{/* Amenities */}
|
|
817
|
+
<div className="flex items-center">
|
|
818
|
+
<div>
|
|
819
|
+
{serviceItem?.is_tracking_enabled && (
|
|
820
|
+
<div className="flex items-center mr-[10px]">
|
|
821
|
+
<div
|
|
822
|
+
className={`h-auto mr-[4px] text-[13px] text-[#464647] ${
|
|
823
|
+
isSoldOut ? "grayscale" : ""
|
|
824
|
+
}`}
|
|
825
|
+
>
|
|
826
|
+
<LottiePlayer
|
|
827
|
+
animationData={serviceItem.icons.locationAnim}
|
|
828
|
+
width="20px"
|
|
829
|
+
height="20px"
|
|
830
|
+
/>
|
|
831
|
+
</div>
|
|
832
|
+
</div>
|
|
833
|
+
)}
|
|
834
|
+
</div>
|
|
835
|
+
<div>
|
|
836
|
+
{metaData && serviceItem.operator_details[4] && (
|
|
837
|
+
<div className="flex items-center gap-[6px]">
|
|
838
|
+
{/* Show first three amenities */}
|
|
839
|
+
{(serviceItem.operator_details[3]?.includes("18")
|
|
840
|
+
? [...serviceItem.operator_details[4], "18"]
|
|
841
|
+
: serviceItem.operator_details[4]
|
|
842
|
+
).map((val, key) => {
|
|
843
|
+
return (key < 3 &&
|
|
844
|
+
metaData?.amenities[val]
|
|
845
|
+
?.split(".")[0]
|
|
846
|
+
?.toUpperCase() !== "WATER") ||
|
|
847
|
+
val === "18" ? (
|
|
848
|
+
<div key={key} className="relative mr-2 cursor-pointer">
|
|
849
|
+
<div className="group">
|
|
850
|
+
<div className={`${isSoldOut ? "grayscale" : ""}`}>
|
|
851
|
+
<SvgAmenities
|
|
852
|
+
moreAnemities={false}
|
|
853
|
+
name={metaData.amenities[val]
|
|
854
|
+
?.split(".")[0]
|
|
855
|
+
.toLowerCase()}
|
|
856
|
+
/>
|
|
857
|
+
</div>
|
|
858
|
+
<div
|
|
859
|
+
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 text-center shadow-service text-[13.33px]"
|
|
860
|
+
style={{ backgroundColor: colors.tooltipColor }}
|
|
861
|
+
>
|
|
862
|
+
{/* Tooltip arrow */}
|
|
863
|
+
<div
|
|
864
|
+
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"
|
|
865
|
+
style={{
|
|
866
|
+
borderBottomColor: colors.tooltipColor,
|
|
867
|
+
}}
|
|
868
|
+
></div>
|
|
869
|
+
{getAmenityName(
|
|
870
|
+
metaData.amenities[val]
|
|
871
|
+
?.split(".")[0]
|
|
872
|
+
.split("_")
|
|
873
|
+
.join(" ")
|
|
874
|
+
)}
|
|
875
|
+
</div>
|
|
876
|
+
</div>
|
|
877
|
+
</div>
|
|
878
|
+
) : null;
|
|
879
|
+
})}
|
|
880
|
+
|
|
881
|
+
{/* Plus icon for more amenities */}
|
|
882
|
+
{serviceItem.operator_details[4]?.length > 3 && (
|
|
883
|
+
<div className="relative ml-1 cursor-pointer">
|
|
884
|
+
<div className="w-[16px] h-[16px] bg-gray-200 rounded-full flex items-center justify-center text-sm font-bold ml-[5px] group">
|
|
885
|
+
<img
|
|
886
|
+
src={
|
|
887
|
+
serviceItem.icons?.plus ||
|
|
888
|
+
"/images/icons/amenities/icon_plus.svg"
|
|
889
|
+
}
|
|
890
|
+
className="w-[16px] h-[16px]"
|
|
891
|
+
alt="plus"
|
|
892
|
+
/>
|
|
893
|
+
<div className="hidden group-hover:block absolute -top-[13px] left-[40px] z-20 pl-[10px]">
|
|
894
|
+
<div
|
|
895
|
+
className="flex flex-col gap-[10px] p-3 rounded-[8px] shadow-md animate-fadeIn relative"
|
|
896
|
+
style={{ backgroundColor: colors.tooltipColor }}
|
|
897
|
+
>
|
|
898
|
+
{/* Additional amenities */}
|
|
899
|
+
{metaData &&
|
|
900
|
+
serviceItem.operator_details[4]?.map(
|
|
901
|
+
(val, key) => {
|
|
902
|
+
const exceptions = [
|
|
903
|
+
1, 2, 5, 7, 8, 9, 12, 13, 14, 15,
|
|
904
|
+
];
|
|
905
|
+
return exceptions.includes(
|
|
906
|
+
key
|
|
907
|
+
) ? null : key >= 3 &&
|
|
908
|
+
metaData.amenities[val]
|
|
909
|
+
?.split(".")[0]
|
|
910
|
+
?.toUpperCase() !== "WATER" ? (
|
|
911
|
+
<div
|
|
912
|
+
key={key}
|
|
913
|
+
className="flex items-center gap-[5px] whitespace-nowrap text-[13.33px]"
|
|
914
|
+
>
|
|
915
|
+
<div
|
|
916
|
+
className={`${
|
|
917
|
+
isSoldOut ? "grayscale" : ""
|
|
918
|
+
}`}
|
|
919
|
+
>
|
|
920
|
+
<SvgAmenities
|
|
921
|
+
moreAnemities={true}
|
|
922
|
+
name={metaData.amenities[val]
|
|
923
|
+
?.split(".")[0]
|
|
924
|
+
?.toUpperCase()}
|
|
925
|
+
color="white"
|
|
926
|
+
/>
|
|
927
|
+
</div>
|
|
928
|
+
<span className="text-white text-xs">
|
|
929
|
+
{getAmenityName(
|
|
930
|
+
metaData.amenities[val]
|
|
931
|
+
?.split(".")[0]
|
|
932
|
+
?.split("_")
|
|
933
|
+
?.join(" ")
|
|
934
|
+
)}
|
|
935
|
+
</span>
|
|
936
|
+
</div>
|
|
937
|
+
) : null;
|
|
938
|
+
}
|
|
939
|
+
)}
|
|
940
|
+
{/* Tooltip arrow */}
|
|
941
|
+
<div
|
|
942
|
+
className="tooltip-arrow absolute -left-[6px] top-[15px] w-0 h-0 border-t-8 border-b-8 border-r-8 border-t-transparent border-b-transparent "
|
|
943
|
+
style={{
|
|
944
|
+
borderRightColor: colors.tooltipColor,
|
|
945
|
+
}}
|
|
946
|
+
></div>
|
|
947
|
+
</div>
|
|
948
|
+
</div>
|
|
949
|
+
</div>
|
|
950
|
+
</div>
|
|
951
|
+
)}
|
|
952
|
+
</div>
|
|
953
|
+
)}
|
|
954
|
+
</div>
|
|
955
|
+
{/* </div> */}
|
|
956
|
+
</div>
|
|
957
|
+
</div>
|
|
958
|
+
</div>
|
|
959
|
+
</div>
|
|
960
|
+
|
|
961
|
+
{children}
|
|
962
|
+
{/* Bottom discount banner */}
|
|
963
|
+
{serviceItem?.offer_text && (
|
|
964
|
+
<div
|
|
965
|
+
className={` text-white p-[10px_15px] text-left w-full flex items-center absolute -bottom-[36px] pt-[50px] -z-10 rounded-b-[14px] text-[14px]`}
|
|
966
|
+
style={{ backgroundColor: isSoldOut ? "" : colors?.bottomStripColor }}
|
|
967
|
+
>
|
|
968
|
+
<LottiePlayer
|
|
969
|
+
animationData={serviceItem.icons.promoAnim}
|
|
970
|
+
width="18px"
|
|
971
|
+
height="18px"
|
|
972
|
+
/>
|
|
973
|
+
<span className="ml-[10px]">{serviceItem?.offer_text}</span>
|
|
974
|
+
</div>
|
|
975
|
+
)}
|
|
976
|
+
|
|
977
|
+
<div className="absolute -top-[17px] left-0 w-full flex items-center justify-end gap-[12px] pr-[20px] z-10 ">
|
|
978
|
+
{showTopLabel && (
|
|
979
|
+
<div
|
|
980
|
+
className={`flex items-center gap-[10px] py-[8px] px-[20px] rounded-[38px] text-[13.33px] z-20 ${
|
|
981
|
+
isSoldOut ? "bg-[#ddd]" : ``
|
|
982
|
+
}`}
|
|
983
|
+
style={{ backgroundColor: !isSoldOut && colors.ratingBottomColor }}
|
|
984
|
+
>
|
|
985
|
+
<div className={isSoldOut ? "grayscale" : ""}>
|
|
986
|
+
<LottiePlayer
|
|
987
|
+
animationData={serviceItem.icons.priorityStageAnim}
|
|
988
|
+
width="20px"
|
|
989
|
+
height="20px"
|
|
990
|
+
/>
|
|
991
|
+
</div>
|
|
992
|
+
<div
|
|
993
|
+
className={
|
|
994
|
+
isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
|
|
995
|
+
}
|
|
996
|
+
>
|
|
997
|
+
{showTopLabel}
|
|
998
|
+
</div>
|
|
999
|
+
</div>
|
|
1000
|
+
)}
|
|
1001
|
+
{serviceItem?.is_transpordo && (
|
|
1002
|
+
<div
|
|
1003
|
+
className={`flex items-center gap-[10px] py-[8px] text-white px-[20px] rounded-[38px] text-[13.33px] z-20 ${
|
|
1004
|
+
isSoldOut ? "bg-[#ddd]" : `bg-[${colors.tooltipColor}]`
|
|
1005
|
+
}`}
|
|
1006
|
+
>
|
|
1007
|
+
<LottiePlayer
|
|
1008
|
+
animationData={serviceItem.icons.connectingServiceIcon}
|
|
1009
|
+
width="20px"
|
|
1010
|
+
height="20px"
|
|
1011
|
+
/>
|
|
1012
|
+
<div>{"Conexión"}</div>
|
|
1013
|
+
</div>
|
|
1014
|
+
)}
|
|
1015
|
+
{serviceItem?.is_direct_trip && (
|
|
1016
|
+
<div
|
|
1017
|
+
className={`flex items-center gap-[10px] py-[8px] text-white px-[20px] rounded-[38px] text-[13.33px] z-20 ${
|
|
1018
|
+
isSoldOut ? "bg-[#ddd]" : `bg-[${colors.tooltipColor}]`
|
|
1019
|
+
}`}
|
|
1020
|
+
>
|
|
1021
|
+
<LottiePlayer
|
|
1022
|
+
animationData={serviceItem.icons.directoAnim}
|
|
1023
|
+
width="20px"
|
|
1024
|
+
height="20px"
|
|
1025
|
+
/>
|
|
1026
|
+
<div>{translation?.directService}</div>
|
|
1027
|
+
</div>
|
|
1028
|
+
)}
|
|
1029
|
+
{serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
|
|
1030
|
+
<div
|
|
1031
|
+
className={`flex items-center gap-[10px] py-[8px] text-white px-[20px] rounded-[38px] text-[13.33px] z-20 ${
|
|
1032
|
+
isSoldOut ? "bg-[#ddd]" : `bg-[${colors.tooltipColor}]`
|
|
1033
|
+
}`}
|
|
1034
|
+
>
|
|
1035
|
+
<LottiePlayer
|
|
1036
|
+
animationData={serviceItem.icons.directoAnim}
|
|
1037
|
+
width="20px"
|
|
1038
|
+
height="20px"
|
|
1039
|
+
/>
|
|
1040
|
+
<div>{"Tren Express"}</div>
|
|
1041
|
+
</div>
|
|
1042
|
+
)}
|
|
1043
|
+
</div>
|
|
1044
|
+
</div>
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
export default ServiceItemPB;
|