kupos-ui-components-lib 10.4.11 → 10.4.13

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 (93) hide show
  1. package/dist/assets/images/filter/bus.svg +19 -0
  2. package/dist/assets/images/filter/clock.svg +4 -0
  3. package/dist/assets/images/filter/filter.svg +3 -0
  4. package/dist/assets/images/filter/money.svg +12 -0
  5. package/dist/assets/images/filter/night.svg +5 -0
  6. package/dist/assets/images/filter/rise.svg +20 -0
  7. package/dist/assets/images/filter/search.svg +4 -0
  8. package/dist/assets/images/filter/seat.svg +4 -0
  9. package/dist/assets/images/filter/star.svg +10 -0
  10. package/dist/assets/images/filter/sun.svg +20 -0
  11. package/dist/assets/images/filter/sunset.svg +15 -0
  12. package/dist/assets/images/filter/track.svg +4 -0
  13. package/dist/components/FilterSortBar/FilterChip.d.ts +21 -0
  14. package/dist/components/FilterSortBar/FilterChip.js +42 -0
  15. package/dist/components/FilterSortBar/FilterSortBarMobile.d.ts +10 -0
  16. package/dist/components/FilterSortBar/FilterSortBarMobile.js +121 -0
  17. package/dist/components/FilterSortBar/FiltersMasterSheet.d.ts +16 -0
  18. package/dist/components/FilterSortBar/FiltersMasterSheet.js +111 -0
  19. package/dist/components/FilterSortBar/OptionCheckboxList.d.ts +13 -0
  20. package/dist/components/FilterSortBar/OptionCheckboxList.js +30 -0
  21. package/dist/components/FilterSortBar/PriceRangeSlider.d.ts +12 -0
  22. package/dist/components/FilterSortBar/PriceRangeSlider.js +113 -0
  23. package/dist/components/FilterSortBar/SheetFooter.d.ts +9 -0
  24. package/dist/components/FilterSortBar/SheetFooter.js +36 -0
  25. package/dist/components/FilterSortBar/SingleFilterSheet.d.ts +15 -0
  26. package/dist/components/FilterSortBar/SingleFilterSheet.js +21 -0
  27. package/dist/components/FilterSortBar/defaultIcons.d.ts +2 -0
  28. package/dist/components/FilterSortBar/defaultIcons.js +18 -0
  29. package/dist/components/FilterSortBar/icons.d.ts +50 -0
  30. package/dist/components/FilterSortBar/icons.js +67 -0
  31. package/dist/components/FilterSortBar/index.d.ts +4 -0
  32. package/dist/components/FilterSortBar/index.js +3 -0
  33. package/dist/components/FilterSortBar/types.d.ts +57 -0
  34. package/dist/components/FilterSortBar/types.js +8 -0
  35. package/dist/components/PaymentSideBar/PaymentSideBarMobile.js +15 -8
  36. package/dist/components/PaymentSideBar/types.d.ts +3 -0
  37. package/dist/index.d.ts +4 -1
  38. package/dist/index.js +5 -0
  39. package/dist/styles.css +64 -0
  40. package/dist/ui/BottomSheet/BottomSheet.d.ts +2 -1
  41. package/dist/ui/BottomSheet/BottomSheet.js +2 -1
  42. package/package.json +1 -1
  43. package/patch.py +35 -0
  44. package/src/assets/images/filter/bus.svg +19 -0
  45. package/src/assets/images/filter/clock.svg +4 -0
  46. package/src/assets/images/filter/filter.svg +3 -0
  47. package/src/assets/images/filter/money.svg +12 -0
  48. package/src/assets/images/filter/night.svg +5 -0
  49. package/src/assets/images/filter/rise.svg +20 -0
  50. package/src/assets/images/filter/search.svg +4 -0
  51. package/src/assets/images/filter/seat.svg +4 -0
  52. package/src/assets/images/filter/star.svg +10 -0
  53. package/src/assets/images/filter/sun.svg +20 -0
  54. package/src/assets/images/filter/sunset.svg +15 -0
  55. package/src/assets/images/filter/track.svg +4 -0
  56. package/src/components/FilterSortBar/FilterChip.tsx +113 -0
  57. package/src/components/FilterSortBar/FilterSortBarMobile.tsx +236 -0
  58. package/src/components/FilterSortBar/FiltersMasterSheet.tsx +208 -0
  59. package/src/components/FilterSortBar/OptionCheckboxList.tsx +86 -0
  60. package/src/components/FilterSortBar/PriceRangeSlider.tsx +184 -0
  61. package/src/components/FilterSortBar/SheetFooter.tsx +61 -0
  62. package/src/components/FilterSortBar/SingleFilterSheet.tsx +82 -0
  63. package/src/components/FilterSortBar/defaultIcons.ts +29 -0
  64. package/src/components/FilterSortBar/icons.tsx +237 -0
  65. package/src/components/FilterSortBar/index.ts +15 -0
  66. package/src/components/FilterSortBar/types.ts +79 -0
  67. package/src/components/PaymentSideBar/PaymentSideBarMobile.tsx +553 -526
  68. package/src/components/PaymentSideBar/types.ts +3 -0
  69. package/src/index.ts +18 -0
  70. package/src/ui/BottomSheet/BottomSheet.tsx +4 -1
  71. package/src/ui/PaymentCardMobile/PaymentCardMobile.tsx +982 -0
  72. package/src/ui/PaymentCardMobile/index.ts +1 -0
  73. package/src/ui/SlidingModal/SlidingModal.tsx +145 -0
  74. package/src/ui/SlidingModal/index.ts +2 -0
  75. package/dist/assets/images/anims/service_list/60_percent_anim.json +0 -1
  76. package/dist/components/PaymentOptions/PaymentOptionsDesktop.d.ts +0 -4
  77. package/dist/components/PaymentOptions/PaymentOptionsDesktop.js +0 -5
  78. package/dist/components/PaymentOptions/PaymentOptionsMobile.d.ts +0 -4
  79. package/dist/components/PaymentOptions/PaymentOptionsMobile.js +0 -5
  80. package/dist/components/PaymentOptions/ResponsivePaymentOptions.d.ts +0 -3
  81. package/dist/components/PaymentOptions/ResponsivePaymentOptions.js +0 -10
  82. package/dist/components/PaymentOptions/index.d.ts +0 -5
  83. package/dist/components/PaymentOptions/index.js +0 -4
  84. package/dist/components/PaymentOptions/mobileTypes.d.ts +0 -0
  85. package/dist/components/PaymentOptions/mobileTypes.js +0 -0
  86. package/dist/components/PaymentOptions/type.d.ts +0 -4
  87. package/dist/components/PaymentOptions/type.js +0 -1
  88. package/dist/components/ServiceItem/ExpandedDropdown.d.ts +0 -19
  89. package/dist/components/ServiceItem/ExpandedDropdown.js +0 -28
  90. package/dist/components/ServiceItem/ServiceItemDesktopPeru.d.ts +0 -6
  91. package/dist/components/ServiceItem/ServiceItemDesktopPeru.js +0 -612
  92. package/dist/ui/TopAmenities/PromoCountdown.d.ts +0 -18
  93. package/dist/ui/TopAmenities/PromoCountdown.js +0 -55
@@ -0,0 +1,982 @@
1
+ import React from "react";
2
+ import { PaymentSideBarProps } from "../../components/PaymentSideBar/types";
3
+ import DateService from "../../utils/DateService";
4
+ import CommonService from "../../utils/CommonService";
5
+ import SlidingModal from "../SlidingModal/SlidingModal";
6
+
7
+ class ModalTabStateWrapper extends React.Component<any, any> {
8
+ constructor(props: any) {
9
+ super(props);
10
+ this.state = { modalTab: props.initialTab };
11
+ }
12
+
13
+ componentDidUpdate(prevProps: any) {
14
+ if (this.props.showDetails && !prevProps.showDetails) {
15
+ this.setState({ modalTab: this.props.initialTab });
16
+ }
17
+ }
18
+
19
+ render() {
20
+ return this.props.render(this.state.modalTab, (tab: number) =>
21
+ this.setState({ modalTab: tab }),
22
+ );
23
+ }
24
+ }
25
+
26
+ export const PaymentCardMobile: React.FC<PaymentSideBarProps> = (props) => {
27
+ const {
28
+ serviceNameOnward,
29
+ serviceNameReturn,
30
+ currencySign,
31
+ dateOnward,
32
+ dateReturn,
33
+ sourceOnward,
34
+ sourceReturn,
35
+ destinationOnward,
36
+ destinationReturn,
37
+ boardingStageOnward,
38
+ boardingStageReturn,
39
+ droppingStageOnward,
40
+ droppingStageReturn,
41
+ boardingTimeOnward,
42
+ boardingTimeReturn,
43
+ droppingTimeOnward,
44
+ droppingTimeReturn,
45
+ durationOnward,
46
+ durationReturn,
47
+ selectSeatOnward,
48
+ selectSeatReturn,
49
+ journeyTypeActive,
50
+ setJourneyTypeActive,
51
+ translation,
52
+ trainTypeOnward,
53
+ trainTypeReturn,
54
+ colors,
55
+ trainType,
56
+ icons,
57
+ selectedOnward,
58
+ selectedReturn,
59
+ removeDiscountAtomValue,
60
+ netFare,
61
+ promoCode,
62
+ onPromoRemove,
63
+ renderDiscount,
64
+ discountAmount,
65
+ currency,
66
+ insuranceData,
67
+ isPeru,
68
+ showDetails = false,
69
+ setShowDetails,
70
+ } = props;
71
+ console.log("🚀 ~ PaymentCardMobile ~ selectSeatOnward:", selectSeatOnward);
72
+
73
+ // We use a Class component wrapper below to hold the state,
74
+ // avoiding Invalid Hook Call issues when linked in external apps with multiple React instances.
75
+
76
+ // These will be derived inside the render prop of ModalTabStateWrapper
77
+
78
+ // Derive active journey data
79
+ const isReturn = journeyTypeActive === 2;
80
+ const activeBoardingStage = isReturn
81
+ ? boardingStageReturn
82
+ : boardingStageOnward;
83
+ const activeBoardingTime = isReturn ? boardingTimeReturn : boardingTimeOnward;
84
+ const activeDroppingStage = isReturn
85
+ ? droppingStageReturn
86
+ : droppingStageOnward;
87
+ const activeDroppingTime = isReturn ? droppingTimeReturn : droppingTimeOnward;
88
+ const activeSource = isReturn ? sourceReturn : sourceOnward;
89
+ const activeDest = isReturn ? destinationReturn : destinationOnward;
90
+ const activeServiceName = isReturn ? serviceNameReturn : serviceNameOnward;
91
+ const activeDate = isReturn ? dateReturn : dateOnward;
92
+ const activeDuration = isReturn ? durationReturn : durationOnward;
93
+ const activeTrainType = isReturn ? trainTypeReturn : trainTypeOnward;
94
+
95
+ const formatDateBadge = (date?: string) => {
96
+ if (!date) return "";
97
+ const day = DateService.getDayNameFromDate(date);
98
+ const d = DateService.getDateFromDate(date);
99
+ const month = DateService.getMonthNameFromDate(date);
100
+ const year = DateService.getYearFromDate(date);
101
+ return `${day ? day.charAt(0).toUpperCase() + day.slice(1) : ""}, ${d} de ${
102
+ month ? month.toLowerCase() : ""
103
+ } de ${year}`;
104
+ };
105
+
106
+ const formatSubText = (stage?: string, time?: string) => {
107
+ if (!stage && !time) return null;
108
+ const timePart = time
109
+ ? ` - ${DateService.formatTime ? DateService.formatTime(time) : time}`
110
+ : "";
111
+ return `${stage || ""}${timePart}`;
112
+ };
113
+
114
+ // ── Shared style objects ────────────────────────────────────────────────────
115
+ const S = {
116
+ sectionRow: {
117
+ display: "flex",
118
+ justifyContent: "space-between",
119
+ alignItems: "center",
120
+ fontSize: "14px",
121
+ marginBottom: "10px",
122
+ } as React.CSSProperties,
123
+ sectionRowValue: {
124
+ textAlign: "right",
125
+ } as React.CSSProperties,
126
+ sectionTitle: {
127
+ fontSize: "14px",
128
+ marginBottom: "10px",
129
+ } as React.CSSProperties,
130
+ section: {
131
+ marginBottom: "20px",
132
+ } as React.CSSProperties,
133
+ };
134
+
135
+ return (
136
+ <div>
137
+ <div
138
+ style={{
139
+ borderRadius: "20px",
140
+ position: "relative",
141
+ backgroundColor: "#fff",
142
+ margin: "0 20px",
143
+ overflow: "visible",
144
+ border: "1px solid #e0e0e0",
145
+ }}
146
+ >
147
+ {/* ── TOP CARD BODY ── */}
148
+ <div>
149
+ {/* Ida / Vuelta toggle */}
150
+ {dateReturn ? (
151
+ <div
152
+ style={{
153
+ display: "flex",
154
+ width: "100%",
155
+ boxShadow: "inset 0 -1px 0 #e0e0e0",
156
+ }}
157
+ >
158
+ <div
159
+ onClick={() => setJourneyTypeActive && setJourneyTypeActive(1)}
160
+ style={{
161
+ flex: 1,
162
+ textAlign: "center",
163
+ padding: "16px 0",
164
+ cursor: "pointer",
165
+ fontSize: "14px",
166
+ fontWeight: journeyTypeActive === 1 ? 600 : 500,
167
+ color:
168
+ journeyTypeActive === 1
169
+ ? colors?.idaBgColor || "#e05252"
170
+ : "#999999",
171
+ borderBottom:
172
+ journeyTypeActive === 1
173
+ ? `2px solid ${colors?.idaBgColor || "#e05252"}`
174
+ : "2px solid transparent",
175
+ transition: "all 0.2s ease",
176
+ }}
177
+ >
178
+ {translation?.going || "Ida"}
179
+ </div>
180
+ <div
181
+ onClick={() => setJourneyTypeActive && setJourneyTypeActive(2)}
182
+ style={{
183
+ flex: 1,
184
+ textAlign: "center",
185
+ padding: "16px 0",
186
+ cursor: "pointer",
187
+ fontSize: "14px",
188
+ fontWeight: journeyTypeActive === 2 ? 600 : 500,
189
+ color:
190
+ journeyTypeActive === 2
191
+ ? colors?.vueltaBgColor || "#e05252"
192
+ : "#999999",
193
+ borderBottom:
194
+ journeyTypeActive === 2
195
+ ? `2px solid ${colors?.vueltaBgColor || "#e05252"}`
196
+ : "2px solid transparent",
197
+ transition: "all 0.2s ease",
198
+ }}
199
+ >
200
+ {translation?.return || "Vuelta"}
201
+ </div>
202
+ </div>
203
+ ) : null}
204
+
205
+ <div style={{ padding: "16px 16px 0 16px" }}>
206
+ {/* Service Name + Date Badge */}
207
+ <div
208
+ style={{
209
+ display: "flex",
210
+ alignItems: "flex-start",
211
+ justifyContent: "space-between",
212
+ gap: "8px",
213
+ marginBottom: "14px",
214
+ }}
215
+ >
216
+ <div
217
+ style={{
218
+ fontSize: "16px",
219
+ fontWeight: 700,
220
+ color: "#2d2d2d",
221
+ lineHeight: 1.3,
222
+ flex: 1,
223
+ }}
224
+ >
225
+ {activeServiceName}
226
+ {trainType && activeTrainType && (
227
+ <div
228
+ style={{
229
+ fontSize: "12px",
230
+ fontWeight: 400,
231
+ color: "#666",
232
+ marginTop: "2px",
233
+ }}
234
+ >
235
+ {activeTrainType}
236
+ </div>
237
+ )}
238
+ </div>
239
+ {activeDate && (
240
+ <div
241
+ style={{
242
+ fontSize: "11px",
243
+ color: "#555",
244
+ textTransform: "capitalize",
245
+ whiteSpace: "nowrap",
246
+ borderRadius: "12px",
247
+ padding: "4px 10px",
248
+ flexShrink: 0,
249
+ backgroundColor: "#F8F8F8",
250
+ }}
251
+ >
252
+ {formatDateBadge(activeDate)}
253
+ </div>
254
+ )}
255
+ </div>
256
+
257
+ {/* Origin row */}
258
+ <div
259
+ style={{
260
+ display: "flex",
261
+ alignItems: "flex-start",
262
+ gap: "6px",
263
+ marginBottom: "16px",
264
+ }}
265
+ >
266
+ <div
267
+ style={{
268
+ flexShrink: 0,
269
+ width: "28px",
270
+ height: "28px",
271
+ display: "flex",
272
+ alignItems: "center",
273
+ justifyContent: "center",
274
+ marginTop: "2px",
275
+ }}
276
+ >
277
+ {icons?.origin ? (
278
+ <img
279
+ src={icons.origin}
280
+ style={{ width: "18px", height: "18px" }}
281
+ alt="origin"
282
+ />
283
+ ) : (
284
+ <div
285
+ style={{
286
+ width: "22px",
287
+ height: "22px",
288
+ borderRadius: "50%",
289
+ border: "2.5px solid #e0321c",
290
+ display: "flex",
291
+ alignItems: "center",
292
+ justifyContent: "center",
293
+ }}
294
+ >
295
+ <div
296
+ style={{
297
+ width: "8px",
298
+ height: "8px",
299
+ borderRadius: "50%",
300
+ backgroundColor: "#e0321c",
301
+ }}
302
+ />
303
+ </div>
304
+ )}
305
+ </div>
306
+ <div style={{ flex: 1 }}>
307
+ <div
308
+ style={{
309
+ fontSize: "15px",
310
+ fontWeight: 700,
311
+ color: "#464647",
312
+ textTransform: "capitalize",
313
+ lineHeight: 1.3,
314
+ }}
315
+ >
316
+ {activeSource}
317
+ </div>
318
+ {formatSubText(activeBoardingStage, activeBoardingTime) && (
319
+ <div
320
+ style={{
321
+ fontSize: "12px",
322
+ color: "#464647",
323
+ marginTop: "3px",
324
+ lineHeight: 1.3,
325
+ }}
326
+ >
327
+ {formatSubText(activeBoardingStage, activeBoardingTime)}
328
+ </div>
329
+ )}
330
+ </div>
331
+ </div>
332
+
333
+ {/* Destination row */}
334
+ <div
335
+ style={{
336
+ display: "flex",
337
+ alignItems: "flex-start",
338
+ gap: "8px",
339
+ }}
340
+ >
341
+ <div
342
+ style={{
343
+ flexShrink: 0,
344
+ width: "28px",
345
+ height: "28px",
346
+ display: "flex",
347
+ alignItems: "center",
348
+ justifyContent: "center",
349
+ marginTop: "2px",
350
+ }}
351
+ >
352
+ {icons?.destination ? (
353
+ <img
354
+ src={icons.destination}
355
+ style={{ width: "18px", height: "18px" }}
356
+ alt="destination"
357
+ />
358
+ ) : (
359
+ <div
360
+ style={{
361
+ width: "22px",
362
+ height: "22px",
363
+ display: "flex",
364
+ alignItems: "center",
365
+ justifyContent: "center",
366
+ }}
367
+ >
368
+ <svg viewBox="0 0 24 24" width="24" height="24" fill="none">
369
+ <path
370
+ d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"
371
+ fill="#e05252"
372
+ />
373
+ </svg>
374
+ </div>
375
+ )}
376
+ </div>
377
+ <div style={{ flex: 1 }}>
378
+ <div
379
+ style={{
380
+ fontSize: "15px",
381
+ fontWeight: 700,
382
+ color: "#464647",
383
+ textTransform: "capitalize",
384
+ lineHeight: 1.3,
385
+ }}
386
+ >
387
+ {activeDest}
388
+ </div>
389
+ {formatSubText(activeDroppingStage, activeDroppingTime) && (
390
+ <div
391
+ style={{
392
+ fontSize: "12px",
393
+ color: "#464647",
394
+ marginTop: "3px",
395
+ lineHeight: 1.3,
396
+ }}
397
+ >
398
+ {formatSubText(activeDroppingStage, activeDroppingTime)}
399
+ </div>
400
+ )}
401
+ </div>
402
+ </div>
403
+ </div>
404
+ </div>
405
+
406
+ {/* ── NOTCHED DASHED SEPARATOR ── */}
407
+ <div
408
+ style={{
409
+ position: "relative",
410
+ display: "flex",
411
+ alignItems: "center",
412
+ height: "26px",
413
+ }}
414
+ >
415
+ {/* left notch */}
416
+ <div
417
+ style={{
418
+ position: "absolute",
419
+ left: "-1.5px",
420
+ top: 0,
421
+ width: "13px",
422
+ height: "26px",
423
+ borderRadius: "0 13px 13px 0",
424
+ backgroundColor: "#fff",
425
+ border: "1px solid #ccc",
426
+ borderLeft: "none",
427
+ boxSizing: "border-box",
428
+ zIndex: 20,
429
+ }}
430
+ />
431
+ {/* dashed line */}
432
+ <div
433
+ style={{
434
+ flex: 1,
435
+ margin: "0 13px",
436
+ borderTop: "1.5px dashed #ccc",
437
+ }}
438
+ />
439
+ {/* right notch */}
440
+ <div
441
+ style={{
442
+ position: "absolute",
443
+ right: "-1.5px",
444
+ top: 0,
445
+ width: "13px",
446
+ height: "26px",
447
+ borderRadius: "13px 0 0 13px",
448
+ backgroundColor: "#fff",
449
+ border: "1px solid #ccc",
450
+ borderRight: "none",
451
+ boxSizing: "border-box",
452
+ zIndex: 20,
453
+ }}
454
+ />
455
+ </div>
456
+
457
+ {/* ── SLIDING MODAL: Payment Details ── */}
458
+ <ModalTabStateWrapper
459
+ initialTab={journeyTypeActive || 1}
460
+ showDetails={showDetails}
461
+ render={(modalTab, setModalTab) => {
462
+ const modalIsReturn = modalTab === 2;
463
+ const modalBoardingStage = modalIsReturn
464
+ ? boardingStageReturn
465
+ : boardingStageOnward;
466
+ const modalBoardingTime = modalIsReturn
467
+ ? boardingTimeReturn
468
+ : boardingTimeOnward;
469
+ const modalDroppingStage = modalIsReturn
470
+ ? droppingStageReturn
471
+ : droppingStageOnward;
472
+ const modalDroppingTime = modalIsReturn
473
+ ? droppingTimeReturn
474
+ : droppingTimeOnward;
475
+ const modalSource = modalIsReturn ? sourceReturn : sourceOnward;
476
+ const modalDest = modalIsReturn
477
+ ? destinationReturn
478
+ : destinationOnward;
479
+ const modalServiceName = modalIsReturn
480
+ ? serviceNameReturn
481
+ : serviceNameOnward;
482
+ const modalDuration = modalIsReturn
483
+ ? durationReturn
484
+ : durationOnward;
485
+
486
+ return (
487
+ <SlidingModal
488
+ isOpen={showDetails}
489
+ onClose={() => setShowDetails && setShowDetails(false)}
490
+ title="Detalles del viaje"
491
+ >
492
+ {/* Ida / Vuelta toggle in Modal */}
493
+ {dateReturn ? (
494
+ <div
495
+ style={{
496
+ display: "flex",
497
+ width: "100%",
498
+ boxShadow: "inset 0 -1px 0 #e0e0e0",
499
+ marginBottom: "20px",
500
+ marginTop: "-10px",
501
+ }}
502
+ >
503
+ <div
504
+ onClick={() => setModalTab(1)}
505
+ style={{
506
+ flex: 1,
507
+ textAlign: "center",
508
+ padding: "10px 0 14px 0",
509
+ cursor: "pointer",
510
+ fontSize: "14px",
511
+ fontWeight: modalTab === 1 ? 600 : 500,
512
+ color:
513
+ modalTab === 1
514
+ ? colors?.idaBgColor || "#e05252"
515
+ : "#999999",
516
+ borderBottom:
517
+ modalTab === 1
518
+ ? `2px solid ${colors?.idaBgColor || "#e05252"}`
519
+ : "2px solid transparent",
520
+ transition: "all 0.2s ease",
521
+ }}
522
+ >
523
+ {translation?.going || "Ida"}
524
+ </div>
525
+ <div
526
+ onClick={() => setModalTab(2)}
527
+ style={{
528
+ flex: 1,
529
+ textAlign: "center",
530
+ padding: "10px 0 14px 0",
531
+ cursor: "pointer",
532
+ fontSize: "14px",
533
+ fontWeight: modalTab === 2 ? 600 : 500,
534
+ color:
535
+ modalTab === 2
536
+ ? colors?.vueltaBgColor || "#e05252"
537
+ : "#999999",
538
+ borderBottom:
539
+ modalTab === 2
540
+ ? `2px solid ${colors?.vueltaBgColor || "#e05252"}`
541
+ : "2px solid transparent",
542
+ transition: "all 0.2s ease",
543
+ }}
544
+ >
545
+ {translation?.return || "Vuelta"}
546
+ </div>
547
+ </div>
548
+ ) : null}
549
+
550
+ {/* ── Origin / Destination summary ── */}
551
+ <div
552
+ style={{
553
+ display: "flex",
554
+ flexDirection: "column",
555
+ gap: "12px",
556
+ marginBottom: "30px",
557
+ // borderBottom: "1px solid #f0f0f0",
558
+ }}
559
+ >
560
+ {/* Origin */}
561
+ <div className="flex items-center gap-[12px] leading-[1.5]">
562
+ <div
563
+ style={{
564
+ flexShrink: 0,
565
+ }}
566
+ className="w-[22px] h-[22px] flex items-center justify-center mt-[2px] "
567
+ >
568
+ <img
569
+ src={icons.origin}
570
+ style={{ width: "20px", height: "20px" }}
571
+ alt="origin"
572
+ />
573
+ </div>
574
+ <div>
575
+ <div
576
+ style={{
577
+ fontSize: "15px",
578
+ textTransform: "capitalize",
579
+ }}
580
+ >
581
+ {modalSource}
582
+ </div>
583
+ {formatSubText(modalBoardingStage, modalBoardingTime) && (
584
+ <div
585
+ style={{
586
+ fontSize: "13px",
587
+ marginTop: "2px",
588
+ }}
589
+ >
590
+ {formatSubText(modalBoardingStage, modalBoardingTime)}
591
+ </div>
592
+ )}
593
+ </div>
594
+ </div>
595
+
596
+ {/* Destination */}
597
+ <div className="flex items-start gap-[12px] leading-[1.5]">
598
+ <div
599
+ style={{
600
+ flexShrink: 0,
601
+ }}
602
+ className="w-[22px] h-[22px] flex items-center justify-center mt-[2px] "
603
+ >
604
+ <img
605
+ src={icons.destination}
606
+ style={{ width: "20px", height: "20px" }}
607
+ alt="destination"
608
+ />
609
+ </div>
610
+ <div>
611
+ <div
612
+ style={{
613
+ fontSize: "15px",
614
+ fontWeight: 700,
615
+ textTransform: "capitalize",
616
+ }}
617
+ >
618
+ {modalDest}
619
+ </div>
620
+ {formatSubText(modalDroppingStage, modalDroppingTime) && (
621
+ <div
622
+ style={{
623
+ fontSize: "13px",
624
+ marginTop: "2px",
625
+ }}
626
+ >
627
+ {formatSubText(modalDroppingStage, modalDroppingTime)}
628
+ </div>
629
+ )}
630
+ </div>
631
+ </div>
632
+ </div>
633
+
634
+ {/* ── VIAJE ── */}
635
+ <div style={S.section} className="mt-[30px]">
636
+ <div style={S.sectionTitle} className="bold-text">
637
+ Viaje
638
+ </div>
639
+
640
+ {/* Empresa */}
641
+ <div style={S.sectionRow}>
642
+ <span style={{ flex: 1 }}>Empresa</span>
643
+ <span style={S.sectionRowValue} className="bold-text">
644
+ {modalServiceName}
645
+ </span>
646
+ </div>
647
+
648
+ {/* Duración */}
649
+ {modalDuration && (
650
+ <div style={S.sectionRow}>
651
+ <span style={{ flex: 1 }}>Duración</span>
652
+ <span style={S.sectionRowValue} className="bold-text">
653
+ {modalDuration}
654
+ </span>
655
+ </div>
656
+ )}
657
+
658
+ {/* Asiento N° */}
659
+ {(modalIsReturn ? selectSeatReturn : selectSeatOnward) &&
660
+ (modalIsReturn ? selectedReturn : selectedOnward) &&
661
+ (modalIsReturn ? selectedReturn[0] : selectedOnward[0]) &&
662
+ (modalIsReturn ? selectedReturn[0] : selectedOnward[0])
663
+ .length > 0 && (
664
+ <div
665
+ style={{ ...S.sectionRow, alignItems: "flex-start" }}
666
+ >
667
+ <span style={{ flex: 1 }}>Asiento N°</span>
668
+ <span className="bold-text flex items-center justify-end gap-[4px] flex-wrap">
669
+ {(modalIsReturn
670
+ ? selectedReturn[0]
671
+ : selectedOnward[0]
672
+ ).map((val: any, idx: number) => (
673
+ <span
674
+ key={idx}
675
+ style={{
676
+ display: "inline-flex",
677
+ alignItems: "center",
678
+ }}
679
+ >
680
+ {val.number ||
681
+ val.seat_number ||
682
+ val.seatNumber ||
683
+ val.name ||
684
+ ""}
685
+ {val.type && (
686
+ <span
687
+ style={{
688
+ display: "inline-flex",
689
+ alignItems: "center",
690
+ justifyContent: "center",
691
+ fontSize: "12px",
692
+ marginLeft: "4px",
693
+ }}
694
+ >
695
+ {val.type?.charAt(0)?.toUpperCase()}
696
+ </span>
697
+ )}
698
+ </span>
699
+ ))}
700
+ </span>
701
+ </div>
702
+ )}
703
+ </div>
704
+
705
+ {/* ── POLÍTICA ── */}
706
+ <div style={S.section} className="mt-[30px]">
707
+ <div style={S.sectionTitle} className="bold-text">
708
+ Política
709
+ </div>
710
+ <div style={S.sectionRow}>
711
+ <span style={{ flex: 1 }}>Cancelación</span>
712
+ <span
713
+ style={{ ...S.sectionRowValue, fontSize: "13px" }}
714
+ className="bold-text"
715
+ >
716
+ Gratis hasta 24h antes
717
+ </span>
718
+ </div>
719
+ </div>
720
+
721
+ {/* ── TARIFA ── */}
722
+ <div style={S.section} className="mt-[30px]">
723
+ <div style={S.sectionTitle} className="bold-text">
724
+ Tarifa
725
+ </div>
726
+
727
+ {/* Onward seat fare rows */}
728
+ {selectSeatOnward && selectedOnward && selectedOnward[0]
729
+ ? selectedOnward[0].map((val: any, key: number) => (
730
+ <div key={key} style={S.sectionRow}>
731
+ <span style={{ flex: 1 }}>
732
+ Tarifa base - ida ({selectedOnward[1][key]} x{" "}
733
+ {val.is_pet_seat ? "Asiento Mascota" : val.type})
734
+ </span>
735
+ <span style={S.sectionRowValue} className="bold-text">
736
+ {CommonService.currency(
737
+ isPeru
738
+ ? Math.round(
739
+ val.fare * selectedOnward[1][key] * 100,
740
+ ) / 100
741
+ : val.fare * selectedOnward[1][key],
742
+ currencySign,
743
+ )}
744
+ </span>
745
+ </div>
746
+ ))
747
+ : null}
748
+
749
+ {/* Return seat fare rows */}
750
+ {selectSeatReturn && selectedReturn && selectedReturn[0]
751
+ ? selectedReturn[0].map((val: any, key: number) => (
752
+ <div key={key} style={S.sectionRow}>
753
+ <span style={{ flex: 1 }}>
754
+ Tarifa base - vuelta ({selectedReturn[1][key]} x{" "}
755
+ {val.is_pet_seat ? "Asiento Mascota" : val.type})
756
+ </span>
757
+ <span style={S.sectionRowValue} className="bold-text">
758
+ {CommonService.currency(
759
+ isPeru
760
+ ? Math.round(
761
+ val.fare * selectedReturn[1][key] * 100,
762
+ ) / 100
763
+ : val.fare * selectedReturn[1][key],
764
+ currencySign,
765
+ )}
766
+ </span>
767
+ </div>
768
+ ))
769
+ : null}
770
+
771
+ {/* Insurance */}
772
+ {insuranceData?.insurance_enabled ? (
773
+ <div style={S.sectionRow}>
774
+ <span style={{ flex: 1 }}>
775
+ {(selectedOnward?.[1]?.reduce(
776
+ (acc: number, qty: number) => acc + qty,
777
+ 0,
778
+ ) ?? 0) +
779
+ (selectedReturn?.[1]?.reduce(
780
+ (acc: number, qty: number) => acc + qty,
781
+ 0,
782
+ ) ?? 0)}{" "}
783
+ x Viajero Seguro
784
+ </span>
785
+ <span style={S.sectionRowValue} className="bold-text">
786
+ {CommonService.currency(
787
+ insuranceData?.insurance_total ?? 0,
788
+ currencySign,
789
+ )}
790
+ </span>
791
+ </div>
792
+ ) : null}
793
+
794
+ {/* Service fee */}
795
+ {props.serviceFeeDataStateValue?.service_fee > 0 && (
796
+ <div style={S.sectionRow}>
797
+ <span style={{ flex: 1 }}>Cargo por servicio</span>
798
+ <span style={S.sectionRowValue} className="bold-text">
799
+ {CommonService.currency(
800
+ props.serviceFeeDataStateValue.service_fee,
801
+ currencySign,
802
+ )}
803
+ </span>
804
+ </div>
805
+ )}
806
+
807
+ {/* Promo code */}
808
+ {promoCode?.promoCodeApplied && (
809
+ <>
810
+ <div style={S.sectionRow}>
811
+ <span style={{ flex: 1 }}>
812
+ {translation?.promotionalCode || "Código promocional"}
813
+ </span>
814
+ <span
815
+ style={{
816
+ ...S.sectionRowValue,
817
+ color: colors?.promoCodePriceColor,
818
+ }}
819
+ className="bold-text"
820
+ >
821
+ {CommonService.currency(
822
+ promoCode?.promoCouponAmount ?? 0,
823
+ currencySign,
824
+ )}
825
+ </span>
826
+ </div>
827
+ {promoCode?.promoCouponAmount ? (
828
+ <div
829
+ style={{
830
+ display: "flex",
831
+ alignItems: "center",
832
+ gap: "5px",
833
+ marginBottom: "8px",
834
+ }}
835
+ >
836
+ <span style={{ color: "#555", fontSize: "13px" }}>
837
+ {promoCode?.promoCode}
838
+ </span>
839
+ <span
840
+ style={{ cursor: "pointer" }}
841
+ onClick={onPromoRemove}
842
+ >
843
+ {icons?.closeIcon && (
844
+ <img
845
+ src={icons.closeIcon}
846
+ alt="close"
847
+ style={{ width: "14px", height: "14px" }}
848
+ />
849
+ )}
850
+ </span>
851
+ </div>
852
+ ) : null}
853
+ </>
854
+ )}
855
+
856
+ {/* Discount */}
857
+ {discountAmount ? (
858
+ <div
859
+ style={{
860
+ display: "flex",
861
+ flexDirection: "column",
862
+ marginBottom: "10px",
863
+ }}
864
+ >
865
+ <div
866
+ style={{
867
+ display: "flex",
868
+ justifyContent: "space-between",
869
+ fontSize: "14px",
870
+ }}
871
+ >
872
+ <span>Descuento</span>
873
+ <span style={{ fontWeight: 700, color: "#e05252" }}>
874
+ {renderDiscount ? "" : "- "}
875
+ {currency ? currency : ""}{" "}
876
+ {CommonService.currency(discountAmount, currencySign)}
877
+ </span>
878
+ </div>
879
+ <div
880
+ className="discount-label-wrapper"
881
+ style={{ marginTop: "2px" }}
882
+ >
883
+ <style>{`
884
+ .discount-label-wrapper .discount-row {
885
+ justify-content: flex-start !important;
886
+ margin: 0 !important;
887
+ }
888
+ .discount-label-wrapper .discount-row > div:last-child {
889
+ display: none !important;
890
+ }
891
+ .discount-label-wrapper .font10 span {
892
+ font-size: 13px !important;
893
+ font-weight: 500 !important;
894
+ color: #e05252 !important;
895
+ }
896
+ `}</style>
897
+ {renderDiscount && renderDiscount(discountAmount)}
898
+ </div>
899
+ </div>
900
+ ) : null}
901
+
902
+ {/* Dashed separator */}
903
+ <div
904
+ style={{
905
+ borderTop: "1.5px dashed #464647",
906
+ margin: "14px 0",
907
+ }}
908
+ />
909
+
910
+ {/* Total */}
911
+ <div
912
+ style={{
913
+ display: "flex",
914
+ justifyContent: "space-between",
915
+ alignItems: "center",
916
+ fontSize: "16px",
917
+ fontWeight: 700,
918
+ color: "#1a1a1a",
919
+ }}
920
+ >
921
+ <span>Total</span>
922
+ <span>
923
+ {currency ? currency : ""}{" "}
924
+ {CommonService.currency(
925
+ isPeru
926
+ ? Math.round(
927
+ (removeDiscountAtomValue ? 0 : netFare) * 100,
928
+ ) / 100
929
+ : removeDiscountAtomValue
930
+ ? 0
931
+ : netFare,
932
+ currencySign,
933
+ )}
934
+ </span>
935
+ </div>
936
+ </div>
937
+ </SlidingModal>
938
+ );
939
+ }}
940
+ />
941
+
942
+ {/* ── FOOTER: Ver todos los detalles ── */}
943
+ <div
944
+ style={{
945
+ display: "flex",
946
+ alignItems: "center",
947
+ justifyContent: "center",
948
+ gap: "6px",
949
+ paddingBottom: "14px",
950
+ cursor: "pointer",
951
+ userSelect: "none",
952
+ }}
953
+ onClick={() => setShowDetails && setShowDetails(!showDetails)}
954
+ >
955
+ <span style={{ fontSize: "14px", fontWeight: 700, color: "#464647" }}>
956
+ Ver todos los detalles
957
+ </span>
958
+ <svg
959
+ width="20"
960
+ height="20"
961
+ viewBox="0 0 24 24"
962
+ fill="none"
963
+ style={{
964
+ display: "inline-block",
965
+ transition: "transform 0.2s ease",
966
+ flexShrink: 0,
967
+ }}
968
+ >
969
+ <path
970
+ d="M6 9l6 6 6-6"
971
+ stroke="#2d2d2d"
972
+ strokeWidth="2.5"
973
+ strokeLinecap="round"
974
+ strokeLinejoin="round"
975
+ />
976
+ </svg>
977
+ </div>
978
+ </div>
979
+ </div>
980
+ );
981
+ };
982
+ export default PaymentCardMobile;