kupos-ui-components-lib 9.1.2 → 9.1.3
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 +67 -223
- package/dist/assets/images/anims/service_list/directo.json +1 -1
- package/dist/components/ServiceItem/PeruServiceItemDesktop.js +1 -1
- package/dist/components/ServiceItem/RatingHover.js +33 -32
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +267 -147
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +278 -87
- package/dist/components/ServiceItem/mobileTypes.d.ts +0 -5
- package/dist/components/ServiceItem/types.d.ts +0 -7
- package/dist/styles.css +32 -131
- package/dist/ui/AmenitiesBlock.js +30 -23
- package/dist/ui/DurationBlock.js +4 -4
- package/dist/ui/FlexibleBlock.js +6 -5
- package/dist/ui/PetBlock.js +3 -1
- package/dist/ui/RatingBlock.d.ts +1 -9
- package/dist/ui/RatingBlock.js +3 -7
- package/dist/utils/CommonService.d.ts +1 -1
- package/dist/utils/CommonService.js +0 -2
- package/package.json +1 -2
- package/src/assets/images/anims/service_list/directo.json +1 -1
- package/src/components/ServiceItem/PeruServiceItemDesktop.tsx +0 -1
- package/src/components/ServiceItem/RatingHover.tsx +45 -44
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +537 -313
- package/src/components/ServiceItem/ServiceItemMobile.tsx +530 -213
- package/src/components/ServiceItem/mobileTypes.ts +0 -5
- package/src/components/ServiceItem/types.ts +0 -7
- package/src/ui/AmenitiesBlock.tsx +29 -50
- package/src/ui/DurationBlock.tsx +4 -4
- package/src/ui/FlexibleBlock.tsx +5 -6
- package/src/ui/PetBlock.tsx +2 -2
- package/src/ui/RatingBlock.tsx +6 -18
- package/src/utils/CommonService.ts +0 -2
- package/src/assets/images/anims/service_list/bomb.json +0 -1
- package/src/ui/BottomAmenities/BottomAmenities.tsx +0 -110
- package/src/ui/DateTimeSection/DateTimeSection.tsx +0 -207
- package/src/ui/DirectoBlock.tsx +0 -31
- package/src/ui/ExpendedDropDown/ExpandedDropdown.tsx +0 -103
- package/src/ui/KuposButton/KuposButton.tsx +0 -48
- package/src/ui/SeatSection/SeatSection.tsx +0 -207
- package/src/ui/TopAmenities/TopAmenities.tsx +0 -127
- package/src/ui/mobileweb/BottomAmenitiesMobile.tsx +0 -169
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +0 -192
- package/src/ui/mobileweb/ExpandedDropdownMobile.tsx +0 -56
- package/src/ui/mobileweb/SeatSectionMobile.tsx +0 -256
- package/src/ui/mobileweb/TopAmenitieMobile.tsx +0 -126
|
@@ -3,11 +3,6 @@ import LottiePlayer from "../../assets/LottiePlayer";
|
|
|
3
3
|
import DateService from "../../utils/DateService";
|
|
4
4
|
import { MobileServiceItemProps } from "./mobileTypes";
|
|
5
5
|
import commonService from "../../utils/CommonService";
|
|
6
|
-
import TopAmenitieMobile from "../../ui/mobileweb/TopAmenitieMobile";
|
|
7
|
-
import BottomAmenitiesMobile from "../../ui/mobileweb/BottomAmenitiesMobile";
|
|
8
|
-
import SeatSectionMobile from "../../ui/mobileweb/SeatSectionMobile";
|
|
9
|
-
import DateTimeSectionMobile from "../../ui/mobileweb/DateTimeSectionMobile";
|
|
10
|
-
import ExpandedDropdownMobile from "../../ui/mobileweb/ExpandedDropdownMobile";
|
|
11
6
|
|
|
12
7
|
const SEAT_EXCEPTIONS = ["Asiento mascota"];
|
|
13
8
|
|
|
@@ -33,8 +28,6 @@ function ServiceItemMobile({
|
|
|
33
28
|
amenitiesData,
|
|
34
29
|
setShowDropdown,
|
|
35
30
|
showDropdown,
|
|
36
|
-
isExpanded,
|
|
37
|
-
setIsExpanded,
|
|
38
31
|
setAmenetiesAtomValue,
|
|
39
32
|
isCiva,
|
|
40
33
|
currencySign,
|
|
@@ -44,41 +37,8 @@ function ServiceItemMobile({
|
|
|
44
37
|
removeDuplicateSeats,
|
|
45
38
|
isLinatal,
|
|
46
39
|
}: MobileServiceItemProps): React.ReactElement {
|
|
47
|
-
const isItemExpanded = serviceItem.id === isExpanded;
|
|
48
40
|
const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
|
|
49
41
|
let isSoldOut = serviceItem.available_seats <= 0;
|
|
50
|
-
const showPromo = Math.random() > 0.5;
|
|
51
|
-
|
|
52
|
-
const countdownSeconds = 7830;
|
|
53
|
-
|
|
54
|
-
const startCountdown = (node: HTMLSpanElement | null) => {
|
|
55
|
-
if (!node) return;
|
|
56
|
-
|
|
57
|
-
const prevId = node.dataset.countdownId;
|
|
58
|
-
if (prevId) clearInterval(Number(prevId));
|
|
59
|
-
|
|
60
|
-
let remaining = countdownSeconds;
|
|
61
|
-
|
|
62
|
-
const formatTime = (totalSecs: number) => {
|
|
63
|
-
const h = Math.floor(totalSecs / 3600);
|
|
64
|
-
const m = Math.floor((totalSecs % 3600) / 60);
|
|
65
|
-
const s = totalSecs % 60;
|
|
66
|
-
return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
node.textContent = formatTime(remaining);
|
|
70
|
-
|
|
71
|
-
const id = setInterval(() => {
|
|
72
|
-
remaining -= 1;
|
|
73
|
-
if (remaining <= 0) {
|
|
74
|
-
remaining = 0;
|
|
75
|
-
clearInterval(id);
|
|
76
|
-
}
|
|
77
|
-
node.textContent = formatTime(remaining);
|
|
78
|
-
}, 1000);
|
|
79
|
-
|
|
80
|
-
node.dataset.countdownId = String(id);
|
|
81
|
-
};
|
|
82
42
|
|
|
83
43
|
const labelId =
|
|
84
44
|
typeof serviceItem.boarding_stages === "string"
|
|
@@ -101,6 +61,194 @@ function ServiceItemMobile({
|
|
|
101
61
|
}
|
|
102
62
|
};
|
|
103
63
|
|
|
64
|
+
const seatTypes = () => {
|
|
65
|
+
let seatTypes = serviceItem.seat_types
|
|
66
|
+
?.filter((item) => getFilteredSeats(item.label))
|
|
67
|
+
?.sort((a, b) => a.fare - b.fare) // Add this line to sort by fare
|
|
68
|
+
?.slice(0, 2)
|
|
69
|
+
?.map((type, i) =>
|
|
70
|
+
exceptions.includes(type.label) ? null : (
|
|
71
|
+
<div
|
|
72
|
+
className={
|
|
73
|
+
serviceItem.seat_types?.length > 2
|
|
74
|
+
? "w-[100%] flex flex-row justify-between "
|
|
75
|
+
: "w-[100%] flex flex-row justify-between items-center"
|
|
76
|
+
}
|
|
77
|
+
key={i}
|
|
78
|
+
>
|
|
79
|
+
<span
|
|
80
|
+
className="min-[420]:text-[13px] text-[12px] "
|
|
81
|
+
style={{
|
|
82
|
+
// marginLeft: "10px",
|
|
83
|
+
color: isSoldOut ? "#bbb" : "#464647",
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
{type.label}
|
|
87
|
+
</span>
|
|
88
|
+
<span
|
|
89
|
+
className={"min-[420]:text-[13px] text-[12px] bold-text"}
|
|
90
|
+
style={{ color: isSoldOut ? "#bbb" : colors.seatPriceColor }}
|
|
91
|
+
>
|
|
92
|
+
{commonService.currency(type.fare, currencySign)}
|
|
93
|
+
</span>
|
|
94
|
+
</div>
|
|
95
|
+
),
|
|
96
|
+
);
|
|
97
|
+
return seatTypes;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const seatTypesWithRemoveDuplicateSeats = () => {
|
|
101
|
+
const seatMap = new Map();
|
|
102
|
+
|
|
103
|
+
serviceItem.seat_types
|
|
104
|
+
?.filter((item) => getFilteredSeats(item.label))
|
|
105
|
+
?.forEach((item) => {
|
|
106
|
+
if (exceptions.includes(item.key as any)) return;
|
|
107
|
+
const existing = seatMap.get(item.label);
|
|
108
|
+
if (
|
|
109
|
+
!existing ||
|
|
110
|
+
parseFloat(item.fare as any) < parseFloat(existing.fare)
|
|
111
|
+
) {
|
|
112
|
+
seatMap.set(item.label, item);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const uniqueSeats = Array.from(seatMap.values())
|
|
117
|
+
.sort((a, b) => a.fare - b.fare)
|
|
118
|
+
.slice(0, 3);
|
|
119
|
+
return uniqueSeats.map((type, i) => {
|
|
120
|
+
return exceptions.includes(type.label) ? null : (
|
|
121
|
+
<div
|
|
122
|
+
className={
|
|
123
|
+
serviceItem.seat_types?.length > 2
|
|
124
|
+
? "w-[100%] flex flex-row justify-between "
|
|
125
|
+
: "w-[100%] flex flex-row justify-between items-center"
|
|
126
|
+
}
|
|
127
|
+
key={i}
|
|
128
|
+
>
|
|
129
|
+
<span
|
|
130
|
+
className="min-[420]:text-[13px] text-[11px] "
|
|
131
|
+
style={{
|
|
132
|
+
// marginLeft: "10px",
|
|
133
|
+
color: isSoldOut ? "#bbb" : "#464647",
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
{commonService.truncateSeatLabel(type.label)}
|
|
137
|
+
</span>
|
|
138
|
+
<span
|
|
139
|
+
className={"min-[420]:text-[13px] text-[11px] bold-text"}
|
|
140
|
+
style={{ color: isSoldOut ? "#bbb" : colors.seatPriceColor }}
|
|
141
|
+
>
|
|
142
|
+
{/* {serviceItem?.operator_service_name === "Pullman San Andrés" &&
|
|
143
|
+
serviceItem?.available_seats <= 0
|
|
144
|
+
? null
|
|
145
|
+
: commonService.currency(type.fare, currencySign)} */}
|
|
146
|
+
|
|
147
|
+
{serviceItem?.available_seats <= 0 && !isPeru
|
|
148
|
+
? commonService.currency(0, currencySign)
|
|
149
|
+
: commonService.currency(type.fare, currencySign)}
|
|
150
|
+
</span>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const getFilteredSeats = (item) => {
|
|
157
|
+
return item;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const getAmenitiesImage = (name: string): string => {
|
|
161
|
+
switch (name) {
|
|
162
|
+
case "air_condtion.png": {
|
|
163
|
+
return serviceItem?.icons?.airConditionIcon;
|
|
164
|
+
}
|
|
165
|
+
case "baggage.png": {
|
|
166
|
+
return serviceItem?.icons?.baggageIcon;
|
|
167
|
+
}
|
|
168
|
+
case "charging_plug.png": {
|
|
169
|
+
return serviceItem?.icons?.chargingIcon;
|
|
170
|
+
}
|
|
171
|
+
case "coffee.png": {
|
|
172
|
+
return serviceItem?.icons?.coffeeIcon;
|
|
173
|
+
}
|
|
174
|
+
case "food_new_icon.png": {
|
|
175
|
+
return serviceItem?.icons?.foodIcon;
|
|
176
|
+
}
|
|
177
|
+
case "gaming.png": {
|
|
178
|
+
return serviceItem?.icons?.gamingIcon;
|
|
179
|
+
}
|
|
180
|
+
case "handicap.png": {
|
|
181
|
+
return serviceItem?.icons?.handicapIcon;
|
|
182
|
+
}
|
|
183
|
+
case "mobile_ticket.png": {
|
|
184
|
+
return serviceItem?.icons?.mobileTicketIcon;
|
|
185
|
+
}
|
|
186
|
+
case "movie.png": {
|
|
187
|
+
return serviceItem?.icons?.movieIcon;
|
|
188
|
+
}
|
|
189
|
+
case "restrooms.png": {
|
|
190
|
+
return serviceItem?.icons?.restroomsIcon;
|
|
191
|
+
}
|
|
192
|
+
case "snacks_new.png": {
|
|
193
|
+
return serviceItem?.icons?.snackIcon;
|
|
194
|
+
}
|
|
195
|
+
case "wifi.png": {
|
|
196
|
+
return serviceItem?.icons?.wifiIcon;
|
|
197
|
+
}
|
|
198
|
+
case "cortina_divisoria.png": {
|
|
199
|
+
return serviceItem?.icons?.cortinaIcon;
|
|
200
|
+
}
|
|
201
|
+
case "frazada.png": {
|
|
202
|
+
return serviceItem?.icons?.frazaIcon;
|
|
203
|
+
}
|
|
204
|
+
case "blanket.png": {
|
|
205
|
+
return serviceItem?.icons?.blankketIcon;
|
|
206
|
+
}
|
|
207
|
+
case "cctv.png": {
|
|
208
|
+
return serviceItem?.icons?.cctvIcon;
|
|
209
|
+
}
|
|
210
|
+
case "cup_holder.png": {
|
|
211
|
+
return serviceItem?.icons?.cupHolderIcon;
|
|
212
|
+
}
|
|
213
|
+
case "emergency_contact.png": {
|
|
214
|
+
return serviceItem?.icons?.emergencyContactIcon;
|
|
215
|
+
}
|
|
216
|
+
case "emergency_exit.png": {
|
|
217
|
+
return serviceItem?.icons?.emergencyExitIcon;
|
|
218
|
+
}
|
|
219
|
+
case "fire_extinguisher.png": {
|
|
220
|
+
return serviceItem?.icons?.fireExtinguisherIcon;
|
|
221
|
+
}
|
|
222
|
+
case "reading_light.png": {
|
|
223
|
+
return serviceItem?.icons?.readingLIghtIcon;
|
|
224
|
+
}
|
|
225
|
+
case "seat_belt.png": {
|
|
226
|
+
return serviceItem?.icons?.sercurityBeltIcon;
|
|
227
|
+
}
|
|
228
|
+
case "service_on_board.png": {
|
|
229
|
+
return serviceItem?.icons?.serviceOnBoardIcon;
|
|
230
|
+
}
|
|
231
|
+
case "personal_tv.png": {
|
|
232
|
+
return serviceItem?.icons?.personalTVIcon;
|
|
233
|
+
}
|
|
234
|
+
case "pet_admission.png": {
|
|
235
|
+
return serviceItem?.icons?.petAdmissionIcon;
|
|
236
|
+
}
|
|
237
|
+
case "music.png": {
|
|
238
|
+
return serviceItem?.icons?.musicIcon;
|
|
239
|
+
}
|
|
240
|
+
case "headset.png": {
|
|
241
|
+
return serviceItem?.icons?.headPhoneIcon;
|
|
242
|
+
}
|
|
243
|
+
case "allows_cancellation.png": {
|
|
244
|
+
return serviceItem?.icons?.allowCancellationIcon;
|
|
245
|
+
}
|
|
246
|
+
default: {
|
|
247
|
+
return "";
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
104
252
|
const amenities = () => {
|
|
105
253
|
const raw = serviceItem?.operator_details?.[3];
|
|
106
254
|
const list = Array.isArray(raw)
|
|
@@ -113,8 +261,8 @@ function ServiceItemMobile({
|
|
|
113
261
|
<img
|
|
114
262
|
key={i}
|
|
115
263
|
className="amenity"
|
|
116
|
-
height={
|
|
117
|
-
width={
|
|
264
|
+
height={14}
|
|
265
|
+
width={14}
|
|
118
266
|
// src={getAmenitiesImage(amenitiesData?.[am]?.toLowerCase())}
|
|
119
267
|
src={commonService.getAmenitiesImage(
|
|
120
268
|
amenitiesData?.[am]?.toLowerCase(),
|
|
@@ -150,6 +298,32 @@ function ServiceItemMobile({
|
|
|
150
298
|
isConexion = true;
|
|
151
299
|
}
|
|
152
300
|
|
|
301
|
+
const depTime = serviceItem.dep_time || "";
|
|
302
|
+
|
|
303
|
+
// Extract hours and minutes and check for AM/PM
|
|
304
|
+
const hasAM = depTime.includes("AM");
|
|
305
|
+
const hasPM = depTime.includes("PM");
|
|
306
|
+
const [timePart] = depTime.split(/AM|PM/).map((part) => part.trim());
|
|
307
|
+
const [hour, minute] = timePart.split(":").map(Number);
|
|
308
|
+
|
|
309
|
+
// Convert to 24-hour format
|
|
310
|
+
let cleanedDepTime;
|
|
311
|
+
if (hasAM) {
|
|
312
|
+
cleanedDepTime =
|
|
313
|
+
hour === 12
|
|
314
|
+
? `00:${minute < 10 ? "0" + minute : minute}`
|
|
315
|
+
: `${hour < 10 ? "0" + hour : hour}:${
|
|
316
|
+
minute < 10 ? "0" + minute : minute
|
|
317
|
+
}`;
|
|
318
|
+
} else if (hasPM) {
|
|
319
|
+
cleanedDepTime =
|
|
320
|
+
hour === 12
|
|
321
|
+
? `${hour}:${minute < 10 ? "0" + minute : minute}`
|
|
322
|
+
: `${hour + 12}:${minute < 10 ? "0" + minute : minute}`;
|
|
323
|
+
} else {
|
|
324
|
+
cleanedDepTime = timePart;
|
|
325
|
+
}
|
|
326
|
+
|
|
153
327
|
return (
|
|
154
328
|
<div
|
|
155
329
|
className={`relative ${
|
|
@@ -164,39 +338,23 @@ function ServiceItemMobile({
|
|
|
164
338
|
} `}
|
|
165
339
|
style={{ backgroundColor: "#fff", zIndex: 1 }}
|
|
166
340
|
>
|
|
167
|
-
{/* <TopAmenitieMobile
|
|
168
|
-
showTopLabel={showTopLabel}
|
|
169
|
-
isSoldOut={isSoldOut}
|
|
170
|
-
seatPriceColor={colors.seatPriceColor}
|
|
171
|
-
bombAnim={serviceItem.icons.bombAnim}
|
|
172
|
-
priorityStageAnim={serviceItem.icons.priorityStageAnim}
|
|
173
|
-
countdownSeconds={countdownSeconds}
|
|
174
|
-
onCountdownEnd={() => {
|
|
175
|
-
const cardEl = document.getElementById(
|
|
176
|
-
`service-card-${serviceItem.id}`,
|
|
177
|
-
);
|
|
178
|
-
if (!cardEl) return;
|
|
179
|
-
cardEl.style.border = "1px solid #ccc";
|
|
180
|
-
if (!showTopLabel) {
|
|
181
|
-
cardEl.style.borderRadius = "10px";
|
|
182
|
-
}
|
|
183
|
-
}}
|
|
184
|
-
offerText={serviceItem?.offer_text}
|
|
185
|
-
/> */}
|
|
186
341
|
<div
|
|
187
|
-
className={" rounded-[20px]"}
|
|
188
|
-
style={{
|
|
189
|
-
backgroundColor: "#fff",
|
|
190
|
-
zIndex: 1,
|
|
191
|
-
// borderRadius: showTopLabel ? "10px 0 10px 10px" : "10px",
|
|
192
|
-
borderRadius: "12px",
|
|
193
|
-
border: "1px solid #ccc",
|
|
194
|
-
}}
|
|
342
|
+
className={"border border-[#E6E6E6] rounded-[20px]"}
|
|
343
|
+
style={{ backgroundColor: "#fff", zIndex: 1 }}
|
|
195
344
|
>
|
|
196
|
-
<div
|
|
345
|
+
<div
|
|
346
|
+
className={`p-[12px] ${
|
|
347
|
+
serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
|
|
348
|
+
showTopLabel ||
|
|
349
|
+
serviceItem?.is_direct_trip ||
|
|
350
|
+
serviceItem?.is_transpordo
|
|
351
|
+
? "mt-[10px]"
|
|
352
|
+
: ""
|
|
353
|
+
}`}
|
|
354
|
+
>
|
|
197
355
|
{/* Header with operator info and favorite */}
|
|
198
|
-
<div className="flex justify-between
|
|
199
|
-
<div className="flex items-center
|
|
356
|
+
<div className="flex justify-between mb-[8px]">
|
|
357
|
+
<div className="flex items-center w-[50%] justify-between">
|
|
200
358
|
<div className="w-[120px] overflow-y-hidden">
|
|
201
359
|
<img
|
|
202
360
|
src={serviceItem.operator_details[0]}
|
|
@@ -211,99 +369,296 @@ function ServiceItemMobile({
|
|
|
211
369
|
{serviceItem?.operator_details[2]}
|
|
212
370
|
</div>
|
|
213
371
|
) : showRating ? (
|
|
214
|
-
<div className="flex min-[420]:text-[13px] text-[12px]
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
{getServiceStars(serviceItem)}
|
|
226
|
-
</span>
|
|
227
|
-
</div>
|
|
228
|
-
|
|
229
|
-
<div
|
|
230
|
-
className="flex items-center cursor-pointer "
|
|
231
|
-
style={{ color: isSoldOut ? "#bbb" : "text-[#464647]" }}
|
|
232
|
-
>
|
|
233
|
-
<span className="ml-[3px] min-[420]:text-[13px] text-[12px] text-ellipsis">
|
|
234
|
-
{serviceItem.operator_details[2]}
|
|
235
|
-
</span>
|
|
236
|
-
</div>
|
|
237
|
-
</div>
|
|
372
|
+
<div className="flex min-[420]:text-[13px] text-[12px] bold-text items-center">
|
|
373
|
+
<img
|
|
374
|
+
src={serviceItem.icons.rating}
|
|
375
|
+
alt="origin"
|
|
376
|
+
className={`w-[12px] h-[12px] mr-[4px] object-contain ${
|
|
377
|
+
isSoldOut ? "grayscale" : ""
|
|
378
|
+
}`}
|
|
379
|
+
/>
|
|
380
|
+
<span style={{ lineHeight: "normal" }}>
|
|
381
|
+
{getServiceStars(serviceItem)}
|
|
382
|
+
</span>
|
|
238
383
|
</div>
|
|
239
384
|
) : null}
|
|
240
385
|
</div>
|
|
241
386
|
{showLastSeats ? (
|
|
242
|
-
<div className="flex justify-end ">
|
|
387
|
+
<div className="flex justify-end -mt-[5px] -mb-[5px] items-center pt-[5px] pb-[5px] text-center ">
|
|
243
388
|
{serviceItem?.available_seats < 10 &&
|
|
244
389
|
serviceItem?.available_seats > 0 && (
|
|
245
|
-
<
|
|
390
|
+
<span
|
|
391
|
+
className="text-[12px] text-[red] mt-1 flex justify-end pt-[5px] pb-[5px] pl-[15px] pr-[15px] rounded-[8px] "
|
|
392
|
+
style={{
|
|
393
|
+
backgroundColor: colors.lastSeatBg,
|
|
394
|
+
color: colors.lastSeatText,
|
|
395
|
+
}}
|
|
396
|
+
>
|
|
246
397
|
¡ Últimos Asientos!
|
|
247
|
-
</
|
|
398
|
+
</span>
|
|
248
399
|
)}
|
|
249
400
|
</div>
|
|
250
401
|
) : null}
|
|
251
402
|
</div>
|
|
252
403
|
|
|
253
|
-
<
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
404
|
+
<div
|
|
405
|
+
className="flex justify-between gap-[5px] w-full"
|
|
406
|
+
onClick={onBookButtonPress}
|
|
407
|
+
>
|
|
408
|
+
{/* DATE AND TIME */}
|
|
409
|
+
<div
|
|
410
|
+
className="min-h-[2.5rem] flex flex-col justify-between gap-[4px] w-[50%] "
|
|
411
|
+
style={{ justifyContent: isCiva && "center" }}
|
|
412
|
+
>
|
|
413
|
+
<div
|
|
414
|
+
className={`flex items-center min-[420]:text-[13px] text-[12px] justify-between ${
|
|
415
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
416
|
+
}`}
|
|
417
|
+
>
|
|
418
|
+
<div className="flex items-center" style={{ flex: 1 }}>
|
|
419
|
+
<div>
|
|
420
|
+
{" "}
|
|
421
|
+
{orignLabel ? (
|
|
422
|
+
<div className="w-[60px]">{orignLabel}</div>
|
|
423
|
+
) : (
|
|
424
|
+
<div className="w-[14px] h-auto mr-[5px]">
|
|
425
|
+
<img
|
|
426
|
+
src={serviceItem.icons?.origin}
|
|
427
|
+
alt="origin"
|
|
428
|
+
className={`w-[14px] h-auto mr-[5px] ${
|
|
429
|
+
isSoldOut ? "grayscale" : ""
|
|
430
|
+
}`}
|
|
431
|
+
/>
|
|
432
|
+
</div>
|
|
433
|
+
)}
|
|
434
|
+
</div>
|
|
435
|
+
<div
|
|
436
|
+
className="flex items-center relative capitalize justify-between "
|
|
437
|
+
style={{ flex: 1 }}
|
|
438
|
+
>
|
|
439
|
+
<span className="cursor-pointer black-text">
|
|
440
|
+
{DateService.getServiceItemDate(serviceItem.travel_date)}
|
|
441
|
+
</span>
|
|
442
|
+
<div className="absolute left-[50%]">•</div>
|
|
443
|
+
<div className="font-[900] relative black-text">
|
|
444
|
+
{isLinatal ? (
|
|
445
|
+
<div>
|
|
446
|
+
<span>
|
|
447
|
+
{" "}
|
|
448
|
+
{cleanedDepTime}{" "}
|
|
449
|
+
<span>{hasPM ? "PM" : hasAM ? "AM" : ""}</span>
|
|
450
|
+
</span>
|
|
451
|
+
<span>
|
|
452
|
+
{serviceItem?.dep_time.includes("AM") ||
|
|
453
|
+
serviceItem?.dep_time.includes("PM")
|
|
454
|
+
? null
|
|
455
|
+
: DateService.ampmOnly(serviceItem.dep_time)}
|
|
456
|
+
</span>
|
|
457
|
+
</div>
|
|
458
|
+
) : (
|
|
459
|
+
DateService.formatTime(serviceItem.dep_time)
|
|
460
|
+
)}
|
|
461
|
+
</div>
|
|
462
|
+
</div>
|
|
463
|
+
</div>
|
|
464
|
+
</div>
|
|
465
|
+
{isCiva ? null : (
|
|
466
|
+
<div
|
|
467
|
+
className={`flex items-center min-[420]:text-[13px] text-[12px] justify-between ${
|
|
468
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
469
|
+
}`}
|
|
470
|
+
>
|
|
471
|
+
<div className="flex items-center" style={{ flex: 1 }}>
|
|
472
|
+
<div>
|
|
473
|
+
{" "}
|
|
474
|
+
{destinationLabel ? (
|
|
475
|
+
<div className="w-[60px]">{destinationLabel}</div>
|
|
476
|
+
) : (
|
|
477
|
+
<div className="w-[14px] h-auto mr-[5px]">
|
|
478
|
+
<img
|
|
479
|
+
src={serviceItem.icons?.destination}
|
|
480
|
+
alt="destination"
|
|
481
|
+
className={`w-[14px] h-auto mr-[5px] ${
|
|
482
|
+
isSoldOut ? "grayscale" : ""
|
|
483
|
+
}`}
|
|
484
|
+
/>
|
|
485
|
+
</div>
|
|
486
|
+
)}
|
|
487
|
+
</div>
|
|
488
|
+
<div
|
|
489
|
+
className="flex items-center relative capitalize justify-between "
|
|
490
|
+
style={{ flex: 1 }}
|
|
491
|
+
>
|
|
492
|
+
<span className="cursor-pointer black-text">
|
|
493
|
+
{DateService.getServiceItemDate(
|
|
494
|
+
serviceItem.arrival_date,
|
|
495
|
+
)}
|
|
496
|
+
</span>
|
|
497
|
+
<div className="absolute left-[50%]">•</div>
|
|
498
|
+
<div className="font-[900] relative black-text">
|
|
499
|
+
{DateService.formatTime(serviceItem.arr_time)}
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
</div>
|
|
503
|
+
</div>
|
|
504
|
+
)}
|
|
505
|
+
</div>
|
|
506
|
+
<div
|
|
507
|
+
style={{
|
|
508
|
+
width: "1px",
|
|
509
|
+
height: "2.5rem",
|
|
510
|
+
backgroundColor: "#ccc",
|
|
511
|
+
margin: "auto",
|
|
512
|
+
}}
|
|
513
|
+
></div>
|
|
514
|
+
{/* SEATS */}
|
|
515
|
+
<div
|
|
516
|
+
className="content-center"
|
|
517
|
+
style={{
|
|
518
|
+
width: isPeru ? "40%" : "40%",
|
|
519
|
+
}}
|
|
520
|
+
>
|
|
521
|
+
<div
|
|
522
|
+
className="flex flex-col justify-between h-[2.5rem] "
|
|
523
|
+
style={{
|
|
524
|
+
gap: isSoldOut ? "0px" : "5px",
|
|
525
|
+
justifyContent:
|
|
526
|
+
serviceItem.seat_types?.length > 2
|
|
527
|
+
? "space-between"
|
|
528
|
+
: "center",
|
|
529
|
+
}}
|
|
530
|
+
>
|
|
531
|
+
{removeDuplicateSeats
|
|
532
|
+
? seatTypesWithRemoveDuplicateSeats()
|
|
533
|
+
: seatTypes()}
|
|
534
|
+
|
|
535
|
+
{isSoldOut ? (
|
|
536
|
+
<div className="flex justify-end">
|
|
537
|
+
<span
|
|
538
|
+
className={
|
|
539
|
+
"min-[420]:text-[13px] text-[12px] text-[#ccc]"
|
|
540
|
+
}
|
|
541
|
+
>
|
|
542
|
+
Agotado
|
|
543
|
+
</span>
|
|
544
|
+
</div>
|
|
545
|
+
) : null}
|
|
546
|
+
</div>
|
|
547
|
+
</div>
|
|
548
|
+
</div>
|
|
549
|
+
<div className="bg-[#E6E6E6] -ml-[12px] -mr-[12px] mt-[10px] mb-[10px] h-[1px]"></div>
|
|
550
|
+
<div
|
|
551
|
+
className={`${"flex justify-between items-center items-center "}`}
|
|
552
|
+
>
|
|
553
|
+
{/* Rating */}
|
|
554
|
+
<div>
|
|
555
|
+
<div className="flex items-center ">
|
|
556
|
+
<div
|
|
557
|
+
className="flex items-center cursor-pointer "
|
|
558
|
+
style={{ color: isSoldOut ? "#bbb" : "text-[#464647]" }}
|
|
559
|
+
>
|
|
560
|
+
<span className="ml-[3px] min-[420]:text-[13px] text-[12px] bold-text">
|
|
561
|
+
{serviceItem.operator_details[2]}
|
|
562
|
+
</span>
|
|
563
|
+
</div>
|
|
564
|
+
</div>
|
|
565
|
+
</div>
|
|
566
|
+
|
|
567
|
+
<div
|
|
568
|
+
className="flex relative "
|
|
569
|
+
style={{ color: isSoldOut ? "#bbb" : "text-[#464647]" }}
|
|
570
|
+
>
|
|
571
|
+
<div
|
|
572
|
+
className={`w-[12px] h-auto mr-[2px] ${
|
|
573
|
+
isSoldOut ? "grayscale" : ""
|
|
574
|
+
}`}
|
|
575
|
+
>
|
|
576
|
+
{renderIcon("hours", "14px")}
|
|
577
|
+
</div>
|
|
578
|
+
|
|
579
|
+
<div
|
|
580
|
+
className={`cursor-default group min-[420]:text-[13px] text-[12px] ${
|
|
581
|
+
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
582
|
+
}`}
|
|
583
|
+
style={{ lineHeight: "normal" }}
|
|
584
|
+
>
|
|
585
|
+
{serviceItem.duration}hrs
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
|
|
589
|
+
<div style={{ opacity: isSoldOut ? 0.5 : 1 }}>{amenities()}</div>
|
|
590
|
+
|
|
591
|
+
{(serviceItem.is_change_ticket || isPetSeat) && (
|
|
592
|
+
<div
|
|
593
|
+
onClick={() => {
|
|
594
|
+
setShowDropdown(!showDropdown);
|
|
595
|
+
setAmenetiesAtomValue({
|
|
596
|
+
service: serviceItem,
|
|
597
|
+
showTopLabel: showTopLabel,
|
|
598
|
+
});
|
|
599
|
+
}}
|
|
600
|
+
className="flex items-center"
|
|
601
|
+
>
|
|
602
|
+
{serviceItem.pet_seat_info &&
|
|
603
|
+
Object.keys(serviceItem.pet_seat_info).length > 0 ? (
|
|
604
|
+
<div className="flex items-center">
|
|
605
|
+
<div className={`relative group cursor-default `}>
|
|
606
|
+
<div className="flex items-center">
|
|
607
|
+
<div
|
|
608
|
+
className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}
|
|
609
|
+
>
|
|
610
|
+
<LottiePlayer
|
|
611
|
+
animationData={serviceItem.icons.petFriendlyAnim}
|
|
612
|
+
width="20px"
|
|
613
|
+
height="20px"
|
|
614
|
+
/>
|
|
615
|
+
</div>
|
|
616
|
+
</div>
|
|
617
|
+
</div>
|
|
618
|
+
</div>
|
|
619
|
+
) : null}
|
|
620
|
+
|
|
621
|
+
{/* Flexible ticket */}
|
|
622
|
+
{serviceItem.is_change_ticket === true && (
|
|
623
|
+
<div className="flex items-center">
|
|
624
|
+
<div className="relative group cursor-default">
|
|
625
|
+
<div className="flex items-center">
|
|
626
|
+
<div
|
|
627
|
+
className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}
|
|
628
|
+
>
|
|
629
|
+
<LottiePlayer
|
|
630
|
+
animationData={serviceItem.icons.flexibleAnim}
|
|
631
|
+
width="20px"
|
|
632
|
+
height="20px"
|
|
633
|
+
/>
|
|
634
|
+
</div>
|
|
635
|
+
</div>
|
|
636
|
+
</div>
|
|
637
|
+
</div>
|
|
638
|
+
)}
|
|
639
|
+
|
|
640
|
+
{serviceItem?.is_tracking_enabled === true && (
|
|
641
|
+
<div className="flex items-center mr-[10px]">
|
|
642
|
+
<div
|
|
643
|
+
className={`h-auto mr-[4px] min-[420]:text-[13px] text-[11px] text-[#464647] ${
|
|
644
|
+
isSoldOut ? "grayscale" : ""
|
|
645
|
+
}`}
|
|
646
|
+
>
|
|
647
|
+
<LottiePlayer
|
|
648
|
+
animationData={serviceItem.icons.locationAnim}
|
|
649
|
+
width="20px"
|
|
650
|
+
height="20px"
|
|
651
|
+
/>
|
|
652
|
+
</div>
|
|
653
|
+
</div>
|
|
654
|
+
)}
|
|
655
|
+
|
|
656
|
+
{(serviceItem.is_change_ticket || isPetSeat) && (
|
|
657
|
+
<img src={serviceItem.icons.plus} alt="icon" width={11} />
|
|
658
|
+
)}
|
|
659
|
+
</div>
|
|
660
|
+
)}
|
|
661
|
+
</div>
|
|
307
662
|
</div>
|
|
308
663
|
|
|
309
664
|
{serviceItem?.offer_text && (
|
|
@@ -317,58 +672,21 @@ function ServiceItemMobile({
|
|
|
317
672
|
opacity: isSoldOut ? 0.5 : 1,
|
|
318
673
|
}}
|
|
319
674
|
>
|
|
320
|
-
{/* <div className="flex justify-between items-center w-full">
|
|
321
|
-
<div className="flex items-center">
|
|
322
|
-
<LottiePlayer
|
|
323
|
-
animationData={serviceItem.icons.bombAnim}
|
|
324
|
-
width="18px"
|
|
325
|
-
height="18px"
|
|
326
|
-
/>
|
|
327
|
-
<span className="bold-text ml-[8px]">
|
|
328
|
-
{" "}
|
|
329
|
-
{serviceItem?.offer_text || ""}
|
|
330
|
-
</span>
|
|
331
|
-
</div>
|
|
332
|
-
<div>
|
|
333
|
-
Termina en
|
|
334
|
-
<span
|
|
335
|
-
className="bold-text text-end"
|
|
336
|
-
ref={startCountdown}
|
|
337
|
-
style={{
|
|
338
|
-
fontVariantNumeric: "tabular-nums",
|
|
339
|
-
display: "inline-block",
|
|
340
|
-
// minWidth: "70px",
|
|
341
|
-
}}
|
|
342
|
-
/>
|
|
343
|
-
</div>
|
|
344
|
-
</div> */}
|
|
345
675
|
<LottiePlayer
|
|
346
676
|
animationData={serviceItem.icons.promoAnim}
|
|
347
677
|
width="18px"
|
|
348
678
|
height="18px"
|
|
349
679
|
/>
|
|
350
|
-
<
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
</span>{" "}
|
|
354
|
-
| Termina en
|
|
355
|
-
<span
|
|
356
|
-
className="bold-text"
|
|
357
|
-
ref={startCountdown}
|
|
358
|
-
style={{
|
|
359
|
-
fontVariantNumeric: "tabular-nums",
|
|
360
|
-
display: "inline-block",
|
|
361
|
-
// minWidth: "70px",
|
|
362
|
-
}}
|
|
363
|
-
/>
|
|
364
|
-
</div>
|
|
680
|
+
<span className="ml-[10px] text-[#fff] min-[380px]:text-[11px] text-[10px]">
|
|
681
|
+
{serviceItem?.offer_text}
|
|
682
|
+
</span>
|
|
365
683
|
</div>
|
|
366
684
|
)}
|
|
367
685
|
|
|
368
|
-
<div className="absolute -top-[14px] left-0 w-full flex items-center justify-end gap-[12px] pr-[
|
|
686
|
+
<div className="absolute -top-[14px] left-0 w-full flex items-center justify-end gap-[12px] pr-[20px] z-10 ">
|
|
369
687
|
{showTopLabel && (
|
|
370
688
|
<div
|
|
371
|
-
className={`flex items-center gap-[2px] py-[
|
|
689
|
+
className={`flex items-center gap-[2px] py-[5px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
372
690
|
style={{
|
|
373
691
|
backgroundColor: isSoldOut ? "#ccc" : colors.ratingBottomColor,
|
|
374
692
|
}}
|
|
@@ -389,6 +707,7 @@ function ServiceItemMobile({
|
|
|
389
707
|
</div>
|
|
390
708
|
</div>
|
|
391
709
|
)}
|
|
710
|
+
|
|
392
711
|
{isConexion && (
|
|
393
712
|
<div
|
|
394
713
|
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[11px] z-20 ${
|
|
@@ -403,7 +722,22 @@ function ServiceItemMobile({
|
|
|
403
722
|
<div>Conexión</div>
|
|
404
723
|
</div>
|
|
405
724
|
)}
|
|
406
|
-
|
|
725
|
+
{serviceItem?.is_direct_trip && (
|
|
726
|
+
<div
|
|
727
|
+
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
728
|
+
style={{
|
|
729
|
+
backgroundColor: isSoldOut ? "#ddd" : colors.tooltipBgColor,
|
|
730
|
+
color: isSoldOut ? "#bbb" : colors.directoColor,
|
|
731
|
+
}}
|
|
732
|
+
>
|
|
733
|
+
<LottiePlayer
|
|
734
|
+
animationData={serviceItem.icons.directoAnim}
|
|
735
|
+
width="16px"
|
|
736
|
+
height="16px"
|
|
737
|
+
/>
|
|
738
|
+
<div className="ml-[5px]">Directo</div>
|
|
739
|
+
</div>
|
|
740
|
+
)}
|
|
407
741
|
{serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
|
|
408
742
|
<div
|
|
409
743
|
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
@@ -421,23 +755,6 @@ function ServiceItemMobile({
|
|
|
421
755
|
)}
|
|
422
756
|
</div>
|
|
423
757
|
</div>
|
|
424
|
-
|
|
425
|
-
{/* 🔹 EXPANDABLE DROPDOWN (below the card) */}
|
|
426
|
-
<div
|
|
427
|
-
style={{
|
|
428
|
-
display: "grid",
|
|
429
|
-
gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
|
|
430
|
-
opacity: isItemExpanded ? 1 : 0,
|
|
431
|
-
transition:
|
|
432
|
-
"grid-template-rows 0.3s ease-in-out, opacity 0.25s ease-in-out",
|
|
433
|
-
position: "relative",
|
|
434
|
-
zIndex: -1,
|
|
435
|
-
}}
|
|
436
|
-
>
|
|
437
|
-
<div style={{ overflow: "hidden", minHeight: 0, marginTop: "-10px" }}>
|
|
438
|
-
<ExpandedDropdownMobile serviceItem={serviceItem} />
|
|
439
|
-
</div>
|
|
440
|
-
</div>
|
|
441
758
|
</div>
|
|
442
759
|
);
|
|
443
760
|
}
|