kupos-ui-components-lib 9.7.0 → 9.7.1
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/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +6 -2
- package/dist/components/ServiceItem/types.d.ts +5 -0
- package/dist/styles.css +45 -9
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.d.ts +7 -1
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +55 -24
- package/dist/utils/CommonService.js +11 -1
- package/package.json +1 -1
- package/src/KuposUIComponent.tsx +3 -0
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +19 -0
- package/src/components/ServiceItem/types.ts +5 -0
- package/src/ui/FeatureServiceUI/FeatureServiceUi.tsx +125 -52
- package/src/utils/CommonService.ts +13 -1
|
@@ -15,6 +15,9 @@ interface KuposUIComponentProps {
|
|
|
15
15
|
orignLabel?: string;
|
|
16
16
|
destinationLabel?: string;
|
|
17
17
|
t?: (key: string) => string;
|
|
18
|
+
ticketQuantity?: number;
|
|
19
|
+
onIncreaseTicketQuantity?: (serviceItem: any) => void;
|
|
20
|
+
onDecreaseTicketQuantity?: (serviceItem: any) => void;
|
|
18
21
|
id?: string;
|
|
19
22
|
name?: string;
|
|
20
23
|
description?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { ServiceItemProps } from "./types";
|
|
3
|
-
declare function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, }: ServiceItemProps & {
|
|
3
|
+
declare function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, }: ServiceItemProps & {
|
|
4
4
|
currencySign?: string;
|
|
5
5
|
}): React.ReactElement;
|
|
6
6
|
export default ServiceItemPB;
|
|
@@ -79,7 +79,7 @@ const ANIMATION_MAP = {
|
|
|
79
79
|
kupos: femaleAnimation,
|
|
80
80
|
},
|
|
81
81
|
};
|
|
82
|
-
function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t = (key) => key, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, }) {
|
|
82
|
+
function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t = (key) => key, siteType, isAllinBus, isExpand, setIsExpand, coachKey, viewersConfig, isNewUi, showLoginModal, isLoggedIn, showLoginOption, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, }) {
|
|
83
83
|
var _a;
|
|
84
84
|
const getAnimationIcon = (icon) => {
|
|
85
85
|
var _a;
|
|
@@ -248,7 +248,11 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
|
|
|
248
248
|
},
|
|
249
249
|
];
|
|
250
250
|
const otherItems = items.filter((i) => i.key !== "pet" && i.key !== "flexible" && !!i.condition);
|
|
251
|
-
return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus })) : isNewUi ? (React.createElement(FeatureServiceUi, { serviceItem: serviceItem, showTopLabel: showTopLabel, colors: colors, isSoldOut: isSoldOut, getAnimationIcon: getAnimationIcon, cityOrigin: cityOrigin, cityDestination: cityDestination, renderIcon: renderIcon, viewersConfig: viewersConfig
|
|
251
|
+
return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus })) : isNewUi ? (React.createElement(FeatureServiceUi, { serviceItem: serviceItem, showTopLabel: showTopLabel, colors: colors, isSoldOut: isSoldOut, getAnimationIcon: getAnimationIcon, cityOrigin: cityOrigin, cityDestination: cityDestination, renderIcon: renderIcon, viewersConfig: viewersConfig, isFeatureDropDownExpand: isFeatureDropDownExpand, ticketQuantity: ticketQuantity, onIncreaseTicketQuantity: onIncreaseTicketQuantity, onDecreaseTicketQuantity: onDecreaseTicketQuantity, onBookButtonPress: onBookButtonPress, onToggleExpand: () => setIsFeatureDropDownExpand &&
|
|
252
|
+
setIsFeatureDropDownExpand(isFeatureDropDownExpand === serviceItem.id ||
|
|
253
|
+
isFeatureDropDownExpand === true
|
|
254
|
+
? null
|
|
255
|
+
: serviceItem.id) })) : (React.createElement("div", { className: `relative hover:z-[150] ${hasOfferText || hasDpEnabled ? "mb-[55px]" : "mb-[10px]"} ${(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ||
|
|
252
256
|
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" ||
|
|
253
257
|
showTopLabel
|
|
254
258
|
? "mt-[24px]"
|
|
@@ -219,6 +219,11 @@ export interface ServiceItemProps {
|
|
|
219
219
|
isAllinBus?: boolean;
|
|
220
220
|
isExpand?: any;
|
|
221
221
|
setIsExpand?: (value: any) => void;
|
|
222
|
+
isFeatureDropDownExpand?: any;
|
|
223
|
+
setIsFeatureDropDownExpand?: (value: any) => void;
|
|
224
|
+
ticketQuantity?: number;
|
|
225
|
+
onIncreaseTicketQuantity?: (serviceItem: ServiceItemProps["serviceItem"]) => void;
|
|
226
|
+
onDecreaseTicketQuantity?: (serviceItem: ServiceItemProps["serviceItem"]) => void;
|
|
222
227
|
coachKey?: number;
|
|
223
228
|
viewersConfig?: {
|
|
224
229
|
min: number;
|
package/dist/styles.css
CHANGED
|
@@ -177,6 +177,9 @@
|
|
|
177
177
|
.mx-auto {
|
|
178
178
|
margin-inline: auto;
|
|
179
179
|
}
|
|
180
|
+
.my-\[14px\] {
|
|
181
|
+
margin-block: 14px;
|
|
182
|
+
}
|
|
180
183
|
.-mt-\[15px\] {
|
|
181
184
|
margin-top: calc(15px * -1);
|
|
182
185
|
}
|
|
@@ -249,9 +252,6 @@
|
|
|
249
252
|
.mb-\[5px\] {
|
|
250
253
|
margin-bottom: 5px;
|
|
251
254
|
}
|
|
252
|
-
.mb-\[6px\] {
|
|
253
|
-
margin-bottom: 6px;
|
|
254
|
-
}
|
|
255
255
|
.mb-\[8px\] {
|
|
256
256
|
margin-bottom: 8px;
|
|
257
257
|
}
|
|
@@ -357,6 +357,9 @@
|
|
|
357
357
|
.h-\[30px\] {
|
|
358
358
|
height: 30px;
|
|
359
359
|
}
|
|
360
|
+
.h-\[34px\] {
|
|
361
|
+
height: 34px;
|
|
362
|
+
}
|
|
360
363
|
.h-\[100\%\] {
|
|
361
364
|
height: 100%;
|
|
362
365
|
}
|
|
@@ -396,6 +399,9 @@
|
|
|
396
399
|
.w-\[30px\] {
|
|
397
400
|
width: 30px;
|
|
398
401
|
}
|
|
402
|
+
.w-\[34px\] {
|
|
403
|
+
width: 34px;
|
|
404
|
+
}
|
|
399
405
|
.w-\[50\%\] {
|
|
400
406
|
width: 50%;
|
|
401
407
|
}
|
|
@@ -500,6 +506,9 @@
|
|
|
500
506
|
.cursor-default {
|
|
501
507
|
cursor: default;
|
|
502
508
|
}
|
|
509
|
+
.cursor-not-allowed {
|
|
510
|
+
cursor: not-allowed;
|
|
511
|
+
}
|
|
503
512
|
.cursor-pointer {
|
|
504
513
|
cursor: pointer;
|
|
505
514
|
}
|
|
@@ -512,18 +521,21 @@
|
|
|
512
521
|
.grid-cols-2 {
|
|
513
522
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
514
523
|
}
|
|
524
|
+
.grid-cols-3 {
|
|
525
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
526
|
+
}
|
|
515
527
|
.grid-cols-4 {
|
|
516
528
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
517
529
|
}
|
|
518
530
|
.grid-cols-\[0\.8fr_auto_26\%_1fr\] {
|
|
519
531
|
grid-template-columns: 0.8fr auto 26% 1fr;
|
|
520
532
|
}
|
|
521
|
-
.grid-cols-\[1\.3fr_2fr_1\.2fr\] {
|
|
522
|
-
grid-template-columns: 1.3fr 2fr 1.2fr;
|
|
523
|
-
}
|
|
524
533
|
.grid-cols-\[1\.5fr_1fr_auto\] {
|
|
525
534
|
grid-template-columns: 1.5fr 1fr auto;
|
|
526
535
|
}
|
|
536
|
+
.grid-cols-\[23\%_50\%_27\%\] {
|
|
537
|
+
grid-template-columns: 23% 50% 27%;
|
|
538
|
+
}
|
|
527
539
|
.grid-cols-\[26px_auto_26\%_1fr\] {
|
|
528
540
|
grid-template-columns: 26px auto 26% 1fr;
|
|
529
541
|
}
|
|
@@ -630,15 +642,15 @@
|
|
|
630
642
|
.rounded-\[10px\] {
|
|
631
643
|
border-radius: 10px;
|
|
632
644
|
}
|
|
633
|
-
.rounded-\[12px\] {
|
|
634
|
-
border-radius: 12px;
|
|
635
|
-
}
|
|
636
645
|
.rounded-\[14px\] {
|
|
637
646
|
border-radius: 14px;
|
|
638
647
|
}
|
|
639
648
|
.rounded-\[15px\] {
|
|
640
649
|
border-radius: 15px;
|
|
641
650
|
}
|
|
651
|
+
.rounded-\[16px\] {
|
|
652
|
+
border-radius: 16px;
|
|
653
|
+
}
|
|
642
654
|
.rounded-\[18px\] {
|
|
643
655
|
border-radius: 18px;
|
|
644
656
|
}
|
|
@@ -758,6 +770,12 @@
|
|
|
758
770
|
.bg-\[\#0C1421\] {
|
|
759
771
|
background-color: #0C1421;
|
|
760
772
|
}
|
|
773
|
+
.bg-\[\#2d374d\] {
|
|
774
|
+
background-color: #2d374d;
|
|
775
|
+
}
|
|
776
|
+
.bg-\[\#222b3d\] {
|
|
777
|
+
background-color: #222b3d;
|
|
778
|
+
}
|
|
761
779
|
.bg-\[\#E6E6E6\] {
|
|
762
780
|
background-color: #E6E6E6;
|
|
763
781
|
}
|
|
@@ -846,6 +864,9 @@
|
|
|
846
864
|
.px-\[20px\] {
|
|
847
865
|
padding-inline: 20px;
|
|
848
866
|
}
|
|
867
|
+
.px-\[22px\] {
|
|
868
|
+
padding-inline: 22px;
|
|
869
|
+
}
|
|
849
870
|
.py-\[2px\] {
|
|
850
871
|
padding-block: 2px;
|
|
851
872
|
}
|
|
@@ -894,6 +915,9 @@
|
|
|
894
915
|
.pt-\[50px\] {
|
|
895
916
|
padding-top: 50px;
|
|
896
917
|
}
|
|
918
|
+
.pr-\[10px\] {
|
|
919
|
+
padding-right: 10px;
|
|
920
|
+
}
|
|
897
921
|
.pr-\[15px\] {
|
|
898
922
|
padding-right: 15px;
|
|
899
923
|
}
|
|
@@ -924,6 +948,9 @@
|
|
|
924
948
|
.pl-\[6px\] {
|
|
925
949
|
padding-left: 6px;
|
|
926
950
|
}
|
|
951
|
+
.pl-\[22px\] {
|
|
952
|
+
padding-left: 22px;
|
|
953
|
+
}
|
|
927
954
|
.text-center {
|
|
928
955
|
text-align: center;
|
|
929
956
|
}
|
|
@@ -969,9 +996,15 @@
|
|
|
969
996
|
.text-\[18px\] {
|
|
970
997
|
font-size: 18px;
|
|
971
998
|
}
|
|
999
|
+
.text-\[20px\] {
|
|
1000
|
+
font-size: 20px;
|
|
1001
|
+
}
|
|
972
1002
|
.text-\[22px\] {
|
|
973
1003
|
font-size: 22px;
|
|
974
1004
|
}
|
|
1005
|
+
.text-\[25px\] {
|
|
1006
|
+
font-size: 25px;
|
|
1007
|
+
}
|
|
975
1008
|
.text-\[26px\] {
|
|
976
1009
|
font-size: 26px;
|
|
977
1010
|
}
|
|
@@ -1092,6 +1125,9 @@
|
|
|
1092
1125
|
.opacity-0 {
|
|
1093
1126
|
opacity: 0%;
|
|
1094
1127
|
}
|
|
1128
|
+
.opacity-50 {
|
|
1129
|
+
opacity: 50%;
|
|
1130
|
+
}
|
|
1095
1131
|
.opacity-100 {
|
|
1096
1132
|
opacity: 100%;
|
|
1097
1133
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
declare const FeatureServiceUi: ({ serviceItem, showTopLabel, colors, isSoldOut, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, }: {
|
|
2
|
+
declare const FeatureServiceUi: ({ serviceItem, showTopLabel, colors, isSoldOut, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, isFeatureDropDownExpand, onToggleExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onBookButtonPress, }: {
|
|
3
3
|
serviceItem: any;
|
|
4
4
|
showTopLabel: any;
|
|
5
5
|
colors: any;
|
|
@@ -9,5 +9,11 @@ declare const FeatureServiceUi: ({ serviceItem, showTopLabel, colors, isSoldOut,
|
|
|
9
9
|
cityDestination: any;
|
|
10
10
|
renderIcon: any;
|
|
11
11
|
viewersConfig: any;
|
|
12
|
+
isFeatureDropDownExpand: any;
|
|
13
|
+
onToggleExpand: any;
|
|
14
|
+
ticketQuantity?: number;
|
|
15
|
+
onIncreaseTicketQuantity: any;
|
|
16
|
+
onDecreaseTicketQuantity: any;
|
|
17
|
+
onBookButtonPress: any;
|
|
12
18
|
}) => React.JSX.Element;
|
|
13
19
|
export default FeatureServiceUi;
|
|
@@ -77,11 +77,14 @@ const AssuranceIcon = ({ type }) => {
|
|
|
77
77
|
React.createElement("path", { 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", stroke: "currentColor", strokeWidth: "1.6", strokeLinejoin: "round" }),
|
|
78
78
|
React.createElement("path", { d: "m6.9 9.7 2.1 2.1 4.3-4.4", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round" })));
|
|
79
79
|
};
|
|
80
|
-
const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, }) => {
|
|
80
|
+
const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, isFeatureDropDownExpand, onToggleExpand, ticketQuantity = 1, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onBookButtonPress, }) => {
|
|
81
81
|
var _a, _b, _c, _d, _e;
|
|
82
82
|
const operators = ((_a = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operators) === null || _a === void 0 ? void 0 : _a.length) > 0
|
|
83
83
|
? serviceItem.operators
|
|
84
84
|
: HARDCODED_OPERATORS;
|
|
85
|
+
const isItemExpanded = serviceItem.id === isFeatureDropDownExpand ||
|
|
86
|
+
isFeatureDropDownExpand === true;
|
|
87
|
+
const canDecreaseTicketQuantity = ticketQuantity > 1;
|
|
85
88
|
return (React.createElement("div", {
|
|
86
89
|
// ${
|
|
87
90
|
// serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"
|
|
@@ -118,52 +121,51 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAni
|
|
|
118
121
|
fontVariantNumeric: "tabular-nums",
|
|
119
122
|
display: "inline-block",
|
|
120
123
|
color: "#FF5C60",
|
|
124
|
+
minWidth: "40px",
|
|
121
125
|
} })))),
|
|
122
126
|
React.createElement("div", { id: `service-card-${serviceItem.id}`, className: "bg-[#0C1421] text-white mx-auto relative rounded-[14px] p-[14px] text-[13.33px]" },
|
|
123
|
-
React.createElement("div", { className: "grid grid-cols-[
|
|
124
|
-
React.createElement("div", { className: "flex flex-col justify-between gap-[20px]
|
|
127
|
+
React.createElement("div", { className: "grid grid-cols-[23%_50%_27%] items-stretch" },
|
|
128
|
+
React.createElement("div", { className: "flex flex-col justify-between gap-[20px] my-[14px] pr-[22px]" },
|
|
125
129
|
React.createElement("div", { className: "flex flex-col gap-[8px]" },
|
|
126
130
|
React.createElement("div", { className: "flex items-center gap-[8px]" },
|
|
127
131
|
React.createElement("img", { src: (_b = serviceItem.icons) === null || _b === void 0 ? void 0 : _b.whiteOrigin, alt: "origin", className: `w-[14px] h-[14px] shrink-0 ${isSoldOut ? "grayscale" : ""}` }),
|
|
128
132
|
React.createElement("span", { className: "text-[13px] bold-text" }, cityOrigin === null || cityOrigin === void 0 ? void 0 : cityOrigin.label.split(",")[0])),
|
|
129
133
|
React.createElement("div", { className: "flex items-center gap-[8px]" },
|
|
130
|
-
React.createElement("img", { src: (_c = serviceItem.icons) === null || _c === void 0 ? void 0 : _c.whiteDestination, alt: "destination", className: `w-[
|
|
134
|
+
React.createElement("img", { src: (_c = serviceItem.icons) === null || _c === void 0 ? void 0 : _c.whiteDestination, alt: "destination", className: `w-[14px] h-[14px] shrink-0 ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }),
|
|
131
135
|
React.createElement("span", { className: "text-[13px] bold-text" }, cityDestination === null || cityDestination === void 0 ? void 0 : cityDestination.label.split(",")[0]))),
|
|
132
136
|
React.createElement("div", { className: "flex flex-col gap-[8px]" },
|
|
133
137
|
React.createElement("div", { className: "text-[12px] bold-text whitespace-nowrap" }, "Entre 07:00 AM y 10:00 AM"),
|
|
134
138
|
React.createElement("div", { className: "text-[11px] bold-text" }, "Viernes 23 de mayo")),
|
|
135
139
|
React.createElement("div", { className: "flex flex-col items-start gap-[10px] text-[12px] " },
|
|
136
|
-
React.createElement("div", { className: "flex items-
|
|
140
|
+
React.createElement("div", { className: "flex items-justify gap-[8px]" },
|
|
137
141
|
React.createElement(AssuranceIcon, { type: "pending" }),
|
|
138
142
|
React.createElement("span", { className: "text-[10px]", style: {
|
|
139
143
|
lineHeight: 1.3,
|
|
140
144
|
} }, "Empresa y hora a confirmar luego del pago.")),
|
|
141
|
-
React.createElement("div", { className: "flex items-
|
|
145
|
+
React.createElement("div", { className: "flex items-justify gap-[8px]" },
|
|
142
146
|
React.createElement(AssuranceIcon, { type: "secured" }),
|
|
143
147
|
React.createElement("span", { className: "text-[10px]", style: {
|
|
144
148
|
lineHeight: 1.3,
|
|
145
149
|
} }, "Tu compra est\u00E1 100% asegurada.")))),
|
|
146
|
-
React.createElement("div", { className: "px-[
|
|
150
|
+
React.createElement("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]" },
|
|
147
151
|
React.createElement("div", { className: "text-center" },
|
|
148
152
|
React.createElement("div", { className: "bold-text text-[14px]" }, "3 operadores compitiendo por tu compra")),
|
|
149
|
-
React.createElement("div", { className: "
|
|
150
|
-
width: "140px",
|
|
153
|
+
React.createElement("div", { className: "grid w-full grid-cols-3 items-stretch gap-[14px] mb-[12px]" }, operators.map((op, idx) => (React.createElement("div", { key: idx, className: "flex min-w-0 flex-col items-center justify-center gap-[8px] rounded-[8px]", style: {
|
|
151
154
|
// height: "80px",
|
|
152
155
|
border: "1px solid #363c48",
|
|
153
156
|
backgroundColor: "#1a202e",
|
|
154
|
-
padding: "14px",
|
|
157
|
+
padding: "14px 10px",
|
|
155
158
|
} },
|
|
156
|
-
React.createElement("img", { src: serviceItem.operator_details[0], alt: op.name, className: `h-[24px] w-
|
|
159
|
+
React.createElement("img", { src: serviceItem.operator_details[0], alt: op.name, className: `h-[24px] max-w-full object-contain ${isSoldOut ? "grayscale" : ""}` }),
|
|
157
160
|
React.createElement("span", { className: "text-[11px] truncate max-w-full text-center" }, serviceItem.operator_details[2]),
|
|
158
|
-
React.createElement("div", { className: "bg-[#FF8F45] text-white text-[12px] font-bold px-[
|
|
161
|
+
React.createElement("div", { className: "bg-[#FF8F45] text-white text-[12px] font-bold px-[10px] py-[4px] rounded-[4px] bold-text whitespace-nowrap" },
|
|
159
162
|
React.createElement("span", null, op === null || op === void 0 ? void 0 : op.time)),
|
|
160
163
|
React.createElement("span", { className: "text-[10px] mt-[6px]" }, op === null || op === void 0 ? void 0 : op.seatsAvailable))))),
|
|
161
|
-
React.createElement("div", { className: "flex items-center justify-center gap-[6px] text-[12px]", style: {
|
|
164
|
+
React.createElement("div", { className: "flex w-full items-center justify-center gap-[6px] text-[12px]", style: {
|
|
162
165
|
border: "1px solid #363c48",
|
|
163
166
|
backgroundColor: "#1a202e",
|
|
164
167
|
padding: "8px 14px",
|
|
165
168
|
borderRadius: "24px",
|
|
166
|
-
width: "430px",
|
|
167
169
|
} },
|
|
168
170
|
React.createElement("img", { src: (_d = serviceItem.icons) === null || _d === void 0 ? void 0 : _d.userIcon, alt: "eye", style: { width: "16px", height: "16px" } }),
|
|
169
171
|
React.createElement("span", null,
|
|
@@ -183,14 +185,38 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAni
|
|
|
183
185
|
React.createElement("span", { className: "bold-text", ref: (node) => commonService.startComprandoCount(node, 4, 16), style: { fontVariantNumeric: "tabular-nums" } }),
|
|
184
186
|
" ",
|
|
185
187
|
"han comprado"))),
|
|
186
|
-
React.createElement("div", { className: "flex flex-col
|
|
188
|
+
React.createElement("div", { className: "flex flex-col justify-center gap-[12px] py-[2px] pl-[22px] pr-[10px] relative mb-[16px]" },
|
|
187
189
|
React.createElement("div", { className: "flex flex-col gap-[6px] ", style: {
|
|
188
190
|
alignItems: "center",
|
|
189
191
|
} },
|
|
190
192
|
React.createElement("span", { className: "text-[#FF8F45] bold-text text-[26px] leading-tight" }, "60% OFF"),
|
|
191
|
-
React.createElement("span", { className: "text-[
|
|
193
|
+
React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative", style: { position: "relative" } },
|
|
194
|
+
"$10.000",
|
|
195
|
+
React.createElement("span", { style: {
|
|
196
|
+
position: "absolute",
|
|
197
|
+
left: "-2px",
|
|
198
|
+
top: "50%",
|
|
199
|
+
width: "calc(100% + 4px)",
|
|
200
|
+
height: "1px",
|
|
201
|
+
backgroundColor: "#FF5C60",
|
|
202
|
+
transform: "rotate(-10deg)",
|
|
203
|
+
transformOrigin: "center",
|
|
204
|
+
} })),
|
|
192
205
|
React.createElement("span", { className: "text-white bold-text text-[28px] leading-none" }, "$4.000")),
|
|
193
|
-
React.createElement("
|
|
206
|
+
React.createElement("div", { className: "mt-[4px] flex flex-col items-center gap-[8px]" },
|
|
207
|
+
React.createElement("span", { className: "text-[12px] text-white" }, "\u00BFCu\u00E1ntos pasajes quieres?"),
|
|
208
|
+
React.createElement("div", { className: "flex w-full items-center justify-between", style: {
|
|
209
|
+
border: "1px solid #363c48",
|
|
210
|
+
backgroundColor: "#1a202e",
|
|
211
|
+
padding: "6px 14px",
|
|
212
|
+
borderRadius: "14px",
|
|
213
|
+
} },
|
|
214
|
+
React.createElement("button", { type: "button", "aria-label": "Disminuir pasajes", disabled: !canDecreaseTicketQuantity, onClick: () => onDecreaseTicketQuantity === null || onDecreaseTicketQuantity === void 0 ? void 0 : onDecreaseTicketQuantity(serviceItem), className: `flex h-[34px] w-[34px] items-center justify-center rounded-full border-none text-[25px] leading-none text-white ${canDecreaseTicketQuantity
|
|
215
|
+
? "cursor-pointer bg-[#2d374d]"
|
|
216
|
+
: "cursor-not-allowed bg-[#222b3d] opacity-50"}` }, "-"),
|
|
217
|
+
React.createElement("span", { className: "bold-text text-[20px] text-white" }, ticketQuantity),
|
|
218
|
+
React.createElement("button", { type: "button", "aria-label": "Aumentar pasajes", onClick: () => onIncreaseTicketQuantity === null || onIncreaseTicketQuantity === void 0 ? void 0 : onIncreaseTicketQuantity(serviceItem), className: "flex h-[34px] w-[34px] cursor-pointer items-center justify-center rounded-full border-none bg-[#2d374d] text-[25px] leading-none text-white" }, "+"))),
|
|
219
|
+
React.createElement("button", { type: "button", onClick: onBookButtonPress, 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", style: {
|
|
194
220
|
backgroundColor: "#FF5C60",
|
|
195
221
|
} },
|
|
196
222
|
React.createElement(LottiePlayer
|
|
@@ -199,17 +225,22 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAni
|
|
|
199
225
|
// animationData={serviceItem.icons.flexibleAnim}
|
|
200
226
|
animationData: getAnimationIcon("thunderAnimation"), width: "18px", height: "18px" }),
|
|
201
227
|
React.createElement("span", { className: "whitespace-nowrap" }, "\u00A1Lo quiero!"))),
|
|
202
|
-
React.createElement("div", { className:
|
|
228
|
+
React.createElement("div", { className: `absolute bottom-[11px] right-[18px] cursor-pointer transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`, onClick: onToggleExpand },
|
|
203
229
|
React.createElement("img", { src: (_e = serviceItem.icons) === null || _e === void 0 ? void 0 : _e.downArrow, alt: "down arrow", style: {
|
|
204
230
|
width: "14px",
|
|
205
231
|
height: "8px",
|
|
206
232
|
filter: "brightness(0) invert(1)",
|
|
207
233
|
} })))),
|
|
208
|
-
React.createElement("div", { className: "
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
234
|
+
React.createElement("div", { className: "grid", style: {
|
|
235
|
+
gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
|
|
236
|
+
opacity: isItemExpanded ? 1 : 0,
|
|
237
|
+
transition: "grid-template-rows 300ms ease-in-out, opacity 250ms ease-in-out",
|
|
238
|
+
} },
|
|
239
|
+
React.createElement("div", { className: `min-h-0 overflow-hidden px-[16px] text-[13.33px] ${isItemExpanded ? "pt-[14px] pb-[6px]" : "py-0"}`, style: { transition: "padding 300ms ease-in-out" } },
|
|
240
|
+
React.createElement("span", { className: "bold-text" }, "\u00BFC\u00F3mo funciona?"),
|
|
241
|
+
React.createElement("div", { className: "mt-[14px] grid grid-cols-4 gap-[20px] px-[16px] " }, HOW_IT_WORKS_STEPS.map((step) => (React.createElement("div", { key: step.name, className: "flex flex-col items-center text-center text-[#272727]" },
|
|
242
|
+
React.createElement(FeatureStepIcon, { icon: step.icon }),
|
|
243
|
+
React.createElement("span", { className: "bold-text mt-[10px] text-[12px] leading-[14px]" }, step.name),
|
|
244
|
+
React.createElement("span", { className: "mt-[2px] max-w-[220px] text-[12px] leading-[14px] text-[#4a4a4a]" }, step.text))))))))));
|
|
214
245
|
};
|
|
215
246
|
export default FeatureServiceUi;
|
|
@@ -296,10 +296,14 @@ const commonService = {
|
|
|
296
296
|
startViewerCount: (node, viewersConfig) => {
|
|
297
297
|
if (!node || !viewersConfig)
|
|
298
298
|
return;
|
|
299
|
+
const { min, max, interval = 5000 } = viewersConfig;
|
|
300
|
+
const configKey = `${min}-${max}-${interval}`;
|
|
301
|
+
if (node.dataset.viewerId && node.dataset.viewerConfig === configKey) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
299
304
|
const prevId = node.dataset.viewerId;
|
|
300
305
|
if (prevId)
|
|
301
306
|
clearInterval(Number(prevId));
|
|
302
|
-
const { min, max, interval = 5000 } = viewersConfig;
|
|
303
307
|
const clamp = (v) => Math.min(max, Math.max(min, v));
|
|
304
308
|
const initialValue = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
305
309
|
node.textContent = String(initialValue);
|
|
@@ -310,6 +314,7 @@ const commonService = {
|
|
|
310
314
|
node.textContent = String(clamp(Math.round(next)));
|
|
311
315
|
}, interval);
|
|
312
316
|
node.dataset.viewerId = String(id);
|
|
317
|
+
node.dataset.viewerConfig = configKey;
|
|
313
318
|
},
|
|
314
319
|
startCountdown: (node, countdownSeconds = 599) => {
|
|
315
320
|
if (!node)
|
|
@@ -339,6 +344,10 @@ const commonService = {
|
|
|
339
344
|
startComprandoCount: (node, min = 4, max = 16) => {
|
|
340
345
|
if (!node)
|
|
341
346
|
return;
|
|
347
|
+
const configKey = `${min}-${max}`;
|
|
348
|
+
if (node.dataset.comprandoId && node.dataset.comprandoConfig === configKey) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
342
351
|
const prevId = node.dataset.comprandoId;
|
|
343
352
|
if (prevId)
|
|
344
353
|
clearInterval(Number(prevId));
|
|
@@ -355,6 +364,7 @@ const commonService = {
|
|
|
355
364
|
node.textContent = String(next);
|
|
356
365
|
}, 5000); // Update every 5 seconds
|
|
357
366
|
node.dataset.comprandoId = String(id);
|
|
367
|
+
node.dataset.comprandoConfig = configKey;
|
|
358
368
|
},
|
|
359
369
|
};
|
|
360
370
|
export default commonService;
|
package/package.json
CHANGED
package/src/KuposUIComponent.tsx
CHANGED
|
@@ -32,6 +32,9 @@ interface KuposUIComponentProps {
|
|
|
32
32
|
orignLabel?: string;
|
|
33
33
|
destinationLabel?: string;
|
|
34
34
|
t?: (key: string) => string;
|
|
35
|
+
ticketQuantity?: number;
|
|
36
|
+
onIncreaseTicketQuantity?: (serviceItem: any) => void;
|
|
37
|
+
onDecreaseTicketQuantity?: (serviceItem: any) => void;
|
|
35
38
|
|
|
36
39
|
// New ServiceItem props
|
|
37
40
|
id?: string;
|
|
@@ -123,6 +123,11 @@ function ServiceItemPB({
|
|
|
123
123
|
showLoginModal,
|
|
124
124
|
isLoggedIn,
|
|
125
125
|
showLoginOption,
|
|
126
|
+
isFeatureDropDownExpand,
|
|
127
|
+
setIsFeatureDropDownExpand,
|
|
128
|
+
ticketQuantity,
|
|
129
|
+
onIncreaseTicketQuantity,
|
|
130
|
+
onDecreaseTicketQuantity,
|
|
126
131
|
}: ServiceItemProps & { currencySign?: string }): React.ReactElement {
|
|
127
132
|
const getAnimationIcon = (icon: string) => {
|
|
128
133
|
const animation = ANIMATION_MAP[icon];
|
|
@@ -433,6 +438,20 @@ function ServiceItemPB({
|
|
|
433
438
|
cityDestination={cityDestination}
|
|
434
439
|
renderIcon={renderIcon}
|
|
435
440
|
viewersConfig={viewersConfig}
|
|
441
|
+
isFeatureDropDownExpand={isFeatureDropDownExpand}
|
|
442
|
+
ticketQuantity={ticketQuantity}
|
|
443
|
+
onIncreaseTicketQuantity={onIncreaseTicketQuantity}
|
|
444
|
+
onDecreaseTicketQuantity={onDecreaseTicketQuantity}
|
|
445
|
+
onBookButtonPress={onBookButtonPress}
|
|
446
|
+
onToggleExpand={() =>
|
|
447
|
+
setIsFeatureDropDownExpand &&
|
|
448
|
+
setIsFeatureDropDownExpand(
|
|
449
|
+
isFeatureDropDownExpand === serviceItem.id ||
|
|
450
|
+
isFeatureDropDownExpand === true
|
|
451
|
+
? null
|
|
452
|
+
: serviceItem.id,
|
|
453
|
+
)
|
|
454
|
+
}
|
|
436
455
|
/>
|
|
437
456
|
) : (
|
|
438
457
|
<div
|
|
@@ -222,6 +222,11 @@ export interface ServiceItemProps {
|
|
|
222
222
|
isAllinBus?: boolean;
|
|
223
223
|
isExpand?: any;
|
|
224
224
|
setIsExpand?: (value: any) => void;
|
|
225
|
+
isFeatureDropDownExpand?: any;
|
|
226
|
+
setIsFeatureDropDownExpand?: (value: any) => void;
|
|
227
|
+
ticketQuantity?: number;
|
|
228
|
+
onIncreaseTicketQuantity?: (serviceItem: ServiceItemProps["serviceItem"]) => void;
|
|
229
|
+
onDecreaseTicketQuantity?: (serviceItem: ServiceItemProps["serviceItem"]) => void;
|
|
225
230
|
coachKey?: number
|
|
226
231
|
viewersConfig?: {
|
|
227
232
|
min: number;
|
|
@@ -217,12 +217,23 @@ const FeatureServiceUi = ({
|
|
|
217
217
|
cityDestination,
|
|
218
218
|
renderIcon,
|
|
219
219
|
viewersConfig,
|
|
220
|
+
isFeatureDropDownExpand,
|
|
221
|
+
onToggleExpand,
|
|
222
|
+
ticketQuantity = 1,
|
|
223
|
+
onIncreaseTicketQuantity,
|
|
224
|
+
onDecreaseTicketQuantity,
|
|
225
|
+
onBookButtonPress,
|
|
220
226
|
}) => {
|
|
221
227
|
const operators =
|
|
222
228
|
serviceItem?.operators?.length > 0
|
|
223
229
|
? serviceItem.operators
|
|
224
230
|
: HARDCODED_OPERATORS;
|
|
225
231
|
|
|
232
|
+
const isItemExpanded =
|
|
233
|
+
serviceItem.id === isFeatureDropDownExpand ||
|
|
234
|
+
isFeatureDropDownExpand === true;
|
|
235
|
+
const canDecreaseTicketQuantity = ticketQuantity > 1;
|
|
236
|
+
|
|
226
237
|
return (
|
|
227
238
|
<div
|
|
228
239
|
// ${
|
|
@@ -271,6 +282,7 @@ const FeatureServiceUi = ({
|
|
|
271
282
|
fontVariantNumeric: "tabular-nums",
|
|
272
283
|
display: "inline-block",
|
|
273
284
|
color: "#FF5C60",
|
|
285
|
+
minWidth: "40px",
|
|
274
286
|
}}
|
|
275
287
|
/>
|
|
276
288
|
</span>
|
|
@@ -280,9 +292,9 @@ const FeatureServiceUi = ({
|
|
|
280
292
|
id={`service-card-${serviceItem.id}`}
|
|
281
293
|
className="bg-[#0C1421] text-white mx-auto relative rounded-[14px] p-[14px] text-[13.33px]"
|
|
282
294
|
>
|
|
283
|
-
<div className="grid grid-cols-[
|
|
295
|
+
<div className="grid grid-cols-[23%_50%_27%] items-stretch">
|
|
284
296
|
{/* LEFT: origin, destination, flexible, time, confirmed seat */}
|
|
285
|
-
<div className="flex flex-col justify-between gap-[20px]
|
|
297
|
+
<div className="flex flex-col justify-between gap-[20px] my-[14px] pr-[22px]">
|
|
286
298
|
<div className="flex flex-col gap-[8px]">
|
|
287
299
|
<div className="flex items-center gap-[8px]">
|
|
288
300
|
<img
|
|
@@ -300,7 +312,7 @@ const FeatureServiceUi = ({
|
|
|
300
312
|
<img
|
|
301
313
|
src={serviceItem.icons?.whiteDestination}
|
|
302
314
|
alt="destination"
|
|
303
|
-
className={`w-[
|
|
315
|
+
className={`w-[14px] h-[14px] shrink-0 ${
|
|
304
316
|
isSoldOut ? "grayscale" : ""
|
|
305
317
|
}`}
|
|
306
318
|
style={{ opacity: isSoldOut ? 0.5 : 1 }}
|
|
@@ -312,23 +324,6 @@ const FeatureServiceUi = ({
|
|
|
312
324
|
</div>
|
|
313
325
|
|
|
314
326
|
<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
327
|
<div className="text-[12px] bold-text whitespace-nowrap">
|
|
333
328
|
Entre 07:00 AM y 10:00 AM
|
|
334
329
|
</div>
|
|
@@ -336,7 +331,7 @@ const FeatureServiceUi = ({
|
|
|
336
331
|
</div>
|
|
337
332
|
|
|
338
333
|
<div className="flex flex-col items-start gap-[10px] text-[12px] ">
|
|
339
|
-
<div className="flex items-
|
|
334
|
+
<div className="flex items-justify gap-[8px]">
|
|
340
335
|
<AssuranceIcon type="pending" />
|
|
341
336
|
|
|
342
337
|
<span
|
|
@@ -348,7 +343,7 @@ const FeatureServiceUi = ({
|
|
|
348
343
|
Empresa y hora a confirmar luego del pago.
|
|
349
344
|
</span>
|
|
350
345
|
</div>
|
|
351
|
-
<div className="flex items-
|
|
346
|
+
<div className="flex items-justify gap-[8px]">
|
|
352
347
|
<AssuranceIcon type="secured" />
|
|
353
348
|
|
|
354
349
|
<span
|
|
@@ -364,7 +359,7 @@ const FeatureServiceUi = ({
|
|
|
364
359
|
</div>
|
|
365
360
|
|
|
366
361
|
{/* MIDDLE: competing operators + viewers */}
|
|
367
|
-
<div className="px-[
|
|
362
|
+
<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
363
|
<div className="text-center">
|
|
369
364
|
<div className="bold-text text-[14px]">
|
|
370
365
|
3 operadores compitiendo por tu compra
|
|
@@ -374,30 +369,29 @@ const FeatureServiceUi = ({
|
|
|
374
369
|
</div> */}
|
|
375
370
|
</div>
|
|
376
371
|
|
|
377
|
-
<div className="
|
|
372
|
+
<div className="grid w-full grid-cols-3 items-stretch gap-[14px] mb-[12px]">
|
|
378
373
|
{operators.map((op, idx) => (
|
|
379
374
|
<div
|
|
380
375
|
key={idx}
|
|
381
|
-
className="flex flex-col items-center justify-center gap-[8px] rounded-[8px]"
|
|
376
|
+
className="flex min-w-0 flex-col items-center justify-center gap-[8px] rounded-[8px]"
|
|
382
377
|
style={{
|
|
383
|
-
width: "140px",
|
|
384
378
|
// height: "80px",
|
|
385
379
|
border: "1px solid #363c48",
|
|
386
380
|
backgroundColor: "#1a202e",
|
|
387
|
-
padding: "14px",
|
|
381
|
+
padding: "14px 10px",
|
|
388
382
|
}}
|
|
389
383
|
>
|
|
390
384
|
<img
|
|
391
385
|
src={serviceItem.operator_details[0]}
|
|
392
386
|
alt={op.name}
|
|
393
|
-
className={`h-[24px] w-
|
|
387
|
+
className={`h-[24px] max-w-full object-contain ${
|
|
394
388
|
isSoldOut ? "grayscale" : ""
|
|
395
389
|
}`}
|
|
396
390
|
/>
|
|
397
391
|
<span className="text-[11px] truncate max-w-full text-center">
|
|
398
392
|
{serviceItem.operator_details[2]}
|
|
399
393
|
</span>
|
|
400
|
-
<div className="bg-[#FF8F45] text-white text-[12px] font-bold px-[
|
|
394
|
+
<div className="bg-[#FF8F45] text-white text-[12px] font-bold px-[10px] py-[4px] rounded-[4px] bold-text whitespace-nowrap">
|
|
401
395
|
<span>{op?.time}</span>
|
|
402
396
|
</div>
|
|
403
397
|
<span className="text-[10px] mt-[6px]">
|
|
@@ -408,13 +402,12 @@ const FeatureServiceUi = ({
|
|
|
408
402
|
</div>
|
|
409
403
|
|
|
410
404
|
<div
|
|
411
|
-
className="flex items-center justify-center gap-[6px] text-[12px]"
|
|
405
|
+
className="flex w-full items-center justify-center gap-[6px] text-[12px]"
|
|
412
406
|
style={{
|
|
413
407
|
border: "1px solid #363c48",
|
|
414
408
|
backgroundColor: "#1a202e",
|
|
415
409
|
padding: "8px 14px",
|
|
416
410
|
borderRadius: "24px",
|
|
417
|
-
width: "430px",
|
|
418
411
|
}}
|
|
419
412
|
>
|
|
420
413
|
<img
|
|
@@ -457,7 +450,7 @@ const FeatureServiceUi = ({
|
|
|
457
450
|
</div>
|
|
458
451
|
|
|
459
452
|
{/* RIGHT: price + button */}
|
|
460
|
-
<div className="flex flex-col
|
|
453
|
+
<div className="flex flex-col justify-center gap-[12px] py-[2px] pl-[22px] pr-[10px] relative mb-[16px]">
|
|
461
454
|
<div
|
|
462
455
|
className="flex flex-col gap-[6px] "
|
|
463
456
|
style={{
|
|
@@ -467,16 +460,78 @@ const FeatureServiceUi = ({
|
|
|
467
460
|
<span className="text-[#FF8F45] bold-text text-[26px] leading-tight">
|
|
468
461
|
60% OFF
|
|
469
462
|
</span>
|
|
470
|
-
<span className="text-[#666] text-[14px] line-through">
|
|
463
|
+
{/* <span className="text-[#666] text-[14px] line-through">
|
|
464
|
+
$10.000
|
|
465
|
+
</span> */}
|
|
466
|
+
<span
|
|
467
|
+
className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative"
|
|
468
|
+
style={{ position: "relative" }}
|
|
469
|
+
>
|
|
471
470
|
$10.000
|
|
471
|
+
<span
|
|
472
|
+
style={{
|
|
473
|
+
position: "absolute",
|
|
474
|
+
left: "-2px",
|
|
475
|
+
top: "50%",
|
|
476
|
+
width: "calc(100% + 4px)",
|
|
477
|
+
height: "1px",
|
|
478
|
+
|
|
479
|
+
backgroundColor: "#FF5C60",
|
|
480
|
+
|
|
481
|
+
transform: "rotate(-10deg)",
|
|
482
|
+
transformOrigin: "center",
|
|
483
|
+
}}
|
|
484
|
+
/>
|
|
472
485
|
</span>
|
|
473
486
|
<span className="text-white bold-text text-[28px] leading-none">
|
|
474
487
|
$4.000
|
|
475
488
|
</span>
|
|
476
489
|
</div>
|
|
477
490
|
|
|
491
|
+
<div className="mt-[4px] flex flex-col items-center gap-[8px]">
|
|
492
|
+
<span className="text-[12px] text-white">
|
|
493
|
+
¿Cuántos pasajes quieres?
|
|
494
|
+
</span>
|
|
495
|
+
<div
|
|
496
|
+
className="flex w-full items-center justify-between"
|
|
497
|
+
style={{
|
|
498
|
+
border: "1px solid #363c48",
|
|
499
|
+
backgroundColor: "#1a202e",
|
|
500
|
+
padding: "6px 14px",
|
|
501
|
+
borderRadius: "14px",
|
|
502
|
+
}}
|
|
503
|
+
>
|
|
504
|
+
<button
|
|
505
|
+
type="button"
|
|
506
|
+
aria-label="Disminuir pasajes"
|
|
507
|
+
disabled={!canDecreaseTicketQuantity}
|
|
508
|
+
onClick={() => onDecreaseTicketQuantity?.(serviceItem)}
|
|
509
|
+
className={`flex h-[34px] w-[34px] items-center justify-center rounded-full border-none text-[25px] leading-none text-white ${
|
|
510
|
+
canDecreaseTicketQuantity
|
|
511
|
+
? "cursor-pointer bg-[#2d374d]"
|
|
512
|
+
: "cursor-not-allowed bg-[#222b3d] opacity-50"
|
|
513
|
+
}`}
|
|
514
|
+
>
|
|
515
|
+
-
|
|
516
|
+
</button>
|
|
517
|
+
<span className="bold-text text-[20px] text-white">
|
|
518
|
+
{ticketQuantity}
|
|
519
|
+
</span>
|
|
520
|
+
<button
|
|
521
|
+
type="button"
|
|
522
|
+
aria-label="Aumentar pasajes"
|
|
523
|
+
onClick={() => onIncreaseTicketQuantity?.(serviceItem)}
|
|
524
|
+
className="flex h-[34px] w-[34px] cursor-pointer items-center justify-center rounded-full border-none bg-[#2d374d] text-[25px] leading-none text-white"
|
|
525
|
+
>
|
|
526
|
+
+
|
|
527
|
+
</button>
|
|
528
|
+
</div>
|
|
529
|
+
</div>
|
|
530
|
+
|
|
478
531
|
<button
|
|
479
|
-
|
|
532
|
+
type="button"
|
|
533
|
+
onClick={onBookButtonPress}
|
|
534
|
+
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
535
|
style={{
|
|
481
536
|
backgroundColor: "#FF5C60",
|
|
482
537
|
}}
|
|
@@ -491,7 +546,10 @@ const FeatureServiceUi = ({
|
|
|
491
546
|
</button>
|
|
492
547
|
</div>
|
|
493
548
|
|
|
494
|
-
<div
|
|
549
|
+
<div
|
|
550
|
+
className={`absolute bottom-[11px] right-[18px] cursor-pointer transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`}
|
|
551
|
+
onClick={onToggleExpand}
|
|
552
|
+
>
|
|
495
553
|
<img
|
|
496
554
|
src={serviceItem.icons?.downArrow}
|
|
497
555
|
alt="down arrow"
|
|
@@ -504,24 +562,39 @@ const FeatureServiceUi = ({
|
|
|
504
562
|
</div>
|
|
505
563
|
</div>
|
|
506
564
|
</div>
|
|
507
|
-
<div
|
|
508
|
-
|
|
565
|
+
<div
|
|
566
|
+
className="grid"
|
|
567
|
+
style={{
|
|
568
|
+
gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
|
|
569
|
+
opacity: isItemExpanded ? 1 : 0,
|
|
570
|
+
transition:
|
|
571
|
+
"grid-template-rows 300ms ease-in-out, opacity 250ms ease-in-out",
|
|
572
|
+
}}
|
|
573
|
+
>
|
|
574
|
+
<div
|
|
575
|
+
className={`min-h-0 overflow-hidden px-[16px] text-[13.33px] ${
|
|
576
|
+
isItemExpanded ? "pt-[14px] pb-[6px]" : "py-0"
|
|
577
|
+
}`}
|
|
578
|
+
style={{ transition: "padding 300ms ease-in-out" }}
|
|
579
|
+
>
|
|
580
|
+
<span className="bold-text">¿Cómo funciona?</span>
|
|
509
581
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
582
|
+
<div className="mt-[14px] grid grid-cols-4 gap-[20px] px-[16px] ">
|
|
583
|
+
{HOW_IT_WORKS_STEPS.map((step) => (
|
|
584
|
+
<div
|
|
585
|
+
key={step.name}
|
|
586
|
+
className="flex flex-col items-center text-center text-[#272727]"
|
|
587
|
+
>
|
|
588
|
+
<FeatureStepIcon icon={step.icon} />
|
|
589
|
+
<span className="bold-text mt-[10px] text-[12px] leading-[14px]">
|
|
590
|
+
{step.name}
|
|
591
|
+
</span>
|
|
592
|
+
<span className="mt-[2px] max-w-[220px] text-[12px] leading-[14px] text-[#4a4a4a]">
|
|
593
|
+
{step.text}
|
|
594
|
+
</span>
|
|
595
|
+
</div>
|
|
596
|
+
))}
|
|
597
|
+
</div>
|
|
525
598
|
</div>
|
|
526
599
|
</div>
|
|
527
600
|
</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
|
|