kupos-ui-components-lib 9.3.2 → 9.3.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/dist/assets/images/anims/service_list/60_percent_anim.json +1 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.js +18 -84
- package/dist/components/ServiceItem/ServiceItemMobile.js +27 -97
- package/dist/components/ServiceItem/types.d.ts +2 -0
- package/dist/styles.css +37 -0
- package/dist/ui/SeatSection/SeatSection.js +17 -2
- package/dist/ui/ServiceBadges/ServiceBadges.d.ts +17 -0
- package/dist/ui/ServiceBadges/ServiceBadges.js +33 -0
- 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 +8 -4
- package/dist/ui/mobileweb/ServiceBadgesMobile.d.ts +17 -0
- package/dist/ui/mobileweb/ServiceBadgesMobile.js +35 -0
- package/dist/utils/CommonService.d.ts +7 -0
- package/dist/utils/CommonService.js +61 -0
- package/package.json +1 -1
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +35 -131
- package/src/components/ServiceItem/ServiceItemMobile.tsx +57 -165
- package/src/components/ServiceItem/types.ts +2 -0
- package/src/styles.css +10 -0
- package/src/ui/SeatSection/SeatSection.tsx +24 -2
- package/src/ui/ServiceBadges/ServiceBadges.tsx +92 -0
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +3 -0
- package/src/ui/mobileweb/SeatSectionMobile.tsx +12 -3
- package/src/ui/mobileweb/ServiceBadgesMobile.tsx +92 -0
- package/src/utils/CommonService.ts +86 -0
|
@@ -8,6 +8,7 @@ import BottomAmenitiesMobile from "../../ui/mobileweb/BottomAmenitiesMobile";
|
|
|
8
8
|
import SeatSectionMobile from "../../ui/mobileweb/SeatSectionMobile";
|
|
9
9
|
import DateTimeSectionMobile from "../../ui/mobileweb/DateTimeSectionMobile";
|
|
10
10
|
import ExpandedDropdownMobile from "../../ui/mobileweb/ExpandedDropdownMobile";
|
|
11
|
+
import ServiceBadgesMobile from "../../ui/mobileweb/ServiceBadgesMobile";
|
|
11
12
|
|
|
12
13
|
const SEAT_EXCEPTIONS = ["Asiento mascota"];
|
|
13
14
|
|
|
@@ -62,58 +63,6 @@ function ServiceItemMobile({
|
|
|
62
63
|
}
|
|
63
64
|
: {};
|
|
64
65
|
|
|
65
|
-
const startViewerCount = (node: HTMLSpanElement | null) => {
|
|
66
|
-
if (!node || !viewersConfig) return;
|
|
67
|
-
|
|
68
|
-
const prevId = node.dataset.viewerId;
|
|
69
|
-
if (prevId) clearInterval(Number(prevId));
|
|
70
|
-
|
|
71
|
-
const { min, max, interval = 5000 } = viewersConfig;
|
|
72
|
-
const clamp = (v: number) => Math.min(max, Math.max(min, v));
|
|
73
|
-
const initialValue = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
74
|
-
|
|
75
|
-
node.textContent = String(initialValue);
|
|
76
|
-
|
|
77
|
-
const id = setInterval(() => {
|
|
78
|
-
const current = Number(node.textContent) || initialValue;
|
|
79
|
-
const delta = Math.ceil(current * 0.2);
|
|
80
|
-
const next =
|
|
81
|
-
current + Math.floor(Math.random() * (2 * delta + 1)) - delta;
|
|
82
|
-
node.textContent = String(clamp(Math.round(next)));
|
|
83
|
-
}, interval);
|
|
84
|
-
|
|
85
|
-
node.dataset.viewerId = String(id);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const countdownSeconds = 599;
|
|
89
|
-
|
|
90
|
-
const startCountdown = (node: HTMLSpanElement | null) => {
|
|
91
|
-
if (!node) return;
|
|
92
|
-
|
|
93
|
-
const prevId = node.dataset.countdownId;
|
|
94
|
-
if (prevId) clearInterval(Number(prevId));
|
|
95
|
-
|
|
96
|
-
let remaining = countdownSeconds;
|
|
97
|
-
|
|
98
|
-
const formatTime = (totalSecs: number) => {
|
|
99
|
-
const m = Math.floor(totalSecs / 60);
|
|
100
|
-
const s = totalSecs % 60;
|
|
101
|
-
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
node.textContent = formatTime(remaining);
|
|
105
|
-
|
|
106
|
-
const id = setInterval(() => {
|
|
107
|
-
remaining -= 1;
|
|
108
|
-
if (remaining <= 0) {
|
|
109
|
-
remaining = countdownSeconds;
|
|
110
|
-
}
|
|
111
|
-
node.textContent = formatTime(remaining);
|
|
112
|
-
}, 1000);
|
|
113
|
-
|
|
114
|
-
node.dataset.countdownId = String(id);
|
|
115
|
-
};
|
|
116
|
-
|
|
117
66
|
const labelId =
|
|
118
67
|
typeof serviceItem.boarding_stages === "string"
|
|
119
68
|
? serviceItem.boarding_stages.split("|")[0]
|
|
@@ -207,7 +156,10 @@ function ServiceItemMobile({
|
|
|
207
156
|
<div style={{ padding: "12px 12px 8px 12px" }}>
|
|
208
157
|
{/* Header with operator info and favorite */}
|
|
209
158
|
<div className="flex justify-between items-center mb-[10px]">
|
|
210
|
-
<div
|
|
159
|
+
<div
|
|
160
|
+
className="flex items-center justify-between"
|
|
161
|
+
style={{ marginBottom: serviceItem?.offer_text ? "10px" : "" }}
|
|
162
|
+
>
|
|
211
163
|
<div className="w-[120px] overflow-y-hidden">
|
|
212
164
|
<img
|
|
213
165
|
src={serviceItem.operator_details[0]}
|
|
@@ -277,6 +229,7 @@ function ServiceItemMobile({
|
|
|
277
229
|
arrTime={serviceItem.arr_time}
|
|
278
230
|
seatTypes={serviceItem.seat_types}
|
|
279
231
|
seatPriceColor={colors.seatPriceColor}
|
|
232
|
+
tooltipBgColor={colors.tooltipBgColor}
|
|
280
233
|
currencySign={currencySign}
|
|
281
234
|
availableSeats={serviceItem.available_seats}
|
|
282
235
|
removeDuplicateSeats={removeDuplicateSeats}
|
|
@@ -305,13 +258,6 @@ function ServiceItemMobile({
|
|
|
305
258
|
setShowDropdown={() =>
|
|
306
259
|
setIsExpanded(isItemExpanded ? null : serviceItem.id)
|
|
307
260
|
}
|
|
308
|
-
// onDropdownToggle={() => {
|
|
309
|
-
// setShowDropdown(!showDropdown);
|
|
310
|
-
// setAmenetiesAtomValue({
|
|
311
|
-
// service: serviceItem,
|
|
312
|
-
// showTopLabel: showTopLabel,
|
|
313
|
-
// });
|
|
314
|
-
// }}
|
|
315
261
|
onDropdownToggle={() => {
|
|
316
262
|
setIsExpanded(isItemExpanded ? null : serviceItem.id);
|
|
317
263
|
}}
|
|
@@ -319,85 +265,14 @@ function ServiceItemMobile({
|
|
|
319
265
|
/>
|
|
320
266
|
</div>
|
|
321
267
|
|
|
322
|
-
<
|
|
323
|
-
{showTopLabel
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}}
|
|
331
|
-
>
|
|
332
|
-
<div className={isSoldOut ? "grayscale" : ""}>
|
|
333
|
-
{renderIcon("specialDeparture", "12px")}
|
|
334
|
-
{/* <LottiePlayer
|
|
335
|
-
animationData={serviceItem.icons.priorityStageAnim}
|
|
336
|
-
width="18px"
|
|
337
|
-
height="18px"
|
|
338
|
-
/> */}
|
|
339
|
-
</div>
|
|
340
|
-
<div
|
|
341
|
-
style={{
|
|
342
|
-
color: colors.topLabelColor,
|
|
343
|
-
}}
|
|
344
|
-
>
|
|
345
|
-
{showTopLabel}
|
|
346
|
-
</div>
|
|
347
|
-
</div>
|
|
348
|
-
)}
|
|
349
|
-
{serviceItem?.is_direct_trip && (
|
|
350
|
-
<div
|
|
351
|
-
className={`flex items-center gap-[2px] py-[5px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
352
|
-
style={{
|
|
353
|
-
backgroundColor: "#fff",
|
|
354
|
-
border: `1px solid ${colors.topLabelColor}`,
|
|
355
|
-
color: colors.topLabelColor,
|
|
356
|
-
}}
|
|
357
|
-
>
|
|
358
|
-
{renderIcon("directo", "12px")}
|
|
359
|
-
{/* <LottiePlayer
|
|
360
|
-
animationData={serviceItem.icons.directoAnim}
|
|
361
|
-
width="16px"
|
|
362
|
-
height="16px"
|
|
363
|
-
/> */}
|
|
364
|
-
<div className="ml-[5px]">Directo</div>
|
|
365
|
-
</div>
|
|
366
|
-
)}
|
|
367
|
-
{isConexion && (
|
|
368
|
-
<div
|
|
369
|
-
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[11px] z-20 `}
|
|
370
|
-
style={{
|
|
371
|
-
backgroundColor: "#fff",
|
|
372
|
-
border: `1px solid ${colors.topLabelColor}`,
|
|
373
|
-
color: colors.topLabelColor,
|
|
374
|
-
}}
|
|
375
|
-
>
|
|
376
|
-
{renderIcon("airportIcon", "14px")}
|
|
377
|
-
|
|
378
|
-
<div>Conexión</div>
|
|
379
|
-
</div>
|
|
380
|
-
)}
|
|
381
|
-
|
|
382
|
-
{serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
|
|
383
|
-
<div
|
|
384
|
-
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
385
|
-
style={{
|
|
386
|
-
backgroundColor: "#fff",
|
|
387
|
-
border: `1px solid ${colors.topLabelColor}`,
|
|
388
|
-
color: colors.topLabelColor,
|
|
389
|
-
}}
|
|
390
|
-
>
|
|
391
|
-
{renderIcon("directo", "12px")}
|
|
392
|
-
{/* <LottiePlayer
|
|
393
|
-
animationData={serviceItem.icons.directoAnim}
|
|
394
|
-
width="20px"
|
|
395
|
-
height="20px"
|
|
396
|
-
/> */}
|
|
397
|
-
<div>{"Tren Express"}</div>
|
|
398
|
-
</div>
|
|
399
|
-
)}
|
|
400
|
-
</div>
|
|
268
|
+
<ServiceBadgesMobile
|
|
269
|
+
showTopLabel={showTopLabel}
|
|
270
|
+
isSoldOut={isSoldOut}
|
|
271
|
+
colors={colors}
|
|
272
|
+
renderIcon={renderIcon}
|
|
273
|
+
serviceItem={serviceItem}
|
|
274
|
+
isConexion={isConexion}
|
|
275
|
+
/>
|
|
401
276
|
</div>
|
|
402
277
|
|
|
403
278
|
{/* 🔹 EXPANDABLE DROPDOWN (below the card) */}
|
|
@@ -415,15 +290,15 @@ function ServiceItemMobile({
|
|
|
415
290
|
className="flex flex-col gap-[8px] text-[12px] min-[420px]:text-[12px] text-[#464647]"
|
|
416
291
|
style={{ lineHeight: 1.6 }}
|
|
417
292
|
>
|
|
418
|
-
<div className="flex justify-between items-
|
|
293
|
+
<div className="flex justify-between items-start">
|
|
419
294
|
<div
|
|
420
295
|
className={`flex ${isLongOfferText ? "items-start" : "items-center"}`}
|
|
421
296
|
>
|
|
422
297
|
<div className={isLongOfferText ? "mt-[2px]" : ""}>
|
|
423
298
|
<LottiePlayer
|
|
424
299
|
animationData={serviceItem.icons.bombAnim}
|
|
425
|
-
width="
|
|
426
|
-
height="
|
|
300
|
+
width="14px"
|
|
301
|
+
height="14px"
|
|
427
302
|
/>
|
|
428
303
|
</div>
|
|
429
304
|
<div
|
|
@@ -441,7 +316,7 @@ function ServiceItemMobile({
|
|
|
441
316
|
Termina en
|
|
442
317
|
<span
|
|
443
318
|
className="bold-text"
|
|
444
|
-
ref={startCountdown}
|
|
319
|
+
ref={(node) => commonService.startCountdown(node, 599)}
|
|
445
320
|
style={{
|
|
446
321
|
fontVariantNumeric: "tabular-nums",
|
|
447
322
|
display: "inline-block",
|
|
@@ -451,32 +326,49 @@ function ServiceItemMobile({
|
|
|
451
326
|
</div>
|
|
452
327
|
</div>
|
|
453
328
|
<div
|
|
454
|
-
className="flex items-
|
|
329
|
+
className="flex flex-col items-end"
|
|
455
330
|
style={{
|
|
456
331
|
color: "#fff",
|
|
457
332
|
}}
|
|
458
333
|
>
|
|
459
|
-
<div className="
|
|
460
|
-
|
|
461
|
-
<LottiePlayer
|
|
462
|
-
animationData={serviceItem.icons.dotAnimation}
|
|
463
|
-
width="12px"
|
|
464
|
-
height="12px"
|
|
465
|
-
/>
|
|
466
|
-
</div>
|
|
467
|
-
<span className="flex-1" style={{ lineHeight: 1.4 }}>
|
|
468
|
-
<span
|
|
469
|
-
className="bold-text"
|
|
470
|
-
ref={startViewerCount}
|
|
471
|
-
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
472
|
-
/>{" "}
|
|
473
|
-
<span className="bold-text">personas</span>{" "}
|
|
474
|
-
<span>
|
|
334
|
+
<div className="flex items-center">
|
|
335
|
+
<div className="mr-[4px]">
|
|
475
336
|
{" "}
|
|
476
|
-
|
|
477
|
-
|
|
337
|
+
<LottiePlayer
|
|
338
|
+
animationData={serviceItem.icons.dotAnimation}
|
|
339
|
+
width="12px"
|
|
340
|
+
height="12px"
|
|
341
|
+
/>
|
|
342
|
+
</div>
|
|
343
|
+
<span className="flex-1" style={{ lineHeight: 1.4 }}>
|
|
344
|
+
<span
|
|
345
|
+
className="bold-text"
|
|
346
|
+
ref={(node) =>
|
|
347
|
+
commonService.startViewerCount(node, viewersConfig)
|
|
348
|
+
}
|
|
349
|
+
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
350
|
+
/>{" "}
|
|
351
|
+
<span className="bold-text">personas</span>{" "}
|
|
352
|
+
<span>
|
|
353
|
+
{" "}
|
|
354
|
+
{/* {viewersConfig.label || " están viendo este viaje"} */}
|
|
355
|
+
viendo
|
|
356
|
+
</span>
|
|
478
357
|
</span>
|
|
479
|
-
</
|
|
358
|
+
</div>
|
|
359
|
+
<div className="flex items-center">
|
|
360
|
+
<span className="whitespace-nowrap">
|
|
361
|
+
⚡ Quedan pocos{" "}
|
|
362
|
+
<span
|
|
363
|
+
className="bold-text"
|
|
364
|
+
ref={(node) =>
|
|
365
|
+
commonService.startComprandoCount(node, 4, 16)
|
|
366
|
+
}
|
|
367
|
+
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
368
|
+
/>{" "}
|
|
369
|
+
comprando
|
|
370
|
+
</span>
|
|
371
|
+
</div>
|
|
480
372
|
</div>
|
|
481
373
|
</div>
|
|
482
374
|
{/* <div className="flex flex-col gap-[4px]">
|
|
@@ -505,7 +397,7 @@ function ServiceItemMobile({
|
|
|
505
397
|
Termina en
|
|
506
398
|
<span
|
|
507
399
|
className="bold-text"
|
|
508
|
-
ref={startCountdown}
|
|
400
|
+
ref={(node) => commonService.startCountdown(node, 599)}
|
|
509
401
|
style={{
|
|
510
402
|
fontVariantNumeric: "tabular-nums",
|
|
511
403
|
display: "inline-block",
|
|
@@ -524,7 +416,7 @@ function ServiceItemMobile({
|
|
|
524
416
|
<span className="flex-1" style={{ lineHeight: 1.4 }}>
|
|
525
417
|
<span
|
|
526
418
|
className="bold-text"
|
|
527
|
-
ref={startViewerCount}
|
|
419
|
+
ref={(node) => commonService.startViewerCount(node, viewersConfig)}
|
|
528
420
|
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
529
421
|
/>{" "}
|
|
530
422
|
<span className="bold-text">personas</span>{" "}
|
|
@@ -149,6 +149,8 @@ export interface ServiceItemProps {
|
|
|
149
149
|
bottomStripColor?: string;
|
|
150
150
|
directoColor?: string;
|
|
151
151
|
seatPriceColor?: string;
|
|
152
|
+
rightGradiantColor?: string;
|
|
153
|
+
leftGradiantColor?: string;
|
|
152
154
|
};
|
|
153
155
|
cityOrigin?: { value: number; label: string };
|
|
154
156
|
cityDestination?: { value: number; label: string };
|
package/src/styles.css
CHANGED
|
@@ -240,7 +240,12 @@ function SeatSection({
|
|
|
240
240
|
style={{ top: "-22px", right: "30px" }}
|
|
241
241
|
>
|
|
242
242
|
{discountValue != null && (
|
|
243
|
-
<span
|
|
243
|
+
<span
|
|
244
|
+
className="rounded-[100px] bg-[#ff5964] px-[6px] text-[12px] bold-text leading-[20px] text-white"
|
|
245
|
+
style={{
|
|
246
|
+
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
247
|
+
}}
|
|
248
|
+
>
|
|
244
249
|
{discountValue}% OFF
|
|
245
250
|
</span>
|
|
246
251
|
)}
|
|
@@ -250,8 +255,25 @@ function SeatSection({
|
|
|
250
255
|
className="col-start-2 row-start-2 flex items-center justify-center "
|
|
251
256
|
style={{ textAlign: "center" }}
|
|
252
257
|
>
|
|
253
|
-
<span
|
|
258
|
+
<span
|
|
259
|
+
className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative"
|
|
260
|
+
style={{
|
|
261
|
+
position: "relative",
|
|
262
|
+
}}
|
|
263
|
+
>
|
|
254
264
|
{formatPrice(discountSeat.originalPrice)}
|
|
265
|
+
<span
|
|
266
|
+
style={{
|
|
267
|
+
position: "absolute",
|
|
268
|
+
left: "-2px",
|
|
269
|
+
top: "50%",
|
|
270
|
+
width: "calc(100% + 4px)",
|
|
271
|
+
height: "1px",
|
|
272
|
+
backgroundColor: "#9f9f9f",
|
|
273
|
+
transform: "rotate(-10deg)",
|
|
274
|
+
transformOrigin: "center",
|
|
275
|
+
}}
|
|
276
|
+
/>
|
|
255
277
|
</span>
|
|
256
278
|
</div>
|
|
257
279
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface ServiceBadgesProps {
|
|
4
|
+
showTopLabel?: string;
|
|
5
|
+
isSoldOut: boolean;
|
|
6
|
+
colors: any;
|
|
7
|
+
renderIcon: (iconKey: string, size?: string) => React.ReactNode;
|
|
8
|
+
translation?: {
|
|
9
|
+
directService?: string;
|
|
10
|
+
};
|
|
11
|
+
serviceItem: {
|
|
12
|
+
is_transpordo?: boolean;
|
|
13
|
+
is_direct_trip?: boolean;
|
|
14
|
+
train_type_label?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ServiceBadges: React.FC<ServiceBadgesProps> = ({
|
|
19
|
+
showTopLabel,
|
|
20
|
+
isSoldOut,
|
|
21
|
+
colors,
|
|
22
|
+
renderIcon,
|
|
23
|
+
translation,
|
|
24
|
+
serviceItem,
|
|
25
|
+
}) => {
|
|
26
|
+
return (
|
|
27
|
+
<div className="absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[22px] z-10">
|
|
28
|
+
{showTopLabel && (
|
|
29
|
+
<div
|
|
30
|
+
className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-10`}
|
|
31
|
+
style={{
|
|
32
|
+
backgroundColor: "#fff",
|
|
33
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
34
|
+
color: colors.topLabelColor,
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<div className={isSoldOut ? "grayscale" : ""}>
|
|
38
|
+
{renderIcon("specialDeparture", "12px")}
|
|
39
|
+
</div>
|
|
40
|
+
<div
|
|
41
|
+
className={
|
|
42
|
+
isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
|
|
43
|
+
}
|
|
44
|
+
>
|
|
45
|
+
{showTopLabel}
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
49
|
+
{serviceItem?.is_transpordo && (
|
|
50
|
+
<div
|
|
51
|
+
className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
52
|
+
style={{
|
|
53
|
+
backgroundColor: "#fff",
|
|
54
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
55
|
+
color: colors.topLabelColor,
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
{renderIcon("connectingServiceIcon", "12px")}
|
|
59
|
+
<div>{"Conexión"}</div>
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
{serviceItem?.is_direct_trip && (
|
|
63
|
+
<div
|
|
64
|
+
className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
65
|
+
style={{
|
|
66
|
+
backgroundColor: "#fff",
|
|
67
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
68
|
+
color: colors.topLabelColor,
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
{renderIcon("directo", "12px")}
|
|
72
|
+
<div>{translation?.directService}</div>
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
{serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
|
|
76
|
+
<div
|
|
77
|
+
className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
78
|
+
style={{
|
|
79
|
+
backgroundColor: "#fff",
|
|
80
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
81
|
+
color: colors.topLabelColor,
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
{renderIcon("directo", "12px")}
|
|
85
|
+
<div>{"Tren Express"}</div>
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default ServiceBadges;
|
|
@@ -22,6 +22,7 @@ interface DateTimeSectionMobileProps {
|
|
|
22
22
|
availableSeats: number;
|
|
23
23
|
removeDuplicateSeats?: boolean;
|
|
24
24
|
serviceItem?: any;
|
|
25
|
+
tooltipBgColor?: string;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const pad = (n: number) => (n < 10 ? "0" + n : String(n));
|
|
@@ -119,6 +120,7 @@ function DateTimeSectionMobile({
|
|
|
119
120
|
availableSeats,
|
|
120
121
|
removeDuplicateSeats,
|
|
121
122
|
serviceItem,
|
|
123
|
+
tooltipBgColor,
|
|
122
124
|
}: DateTimeSectionMobileProps): React.ReactElement {
|
|
123
125
|
const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
|
|
124
126
|
|
|
@@ -187,6 +189,7 @@ function DateTimeSectionMobile({
|
|
|
187
189
|
availableSeats={availableSeats}
|
|
188
190
|
removeDuplicateSeats={removeDuplicateSeats}
|
|
189
191
|
serviceItem={serviceItem}
|
|
192
|
+
tooltipBgColor={tooltipBgColor}
|
|
190
193
|
/>
|
|
191
194
|
</div>
|
|
192
195
|
);
|
|
@@ -28,6 +28,7 @@ interface SeatSectionMobileProps {
|
|
|
28
28
|
availableSeats: number;
|
|
29
29
|
removeDuplicateSeats?: boolean;
|
|
30
30
|
serviceItem?: any;
|
|
31
|
+
tooltipBgColor?: string;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
interface SeatRowProps {
|
|
@@ -112,6 +113,7 @@ function SeatSectionMobile({
|
|
|
112
113
|
availableSeats,
|
|
113
114
|
removeDuplicateSeats,
|
|
114
115
|
serviceItem,
|
|
116
|
+
tooltipBgColor,
|
|
115
117
|
}: SeatSectionMobileProps): React.ReactElement {
|
|
116
118
|
const hasMultipleTypes = (seatTypesData?.length ?? 0) > 2;
|
|
117
119
|
|
|
@@ -249,12 +251,19 @@ function SeatSectionMobile({
|
|
|
249
251
|
return (
|
|
250
252
|
<div className="content-center relative" style={{ width: "40%" }}>
|
|
251
253
|
{hasDiscount && discountSeat ? (
|
|
252
|
-
<div className="relative grid grid-cols-[auto_auto] justify-between gap-x-[8px]">
|
|
254
|
+
<div className="relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] ">
|
|
253
255
|
{discountValue != null && (
|
|
254
|
-
<div
|
|
256
|
+
<div
|
|
257
|
+
className="absolute -top-[18px] right-[0px]"
|
|
258
|
+
style={{
|
|
259
|
+
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
260
|
+
}}
|
|
261
|
+
>
|
|
255
262
|
<span
|
|
256
263
|
className="rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]"
|
|
257
|
-
style={{
|
|
264
|
+
style={{
|
|
265
|
+
backgroundColor: tooltipBgColor,
|
|
266
|
+
}}
|
|
258
267
|
>
|
|
259
268
|
{discountValue}% OFF
|
|
260
269
|
</span>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface ServiceBadgesMobileProps {
|
|
4
|
+
showTopLabel?: string;
|
|
5
|
+
isSoldOut: boolean;
|
|
6
|
+
colors: any;
|
|
7
|
+
renderIcon: (iconKey: string, size?: string) => React.ReactNode;
|
|
8
|
+
translation?: {
|
|
9
|
+
directService?: string;
|
|
10
|
+
};
|
|
11
|
+
serviceItem: {
|
|
12
|
+
is_direct_trip?: boolean;
|
|
13
|
+
train_type_label?: string;
|
|
14
|
+
};
|
|
15
|
+
isConexion?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ServiceBadgesMobile: React.FC<ServiceBadgesMobileProps> = ({
|
|
19
|
+
showTopLabel,
|
|
20
|
+
isSoldOut,
|
|
21
|
+
colors,
|
|
22
|
+
renderIcon,
|
|
23
|
+
serviceItem,
|
|
24
|
+
isConexion,
|
|
25
|
+
}) => {
|
|
26
|
+
return (
|
|
27
|
+
<div className="absolute -top-[9px] left-0 w-full flex items-center justify-end gap-[12px] pr-[20px] z-10">
|
|
28
|
+
{showTopLabel && (
|
|
29
|
+
<div
|
|
30
|
+
className={`flex items-center gap-[2px] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20`}
|
|
31
|
+
style={{
|
|
32
|
+
backgroundColor: "#fff",
|
|
33
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
34
|
+
color: colors.topLabelColor,
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<div className={isSoldOut ? "grayscale" : ""}>
|
|
38
|
+
{renderIcon("specialDeparture", "12px")}
|
|
39
|
+
</div>
|
|
40
|
+
<div
|
|
41
|
+
style={{
|
|
42
|
+
color: colors.topLabelColor,
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
{showTopLabel}
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
)}
|
|
49
|
+
{serviceItem?.is_direct_trip && (
|
|
50
|
+
<div
|
|
51
|
+
className={`flex items-center gap-[2px] py-[5px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20`}
|
|
52
|
+
style={{
|
|
53
|
+
backgroundColor: "#fff",
|
|
54
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
55
|
+
color: colors.topLabelColor,
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
{renderIcon("directo", "12px")}
|
|
59
|
+
<div className="ml-[5px]">Directo</div>
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
{isConexion && (
|
|
63
|
+
<div
|
|
64
|
+
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[11px] z-20`}
|
|
65
|
+
style={{
|
|
66
|
+
backgroundColor: "#fff",
|
|
67
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
68
|
+
color: colors.topLabelColor,
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
{renderIcon("airportIcon", "14px")}
|
|
72
|
+
<div>Conexión</div>
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
{serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
|
|
76
|
+
<div
|
|
77
|
+
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20`}
|
|
78
|
+
style={{
|
|
79
|
+
backgroundColor: "#fff",
|
|
80
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
81
|
+
color: colors.topLabelColor,
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
{renderIcon("directo", "12px")}
|
|
85
|
+
<div>{"Tren Express"}</div>
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default ServiceBadgesMobile;
|