kupos-ui-components-lib 10.4.9 → 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 +6 -0
- 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/PeruOfferBanner.tsx +298 -0
- package/src/ui/SeatSection/PeruSeatSection.tsx +487 -0
- package/src/ui/mobileweb/SeatSectionMobile.tsx +46 -1
|
@@ -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;
|