kupos-ui-components-lib 9.7.8 → 9.7.9

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.
Files changed (26) hide show
  1. package/dist/KuposUIComponent.d.ts +3 -0
  2. package/dist/components/ServiceItem/PeruServiceItemDesktop.d.ts +1 -1
  3. package/dist/components/ServiceItem/PeruServiceItemDesktop.js +134 -188
  4. package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
  5. package/dist/components/ServiceItem/ServiceItemDesktop.js +15 -2
  6. package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
  7. package/dist/components/ServiceItem/ServiceItemMobile.js +16 -7
  8. package/dist/components/ServiceItem/mobileTypes.d.ts +32 -0
  9. package/dist/components/ServiceItem/types.d.ts +22 -0
  10. package/dist/styles.css +221 -0
  11. package/dist/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.js +9 -7
  12. package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +3 -3
  13. package/dist/utils/CommonService.js +11 -1
  14. package/package.json +1 -1
  15. package/src/KuposUIComponent.tsx +3 -0
  16. package/src/assets/images/anims/service_list/thunder_icon.json +1 -0
  17. package/src/assets/images/anims/service_list/users_anim.json +1 -0
  18. package/src/components/ServiceItem/PeruServiceItemDesktop.tsx +254 -345
  19. package/src/components/ServiceItem/ServiceItemDesktop.tsx +49 -5
  20. package/src/components/ServiceItem/ServiceItemMobile.tsx +340 -286
  21. package/src/components/ServiceItem/mobileTypes.ts +29 -1
  22. package/src/components/ServiceItem/types.ts +23 -1
  23. package/src/styles.css +15 -0
  24. package/src/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.tsx +525 -0
  25. package/src/ui/FeatureServiceUI/FeatureServiceUi.tsx +555 -0
  26. package/src/utils/CommonService.ts +13 -1
@@ -127,7 +127,21 @@ export interface MobileServiceItemProps {
127
127
  directoIcon?: string;
128
128
  whiteFireIcon?: string
129
129
  femaleAnim?:string
130
- cancelTicketIcon?: string;
130
+ thunderAnim?: string
131
+ personsAnim?: string
132
+ whiteOrigin?: string,
133
+ whiteDestination?: string,
134
+ userIcon?: string,
135
+
136
+ sheildIcon?: string,
137
+ busIcon?: string,
138
+ whiteDownArrow?: string,
139
+ empressaIcon?: string,
140
+ flexibleIcon?: string,
141
+ listoIcon?: string,
142
+ precioIcon?: string,
143
+ confirmarIcon?: string
144
+ cancelTicketIcon?: string;
131
145
  changeTicketIcon?: string;
132
146
  petFriendlyIcon?: string;
133
147
  womenSeatIcon?: string
@@ -136,6 +150,7 @@ export interface MobileServiceItemProps {
136
150
  useLottieFor?: string[];
137
151
  };
138
152
  onBookButtonPress?: () => void;
153
+ onRemateUiButtonClick?: ()=> void;
139
154
  terminals?: any[];
140
155
  showDropdown?: boolean;
141
156
  setShowDropdown?: (value: boolean) => void;
@@ -199,4 +214,17 @@ export interface MobileServiceItemProps {
199
214
  label?: string; // e.g. "personas están viendo este viaje"
200
215
  icon?: string; // optional icon URL
201
216
  };
217
+ isFeatureDropDownExpand?: any;
218
+ setIsFeatureDropDownExpand?: (value: any) => void;
219
+ ticketQuantity?: number;
220
+ onIncreaseTicketQuantity?: (serviceItem: MobileServiceItemProps["serviceItem"]) => void;
221
+ onDecreaseTicketQuantity?: (serviceItem: MobileServiceItemProps["serviceItem"]) => void;
222
+ cityOrigin?: { value: number; label: string };
223
+ cityDestination?: { value: number; label: string };
224
+ isNewUi?: boolean
225
+
226
+ selectedTimeSlot?: string;
227
+ onTimeSlotChange?: (slot: string) => void;
228
+ isTimeDropdownOpen?: string | number | null;
229
+ onTimeDropdownToggle?: (id?: string | number | null) => void;
202
230
  }
@@ -132,11 +132,24 @@ export interface ServiceItemProps {
132
132
  whiteFireIcon?: string
133
133
  fireIcon?: string
134
134
 
135
+ whiteOrigin?: string,
136
+ whiteDestination?: string,
137
+ userIcon?: string,
138
+
139
+ sheildIcon?: string,
140
+ busIcon?: string,
141
+ whiteDownArrow?: string,
142
+ empressaIcon?: string,
143
+ flexibleIcon?: string,
144
+ listoIcon?: string,
145
+ precioIcon?: string,
146
+ confirmarIcon?: string
135
147
  [key: string]: string | Record<string, string | undefined> | undefined;
136
148
  };
137
149
  useLottieFor?: string[];
138
150
  };
139
151
  onBookButtonPress?: () => void;
152
+ onRemateUiButtonClick?: ()=>void;
140
153
  terminals?: any[];
141
154
  t?: (key: string) => string;
142
155
  serviceDetailsLoading?: boolean;
@@ -215,6 +228,11 @@ export interface ServiceItemProps {
215
228
  isAllinBus?: boolean;
216
229
  isExpand?: any;
217
230
  setIsExpand?: (value: any) => void;
231
+ isFeatureDropDownExpand?: any;
232
+ setIsFeatureDropDownExpand?: (value: any) => void;
233
+ ticketQuantity?: number;
234
+ onIncreaseTicketQuantity?: (serviceItem: ServiceItemProps["serviceItem"]) => void;
235
+ onDecreaseTicketQuantity?: (serviceItem: ServiceItemProps["serviceItem"]) => void;
218
236
  coachKey?: number
219
237
  viewersConfig?: {
220
238
  min: number;
@@ -223,8 +241,12 @@ export interface ServiceItemProps {
223
241
  label?: string; // e.g. "personas están viendo este viaje"
224
242
  icon?: string; // optional icon URL
225
243
  };
244
+ isNewUi?: boolean
226
245
  showLoginModal?: any
227
246
  isLoggedIn?: any
228
247
  showLoginOption?: boolean
229
-
248
+ selectedTimeSlot?: string;
249
+ onTimeSlotChange?: (slot: string) => void;
250
+ isTimeDropdownOpen?: string | number | null;
251
+ onTimeDropdownToggle?: (id?: string | number | null) => void;
230
252
  }
package/src/styles.css CHANGED
@@ -93,6 +93,21 @@
93
93
  display: none;
94
94
  }
95
95
 
96
+ /* Time slot dropdown */
97
+ .kupos-time-dd > summary {
98
+ list-style: none;
99
+ }
100
+ .kupos-time-dd > summary::-webkit-details-marker {
101
+ display: none;
102
+ }
103
+ .kupos-time-chevron {
104
+ transition: transform 200ms ease;
105
+ flex-shrink: 0;
106
+ }
107
+ .kupos-time-dd[open] .kupos-time-chevron {
108
+ transform: rotate(180deg);
109
+ }
110
+
96
111
  .hide-scrollbar {
97
112
  -ms-overflow-style: none;
98
113
  scrollbar-width: none;
@@ -0,0 +1,525 @@
1
+ import React from "react";
2
+ import LottiePlayer from "../../assets/LottiePlayer";
3
+ import commonService from "../../utils/CommonService";
4
+
5
+ const TIME_SLOTS = [
6
+ "Entre 07:00 AM y 10:00 AM",
7
+ "Entre 11:00 AM y 14:00 AM",
8
+ "Entre 15:00 PM y 18:00 PM",
9
+ "Entre 19:00 PM y 22:00 PM",
10
+ ];
11
+
12
+ const HARDCODED_OPERATORS = [
13
+ {
14
+ logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Turbus_logo.svg/320px-Turbus_logo.svg.png",
15
+ name: "Turbus",
16
+ time: "7:00 am",
17
+ seatsAvailable: "3 disponibles",
18
+ },
19
+ {
20
+ logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Pullman_Bus_logo.svg/320px-Pullman_Bus_logo.svg.png",
21
+ name: "Pullmanbus",
22
+ time: "8:00 am",
23
+ seatsAvailable: "5 disponibles",
24
+ },
25
+ {
26
+ logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Turbus_logo.svg/320px-Turbus_logo.svg.png",
27
+ name: "Expreso Santa C...",
28
+ time: "9:00 am",
29
+ seatsAvailable: "3 disponibles",
30
+ },
31
+ ];
32
+
33
+ const FeatureServiceUiMobile = ({
34
+ serviceItem,
35
+ showTopLabel,
36
+ colors,
37
+ isSoldOut,
38
+ cityOrigin,
39
+ cityDestination,
40
+ renderIcon,
41
+ viewersConfig,
42
+ isFeatureDropDownExpand,
43
+ onToggleExpand,
44
+ ticketQuantity = 1,
45
+ onIncreaseTicketQuantity,
46
+ onDecreaseTicketQuantity,
47
+ onBookButtonPress,
48
+ selectedTimeSlot = TIME_SLOTS[0],
49
+ onTimeSlotChange,
50
+ isTimeDropdownOpen,
51
+ onTimeDropdownToggle,
52
+ }) => {
53
+ const operators =
54
+ serviceItem?.operators?.length > 0
55
+ ? serviceItem.operators
56
+ : HARDCODED_OPERATORS;
57
+
58
+ const isItemExpanded =
59
+ serviceItem.id === isFeatureDropDownExpand ||
60
+ isFeatureDropDownExpand === true;
61
+ const isThisTimeDropdownOpen = isTimeDropdownOpen === serviceItem.id;
62
+
63
+ const canDecreaseTicketQuantity = ticketQuantity > 1;
64
+
65
+ const HOW_IT_WORKS_STEPS = [
66
+ {
67
+ icon: "flexible",
68
+ name: "1. Salida flexible",
69
+ text: "Viajas en un horario entre las 07:00 y las 10:00 AM del día elegido.",
70
+ },
71
+ {
72
+ icon: "bus",
73
+ name: "2. Empresa asignada",
74
+ text: "Una de las empresas confirmará tu viaje al instante tras el pago.",
75
+ },
76
+ {
77
+ icon: "price",
78
+ name: "3. Precio garantizado",
79
+ text: "Mejor precio garantizado. Sin cambios ni cancelación.",
80
+ },
81
+ {
82
+ icon: "ticket",
83
+ name: "4. ¡Listo!",
84
+ text: "Recibe todos los detalles de tu viaje al instante tras la compra.",
85
+ },
86
+ ];
87
+
88
+ const FeatureStepIcon = ({ icon }) => {
89
+ switch (icon) {
90
+ case "flexible":
91
+ return renderIcon("flexibleIcon", "20px");
92
+ case "bus":
93
+ return renderIcon("empressaIcon", "20px");
94
+ case "price":
95
+ return renderIcon("precioIcon", "20px");
96
+ default:
97
+ return renderIcon("listoIcon", "20px");
98
+ }
99
+ };
100
+
101
+ return (
102
+ <div
103
+ // ${
104
+ // serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"
105
+ // }
106
+ className={`relative mb-[10px]
107
+ ${
108
+ serviceItem?.is_direct_trip ||
109
+ serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
110
+ showTopLabel
111
+ ? "mt-[24px]"
112
+ : "mt-[20px]"
113
+ }`}
114
+ >
115
+ <div
116
+ // className="shadow-service"
117
+ style={{
118
+ border: "1px solid #c0c0c0",
119
+ padding: "12px",
120
+ borderRadius: "14px",
121
+ }}
122
+ >
123
+ <div className="flex flex-col items-center px-[12px] pb-[8px] text-[13.33px] gap-[8px]">
124
+ <div className="flex items-center gap-[10px] mt-[16px]">
125
+ <span>Salida flexible</span>
126
+ <div
127
+ className="bold-text font-[9px]"
128
+ style={{
129
+ backgroundColor: "#FF5C60",
130
+ padding: "1px 8px",
131
+ borderRadius: "4px",
132
+ color: "#fff",
133
+ animation: "pulse-zoom 2s ease-in-out infinite",
134
+ whiteSpace: "nowrap",
135
+ }}
136
+ >
137
+ <span>AHORRAS 60%</span>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ <div
142
+ id={`service-card-${serviceItem.id}`}
143
+ className="bg-[#0C1421] text-white mx-auto relative rounded-[14px] p-[14px] text-[13.33px]"
144
+ >
145
+ <div className="flex flex-col gap-[10px]">
146
+ <div className=" text-[white]">
147
+ <div className="flex flex-col gap-[10px] relative">
148
+ <div className="flex items-center gap-[6px]">
149
+ <img
150
+ src={serviceItem.icons?.whiteOrigin}
151
+ alt="origin"
152
+ className={`w-[14px] h-[14px] shrink-0 ${
153
+ isSoldOut ? "grayscale" : ""
154
+ }`}
155
+ />
156
+ <span className="text-[13px] bold-text">
157
+ {cityOrigin?.label.split(",")[0]}
158
+ <span className="mx-[10px]">→</span>
159
+ {cityDestination?.label.split(",")[0]}
160
+ </span>
161
+ </div>
162
+ <div
163
+ style={{
164
+ width: "1px",
165
+ flex: 1,
166
+ backgroundColor: "#fff",
167
+ margin: "3px 0",
168
+ minHeight: "8px",
169
+ position: "absolute",
170
+ top: "13px",
171
+ left: "7px",
172
+ }}
173
+ />
174
+ <div className="flex items-center gap-[6px]">
175
+ <img
176
+ src={serviceItem.icons?.whiteDestination}
177
+ alt="destination"
178
+ className={`w-[14px] h-[14px] shrink-0 ${
179
+ isSoldOut ? "grayscale" : ""
180
+ }`}
181
+ style={{ opacity: isSoldOut ? 0.5 : 1 }}
182
+ />
183
+ <div
184
+ className="kupos-time-dd relative"
185
+ tabIndex={0}
186
+ onBlur={(e) => {
187
+ if (!e.currentTarget.contains(e.relatedTarget as Node)) {
188
+ onTimeDropdownToggle?.(null);
189
+ }
190
+ }}
191
+ style={{ outline: "none" }}
192
+ >
193
+ <button
194
+ type="button"
195
+ onClick={() =>
196
+ onTimeDropdownToggle?.(
197
+ isThisTimeDropdownOpen ? null : serviceItem.id,
198
+ )
199
+ }
200
+ className="flex cursor-pointer select-none items-center gap-[6px] border-none bg-transparent p-0 bold-text text-[13px] text-[white]"
201
+ >
202
+ <span>{selectedTimeSlot}</span>
203
+ <img
204
+ src={serviceItem?.icons?.downArrow}
205
+ alt="down arrow"
206
+ className={`kupos-time-chevron transition-transform duration-200 ${isThisTimeDropdownOpen ? "rotate-180" : "rotate-0"}`}
207
+ style={{
208
+ width: "12px",
209
+ height: "8px",
210
+ filter: "brightness(0) invert(1)",
211
+ }}
212
+ />
213
+ </button>
214
+ {isThisTimeDropdownOpen && (
215
+ <>
216
+ <div
217
+ className="absolute left-0 top-[calc(100%+10px)]"
218
+ style={{
219
+ zIndex: 20,
220
+ backgroundColor: "#fff",
221
+ borderRadius: "14px",
222
+ minWidth: "248px",
223
+ boxShadow: "0 8px 32px rgba(0,0,0,0.28)",
224
+ overflow: "hidden",
225
+ padding: "6px 0",
226
+ }}
227
+ >
228
+ {TIME_SLOTS.map((slot) => {
229
+ const isActive = slot === selectedTimeSlot;
230
+ return (
231
+ <button
232
+ key={slot}
233
+ type="button"
234
+ onClick={() => {
235
+ onTimeSlotChange?.(slot);
236
+ onTimeDropdownToggle?.(null);
237
+ }}
238
+ className={`flex w-full cursor-pointer items-center gap-[10px] border-none px-[12px] py-[9px] text-left text-[13px] ${isActive ? "bg-[#FF5C60] font-bold text-[white]" : "bg-transparent font-normal text-[#1a1a1a]"}`}
239
+ >
240
+ <span>{slot}</span>
241
+ </button>
242
+ );
243
+ })}
244
+ </div>
245
+ </>
246
+ )}
247
+ </div>
248
+ </div>
249
+ </div>
250
+ </div>
251
+
252
+ <div className="border-t border-[#363c48] my-[8px]" />
253
+
254
+ <div>
255
+ <span
256
+ className="block w-full text-[14px] bold-text text-[white] mb-[10px]"
257
+ style={{ textAlign: "center" }}
258
+ >
259
+ 3 operadores compitiendo por tu compra
260
+ </span>
261
+ <div
262
+ className="flex gap-[8px] text-[white]"
263
+ style={{ width: "100%" }}
264
+ >
265
+ {operators.map((op, idx) => (
266
+ <div
267
+ key={idx}
268
+ className="flex min-w-0 flex-col items-center justify-center gap-[8px] rounded-[8px]"
269
+ style={{
270
+ flex: 1,
271
+ minWidth: 0,
272
+ height: "100px",
273
+ border: "1px solid #363c48",
274
+ backgroundColor: "#1a202e",
275
+ padding: "14px 6px",
276
+ }}
277
+ >
278
+ <img
279
+ src={serviceItem.operator_details[0]}
280
+ alt={op.name}
281
+ className={`h-[24px] max-w-full object-contain ${
282
+ isSoldOut ? "grayscale" : ""
283
+ }`}
284
+ />
285
+ <span className="text-[12px] truncate max-w-full text-center ">
286
+ {serviceItem.operator_details[2]}
287
+ </span>
288
+ {/* <div className="bg-[#FF8F45] text-[12px] font-bold px-[10px] py-[4px] rounded-[4px] bold-text whitespace-nowrap">
289
+ <span>{op?.time}</span>
290
+ </div> */}
291
+ <span className="text-[11px] mt-[6px] whitespace-nowrap">
292
+ {op?.seatsAvailable}
293
+ </span>
294
+ </div>
295
+ ))}
296
+ </div>
297
+
298
+ <div
299
+ className="flex w-full items-center justify-center gap-[6px] text-[12px] mt-[12px]"
300
+ style={{
301
+ border: "1px solid #363c48",
302
+ backgroundColor: "#1a202e",
303
+ padding: "4px 14px",
304
+ borderRadius: "24px",
305
+ }}
306
+ >
307
+ <LottiePlayer
308
+ animationData={serviceItem.icons.personsAnim}
309
+ width="18px"
310
+ height="18px"
311
+ />
312
+ <span>
313
+ <span className="bold-text text-[white]">
314
+ {" "}
315
+ <span
316
+ className="bold-text"
317
+ ref={(node) =>
318
+ commonService.startViewerCount(node, viewersConfig)
319
+ }
320
+ style={{
321
+ fontVariantNumeric: "tabular-nums",
322
+ color: "#FF5C60",
323
+ }}
324
+ />{" "}
325
+ </span>{" "}
326
+ <span className="text-[white]">viendo |</span>{" "}
327
+ <span
328
+ className="bold-text text-[white]"
329
+ ref={(node) =>
330
+ commonService.startComprandoCount(node, 4, 16)
331
+ }
332
+ style={{ fontVariantNumeric: "tabular-nums" }}
333
+ />{" "}
334
+ <span className="text-[white]">han comprado</span>
335
+ </span>
336
+ </div>
337
+
338
+ <div className="mt-[10px] flex flex-col items-center gap-[8px]">
339
+ <span className="text-[12px] text-[white]">
340
+ ¿Cuántos pasajes quieres?
341
+ </span>
342
+ <div
343
+ className="flex w-[50%] items-center justify-between"
344
+ style={{
345
+ border: "1px solid #363c48",
346
+ backgroundColor: "#1a202e",
347
+ padding: "4px 14px",
348
+ borderRadius: "14px",
349
+ }}
350
+ >
351
+ <button
352
+ type="button"
353
+ aria-label="Disminuir pasajes"
354
+ disabled={!canDecreaseTicketQuantity}
355
+ onClick={() => onDecreaseTicketQuantity?.(serviceItem)}
356
+ className={`flex h-[34px] w-[34px] items-center justify-center rounded-full border-none text-[25px] leading-none text-[white] ${
357
+ canDecreaseTicketQuantity
358
+ ? "cursor-pointer bg-[#2d374d]"
359
+ : "cursor-not-allowed bg-[#222b3d] opacity-50"
360
+ }`}
361
+ >
362
+ -
363
+ </button>
364
+ <span className="bold-text text-[20px] text-[white]">
365
+ {ticketQuantity}
366
+ </span>
367
+ <button
368
+ type="button"
369
+ aria-label="Aumentar pasajes"
370
+ onClick={() => onIncreaseTicketQuantity?.(serviceItem)}
371
+ className="flex h-[34px] w-[34px] cursor-pointer items-center justify-center rounded-full border-none bg-[#2d374d] text-[25px] leading-none text-[white]"
372
+ >
373
+ +
374
+ </button>
375
+ </div>
376
+ </div>
377
+
378
+ <div
379
+ className="mt-[10px] flex justify-between items-center rounded-[14px]"
380
+ style={{
381
+ // height: "80px",
382
+ border: "1px solid #363c48",
383
+ backgroundColor: "#1a202e",
384
+ padding: "14px 10px",
385
+ }}
386
+ >
387
+ <div className="flex flex-col">
388
+ <span
389
+ className="text-[20px] font-normal leading-[20px] text-[#9f9f9f] relative"
390
+ style={{ position: "relative" }}
391
+ >
392
+ $10.000
393
+ <span
394
+ style={{
395
+ position: "absolute",
396
+ left: "-2px",
397
+ top: "50%",
398
+ width: "calc(80% + 4px)",
399
+ height: "1px",
400
+
401
+ backgroundColor: "#FF5C60",
402
+
403
+ transform: "rotate(-10deg)",
404
+ transformOrigin: "center",
405
+ }}
406
+ />
407
+ </span>
408
+ <span className="text-[white] bold-text text-[28px] leading-none mt-[4px]">
409
+ {`$${(4000 * ticketQuantity).toLocaleString()}`}
410
+ </span>
411
+ </div>
412
+ <span
413
+ className="text-[#FF8F45] bold-text text-[26px] leading-tight"
414
+ style={{
415
+ animation: "pulse-zoom 2s ease-in-out infinite",
416
+ whiteSpace: "nowrap",
417
+ }}
418
+ >
419
+ 60% OFF
420
+ </span>
421
+ </div>
422
+
423
+ <button
424
+ type="button"
425
+ onClick={onBookButtonPress}
426
+ className="flex items-center gap-[6px] px-[20px] py-[10px] rounded-[16px] text-[white] bold-text text-[13px] mt-[10px] justify-center border-none cursor-pointer"
427
+ style={{
428
+ backgroundColor: "#FF5C60",
429
+ animation: "pulse-zoom 2s ease-in-out infinite",
430
+ whiteSpace: "nowrap",
431
+ width: "100%",
432
+ }}
433
+ >
434
+ <LottiePlayer
435
+ animationData={serviceItem.icons.thunderAnim}
436
+ width="18px"
437
+ height="18px"
438
+ />
439
+ <span className="whitespace-nowrap">¡Lo quiero!</span>
440
+ </button>
441
+
442
+ <div
443
+ className="flex justify-end mt-[10px]"
444
+ onClick={onToggleExpand}
445
+ >
446
+ <img
447
+ src={serviceItem?.icons?.downArrow}
448
+ alt="down arrow"
449
+ className={`transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`}
450
+ style={{
451
+ width: "14px",
452
+ height: "8px",
453
+ filter: "brightness(0) invert(1)",
454
+ }}
455
+ />
456
+ </div>
457
+ </div>
458
+ </div>
459
+ </div>
460
+
461
+ {isItemExpanded && (
462
+ <div
463
+ className="flex flex-col gap-[10px]"
464
+ style={{
465
+ opacity: isItemExpanded ? 1 : 0,
466
+ transition: "opacity 250ms ease-in-out",
467
+ }}
468
+ >
469
+ <div
470
+ className={` text-[12px] ${
471
+ isItemExpanded ? "pt-[14px] pb-[6px]" : "py-0"
472
+ }`}
473
+ style={{ transition: "padding 300ms ease-in-out" }}
474
+ >
475
+ <span className="bold-text">¿Cómo funciona?</span>
476
+
477
+ <div className="flex flex-col">
478
+ {HOW_IT_WORKS_STEPS.map((step) => (
479
+ <div className="flex items-start gap-[8px] mt-[10px]">
480
+ <div>
481
+ <FeatureStepIcon icon={step.icon} />
482
+ </div>
483
+ <div className="flex flex-col">
484
+ <span className="bold-text">{step.name}</span>
485
+ <span>{step.text}</span>
486
+ </div>
487
+ </div>
488
+ ))}
489
+ </div>
490
+ </div>
491
+ </div>
492
+ )}
493
+ </div>
494
+
495
+ {/* TOP BADGE — "Remate | Termina en 09:55 min" hardcoded, no countdown hook */}
496
+ <div className="absolute -top-[11px] left-0 w-full flex items-center justify-center gap-[12px] z-10 ">
497
+ <div className="flex items-center gap-[6px] py-[5px] px-[14px] rounded-[38px] text-[12.5px] bg-[#FF8F45] text-white whitespace-nowrap">
498
+ <span className="flex items-center">
499
+ <LottiePlayer
500
+ animationData={serviceItem.icons.bombAnim}
501
+ width="14px"
502
+ height="14px"
503
+ />
504
+ <span className="bold-text ml-[5px] text-[white]">
505
+ Remate&nbsp;
506
+ </span>{" "}
507
+ <span className="text-[white]">términa en</span>{" "}
508
+ <span
509
+ className="bold-text text-end"
510
+ ref={(node) => commonService.startCountdown(node, 599)}
511
+ style={{
512
+ fontVariantNumeric: "tabular-nums",
513
+ display: "inline-block",
514
+ color: "#fff",
515
+ minWidth: "40px",
516
+ }}
517
+ />
518
+ </span>
519
+ </div>
520
+ </div>
521
+ </div>
522
+ );
523
+ };
524
+
525
+ export default FeatureServiceUiMobile;