kupos-ui-components-lib 9.7.0 → 9.7.2
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/KuposUIComponent.d.ts +3 -0
- package/dist/assets/images/anims/service_list/users_anim.json +1 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +10 -2
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +16 -7
- package/dist/components/ServiceItem/mobileTypes.d.ts +27 -0
- package/dist/components/ServiceItem/types.d.ts +10 -0
- package/dist/styles.css +62 -14
- package/dist/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.d.ts +18 -0
- package/dist/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.js +233 -0
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.d.ts +7 -2
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +109 -92
- package/dist/ui/SeatSection/SeatSection.js +1 -1
- package/dist/utils/CommonService.js +11 -1
- package/package.json +1 -1
- package/src/KuposUIComponent.tsx +3 -0
- package/src/assets/images/anims/service_list/users_anim.json +1 -0
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +23 -1
- package/src/components/ServiceItem/ServiceItemMobile.tsx +331 -286
- package/src/components/ServiceItem/mobileTypes.ts +22 -0
- package/src/components/ServiceItem/types.ts +11 -1
- package/src/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.tsx +790 -0
- package/src/ui/FeatureServiceUI/FeatureServiceUi.tsx +181 -253
- package/src/ui/SeatSection/SeatSection.tsx +1 -1
- package/src/utils/CommonService.ts +13 -1
|
@@ -23,206 +23,68 @@ const HARDCODED_OPERATORS = [
|
|
|
23
23
|
},
|
|
24
24
|
];
|
|
25
25
|
|
|
26
|
-
const HARDCODED_COUNTDOWN = "09:55";
|
|
27
|
-
|
|
28
|
-
const HOW_IT_WORKS_STEPS = [
|
|
29
|
-
{
|
|
30
|
-
icon: "flexible",
|
|
31
|
-
name: "1. Salida flexible",
|
|
32
|
-
text: "Viajas en un horario entre las 07:00 y las 10:00 AM del día elegido.",
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
icon: "bus",
|
|
36
|
-
name: "2. Empresa asignada",
|
|
37
|
-
text: "Una de las empresas disponibles confirma tu viaje una vez pagado.",
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
icon: "price",
|
|
41
|
-
name: "3. Precio garantizado",
|
|
42
|
-
text: "Al seleccionar este servicio aseguras el precio reducido.",
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
icon: "ticket",
|
|
46
|
-
name: "4. ¡Listo!",
|
|
47
|
-
text: "Recibe todos los detalles de tu viaje al instante tras la compra.",
|
|
48
|
-
},
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
const FeatureStepIcon = ({ icon }) => {
|
|
52
|
-
const iconClassName = "h-[30px] w-[30px] text-[#171717]";
|
|
53
|
-
|
|
54
|
-
switch (icon) {
|
|
55
|
-
case "flexible":
|
|
56
|
-
return (
|
|
57
|
-
<svg
|
|
58
|
-
className={iconClassName}
|
|
59
|
-
viewBox="0 0 40 40"
|
|
60
|
-
fill="none"
|
|
61
|
-
aria-hidden="true"
|
|
62
|
-
>
|
|
63
|
-
<path
|
|
64
|
-
d="M31.5 13.4A13 13 0 0 0 8 12.3"
|
|
65
|
-
stroke="currentColor"
|
|
66
|
-
strokeWidth="2.2"
|
|
67
|
-
strokeLinecap="round"
|
|
68
|
-
/>
|
|
69
|
-
<path
|
|
70
|
-
d="m7.4 7.7.2 5.2 5.1-1.2M8.5 26.6A13 13 0 0 0 32 27.7"
|
|
71
|
-
stroke="currentColor"
|
|
72
|
-
strokeWidth="2.2"
|
|
73
|
-
strokeLinecap="round"
|
|
74
|
-
strokeLinejoin="round"
|
|
75
|
-
/>
|
|
76
|
-
<path
|
|
77
|
-
d="m32.6 32.3-.2-5.2-5.1 1.2"
|
|
78
|
-
stroke="currentColor"
|
|
79
|
-
strokeWidth="2.2"
|
|
80
|
-
strokeLinecap="round"
|
|
81
|
-
strokeLinejoin="round"
|
|
82
|
-
/>
|
|
83
|
-
</svg>
|
|
84
|
-
);
|
|
85
|
-
case "bus":
|
|
86
|
-
return (
|
|
87
|
-
<svg
|
|
88
|
-
className={iconClassName}
|
|
89
|
-
viewBox="0 0 40 40"
|
|
90
|
-
fill="none"
|
|
91
|
-
aria-hidden="true"
|
|
92
|
-
>
|
|
93
|
-
<rect
|
|
94
|
-
x="8"
|
|
95
|
-
y="4.5"
|
|
96
|
-
width="24"
|
|
97
|
-
height="27"
|
|
98
|
-
rx="2.5"
|
|
99
|
-
stroke="currentColor"
|
|
100
|
-
strokeWidth="2.2"
|
|
101
|
-
/>
|
|
102
|
-
<path
|
|
103
|
-
d="M8 18.5h24M12 9h16M12 26h4m8 0h4M11 31.5v3h5v-3m8 0v3h5v-3M5.5 10v7m29-7v7"
|
|
104
|
-
stroke="currentColor"
|
|
105
|
-
strokeWidth="2.2"
|
|
106
|
-
strokeLinecap="round"
|
|
107
|
-
/>
|
|
108
|
-
</svg>
|
|
109
|
-
);
|
|
110
|
-
case "price":
|
|
111
|
-
return (
|
|
112
|
-
<svg
|
|
113
|
-
className={iconClassName}
|
|
114
|
-
viewBox="0 0 40 40"
|
|
115
|
-
fill="none"
|
|
116
|
-
aria-hidden="true"
|
|
117
|
-
>
|
|
118
|
-
<circle
|
|
119
|
-
cx="20"
|
|
120
|
-
cy="20"
|
|
121
|
-
r="14"
|
|
122
|
-
stroke="currentColor"
|
|
123
|
-
strokeWidth="2.2"
|
|
124
|
-
/>
|
|
125
|
-
<path
|
|
126
|
-
d="M23.7 15.4c-1-.7-2.2-1-3.6-1-2.2 0-3.8 1.1-3.8 2.8 0 4.2 7.4 1.8 7.4 5.8 0 1.8-1.6 2.8-4 2.8-1.5 0-2.9-.4-4-1.2M20 11.7v2.5m0 11.8v2.4"
|
|
127
|
-
stroke="currentColor"
|
|
128
|
-
strokeWidth="2.2"
|
|
129
|
-
strokeLinecap="round"
|
|
130
|
-
/>
|
|
131
|
-
</svg>
|
|
132
|
-
);
|
|
133
|
-
default:
|
|
134
|
-
return (
|
|
135
|
-
<svg
|
|
136
|
-
className={iconClassName}
|
|
137
|
-
viewBox="0 0 40 40"
|
|
138
|
-
fill="none"
|
|
139
|
-
aria-hidden="true"
|
|
140
|
-
>
|
|
141
|
-
<path
|
|
142
|
-
d="M7 11h26v6a3.5 3.5 0 0 0 0 7v6H7v-6a3.5 3.5 0 0 0 0-7v-6Z"
|
|
143
|
-
stroke="currentColor"
|
|
144
|
-
strokeWidth="2.2"
|
|
145
|
-
strokeLinejoin="round"
|
|
146
|
-
/>
|
|
147
|
-
<path
|
|
148
|
-
d="M22 12.5v3m0 3v3m0 3v4"
|
|
149
|
-
stroke="currentColor"
|
|
150
|
-
strokeWidth="2.2"
|
|
151
|
-
strokeLinecap="round"
|
|
152
|
-
/>
|
|
153
|
-
</svg>
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const AssuranceIcon = ({ type }) => {
|
|
159
|
-
const iconClassName = "h-[18px] w-[18px] shrink-0 text-white";
|
|
160
|
-
|
|
161
|
-
if (type === "pending") {
|
|
162
|
-
return (
|
|
163
|
-
<svg
|
|
164
|
-
className={iconClassName}
|
|
165
|
-
viewBox="0 0 20 20"
|
|
166
|
-
fill="none"
|
|
167
|
-
aria-hidden="true"
|
|
168
|
-
>
|
|
169
|
-
<path
|
|
170
|
-
d="M4.2 8.2a6.2 6.2 0 1 1 .5 5.1"
|
|
171
|
-
stroke="currentColor"
|
|
172
|
-
strokeWidth="1.8"
|
|
173
|
-
strokeLinecap="round"
|
|
174
|
-
/>
|
|
175
|
-
<path
|
|
176
|
-
d="M4.2 4.8v3.4h3.4"
|
|
177
|
-
stroke="currentColor"
|
|
178
|
-
strokeWidth="1.8"
|
|
179
|
-
strokeLinecap="round"
|
|
180
|
-
strokeLinejoin="round"
|
|
181
|
-
/>
|
|
182
|
-
</svg>
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return (
|
|
187
|
-
<svg
|
|
188
|
-
className={iconClassName}
|
|
189
|
-
viewBox="0 0 20 20"
|
|
190
|
-
fill="none"
|
|
191
|
-
aria-hidden="true"
|
|
192
|
-
>
|
|
193
|
-
<path
|
|
194
|
-
d="M10 2.2 16.3 4v5c0 4-2.4 6.8-6.3 8.7C6.1 15.8 3.7 13 3.7 9V4L10 2.2Z"
|
|
195
|
-
stroke="currentColor"
|
|
196
|
-
strokeWidth="1.6"
|
|
197
|
-
strokeLinejoin="round"
|
|
198
|
-
/>
|
|
199
|
-
<path
|
|
200
|
-
d="m6.9 9.7 2.1 2.1 4.3-4.4"
|
|
201
|
-
stroke="currentColor"
|
|
202
|
-
strokeWidth="1.7"
|
|
203
|
-
strokeLinecap="round"
|
|
204
|
-
strokeLinejoin="round"
|
|
205
|
-
/>
|
|
206
|
-
</svg>
|
|
207
|
-
);
|
|
208
|
-
};
|
|
209
|
-
|
|
210
26
|
const FeatureServiceUi = ({
|
|
211
27
|
serviceItem,
|
|
212
28
|
showTopLabel,
|
|
213
|
-
colors,
|
|
214
29
|
isSoldOut,
|
|
215
30
|
getAnimationIcon,
|
|
216
31
|
cityOrigin,
|
|
217
32
|
cityDestination,
|
|
218
33
|
renderIcon,
|
|
219
34
|
viewersConfig,
|
|
35
|
+
isFeatureDropDownExpand,
|
|
36
|
+
onToggleExpand,
|
|
37
|
+
ticketQuantity = 1,
|
|
38
|
+
onIncreaseTicketQuantity,
|
|
39
|
+
onDecreaseTicketQuantity,
|
|
40
|
+
onBookButtonPress,
|
|
220
41
|
}) => {
|
|
221
42
|
const operators =
|
|
222
43
|
serviceItem?.operators?.length > 0
|
|
223
44
|
? serviceItem.operators
|
|
224
45
|
: HARDCODED_OPERATORS;
|
|
225
46
|
|
|
47
|
+
const isItemExpanded =
|
|
48
|
+
serviceItem.id === isFeatureDropDownExpand ||
|
|
49
|
+
isFeatureDropDownExpand === true;
|
|
50
|
+
const canDecreaseTicketQuantity = ticketQuantity > 1;
|
|
51
|
+
|
|
52
|
+
const HOW_IT_WORKS_STEPS = [
|
|
53
|
+
{
|
|
54
|
+
icon: "flexible",
|
|
55
|
+
name: "1. Salida flexible",
|
|
56
|
+
text: "Viajas en un horario entre las 07:00 y las 10:00 AM del día elegido.",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
icon: "bus",
|
|
60
|
+
name: "2. Empresa asignada",
|
|
61
|
+
text: "Una de las empresas disponibles confirma tu viaje una vez pagado.",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
icon: "price",
|
|
65
|
+
name: "3. Precio garantizado",
|
|
66
|
+
text: "Al seleccionar este servicio aseguras el precio reducido.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
icon: "ticket",
|
|
70
|
+
name: "4. ¡Listo!",
|
|
71
|
+
text: "Recibe todos los detalles de tu viaje al instante tras la compra.",
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
const FeatureStepIcon = ({ icon }) => {
|
|
76
|
+
switch (icon) {
|
|
77
|
+
case "flexible":
|
|
78
|
+
return renderIcon("flexibleIcon", "24px");
|
|
79
|
+
case "bus":
|
|
80
|
+
return renderIcon("empressaIcon", "24px");
|
|
81
|
+
case "price":
|
|
82
|
+
return renderIcon("precioIcon", "24px");
|
|
83
|
+
default:
|
|
84
|
+
return renderIcon("listoIcon", "24px");
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
226
88
|
return (
|
|
227
89
|
<div
|
|
228
90
|
// ${
|
|
@@ -255,6 +117,8 @@ const FeatureServiceUi = ({
|
|
|
255
117
|
padding: "1px 8px",
|
|
256
118
|
borderRadius: "4px",
|
|
257
119
|
color: "#fff",
|
|
120
|
+
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
121
|
+
whiteSpace: "nowrap",
|
|
258
122
|
}}
|
|
259
123
|
>
|
|
260
124
|
<span>AHORRAS 60%</span>
|
|
@@ -271,6 +135,7 @@ const FeatureServiceUi = ({
|
|
|
271
135
|
fontVariantNumeric: "tabular-nums",
|
|
272
136
|
display: "inline-block",
|
|
273
137
|
color: "#FF5C60",
|
|
138
|
+
minWidth: "40px",
|
|
274
139
|
}}
|
|
275
140
|
/>
|
|
276
141
|
</span>
|
|
@@ -280,9 +145,9 @@ const FeatureServiceUi = ({
|
|
|
280
145
|
id={`service-card-${serviceItem.id}`}
|
|
281
146
|
className="bg-[#0C1421] text-white mx-auto relative rounded-[14px] p-[14px] text-[13.33px]"
|
|
282
147
|
>
|
|
283
|
-
<div className="grid grid-cols-[
|
|
148
|
+
<div className="grid grid-cols-[23%_50%_27%] items-stretch">
|
|
284
149
|
{/* LEFT: origin, destination, flexible, time, confirmed seat */}
|
|
285
|
-
<div className="flex flex-col justify-between gap-[20px]
|
|
150
|
+
<div className="flex flex-col justify-between gap-[20px] my-[14px] pr-[22px]">
|
|
286
151
|
<div className="flex flex-col gap-[8px]">
|
|
287
152
|
<div className="flex items-center gap-[8px]">
|
|
288
153
|
<img
|
|
@@ -300,7 +165,7 @@ const FeatureServiceUi = ({
|
|
|
300
165
|
<img
|
|
301
166
|
src={serviceItem.icons?.whiteDestination}
|
|
302
167
|
alt="destination"
|
|
303
|
-
className={`w-[
|
|
168
|
+
className={`w-[14px] h-[14px] shrink-0 ${
|
|
304
169
|
isSoldOut ? "grayscale" : ""
|
|
305
170
|
}`}
|
|
306
171
|
style={{ opacity: isSoldOut ? 0.5 : 1 }}
|
|
@@ -312,23 +177,6 @@ const FeatureServiceUi = ({
|
|
|
312
177
|
</div>
|
|
313
178
|
|
|
314
179
|
<div className="flex flex-col gap-[8px]">
|
|
315
|
-
{/* Salida flexible badge — uses flexibleIcon */}
|
|
316
|
-
{/* <div
|
|
317
|
-
className="flex items-center gap-[6px] rounded-[8px] px-[8px] py-[4px] w-fit mb-[6px]"
|
|
318
|
-
style={{
|
|
319
|
-
border: "1px solid #363c48",
|
|
320
|
-
backgroundColor: "#1a202e",
|
|
321
|
-
}}
|
|
322
|
-
>
|
|
323
|
-
<img
|
|
324
|
-
src={serviceItem.icons?.busIcon}
|
|
325
|
-
alt="bus"
|
|
326
|
-
style={{ width: "20px", height: "20px" }}
|
|
327
|
-
/>
|
|
328
|
-
<span className="text-[12px] whitespace-nowrap">
|
|
329
|
-
Salida flexible
|
|
330
|
-
</span>
|
|
331
|
-
</div> */}
|
|
332
180
|
<div className="text-[12px] bold-text whitespace-nowrap">
|
|
333
181
|
Entre 07:00 AM y 10:00 AM
|
|
334
182
|
</div>
|
|
@@ -336,8 +184,8 @@ const FeatureServiceUi = ({
|
|
|
336
184
|
</div>
|
|
337
185
|
|
|
338
186
|
<div className="flex flex-col items-start gap-[10px] text-[12px] ">
|
|
339
|
-
<div className="flex items-
|
|
340
|
-
|
|
187
|
+
<div className="flex items-justify gap-[8px]">
|
|
188
|
+
{renderIcon("sheildIcon", "16px")}
|
|
341
189
|
|
|
342
190
|
<span
|
|
343
191
|
className="text-[10px]"
|
|
@@ -348,8 +196,8 @@ const FeatureServiceUi = ({
|
|
|
348
196
|
Empresa y hora a confirmar luego del pago.
|
|
349
197
|
</span>
|
|
350
198
|
</div>
|
|
351
|
-
<div className="flex items-
|
|
352
|
-
|
|
199
|
+
<div className="flex items-justify gap-[8px]">
|
|
200
|
+
{renderIcon("confirmarIcon", "16px")}
|
|
353
201
|
|
|
354
202
|
<span
|
|
355
203
|
className="text-[10px]"
|
|
@@ -364,7 +212,7 @@ const FeatureServiceUi = ({
|
|
|
364
212
|
</div>
|
|
365
213
|
|
|
366
214
|
{/* MIDDLE: competing operators + viewers */}
|
|
367
|
-
<div className="px-[
|
|
215
|
+
<div className="min-w-0 px-[22px] flex flex-col items-center justify-between gap-[16px] py-[2px] border-r border-[#363c48] border-l border-[#363c48]">
|
|
368
216
|
<div className="text-center">
|
|
369
217
|
<div className="bold-text text-[14px]">
|
|
370
218
|
3 operadores compitiendo por tu compra
|
|
@@ -374,30 +222,29 @@ const FeatureServiceUi = ({
|
|
|
374
222
|
</div> */}
|
|
375
223
|
</div>
|
|
376
224
|
|
|
377
|
-
<div className="
|
|
225
|
+
<div className="grid w-full grid-cols-3 items-stretch gap-[14px] mb-[12px]">
|
|
378
226
|
{operators.map((op, idx) => (
|
|
379
227
|
<div
|
|
380
228
|
key={idx}
|
|
381
|
-
className="flex flex-col items-center justify-center gap-[8px] rounded-[8px]"
|
|
229
|
+
className="flex min-w-0 flex-col items-center justify-center gap-[8px] rounded-[8px]"
|
|
382
230
|
style={{
|
|
383
|
-
width: "140px",
|
|
384
231
|
// height: "80px",
|
|
385
232
|
border: "1px solid #363c48",
|
|
386
233
|
backgroundColor: "#1a202e",
|
|
387
|
-
padding: "14px",
|
|
234
|
+
padding: "14px 10px",
|
|
388
235
|
}}
|
|
389
236
|
>
|
|
390
237
|
<img
|
|
391
238
|
src={serviceItem.operator_details[0]}
|
|
392
239
|
alt={op.name}
|
|
393
|
-
className={`h-[24px] w-
|
|
240
|
+
className={`h-[24px] max-w-full object-contain ${
|
|
394
241
|
isSoldOut ? "grayscale" : ""
|
|
395
242
|
}`}
|
|
396
243
|
/>
|
|
397
244
|
<span className="text-[11px] truncate max-w-full text-center">
|
|
398
245
|
{serviceItem.operator_details[2]}
|
|
399
246
|
</span>
|
|
400
|
-
<div className="bg-[#FF8F45] text-white text-[12px] font-bold px-[
|
|
247
|
+
<div className="bg-[#FF8F45] text-white text-[12px] font-bold px-[10px] py-[4px] rounded-[4px] bold-text whitespace-nowrap">
|
|
401
248
|
<span>{op?.time}</span>
|
|
402
249
|
</div>
|
|
403
250
|
<span className="text-[10px] mt-[6px]">
|
|
@@ -408,19 +255,19 @@ const FeatureServiceUi = ({
|
|
|
408
255
|
</div>
|
|
409
256
|
|
|
410
257
|
<div
|
|
411
|
-
className="flex items-center justify-center gap-[6px] text-[12px]"
|
|
258
|
+
className="flex w-full items-center justify-center gap-[6px] text-[12px]"
|
|
412
259
|
style={{
|
|
413
260
|
border: "1px solid #363c48",
|
|
414
261
|
backgroundColor: "#1a202e",
|
|
415
262
|
padding: "8px 14px",
|
|
416
263
|
borderRadius: "24px",
|
|
417
|
-
width: "430px",
|
|
418
264
|
}}
|
|
419
265
|
>
|
|
420
|
-
<
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
266
|
+
<LottiePlayer
|
|
267
|
+
// animationData={serviceItem.icons.flexibleAnim}
|
|
268
|
+
animationData={getAnimationIcon("usersAnimation")}
|
|
269
|
+
width="18px"
|
|
270
|
+
height="18px"
|
|
424
271
|
/>
|
|
425
272
|
<span>
|
|
426
273
|
<span className="bold-text text-white">
|
|
@@ -435,15 +282,8 @@ const FeatureServiceUi = ({
|
|
|
435
282
|
color: "#FF5C60",
|
|
436
283
|
}}
|
|
437
284
|
/>{" "}
|
|
438
|
-
<span
|
|
439
|
-
style={{
|
|
440
|
-
color: "#FF5C60",
|
|
441
|
-
}}
|
|
442
|
-
>
|
|
443
|
-
personas
|
|
444
|
-
</span>
|
|
445
285
|
</span>{" "}
|
|
446
|
-
viendo
|
|
286
|
+
viendo |{" "}
|
|
447
287
|
<span
|
|
448
288
|
className="bold-text"
|
|
449
289
|
ref={(node) =>
|
|
@@ -457,28 +297,98 @@ const FeatureServiceUi = ({
|
|
|
457
297
|
</div>
|
|
458
298
|
|
|
459
299
|
{/* RIGHT: price + button */}
|
|
460
|
-
<div className="flex flex-col
|
|
300
|
+
<div className="flex flex-col justify-center gap-[12px] py-[2px] pl-[22px] pr-[10px] relative mb-[16px]">
|
|
461
301
|
<div
|
|
462
302
|
className="flex flex-col gap-[6px] "
|
|
463
303
|
style={{
|
|
464
304
|
alignItems: "center",
|
|
465
305
|
}}
|
|
466
306
|
>
|
|
467
|
-
<span
|
|
307
|
+
<span
|
|
308
|
+
className="text-[#FF8F45] bold-text text-[26px] leading-tight"
|
|
309
|
+
style={{
|
|
310
|
+
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
311
|
+
whiteSpace: "nowrap",
|
|
312
|
+
}}
|
|
313
|
+
>
|
|
468
314
|
60% OFF
|
|
469
315
|
</span>
|
|
470
|
-
<span className="text-[#666] text-[14px] line-through">
|
|
316
|
+
{/* <span className="text-[#666] text-[14px] line-through">
|
|
317
|
+
$10.000
|
|
318
|
+
</span> */}
|
|
319
|
+
<span
|
|
320
|
+
className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative"
|
|
321
|
+
style={{ position: "relative" }}
|
|
322
|
+
>
|
|
471
323
|
$10.000
|
|
324
|
+
<span
|
|
325
|
+
style={{
|
|
326
|
+
position: "absolute",
|
|
327
|
+
left: "-2px",
|
|
328
|
+
top: "50%",
|
|
329
|
+
width: "calc(100% + 4px)",
|
|
330
|
+
height: "1px",
|
|
331
|
+
|
|
332
|
+
backgroundColor: "#FF5C60",
|
|
333
|
+
|
|
334
|
+
transform: "rotate(-10deg)",
|
|
335
|
+
transformOrigin: "center",
|
|
336
|
+
}}
|
|
337
|
+
/>
|
|
472
338
|
</span>
|
|
473
339
|
<span className="text-white bold-text text-[28px] leading-none">
|
|
474
|
-
|
|
340
|
+
{`$${(4000 * ticketQuantity).toLocaleString()}`}
|
|
475
341
|
</span>
|
|
476
342
|
</div>
|
|
477
343
|
|
|
344
|
+
<div className="mt-[4px] flex flex-col items-center gap-[8px]">
|
|
345
|
+
<span className="text-[12px] text-white">
|
|
346
|
+
¿Cuántos pasajes quieres?
|
|
347
|
+
</span>
|
|
348
|
+
<div
|
|
349
|
+
className="flex w-full items-center justify-between"
|
|
350
|
+
style={{
|
|
351
|
+
border: "1px solid #363c48",
|
|
352
|
+
backgroundColor: "#1a202e",
|
|
353
|
+
padding: "6px 14px",
|
|
354
|
+
borderRadius: "14px",
|
|
355
|
+
}}
|
|
356
|
+
>
|
|
357
|
+
<button
|
|
358
|
+
type="button"
|
|
359
|
+
aria-label="Disminuir pasajes"
|
|
360
|
+
disabled={!canDecreaseTicketQuantity}
|
|
361
|
+
onClick={() => onDecreaseTicketQuantity?.(serviceItem)}
|
|
362
|
+
className={`flex h-[34px] w-[34px] items-center justify-center rounded-full border-none text-[25px] leading-none text-white ${
|
|
363
|
+
canDecreaseTicketQuantity
|
|
364
|
+
? "cursor-pointer bg-[#2d374d]"
|
|
365
|
+
: "cursor-not-allowed bg-[#222b3d] opacity-50"
|
|
366
|
+
}`}
|
|
367
|
+
>
|
|
368
|
+
-
|
|
369
|
+
</button>
|
|
370
|
+
<span className="bold-text text-[20px] text-white">
|
|
371
|
+
{ticketQuantity}
|
|
372
|
+
</span>
|
|
373
|
+
<button
|
|
374
|
+
type="button"
|
|
375
|
+
aria-label="Aumentar pasajes"
|
|
376
|
+
onClick={() => onIncreaseTicketQuantity?.(serviceItem)}
|
|
377
|
+
className="flex h-[34px] w-[34px] cursor-pointer items-center justify-center rounded-full border-none bg-[#2d374d] text-[25px] leading-none text-white"
|
|
378
|
+
>
|
|
379
|
+
+
|
|
380
|
+
</button>
|
|
381
|
+
</div>
|
|
382
|
+
</div>
|
|
383
|
+
|
|
478
384
|
<button
|
|
479
|
-
|
|
385
|
+
type="button"
|
|
386
|
+
onClick={onBookButtonPress}
|
|
387
|
+
className="flex items-center gap-[6px] px-[20px] py-[10px] rounded-[16px] text-white bold-text text-[13px] mt-[4px] justify-center border-none cursor-pointer"
|
|
480
388
|
style={{
|
|
481
389
|
backgroundColor: "#FF5C60",
|
|
390
|
+
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
391
|
+
whiteSpace: "nowrap",
|
|
482
392
|
}}
|
|
483
393
|
>
|
|
484
394
|
<LottiePlayer
|
|
@@ -491,7 +401,10 @@ const FeatureServiceUi = ({
|
|
|
491
401
|
</button>
|
|
492
402
|
</div>
|
|
493
403
|
|
|
494
|
-
<div
|
|
404
|
+
<div
|
|
405
|
+
className={`absolute bottom-[11px] right-[18px] cursor-pointer transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`}
|
|
406
|
+
onClick={onToggleExpand}
|
|
407
|
+
>
|
|
495
408
|
<img
|
|
496
409
|
src={serviceItem.icons?.downArrow}
|
|
497
410
|
alt="down arrow"
|
|
@@ -504,24 +417,39 @@ const FeatureServiceUi = ({
|
|
|
504
417
|
</div>
|
|
505
418
|
</div>
|
|
506
419
|
</div>
|
|
507
|
-
<div
|
|
508
|
-
|
|
420
|
+
<div
|
|
421
|
+
className="grid"
|
|
422
|
+
style={{
|
|
423
|
+
gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
|
|
424
|
+
opacity: isItemExpanded ? 1 : 0,
|
|
425
|
+
transition:
|
|
426
|
+
"grid-template-rows 300ms ease-in-out, opacity 250ms ease-in-out",
|
|
427
|
+
}}
|
|
428
|
+
>
|
|
429
|
+
<div
|
|
430
|
+
className={`min-h-0 overflow-hidden px-[16px] text-[13.33px] ${
|
|
431
|
+
isItemExpanded ? "pt-[14px] pb-[6px]" : "py-0"
|
|
432
|
+
}`}
|
|
433
|
+
style={{ transition: "padding 300ms ease-in-out" }}
|
|
434
|
+
>
|
|
435
|
+
<span className="bold-text">¿Cómo funciona?</span>
|
|
509
436
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
437
|
+
<div className="mt-[14px] grid grid-cols-4 gap-[20px] px-[16px] ">
|
|
438
|
+
{HOW_IT_WORKS_STEPS.map((step) => (
|
|
439
|
+
<div
|
|
440
|
+
key={step.name}
|
|
441
|
+
className="flex flex-col items-center text-center text-[#272727]"
|
|
442
|
+
>
|
|
443
|
+
<FeatureStepIcon icon={step.icon} />
|
|
444
|
+
<span className="bold-text mt-[10px] text-[12px] leading-[14px]">
|
|
445
|
+
{step.name}
|
|
446
|
+
</span>
|
|
447
|
+
<span className="mt-[2px] max-w-[220px] text-[12px] leading-[14px] text-[#4a4a4a]">
|
|
448
|
+
{step.text}
|
|
449
|
+
</span>
|
|
450
|
+
</div>
|
|
451
|
+
))}
|
|
452
|
+
</div>
|
|
525
453
|
</div>
|
|
526
454
|
</div>
|
|
527
455
|
</div>
|
|
@@ -329,10 +329,15 @@ const commonService = {
|
|
|
329
329
|
) => {
|
|
330
330
|
if (!node || !viewersConfig) return;
|
|
331
331
|
|
|
332
|
+
const { min, max, interval = 5000 } = viewersConfig;
|
|
333
|
+
const configKey = `${min}-${max}-${interval}`;
|
|
334
|
+
if (node.dataset.viewerId && node.dataset.viewerConfig === configKey) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
332
338
|
const prevId = node.dataset.viewerId;
|
|
333
339
|
if (prevId) clearInterval(Number(prevId));
|
|
334
340
|
|
|
335
|
-
const { min, max, interval = 5000 } = viewersConfig;
|
|
336
341
|
const clamp = (v: number) => Math.min(max, Math.max(min, v));
|
|
337
342
|
const initialValue = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
338
343
|
|
|
@@ -347,6 +352,7 @@ const commonService = {
|
|
|
347
352
|
}, interval);
|
|
348
353
|
|
|
349
354
|
node.dataset.viewerId = String(id);
|
|
355
|
+
node.dataset.viewerConfig = configKey;
|
|
350
356
|
},
|
|
351
357
|
|
|
352
358
|
startCountdown: (
|
|
@@ -388,6 +394,11 @@ const commonService = {
|
|
|
388
394
|
) => {
|
|
389
395
|
if (!node) return;
|
|
390
396
|
|
|
397
|
+
const configKey = `${min}-${max}`;
|
|
398
|
+
if (node.dataset.comprandoId && node.dataset.comprandoConfig === configKey) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
391
402
|
const prevId = node.dataset.comprandoId;
|
|
392
403
|
if (prevId) clearInterval(Number(prevId));
|
|
393
404
|
|
|
@@ -408,6 +419,7 @@ const commonService = {
|
|
|
408
419
|
}, 5000); // Update every 5 seconds
|
|
409
420
|
|
|
410
421
|
node.dataset.comprandoId = String(id);
|
|
422
|
+
node.dataset.comprandoConfig = configKey;
|
|
411
423
|
},
|
|
412
424
|
};
|
|
413
425
|
|