kupos-ui-components-lib 9.7.0 → 9.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/KuposUIComponent.d.ts +3 -0
  2. package/dist/assets/images/anims/service_list/users_anim.json +1 -0
  3. package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
  4. package/dist/components/ServiceItem/ServiceItemDesktop.js +10 -2
  5. package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
  6. package/dist/components/ServiceItem/ServiceItemMobile.js +16 -7
  7. package/dist/components/ServiceItem/mobileTypes.d.ts +27 -0
  8. package/dist/components/ServiceItem/types.d.ts +10 -0
  9. package/dist/styles.css +62 -14
  10. package/dist/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.d.ts +18 -0
  11. package/dist/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.js +233 -0
  12. package/dist/ui/FeatureServiceUI/FeatureServiceUi.d.ts +7 -2
  13. package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +109 -92
  14. package/dist/ui/SeatSection/SeatSection.js +1 -1
  15. package/dist/utils/CommonService.js +11 -1
  16. package/package.json +1 -1
  17. package/src/KuposUIComponent.tsx +3 -0
  18. package/src/assets/images/anims/service_list/users_anim.json +1 -0
  19. package/src/components/ServiceItem/ServiceItemDesktop.tsx +23 -1
  20. package/src/components/ServiceItem/ServiceItemMobile.tsx +331 -286
  21. package/src/components/ServiceItem/mobileTypes.ts +22 -0
  22. package/src/components/ServiceItem/types.ts +11 -1
  23. package/src/ui/FeaturServiceUiMobile/FeatureServiceUiMobile.tsx +790 -0
  24. package/src/ui/FeatureServiceUI/FeatureServiceUi.tsx +181 -253
  25. package/src/ui/SeatSection/SeatSection.tsx +1 -1
  26. package/src/utils/CommonService.ts +13 -1
@@ -0,0 +1,233 @@
1
+ import React from "react";
2
+ import LottiePlayer from "../../assets/LottiePlayer";
3
+ import commonService from "../../utils/CommonService";
4
+ const HARDCODED_OPERATORS = [
5
+ {
6
+ logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Turbus_logo.svg/320px-Turbus_logo.svg.png",
7
+ name: "Turbus",
8
+ time: "7:00 am",
9
+ seatsAvailable: "3 disponibles",
10
+ },
11
+ {
12
+ logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Pullman_Bus_logo.svg/320px-Pullman_Bus_logo.svg.png",
13
+ name: "Pullmanbus",
14
+ time: "8:00 am",
15
+ seatsAvailable: "5 disponibles",
16
+ },
17
+ {
18
+ logo: "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Turbus_logo.svg/320px-Turbus_logo.svg.png",
19
+ name: "Expreso Santa C...",
20
+ time: "9:00 am",
21
+ seatsAvailable: "3 disponibles",
22
+ },
23
+ ];
24
+ const HARDCODED_COUNTDOWN = "09:55";
25
+ const HOW_IT_WORKS_STEPS = [
26
+ {
27
+ icon: "flexible",
28
+ name: "1. Salida flexible",
29
+ text: "Viajas en un horario entre las 07:00 y las 10:00 AM del día elegido.",
30
+ },
31
+ {
32
+ icon: "bus",
33
+ name: "2. Empresa asignada",
34
+ text: "Una de las empresas disponibles confirma tu viaje una vez pagado.",
35
+ },
36
+ {
37
+ icon: "price",
38
+ name: "3. Precio garantizado",
39
+ text: "Al seleccionar este servicio aseguras el precio reducido.",
40
+ },
41
+ {
42
+ icon: "ticket",
43
+ name: "4. ¡Listo!",
44
+ text: "Recibe todos los detalles de tu viaje al instante tras la compra.",
45
+ },
46
+ ];
47
+ const FeatureServiceUiMobile = ({ serviceItem, showTopLabel, colors, isSoldOut, cityOrigin, cityDestination, renderIcon, viewersConfig, isFeatureDropDownExpand, onToggleExpand, ticketQuantity = 1, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onBookButtonPress, }) => {
48
+ var _a, _b, _c, _d;
49
+ const operators = ((_a = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operators) === null || _a === void 0 ? void 0 : _a.length) > 0
50
+ ? serviceItem.operators
51
+ : HARDCODED_OPERATORS;
52
+ const isItemExpanded = serviceItem.id === isFeatureDropDownExpand ||
53
+ isFeatureDropDownExpand === true;
54
+ const canDecreaseTicketQuantity = ticketQuantity > 1;
55
+ const HOW_IT_WORKS_STEPS = [
56
+ {
57
+ icon: "flexible",
58
+ name: "1. Salida flexible",
59
+ text: "Viajas en un horario entre las 07:00 y las 10:00 AM del día elegido.",
60
+ },
61
+ {
62
+ icon: "bus",
63
+ name: "2. Empresa asignada",
64
+ text: "Una de las empresas disponibles confirma tu viaje una vez pagado.",
65
+ },
66
+ {
67
+ icon: "price",
68
+ name: "3. Precio garantizado",
69
+ text: "Al seleccionar este servicio aseguras el precio reducido.",
70
+ },
71
+ {
72
+ icon: "ticket",
73
+ name: "4. ¡Listo!",
74
+ text: "Recibe todos los detalles de tu viaje al instante tras la compra.",
75
+ },
76
+ ];
77
+ const FeatureStepIcon = ({ icon }) => {
78
+ switch (icon) {
79
+ case "flexible":
80
+ return renderIcon("flexibleIcon", "20px");
81
+ case "bus":
82
+ return renderIcon("empressaIcon", "20px");
83
+ case "price":
84
+ return renderIcon("precioIcon", "20px");
85
+ default:
86
+ return renderIcon("listoIcon", "20px");
87
+ }
88
+ };
89
+ return (React.createElement("div", {
90
+ // ${
91
+ // serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"
92
+ // }
93
+ className: `relative mb-[10px]
94
+ ${(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) ||
95
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" ||
96
+ showTopLabel
97
+ ? "mt-[24px]"
98
+ : "mt-[20px]"}` },
99
+ React.createElement("div", { className: "", style: {
100
+ border: "1px solid #c0c0c0",
101
+ padding: "12px",
102
+ borderRadius: "14px",
103
+ } },
104
+ React.createElement("div", { id: `service-card-${serviceItem.id}`, className: "bg-[#0C1421] text-white mx-auto relative rounded-[14px] p-[14px] text-[13.33px]" },
105
+ React.createElement("div", { className: "flex flex-col gap-[10px]" },
106
+ React.createElement("div", { className: "flex justify-between items-center text-[white]" },
107
+ React.createElement("div", { className: "flex flex-col gap-[8px]" },
108
+ React.createElement("div", { className: "flex items-center gap-[8px]" },
109
+ 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" : ""}` }),
110
+ React.createElement("span", { className: "text-[13px] bold-text" }, cityOrigin === null || cityOrigin === void 0 ? void 0 : cityOrigin.label.split(",")[0])),
111
+ React.createElement("div", { className: "flex items-center gap-[8px]" },
112
+ 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 } }),
113
+ React.createElement("span", { className: "text-[13px] bold-text" }, cityDestination === null || cityDestination === void 0 ? void 0 : cityDestination.label.split(",")[0]))),
114
+ React.createElement("div", { className: "flex flex-col justify-end gap-[12px] relative mb-[16px]" },
115
+ React.createElement("div", { className: "flex flex-col gap-[3px] items-end" },
116
+ React.createElement("span", { className: "text-[#FF8F45] bold-text text-[16px] leading-tight", style: {
117
+ animation: "pulse-zoom 2s ease-in-out infinite",
118
+ whiteSpace: "nowrap",
119
+ } }, "60% OFF"),
120
+ React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative", style: { position: "relative" } },
121
+ "$10.000",
122
+ React.createElement("span", { style: {
123
+ position: "absolute",
124
+ left: "-2px",
125
+ top: "50%",
126
+ width: "calc(100% + 4px)",
127
+ height: "1px",
128
+ backgroundColor: "#FF5C60",
129
+ transform: "rotate(-10deg)",
130
+ transformOrigin: "center",
131
+ } })),
132
+ React.createElement("span", { className: "text-white bold-text text-[22px] leading-none" }, `$${(4000 * ticketQuantity).toLocaleString()}`)))),
133
+ React.createElement("div", null,
134
+ React.createElement("div", { className: "flex items-center text-[white]" },
135
+ React.createElement("span", null, "Vie, 04/11"),
136
+ React.createElement("span", { className: "h-[20px] flex items-center justify-center mx-[10px]" }, "\u2022"),
137
+ React.createElement("span", null, "07:00 AM - 10:00 AM")),
138
+ React.createElement("div", { style: {
139
+ // height: "80px",
140
+ border: "1px solid #363c48",
141
+ backgroundColor: "#1a202e",
142
+ padding: "14px 10px",
143
+ borderRadius: "14px",
144
+ marginTop: "14px",
145
+ } },
146
+ React.createElement("div", { className: "flex flex-col justify-center items-center text-[white]" },
147
+ React.createElement("span", { className: "text-[15px] bold-text" }, "3 operadores compitiendo por tu compra"),
148
+ React.createElement("span", { className: "mt-[8px]" }, "Empresa a confirmar despu\u00E9s de tu pago")),
149
+ React.createElement("div", { className: "grid w-full grid-cols-3 items-stretch gap-[14px] mb-[12px] mt-[12px] text-[white]" }, 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: {
150
+ // height: "80px",
151
+ border: "1px solid #363c48",
152
+ backgroundColor: "#1a202e",
153
+ padding: "14px 10px",
154
+ } },
155
+ React.createElement("img", { src: serviceItem.operator_details[0], alt: op.name, className: `h-[24px] max-w-full object-contain ${isSoldOut ? "grayscale" : ""}` }),
156
+ React.createElement("span", { className: "text-[11px] truncate max-w-full text-center" }, serviceItem.operator_details[2]),
157
+ React.createElement("div", { className: "bg-[#FF8F45] text-[12px] font-bold px-[10px] py-[4px] rounded-[4px] bold-text whitespace-nowrap" },
158
+ React.createElement("span", null, op === null || op === void 0 ? void 0 : op.time)),
159
+ React.createElement("span", { className: "text-[10px] mt-[6px]" }, op === null || op === void 0 ? void 0 : op.seatsAvailable))))),
160
+ React.createElement("div", { className: "flex items-center gap-[4px]" },
161
+ renderIcon("sheildIcon", "14px"),
162
+ React.createElement("span", { className: "text-[white]" }, "Tu asiento confirmado al instante.")))),
163
+ React.createElement("div", null,
164
+ React.createElement("div", { className: "mt-[4px] flex flex-col items-center gap-[8px]" },
165
+ React.createElement("span", { className: "text-[12px] text-[white]" }, "\u00BFCu\u00E1ntos pasajes quieres?"),
166
+ React.createElement("div", { className: "flex w-full items-center justify-between", style: {
167
+ border: "1px solid #363c48",
168
+ backgroundColor: "#1a202e",
169
+ padding: "6px 14px",
170
+ borderRadius: "14px",
171
+ } },
172
+ 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
173
+ ? "cursor-pointer bg-[#2d374d]"
174
+ : "cursor-not-allowed bg-[#222b3d] opacity-50"}` }, "-"),
175
+ React.createElement("span", { className: "bold-text text-[20px] text-[white]" }, ticketQuantity),
176
+ 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]" }, "+")),
177
+ 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: {
178
+ backgroundColor: "#FF5C60",
179
+ animation: "pulse-zoom 2s ease-in-out infinite",
180
+ whiteSpace: "nowrap",
181
+ width: "100%",
182
+ } },
183
+ React.createElement(LottiePlayer, { animationData: serviceItem.icons.thunderAnim, width: "18px", height: "18px" }),
184
+ React.createElement("span", { className: "whitespace-nowrap" }, "\u00A1Lo quiero!")))),
185
+ React.createElement("div", { className: "flex justify-between items-center" },
186
+ React.createElement("div", { className: "flex items-center" },
187
+ React.createElement(LottiePlayer, { animationData: serviceItem.icons.dotAnimation, width: "12px", height: "12px" }),
188
+ React.createElement("span", { className: "ml-[5px]" },
189
+ React.createElement("span", { className: "bold-text text-[white]" },
190
+ " ",
191
+ React.createElement("span", { className: "bold-text", ref: (node) => commonService.startViewerCount(node, viewersConfig), style: {
192
+ fontVariantNumeric: "tabular-nums",
193
+ } }),
194
+ " "),
195
+ " ",
196
+ React.createElement("span", { className: "text-[white]" }, "viendo |"),
197
+ " ",
198
+ React.createElement("span", { className: "bold-text text-[white]", ref: (node) => commonService.startComprandoCount(node, 4, 16), style: { fontVariantNumeric: "tabular-nums" } }),
199
+ " ",
200
+ React.createElement("span", { className: "text-[white]" }, "han comprado"))),
201
+ React.createElement("div", { className: `transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`, onClick: onToggleExpand },
202
+ React.createElement("img", { src: (_d = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _d === void 0 ? void 0 : _d.downArrow, alt: "down arrow", style: {
203
+ width: "14px",
204
+ height: "8px",
205
+ filter: "brightness(0) invert(1)",
206
+ } }))))),
207
+ isItemExpanded && (React.createElement("div", { className: "flex flex-col gap-[10px]", style: {
208
+ opacity: isItemExpanded ? 1 : 0,
209
+ transition: "opacity 250ms ease-in-out",
210
+ } },
211
+ React.createElement("div", { className: ` text-[12px] ${isItemExpanded ? "pt-[14px] pb-[6px]" : "py-0"}`, style: { transition: "padding 300ms ease-in-out" } },
212
+ React.createElement("span", { className: "bold-text" }, "\u00BFC\u00F3mo funciona?"),
213
+ React.createElement("div", { className: "flex flex-col" }, HOW_IT_WORKS_STEPS.map((step) => (React.createElement("div", { className: "flex items-start gap-[8px] mt-[10px]" },
214
+ React.createElement("div", null,
215
+ React.createElement(FeatureStepIcon, { icon: step.icon })),
216
+ React.createElement("div", { className: "flex flex-col" },
217
+ React.createElement("span", { className: "bold-text" }, step.name),
218
+ React.createElement("span", null, step.text)))
219
+ // <div
220
+ // key={step.name}
221
+ // className="flex flex-col items-center text-center text-[#272727]"
222
+ // >
223
+ // <FeatureStepIcon icon={step.icon} />
224
+ // <span className="bold-text mt-[10px] text-[12px] leading-[14px]">
225
+ // {step.name}
226
+ // </span>
227
+ // <span className="mt-[2px] max-w-[220px] text-[12px] leading-[14px] text-[#4a4a4a]">
228
+ // {step.text}
229
+ // </span>
230
+ // </div>
231
+ )))))))));
232
+ };
233
+ export default FeatureServiceUiMobile;
@@ -1,13 +1,18 @@
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, isSoldOut, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, isFeatureDropDownExpand, onToggleExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onBookButtonPress, }: {
3
3
  serviceItem: any;
4
4
  showTopLabel: any;
5
- colors: any;
6
5
  isSoldOut: any;
7
6
  getAnimationIcon: any;
8
7
  cityOrigin: any;
9
8
  cityDestination: any;
10
9
  renderIcon: any;
11
10
  viewersConfig: any;
11
+ isFeatureDropDownExpand: any;
12
+ onToggleExpand: any;
13
+ ticketQuantity?: number;
14
+ onIncreaseTicketQuantity: any;
15
+ onDecreaseTicketQuantity: any;
16
+ onBookButtonPress: any;
12
17
  }) => React.JSX.Element;
13
18
  export default FeatureServiceUi;
@@ -21,67 +21,48 @@ const HARDCODED_OPERATORS = [
21
21
  seatsAvailable: "3 disponibles",
22
22
  },
23
23
  ];
24
- const HARDCODED_COUNTDOWN = "09:55";
25
- const HOW_IT_WORKS_STEPS = [
26
- {
27
- icon: "flexible",
28
- name: "1. Salida flexible",
29
- text: "Viajas en un horario entre las 07:00 y las 10:00 AM del día elegido.",
30
- },
31
- {
32
- icon: "bus",
33
- name: "2. Empresa asignada",
34
- text: "Una de las empresas disponibles confirma tu viaje una vez pagado.",
35
- },
36
- {
37
- icon: "price",
38
- name: "3. Precio garantizado",
39
- text: "Al seleccionar este servicio aseguras el precio reducido.",
40
- },
41
- {
42
- icon: "ticket",
43
- name: "4. ¡Listo!",
44
- text: "Recibe todos los detalles de tu viaje al instante tras la compra.",
45
- },
46
- ];
47
- const FeatureStepIcon = ({ icon }) => {
48
- const iconClassName = "h-[30px] w-[30px] text-[#171717]";
49
- switch (icon) {
50
- case "flexible":
51
- return (React.createElement("svg", { className: iconClassName, viewBox: "0 0 40 40", fill: "none", "aria-hidden": "true" },
52
- React.createElement("path", { d: "M31.5 13.4A13 13 0 0 0 8 12.3", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round" }),
53
- React.createElement("path", { d: "m7.4 7.7.2 5.2 5.1-1.2M8.5 26.6A13 13 0 0 0 32 27.7", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }),
54
- React.createElement("path", { d: "m32.6 32.3-.2-5.2-5.1 1.2", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" })));
55
- case "bus":
56
- return (React.createElement("svg", { className: iconClassName, viewBox: "0 0 40 40", fill: "none", "aria-hidden": "true" },
57
- React.createElement("rect", { x: "8", y: "4.5", width: "24", height: "27", rx: "2.5", stroke: "currentColor", strokeWidth: "2.2" }),
58
- React.createElement("path", { d: "M8 18.5h24M12 9h16M12 26h4m8 0h4M11 31.5v3h5v-3m8 0v3h5v-3M5.5 10v7m29-7v7", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round" })));
59
- case "price":
60
- return (React.createElement("svg", { className: iconClassName, viewBox: "0 0 40 40", fill: "none", "aria-hidden": "true" },
61
- React.createElement("circle", { cx: "20", cy: "20", r: "14", stroke: "currentColor", strokeWidth: "2.2" }),
62
- React.createElement("path", { d: "M23.7 15.4c-1-.7-2.2-1-3.6-1-2.2 0-3.8 1.1-3.8 2.8 0 4.2 7.4 1.8 7.4 5.8 0 1.8-1.6 2.8-4 2.8-1.5 0-2.9-.4-4-1.2M20 11.7v2.5m0 11.8v2.4", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round" })));
63
- default:
64
- return (React.createElement("svg", { className: iconClassName, viewBox: "0 0 40 40", fill: "none", "aria-hidden": "true" },
65
- React.createElement("path", { d: "M7 11h26v6a3.5 3.5 0 0 0 0 7v6H7v-6a3.5 3.5 0 0 0 0-7v-6Z", stroke: "currentColor", strokeWidth: "2.2", strokeLinejoin: "round" }),
66
- React.createElement("path", { d: "M22 12.5v3m0 3v3m0 3v4", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round" })));
67
- }
68
- };
69
- const AssuranceIcon = ({ type }) => {
70
- const iconClassName = "h-[18px] w-[18px] shrink-0 text-white";
71
- if (type === "pending") {
72
- return (React.createElement("svg", { className: iconClassName, viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true" },
73
- React.createElement("path", { d: "M4.2 8.2a6.2 6.2 0 1 1 .5 5.1", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
74
- React.createElement("path", { d: "M4.2 4.8v3.4h3.4", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" })));
75
- }
76
- return (React.createElement("svg", { className: iconClassName, viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true" },
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
- 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
- };
80
- const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, }) => {
81
- var _a, _b, _c, _d, _e;
24
+ const FeatureServiceUi = ({ serviceItem, showTopLabel, isSoldOut, getAnimationIcon, cityOrigin, cityDestination, renderIcon, viewersConfig, isFeatureDropDownExpand, onToggleExpand, ticketQuantity = 1, onIncreaseTicketQuantity, onDecreaseTicketQuantity, onBookButtonPress, }) => {
25
+ var _a, _b, _c, _d;
82
26
  const operators = ((_a = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.operators) === null || _a === void 0 ? void 0 : _a.length) > 0
83
27
  ? serviceItem.operators
84
28
  : HARDCODED_OPERATORS;
29
+ const isItemExpanded = serviceItem.id === isFeatureDropDownExpand ||
30
+ isFeatureDropDownExpand === true;
31
+ const canDecreaseTicketQuantity = ticketQuantity > 1;
32
+ const HOW_IT_WORKS_STEPS = [
33
+ {
34
+ icon: "flexible",
35
+ name: "1. Salida flexible",
36
+ text: "Viajas en un horario entre las 07:00 y las 10:00 AM del día elegido.",
37
+ },
38
+ {
39
+ icon: "bus",
40
+ name: "2. Empresa asignada",
41
+ text: "Una de las empresas disponibles confirma tu viaje una vez pagado.",
42
+ },
43
+ {
44
+ icon: "price",
45
+ name: "3. Precio garantizado",
46
+ text: "Al seleccionar este servicio aseguras el precio reducido.",
47
+ },
48
+ {
49
+ icon: "ticket",
50
+ name: "4. ¡Listo!",
51
+ text: "Recibe todos los detalles de tu viaje al instante tras la compra.",
52
+ },
53
+ ];
54
+ const FeatureStepIcon = ({ icon }) => {
55
+ switch (icon) {
56
+ case "flexible":
57
+ return renderIcon("flexibleIcon", "24px");
58
+ case "bus":
59
+ return renderIcon("empressaIcon", "24px");
60
+ case "price":
61
+ return renderIcon("precioIcon", "24px");
62
+ default:
63
+ return renderIcon("listoIcon", "24px");
64
+ }
65
+ };
85
66
  return (React.createElement("div", {
86
67
  // ${
87
68
  // serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"
@@ -105,6 +86,8 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAni
105
86
  padding: "1px 8px",
106
87
  borderRadius: "4px",
107
88
  color: "#fff",
89
+ animation: "pulse-zoom 2s ease-in-out infinite",
90
+ whiteSpace: "nowrap",
108
91
  } },
109
92
  React.createElement("span", null, "AHORRAS 60%"))),
110
93
  React.createElement("div", null,
@@ -118,54 +101,57 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAni
118
101
  fontVariantNumeric: "tabular-nums",
119
102
  display: "inline-block",
120
103
  color: "#FF5C60",
104
+ minWidth: "40px",
121
105
  } })))),
122
106
  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-[1.3fr_2fr_1.2fr] gap-[16px] items-stretch" },
124
- React.createElement("div", { className: "flex flex-col justify-between gap-[20px] py-[2px] " },
107
+ React.createElement("div", { className: "grid grid-cols-[23%_50%_27%] items-stretch" },
108
+ React.createElement("div", { className: "flex flex-col justify-between gap-[20px] my-[14px] pr-[22px]" },
125
109
  React.createElement("div", { className: "flex flex-col gap-[8px]" },
126
110
  React.createElement("div", { className: "flex items-center gap-[8px]" },
127
111
  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
112
  React.createElement("span", { className: "text-[13px] bold-text" }, cityOrigin === null || cityOrigin === void 0 ? void 0 : cityOrigin.label.split(",")[0])),
129
113
  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-[16px] h-[16px] shrink-0 ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }),
114
+ 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
115
  React.createElement("span", { className: "text-[13px] bold-text" }, cityDestination === null || cityDestination === void 0 ? void 0 : cityDestination.label.split(",")[0]))),
132
116
  React.createElement("div", { className: "flex flex-col gap-[8px]" },
133
117
  React.createElement("div", { className: "text-[12px] bold-text whitespace-nowrap" }, "Entre 07:00 AM y 10:00 AM"),
134
118
  React.createElement("div", { className: "text-[11px] bold-text" }, "Viernes 23 de mayo")),
135
119
  React.createElement("div", { className: "flex flex-col items-start gap-[10px] text-[12px] " },
136
- React.createElement("div", { className: "flex items-center gap-[8px]" },
137
- React.createElement(AssuranceIcon, { type: "pending" }),
120
+ React.createElement("div", { className: "flex items-justify gap-[8px]" },
121
+ renderIcon("sheildIcon", "16px"),
138
122
  React.createElement("span", { className: "text-[10px]", style: {
139
123
  lineHeight: 1.3,
140
124
  } }, "Empresa y hora a confirmar luego del pago.")),
141
- React.createElement("div", { className: "flex items-center gap-[8px]" },
142
- React.createElement(AssuranceIcon, { type: "secured" }),
125
+ React.createElement("div", { className: "flex items-justify gap-[8px]" },
126
+ renderIcon("confirmarIcon", "16px"),
143
127
  React.createElement("span", { className: "text-[10px]", style: {
144
128
  lineHeight: 1.3,
145
129
  } }, "Tu compra est\u00E1 100% asegurada.")))),
146
- React.createElement("div", { className: "px-[16px] flex flex-col items-center justify-between gap-[12px] py-[2px] border-r border-[#363c48] border-l border-[#363c48]" },
130
+ 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
131
  React.createElement("div", { className: "text-center" },
148
132
  React.createElement("div", { className: "bold-text text-[14px]" }, "3 operadores compitiendo por tu compra")),
149
- React.createElement("div", { className: "flex items-stretch justify-center gap-[8px] w-full mb-[16px]" }, operators.map((op, idx) => (React.createElement("div", { key: idx, className: "flex flex-col items-center justify-center gap-[8px] rounded-[8px]", style: {
150
- width: "140px",
133
+ 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
134
  // height: "80px",
152
135
  border: "1px solid #363c48",
153
136
  backgroundColor: "#1a202e",
154
- padding: "14px",
137
+ padding: "14px 10px",
155
138
  } },
156
- React.createElement("img", { src: serviceItem.operator_details[0], alt: op.name, className: `h-[24px] w-auto object-contain ${isSoldOut ? "grayscale" : ""}` }),
139
+ React.createElement("img", { src: serviceItem.operator_details[0], alt: op.name, className: `h-[24px] max-w-full object-contain ${isSoldOut ? "grayscale" : ""}` }),
157
140
  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-[16px] py-[4px] rounded-[4px] bold-text" },
141
+ React.createElement("div", { className: "bg-[#FF8F45] text-white text-[12px] font-bold px-[10px] py-[4px] rounded-[4px] bold-text whitespace-nowrap" },
159
142
  React.createElement("span", null, op === null || op === void 0 ? void 0 : op.time)),
160
143
  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: {
144
+ React.createElement("div", { className: "flex w-full items-center justify-center gap-[6px] text-[12px]", style: {
162
145
  border: "1px solid #363c48",
163
146
  backgroundColor: "#1a202e",
164
147
  padding: "8px 14px",
165
148
  borderRadius: "24px",
166
- width: "430px",
167
149
  } },
168
- React.createElement("img", { src: (_d = serviceItem.icons) === null || _d === void 0 ? void 0 : _d.userIcon, alt: "eye", style: { width: "16px", height: "16px" } }),
150
+ React.createElement(LottiePlayer
151
+ // animationData={serviceItem.icons.flexibleAnim}
152
+ , {
153
+ // animationData={serviceItem.icons.flexibleAnim}
154
+ animationData: getAnimationIcon("usersAnimation"), width: "18px", height: "18px" }),
169
155
  React.createElement("span", null,
170
156
  React.createElement("span", { className: "bold-text text-white" },
171
157
  " ",
@@ -173,25 +159,51 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAni
173
159
  fontVariantNumeric: "tabular-nums",
174
160
  color: "#FF5C60",
175
161
  } }),
176
- " ",
177
- React.createElement("span", { style: {
178
- color: "#FF5C60",
179
- } }, "personas")),
162
+ " "),
180
163
  " ",
181
- "viendo este viaje |",
164
+ "viendo |",
182
165
  " ",
183
166
  React.createElement("span", { className: "bold-text", ref: (node) => commonService.startComprandoCount(node, 4, 16), style: { fontVariantNumeric: "tabular-nums" } }),
184
167
  " ",
185
168
  "han comprado"))),
186
- React.createElement("div", { className: "flex flex-col justify-center gap-[12px] py-[2px] relative mb-[16px]" },
169
+ React.createElement("div", { className: "flex flex-col justify-center gap-[12px] py-[2px] pl-[22px] pr-[10px] relative mb-[16px]" },
187
170
  React.createElement("div", { className: "flex flex-col gap-[6px] ", style: {
188
171
  alignItems: "center",
189
172
  } },
190
- React.createElement("span", { className: "text-[#FF8F45] bold-text text-[26px] leading-tight" }, "60% OFF"),
191
- React.createElement("span", { className: "text-[#666] text-[14px] line-through" }, "$10.000"),
192
- React.createElement("span", { className: "text-white bold-text text-[28px] leading-none" }, "$4.000")),
193
- React.createElement("button", { className: "flex items-center gap-[6px] px-[20px] py-[10px] rounded-[12px] text-white bold-text text-[13px] mt-[4px] justify-center border-none cursor-pointer", style: {
173
+ React.createElement("span", { className: "text-[#FF8F45] bold-text text-[26px] leading-tight", style: {
174
+ animation: "pulse-zoom 2s ease-in-out infinite",
175
+ whiteSpace: "nowrap",
176
+ } }, "60% OFF"),
177
+ React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative", style: { position: "relative" } },
178
+ "$10.000",
179
+ React.createElement("span", { style: {
180
+ position: "absolute",
181
+ left: "-2px",
182
+ top: "50%",
183
+ width: "calc(100% + 4px)",
184
+ height: "1px",
185
+ backgroundColor: "#FF5C60",
186
+ transform: "rotate(-10deg)",
187
+ transformOrigin: "center",
188
+ } })),
189
+ React.createElement("span", { className: "text-white bold-text text-[28px] leading-none" }, `$${(4000 * ticketQuantity).toLocaleString()}`)),
190
+ React.createElement("div", { className: "mt-[4px] flex flex-col items-center gap-[8px]" },
191
+ React.createElement("span", { className: "text-[12px] text-white" }, "\u00BFCu\u00E1ntos pasajes quieres?"),
192
+ React.createElement("div", { className: "flex w-full items-center justify-between", style: {
193
+ border: "1px solid #363c48",
194
+ backgroundColor: "#1a202e",
195
+ padding: "6px 14px",
196
+ borderRadius: "14px",
197
+ } },
198
+ 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
199
+ ? "cursor-pointer bg-[#2d374d]"
200
+ : "cursor-not-allowed bg-[#222b3d] opacity-50"}` }, "-"),
201
+ React.createElement("span", { className: "bold-text text-[20px] text-white" }, ticketQuantity),
202
+ 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" }, "+"))),
203
+ 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
204
  backgroundColor: "#FF5C60",
205
+ animation: "pulse-zoom 2s ease-in-out infinite",
206
+ whiteSpace: "nowrap",
195
207
  } },
196
208
  React.createElement(LottiePlayer
197
209
  // animationData={serviceItem.icons.flexibleAnim}
@@ -199,17 +211,22 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, colors, isSoldOut, getAni
199
211
  // animationData={serviceItem.icons.flexibleAnim}
200
212
  animationData: getAnimationIcon("thunderAnimation"), width: "18px", height: "18px" }),
201
213
  React.createElement("span", { className: "whitespace-nowrap" }, "\u00A1Lo quiero!"))),
202
- React.createElement("div", { className: "absolute bottom-[11px] right-[18px]" },
203
- React.createElement("img", { src: (_e = serviceItem.icons) === null || _e === void 0 ? void 0 : _e.downArrow, alt: "down arrow", style: {
214
+ React.createElement("div", { className: `absolute bottom-[11px] right-[18px] cursor-pointer transition-transform duration-300 ease-in-out ${isItemExpanded ? "rotate-180" : ""}`, onClick: onToggleExpand },
215
+ React.createElement("img", { src: (_d = serviceItem.icons) === null || _d === void 0 ? void 0 : _d.downArrow, alt: "down arrow", style: {
204
216
  width: "14px",
205
217
  height: "8px",
206
218
  filter: "brightness(0) invert(1)",
207
219
  } })))),
208
- React.createElement("div", { className: "px-[16px] pt-[14px] pb-[6px] text-[13.33px]" },
209
- React.createElement("span", { className: "bold-text" }, "\u00BFC\u00F3mo funciona?"),
210
- 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]" },
211
- React.createElement(FeatureStepIcon, { icon: step.icon }),
212
- React.createElement("span", { className: "bold-text mt-[10px] text-[12px] leading-[14px]" }, step.name),
213
- React.createElement("span", { className: "mt-[2px] max-w-[220px] text-[12px] leading-[14px] text-[#4a4a4a]" }, step.text)))))))));
220
+ React.createElement("div", { className: "grid", style: {
221
+ gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
222
+ opacity: isItemExpanded ? 1 : 0,
223
+ transition: "grid-template-rows 300ms ease-in-out, opacity 250ms ease-in-out",
224
+ } },
225
+ 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" } },
226
+ React.createElement("span", { className: "bold-text" }, "\u00BFC\u00F3mo funciona?"),
227
+ 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]" },
228
+ React.createElement(FeatureStepIcon, { icon: step.icon }),
229
+ React.createElement("span", { className: "bold-text mt-[10px] text-[12px] leading-[14px]" }, step.name),
230
+ React.createElement("span", { className: "mt-[2px] max-w-[220px] text-[12px] leading-[14px] text-[#4a4a4a]" }, step.text))))))))));
214
231
  };
215
232
  export default FeatureServiceUi;
@@ -240,7 +240,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
240
240
  React.createElement("span", { className: "flex items-center gap-[6px] text-[22px] bold-text leading-[30px]", style: { color: isSoldOut ? "#c0c0c0" : discountSeatPriceColor } },
241
241
  React.createElement("div", { className: "absolute", style: {
242
242
  left: isPeru ? "-1px" : "-18px",
243
- bottom: "1px"
243
+ bottom: "1px",
244
244
  } }, renderIcon("fireIcon", "16px")),
245
245
  availableSeats <= 0
246
246
  ? CommonService.currency(0, currencySign)
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "9.7.0",
3
+ "version": "9.7.2",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -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;