kupos-ui-components-lib 10.4.8 → 10.4.10
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/components/ServiceItem/PeruServiceItemDesktop.js +4 -4
- package/dist/components/ServiceItem/PeruServiceItemMobile.d.ts +7 -0
- package/dist/components/ServiceItem/PeruServiceItemMobile.js +233 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.js +4 -4
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +3 -2
- package/dist/components/ServiceItem/mobileTypes.d.ts +1 -0
- package/dist/styles.css +9 -3
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +2 -2
- package/dist/ui/PaymentCardMobile/PaymentCardMobile.d.ts +4 -0
- package/dist/ui/PaymentCardMobile/PaymentCardMobile.js +531 -0
- package/dist/ui/PaymentCardMobile/index.d.ts +1 -0
- package/dist/ui/PaymentCardMobile/index.js +1 -0
- package/dist/ui/PeruOfferBanner.d.ts +24 -0
- package/dist/ui/PeruOfferBanner.js +94 -0
- package/dist/ui/SeatSection/PeruSeatSection.d.ts +22 -0
- package/dist/ui/SeatSection/PeruSeatSection.js +247 -0
- package/dist/ui/SlidingModal/SlidingModal.d.ts +9 -0
- package/dist/ui/SlidingModal/SlidingModal.js +100 -0
- package/dist/ui/SlidingModal/index.d.ts +2 -0
- package/dist/ui/SlidingModal/index.js +1 -0
- package/dist/ui/mobileweb/SeatSectionMobile.js +15 -1
- package/package.json +1 -1
- package/src/components/ServiceItem/PeruServiceItemDesktop.tsx +7 -6
- package/src/components/ServiceItem/PeruServiceItemMobile.tsx +596 -0
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +2 -2
- package/src/components/ServiceItem/ServiceItemMobile.tsx +44 -1
- package/src/components/ServiceItem/mobileTypes.ts +1 -0
- package/src/ui/FeatureServiceUI/FeatureServiceUi.tsx +2 -2
- package/src/ui/PeruOfferBanner.tsx +298 -0
- package/src/ui/SeatSection/PeruSeatSection.tsx +487 -0
- package/src/ui/mobileweb/SeatSectionMobile.tsx +46 -1
|
@@ -471,7 +471,7 @@ const FeatureServiceUi = ({
|
|
|
471
471
|
// backgroundColor: "#fff",
|
|
472
472
|
border: "1px solid #363c48",
|
|
473
473
|
backgroundColor: "#1a202e",
|
|
474
|
-
padding: "
|
|
474
|
+
padding: "25px 10px",
|
|
475
475
|
}}
|
|
476
476
|
>
|
|
477
477
|
<img
|
|
@@ -548,7 +548,7 @@ const FeatureServiceUi = ({
|
|
|
548
548
|
}}
|
|
549
549
|
>
|
|
550
550
|
<span
|
|
551
|
-
className="text-[#FF8F45] bold-text text-[
|
|
551
|
+
className="text-[#FF8F45] bold-text text-[30px] leading-tight"
|
|
552
552
|
style={{
|
|
553
553
|
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
554
554
|
whiteSpace: "nowrap",
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import LottiePlayer from "../assets/LottiePlayer";
|
|
3
|
+
import CommonService from "../utils/CommonService";
|
|
4
|
+
import { ServiceItemProps } from "../components/ServiceItem/types";
|
|
5
|
+
|
|
6
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
type ServiceItemSlice = Pick<
|
|
9
|
+
ServiceItemProps["serviceItem"],
|
|
10
|
+
| "is_dp_enabled"
|
|
11
|
+
| "offer_text"
|
|
12
|
+
| "dp_discount_percents"
|
|
13
|
+
| "dp_discounted_seats"
|
|
14
|
+
| "show_register_button"
|
|
15
|
+
>;
|
|
16
|
+
|
|
17
|
+
interface OfferBannerColors {
|
|
18
|
+
bottomStripColor?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface PeruOfferBannerProps {
|
|
22
|
+
offerGradient: string;
|
|
23
|
+
isSoldOut: boolean;
|
|
24
|
+
serviceItem: ServiceItemSlice;
|
|
25
|
+
renderIcon: (name: string, size: string) => React.ReactNode;
|
|
26
|
+
isLoggedIn: boolean;
|
|
27
|
+
showLoginModal: () => void;
|
|
28
|
+
viewersConfig: ServiceItemProps["viewersConfig"];
|
|
29
|
+
getAnimationIcon: (name: string) => unknown;
|
|
30
|
+
showLoginOption?: boolean;
|
|
31
|
+
colors: OfferBannerColors;
|
|
32
|
+
isLinatal?: boolean;
|
|
33
|
+
coachKey?: number;
|
|
34
|
+
isExpand?: any;
|
|
35
|
+
isNewUiEnabled?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
const OFFER_TEXT_MAX_LENGTH = 30;
|
|
41
|
+
|
|
42
|
+
function truncateOfferText(text: string): string {
|
|
43
|
+
return text.length > OFFER_TEXT_MAX_LENGTH
|
|
44
|
+
? `${text.slice(0, OFFER_TEXT_MAX_LENGTH)}...`
|
|
45
|
+
: text;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function hasDpDiscounts(serviceItem: ServiceItemSlice): boolean {
|
|
49
|
+
return (
|
|
50
|
+
Object.keys(serviceItem?.dp_discount_percents ?? {}).length > 0 ||
|
|
51
|
+
(serviceItem?.dp_discounted_seats ?? []).length > 0
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ─── Sub-components ───────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
interface AnimationIconProps {
|
|
58
|
+
getAnimationIcon: PeruOfferBannerProps["getAnimationIcon"];
|
|
59
|
+
name: string;
|
|
60
|
+
width?: string;
|
|
61
|
+
height?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const AnimationIcon: React.FC<AnimationIconProps> = ({
|
|
65
|
+
getAnimationIcon,
|
|
66
|
+
name,
|
|
67
|
+
width = "18px",
|
|
68
|
+
height = "18px",
|
|
69
|
+
}) => (
|
|
70
|
+
<LottiePlayer
|
|
71
|
+
animationData={getAnimationIcon(name)}
|
|
72
|
+
width={width}
|
|
73
|
+
height={height}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Shown when DP is enabled but no discounts / discounted seats are present
|
|
78
|
+
const PopularServiceBanner: React.FC<{
|
|
79
|
+
getAnimationIcon: PeruOfferBannerProps["getAnimationIcon"];
|
|
80
|
+
}> = ({ getAnimationIcon }) => (
|
|
81
|
+
<div className="flex items-center gap-[5px]">
|
|
82
|
+
<AnimationIcon getAnimationIcon={getAnimationIcon} name="starAnimation" />
|
|
83
|
+
<span>Servicio popular entre los usuarios</span>
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Shown when an offer text exists
|
|
88
|
+
interface OfferBannerContentProps {
|
|
89
|
+
offerText: string;
|
|
90
|
+
isLoggedIn: boolean;
|
|
91
|
+
showLoginModal: () => void;
|
|
92
|
+
showLoginOption?: boolean;
|
|
93
|
+
getAnimationIcon: PeruOfferBannerProps["getAnimationIcon"];
|
|
94
|
+
hideRegister?: boolean;
|
|
95
|
+
showLoginButton?: boolean;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const OfferBannerContent: React.FC<OfferBannerContentProps> = ({
|
|
99
|
+
offerText,
|
|
100
|
+
isLoggedIn,
|
|
101
|
+
showLoginModal,
|
|
102
|
+
showLoginOption,
|
|
103
|
+
getAnimationIcon,
|
|
104
|
+
hideRegister,
|
|
105
|
+
showLoginButton,
|
|
106
|
+
}) => (
|
|
107
|
+
<div className="flex items-center">
|
|
108
|
+
<AnimationIcon getAnimationIcon={getAnimationIcon} name="bombAnimation" />
|
|
109
|
+
<div className="flex items-center mt-[0px]">
|
|
110
|
+
<span
|
|
111
|
+
className="bold-text"
|
|
112
|
+
style={{ marginLeft: offerText ? "6px" : "3px" }}
|
|
113
|
+
>
|
|
114
|
+
{offerText}{" "}
|
|
115
|
+
{isLoggedIn && showLoginOption
|
|
116
|
+
? null
|
|
117
|
+
: showLoginOption &&
|
|
118
|
+
showLoginButton && (
|
|
119
|
+
<span onClick={showLoginModal} className="cursor-pointer">
|
|
120
|
+
- registro
|
|
121
|
+
</span>
|
|
122
|
+
)}{" "}
|
|
123
|
+
|
|
124
|
+
</span>{" "}
|
|
125
|
+
{offerText ? "| " : ""}
|
|
126
|
+
Termina en
|
|
127
|
+
<span
|
|
128
|
+
className="bold-text text-end"
|
|
129
|
+
ref={(node) => CommonService.startCountdown(node, 599)}
|
|
130
|
+
style={{ fontVariantNumeric: "tabular-nums", display: "inline-block" }}
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// Shown for legacy promo offers
|
|
137
|
+
interface LegacyOfferBannerProps {
|
|
138
|
+
offerText: string;
|
|
139
|
+
getAnimationIcon: PeruOfferBannerProps["getAnimationIcon"];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const LegacyOfferBanner: React.FC<LegacyOfferBannerProps> = ({
|
|
143
|
+
offerText,
|
|
144
|
+
getAnimationIcon,
|
|
145
|
+
}) => (
|
|
146
|
+
<div className="flex items-center">
|
|
147
|
+
<AnimationIcon getAnimationIcon={getAnimationIcon} name="promoAnim" />
|
|
148
|
+
<div className="flex items-center mb-[2px]">
|
|
149
|
+
<span
|
|
150
|
+
className="bold-text"
|
|
151
|
+
style={{ marginLeft: offerText ? "6px" : "3px" }}
|
|
152
|
+
>
|
|
153
|
+
{offerText}
|
|
154
|
+
</span>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Right-side viewers / buying count
|
|
160
|
+
interface ViewersCountProps {
|
|
161
|
+
serviceItem: ServiceItemSlice;
|
|
162
|
+
viewersConfig: ServiceItemProps["viewersConfig"];
|
|
163
|
+
getAnimationIcon: PeruOfferBannerProps["getAnimationIcon"];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const ViewersCount: React.FC<ViewersCountProps> = ({
|
|
167
|
+
serviceItem,
|
|
168
|
+
viewersConfig,
|
|
169
|
+
getAnimationIcon,
|
|
170
|
+
}) => {
|
|
171
|
+
const showScarcity = hasDpDiscounts(serviceItem);
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<div className="flex items-center">
|
|
175
|
+
<AnimationIcon
|
|
176
|
+
getAnimationIcon={getAnimationIcon}
|
|
177
|
+
name="dotAnimation"
|
|
178
|
+
width="12px"
|
|
179
|
+
height="12px"
|
|
180
|
+
/>
|
|
181
|
+
<span className="ml-[6px]">
|
|
182
|
+
<span
|
|
183
|
+
className="bold-text"
|
|
184
|
+
ref={(node) => CommonService.startViewerCount(node, viewersConfig)}
|
|
185
|
+
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
186
|
+
/>{" "}
|
|
187
|
+
<span>
|
|
188
|
+
{viewersConfig?.label || " viendo"} |{" "}
|
|
189
|
+
<span>
|
|
190
|
+
{showScarcity && "Quedan pocos • "}
|
|
191
|
+
<span
|
|
192
|
+
className="bold-text"
|
|
193
|
+
ref={(node) => CommonService.startComprandoCount(node, 4, 16)}
|
|
194
|
+
style={{ fontVariantNumeric: "tabular-nums" }}
|
|
195
|
+
/>{" "}
|
|
196
|
+
comprando
|
|
197
|
+
</span>
|
|
198
|
+
</span>
|
|
199
|
+
</span>
|
|
200
|
+
</div>
|
|
201
|
+
);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// ─── Main Component ───────────────────────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
const PeruOfferBanner: React.FC<PeruOfferBannerProps> = ({
|
|
207
|
+
offerGradient,
|
|
208
|
+
isSoldOut,
|
|
209
|
+
serviceItem,
|
|
210
|
+
isLoggedIn,
|
|
211
|
+
showLoginModal,
|
|
212
|
+
viewersConfig,
|
|
213
|
+
getAnimationIcon,
|
|
214
|
+
showLoginOption,
|
|
215
|
+
colors,
|
|
216
|
+
isLinatal,
|
|
217
|
+
coachKey,
|
|
218
|
+
isExpand,
|
|
219
|
+
isNewUiEnabled,
|
|
220
|
+
}) => {
|
|
221
|
+
const isDiscountBelow20 =
|
|
222
|
+
(serviceItem as any)?.discount_value > 0 &&
|
|
223
|
+
(serviceItem as any)?.discount_value < 20;
|
|
224
|
+
const offerText = isDiscountBelow20 ? "" : serviceItem?.offer_text || "";
|
|
225
|
+
|
|
226
|
+
const isLegacyOffer =
|
|
227
|
+
!!offerText &&
|
|
228
|
+
!isNewUiEnabled;
|
|
229
|
+
|
|
230
|
+
// const showViewers = serviceItem?.is_dp_enabled;
|
|
231
|
+
const showViewers = isNewUiEnabled;
|
|
232
|
+
|
|
233
|
+
const background = isLegacyOffer ? colors?.bottomStripColor : offerGradient;
|
|
234
|
+
|
|
235
|
+
const renderLeftContent = () => {
|
|
236
|
+
const hasDp = hasDpDiscounts(serviceItem);
|
|
237
|
+
|
|
238
|
+
if (serviceItem?.is_dp_enabled && !hasDp) {
|
|
239
|
+
return <PopularServiceBanner getAnimationIcon={getAnimationIcon} />;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// If new UI is enabled, show offer with registro and countdown
|
|
243
|
+
if (isNewUiEnabled && offerText) {
|
|
244
|
+
return (
|
|
245
|
+
<OfferBannerContent
|
|
246
|
+
offerText={offerText}
|
|
247
|
+
isLoggedIn={isLoggedIn}
|
|
248
|
+
showLoginModal={showLoginModal}
|
|
249
|
+
showLoginOption={showLoginOption}
|
|
250
|
+
getAnimationIcon={getAnimationIcon}
|
|
251
|
+
hideRegister={hasDp}
|
|
252
|
+
showLoginButton={serviceItem?.show_register_button}
|
|
253
|
+
/>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// If new UI is disabled, show offer text only
|
|
258
|
+
if (offerText) {
|
|
259
|
+
return (
|
|
260
|
+
<LegacyOfferBanner
|
|
261
|
+
offerText={offerText}
|
|
262
|
+
getAnimationIcon={getAnimationIcon}
|
|
263
|
+
/>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return null;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
<div
|
|
272
|
+
className={`text-white w-full absolute ${coachKey ? "-bottom-[32px]" : isExpand ? "-bottom-[32px]" : "-bottom-[40px]"} rounded-b-[14px] text-[14px] h-[58px] flex items-end pb-[7px]`}
|
|
273
|
+
style={{
|
|
274
|
+
background:
|
|
275
|
+
(serviceItem?.is_dp_enabled && serviceItem?.dp_discount_percents)
|
|
276
|
+
? offerGradient
|
|
277
|
+
: background,
|
|
278
|
+
opacity: isSoldOut ? 0.5 : 1,
|
|
279
|
+
zIndex: isLinatal ? "-1" : "0",
|
|
280
|
+
}}
|
|
281
|
+
>
|
|
282
|
+
<div className="flex items-center w-full gap-[20px] px-[15px] justify-between">
|
|
283
|
+
<div className="flex items-center justify-start">
|
|
284
|
+
{renderLeftContent()}
|
|
285
|
+
</div>
|
|
286
|
+
{showViewers && (
|
|
287
|
+
<ViewersCount
|
|
288
|
+
serviceItem={serviceItem}
|
|
289
|
+
viewersConfig={viewersConfig}
|
|
290
|
+
getAnimationIcon={getAnimationIcon}
|
|
291
|
+
/>
|
|
292
|
+
)}
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
);
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
export default PeruOfferBanner;
|