@opexa/portal-components 0.0.886 → 0.0.887
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/DepositWithdrawal/Deposit/OnlineBankDeposit/OnlineBankDepositContext.d.ts +2 -2
- package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/useOnlineBankDeposit.d.ts +1 -1
- package/dist/components/DepositWithdrawal/Deposit/QRPHDeposit/QRPHDepositContext.d.ts +2 -2
- package/dist/components/DepositWithdrawal/Deposit/QRPHDeposit/useQRPHDeposit.d.ts +1 -1
- package/dist/components/ForgotPassword/Crazywin/CWForgotPassword.d.ts +6 -0
- package/dist/components/ForgotPassword/Crazywin/CWForgotPassword.js +11 -0
- package/dist/components/ForgotPassword/Crazywin/CWForgotPasswordForm.d.ts +2 -0
- package/dist/components/ForgotPassword/Crazywin/CWForgotPasswordForm.js +75 -0
- package/dist/components/ForgotPassword/Crazywin/ForgotPassword.module.css +43 -0
- package/dist/components/ForgotPassword/ForgotPassword.lazy.d.ts +3 -0
- package/dist/components/ForgotPassword/ForgotPassword.lazy.js +6 -1
- package/dist/components/Jackpots/JackpotsCarousel/JackpotsCarouselItem.CrazyWin.js +5 -16
- package/dist/components/Jackpots/JackpotsCarousel/JackpotsCarouselItem.HappyBingo.d.ts +0 -1
- package/dist/components/Jackpots/JackpotsCarousel/JackpotsCarouselItem.HappyBingo.js +2 -8
- package/dist/components/Jackpots/JackpotsList/JackpotsList.js +2 -1
- package/dist/components/Jackpots/JackpotsList/JackpotsListItem.CrazyWin.js +6 -12
- package/dist/components/Jackpots/JackpotsList/JackpotsListItem.HappyBingo.d.ts +6 -0
- package/dist/components/Jackpots/JackpotsList/JackpotsListItem.HappyBingo.js +167 -0
- package/dist/components/Jackpots/utils.d.ts +1 -0
- package/dist/components/Jackpots/utils.js +6 -0
- package/dist/components/Promos/Cashback.d.ts +4 -1
- package/dist/components/Promos/Cashback.js +6 -3
- package/dist/components/Promos/CustomPromo.d.ts +3 -1
- package/dist/components/Promos/CustomPromo.js +3 -2
- package/dist/components/Promos/Promo.d.ts +4 -1
- package/dist/components/Promos/Promo.js +6 -3
- package/dist/components/Promos/PromosGrid.d.ts +3 -0
- package/dist/components/Promos/PromosGrid.js +1 -1
- package/dist/components/Promos/utils.d.ts +1 -0
- package/dist/components/Promos/utils.js +10 -0
- package/dist/components/SignIn/MobileNumberField.js +14 -8
- package/dist/images/3d-star.webp +0 -0
- package/dist/schemas/forgotPasswordSchema.d.ts +32 -0
- package/dist/schemas/forgotPasswordSchema.js +15 -0
- package/dist/services/game.d.ts +1 -1
- package/dist/services/game.js +2 -0
- package/dist/services/queries.d.ts +1 -1
- package/dist/services/queries.js +8 -0
- package/dist/services/wallet.d.ts +1 -1
- package/dist/services/wallet.js +2 -0
- package/package.json +1 -1
package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/OnlineBankDepositContext.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const OnlineBankDepositContext: (props: {
|
|
2
2
|
value: {
|
|
3
3
|
view: "form" | "vca";
|
|
4
|
-
status: "waiting" | "
|
|
4
|
+
status: "waiting" | "failed" | "processing" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
5
5
|
verify: () => void;
|
|
6
6
|
reset: () => void;
|
|
7
7
|
deposit: import("../../../../types").Deposit | null;
|
|
@@ -14,7 +14,7 @@ export declare const OnlineBankDepositContext: (props: {
|
|
|
14
14
|
children?: import("react").ReactNode | undefined;
|
|
15
15
|
}) => React.ReactNode, useOnlineBankDepositContext: () => {
|
|
16
16
|
view: "form" | "vca";
|
|
17
|
-
status: "waiting" | "
|
|
17
|
+
status: "waiting" | "failed" | "processing" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
18
18
|
verify: () => void;
|
|
19
19
|
reset: () => void;
|
|
20
20
|
deposit: import("../../../../types").Deposit | null;
|
package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/useOnlineBankDeposit.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Deposit } from '../../../../types';
|
|
|
2
2
|
export type UseOnlineBankDepositReturn = ReturnType<typeof useOnlineBankDeposit>;
|
|
3
3
|
export declare function useOnlineBankDeposit(): {
|
|
4
4
|
view: "form" | "vca";
|
|
5
|
-
status: "waiting" | "
|
|
5
|
+
status: "waiting" | "failed" | "processing" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
6
6
|
verify: () => void;
|
|
7
7
|
reset: () => void;
|
|
8
8
|
deposit: Deposit | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const QRPHDepositContext: (props: {
|
|
2
2
|
value: {
|
|
3
|
-
status: "
|
|
3
|
+
status: "idle" | "generating-qr-code" | "qr-code-generated" | "failed" | "confirmed";
|
|
4
4
|
deposit: import("../../../../types").Deposit | null;
|
|
5
5
|
errorMessage: {
|
|
6
6
|
name: string;
|
|
@@ -13,7 +13,7 @@ export declare const QRPHDepositContext: (props: {
|
|
|
13
13
|
} & {
|
|
14
14
|
children?: import("react").ReactNode | undefined;
|
|
15
15
|
}) => React.ReactNode, useQRPHDepositContext: () => {
|
|
16
|
-
status: "
|
|
16
|
+
status: "idle" | "generating-qr-code" | "qr-code-generated" | "failed" | "confirmed";
|
|
17
17
|
deposit: import("../../../../types").Deposit | null;
|
|
18
18
|
errorMessage: {
|
|
19
19
|
name: string;
|
|
@@ -5,7 +5,7 @@ export interface GenerateQRCodeInput {
|
|
|
5
5
|
promo?: string | null;
|
|
6
6
|
}
|
|
7
7
|
export declare function useQRPHDeposit(): {
|
|
8
|
-
status: "
|
|
8
|
+
status: "idle" | "generating-qr-code" | "qr-code-generated" | "failed" | "confirmed";
|
|
9
9
|
deposit: Deposit | null;
|
|
10
10
|
errorMessage: {
|
|
11
11
|
name: string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Image, {} from 'next/image';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { XIcon } from '../../../icons/XIcon.js';
|
|
5
|
+
import { Dialog } from '../../../ui/Dialog/index.js';
|
|
6
|
+
import CWForgotPasswordForm from './CWForgotPasswordForm.js';
|
|
7
|
+
import styles from './ForgotPassword.module.css';
|
|
8
|
+
const ForgotPassword = ({ logo }) => {
|
|
9
|
+
return (_jsx(Dialog.Content, { className: "bg-transparent h-full w-full overflow-y-invisible left-0 top-0 flex items-center", children: _jsxs("div", { className: "flex h-[90dvh] w-full flex-col justify-center scroll-smooth", children: [_jsxs("div", { className: "relative mx-auto w-full max-w-[22.5rem]", children: [_jsx(Image, { src: logo, alt: "", width: 200, height: 100, className: "mx-auto mt-8 h-auto w-[12.04544rem]", draggable: false }), _jsx(Dialog.CloseTrigger, { className: 'w-fit h-fit text-[#6C5200] rounded-md bg-gradient-to-t from-[#FFE5AF] to-[#EAC467] p-0.5', children: _jsx(XIcon, {}) })] }), _jsx("h2", { className: "mx-auto mt-10 w-fit bg-[linear-gradient(50deg,#c7802d_-5.1%,#ffe585_44.95%,#c7802d_109.05%)] bg-clip-text text-2xl font-bold uppercase text-transparent", children: "Forgot Password" }), _jsx("div", { className: twMerge('mx-auto mt-7.5 max-w-[20.6875rem] p-7.5', styles.card), children: _jsx(CWForgotPasswordForm, {}) })] }) }));
|
|
10
|
+
};
|
|
11
|
+
export default ForgotPassword;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
3
|
+
import Image from 'next/image';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
import { useForm } from 'react-hook-form';
|
|
6
|
+
import { twMerge } from 'tailwind-merge';
|
|
7
|
+
import { useShallow } from 'zustand/shallow';
|
|
8
|
+
import { useCooldown } from '../../../client/hooks/useCooldown.js';
|
|
9
|
+
import { useGlobalStore } from '../../../client/hooks/useGlobalStore.js';
|
|
10
|
+
import { useLocaleInfo } from '../../../client/hooks/useLocaleInfo.js';
|
|
11
|
+
import { useMobileNumberParser } from '../../../client/hooks/useMobileNumberParser.js';
|
|
12
|
+
import { useResetPasswordMutation } from '../../../client/hooks/useResetPasswordMutation.js';
|
|
13
|
+
import { useSendVerificationCodeMutation } from '../../../client/hooks/useSendVerificationCodeMutation.js';
|
|
14
|
+
import { toaster } from '../../../client/utils/toaster.js';
|
|
15
|
+
import { EyeIcon } from '../../../icons/EyeIcon.js';
|
|
16
|
+
import { EyeOffIcon } from '../../../icons/EyeOffIcon.js';
|
|
17
|
+
import lockIcon from '../../../images/lock-icon.webp';
|
|
18
|
+
import { createForgotPasswordSchema, } from '../../../schemas/forgotPasswordSchema.js';
|
|
19
|
+
import { Button } from '../../../ui/Button/index.js';
|
|
20
|
+
import { Field } from '../../../ui/Field/index.js';
|
|
21
|
+
import { PasswordInput } from '../../../ui/PasswordInput/index.js';
|
|
22
|
+
const CWForgotPasswordForm = () => {
|
|
23
|
+
const mobileNumberParser = useMobileNumberParser();
|
|
24
|
+
const schema = useMemo(() => createForgotPasswordSchema(mobileNumberParser), [mobileNumberParser]);
|
|
25
|
+
const { register, watch, getValues, handleSubmit, formState: { isValid, isDirty, errors }, } = useForm({
|
|
26
|
+
resolver: zodResolver(schema),
|
|
27
|
+
mode: 'onChange',
|
|
28
|
+
});
|
|
29
|
+
const mobileNumberValue = watch('mobileNumber');
|
|
30
|
+
const globalStore = useGlobalStore(useShallow((ctx) => ({
|
|
31
|
+
signIn: ctx.signIn,
|
|
32
|
+
forgotPassword: ctx.forgotPassword,
|
|
33
|
+
})));
|
|
34
|
+
const commonInputClass = 'h-10 w-full rounded-full border-none bg-black/40 text-xs placeholder:text-text-placeholder focus:outline-none focus:ring-0';
|
|
35
|
+
const localeInfo = useLocaleInfo();
|
|
36
|
+
const sendVerificationCodeMutation = useSendVerificationCodeMutation();
|
|
37
|
+
const resetPasswordMutation = useResetPasswordMutation({
|
|
38
|
+
onSuccess() {
|
|
39
|
+
globalStore.forgotPassword.setOpen(false);
|
|
40
|
+
globalStore.signIn.setOpen(true);
|
|
41
|
+
toaster.success({
|
|
42
|
+
description: 'Your password has been updated.',
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
onError(error) {
|
|
46
|
+
toaster.error({
|
|
47
|
+
description: error.message,
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
const cooldown = useCooldown({
|
|
52
|
+
max: 60,
|
|
53
|
+
duration: 1000 * 60,
|
|
54
|
+
});
|
|
55
|
+
const onSubmit = (data) => {
|
|
56
|
+
resetPasswordMutation.mutate({
|
|
57
|
+
mobileNumber: mobileNumberParser.format(data.mobileNumber),
|
|
58
|
+
newPassword: data.password,
|
|
59
|
+
verificationCode: data.verificationCode,
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
return (_jsx("form", { autoComplete: 'off', onSubmit: handleSubmit(onSubmit), children: _jsxs("div", { className: "space-y-4", children: [_jsxs(Field.Root, { invalid: !!errors.mobileNumber, children: [_jsx(Field.Label, { className: "text-xs", children: "Phone Number" }), _jsxs("div", { className: "relative flex h-10 gap-3", children: [_jsxs("div", { className: "flex h-full items-center gap-2 rounded-full bg-black/40 px-3.5 text-xs", children: [_jsx(localeInfo.country.flag, { className: "size-5" }), _jsx("span", { className: "text-text-placeholder", children: localeInfo.mobileNumber.areaCode })] }), _jsx(Field.Input, { className: commonInputClass, placeholder: "Enter Phone Number", ...register('mobileNumber') })] }), _jsx(Field.ErrorText, { className: "text-[#ff2525b3] text-xs", children: errors.mobileNumber?.message })] }), _jsx(Field.Root, { invalid: !!errors.password, children: _jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { className: "text-xs", children: "Password" }), _jsxs("div", { children: [_jsxs(PasswordInput.Control, { className: "relative flex h-10 items-center rounded-full text-xs bg-black/40 border-0", children: [_jsx(Image, { src: lockIcon, alt: "lock icon", width: 20, height: 20, className: "-translate-y-1/2 pointer-events-none absolute top-1/2 left-3 h-5 w-5" }), _jsx(PasswordInput.Input, { className: "pl-10", placeholder: "8 - 20 characters", ...register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, { className: "text-white/50" }), asChild: true, children: _jsx(EyeIcon, { className: "text-white/50" }) }) })] }), _jsx(Field.ErrorText, { className: "text-[#ff2525b3] text-xs", children: errors.password?.message })] })] }) }), _jsx(Field.Root, { invalid: !!errors.confirmPassword, children: _jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { className: "text-xs", children: "Confirm Password" }), _jsxs("div", { children: [_jsxs(PasswordInput.Control, { className: "relative flex h-10 items-center rounded-full text-xs bg-black/40 border-0", children: [_jsx(Image, { src: lockIcon, alt: "lock icon", width: 20, height: 20, className: "-translate-y-1/2 pointer-events-none absolute top-1/2 left-3 h-5 w-5" }), _jsx(PasswordInput.Input, { className: "pl-10", placeholder: "8 - 20 characters", ...register('confirmPassword') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, { className: "text-white/50" }), asChild: true, children: _jsx(EyeIcon, { className: "text-white/50" }) }) })] }), _jsx(Field.ErrorText, { className: "text-[#ff2525b3] text-xs", children: errors.confirmPassword?.message })] })] }) }), _jsxs(Field.Root, { invalid: !!errors.verificationCode, children: [_jsx(Field.Label, { className: "text-xs", children: "OTP Code" }), _jsxs("div", { className: "relative", children: [_jsx(Field.Input, { className: twMerge(commonInputClass, 'pr-[5.75rem]'), placeholder: "Enter OTP Code", ...register('verificationCode') }), _jsx(Button, { type: "button", className: "absolute right-1 top-1/2 h-fit w-fit -translate-y-1/2 rounded-full py-[0.375rem] text-sm shadow-[inset_0px_-1px_2px_1px_#fff7e1] bg-[linear-gradient(89deg,#c7802d_-15.91%,#ffe585_28.75%,#ffeca6_49.46%,#c7802d_112.69%)]", disabled: !mobileNumberValue || !!errors.mobileNumber || cooldown.cooling, onClick: async () => {
|
|
63
|
+
if (!cooldown.cooling) {
|
|
64
|
+
await sendVerificationCodeMutation.mutateAsync({
|
|
65
|
+
channel: 'SMS',
|
|
66
|
+
recipient: mobileNumberParser.format(getValues('mobileNumber'))
|
|
67
|
+
});
|
|
68
|
+
cooldown.start();
|
|
69
|
+
toaster.success({
|
|
70
|
+
description: `OTP sent to ${getValues('mobileNumber')}`
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}, children: cooldown.cooling ? cooldown.countdown : 'Get OTP' })] }), _jsx(Field.ErrorText, { className: "text-[#ff2525b3] text-xs", children: errors.verificationCode?.message })] }), _jsx(Button, { type: "submit", className: "mt-7.5 text-sm rounded-full shadow-[inset_0px_-1px_2px_1px_#fff7e1] bg-[linear-gradient(89deg,#c7802d_-15.91%,#ffe585_28.75%,#ffeca6_49.46%,#c7802d_112.69%)]", fullWidth: true, disabled: !isValid || !isDirty, children: "Change Password" })] }) }));
|
|
74
|
+
};
|
|
75
|
+
export default CWForgotPasswordForm;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.card {
|
|
2
|
+
--gradient-bg: radial-gradient(103.87% 100% at 50.15% 0%, #072b37 20.3%, #051125 100%);
|
|
3
|
+
|
|
4
|
+
--gradient-border-top: radial-gradient(
|
|
5
|
+
139.23% 113.41% at 50.14% 0%,
|
|
6
|
+
#8affdc 0.49%,
|
|
7
|
+
rgba(138, 255, 220, 0) 33.03%
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
--gradient-border-bottom: radial-gradient(
|
|
11
|
+
42.09% 54.21% at 50.14% 100%,
|
|
12
|
+
#8affdc 5.74%,
|
|
13
|
+
rgba(138, 255, 220, 0) 93.84%
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
position: relative;
|
|
17
|
+
background: var(--gradient-bg);
|
|
18
|
+
box-shadow: 0px 4px 14px 6px rgba(0, 0, 0, 0.6);
|
|
19
|
+
backdrop-filter: blur(25px);
|
|
20
|
+
border-radius: 1.25em;
|
|
21
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.card::after,
|
|
25
|
+
.card::before {
|
|
26
|
+
content: '';
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 0;
|
|
29
|
+
left: 0;
|
|
30
|
+
width: 100%;
|
|
31
|
+
height: 100%;
|
|
32
|
+
z-index: -1;
|
|
33
|
+
border: 0.5px solid transparent;
|
|
34
|
+
border-image-slice: 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.card::before {
|
|
38
|
+
border-image-source: var(--gradient-border-bottom);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.card::after {
|
|
42
|
+
border-image-source: var(--gradient-border-top);
|
|
43
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { type ImageProps } from 'next/image';
|
|
2
2
|
import { type ReactNode } from 'react';
|
|
3
|
+
type ForgotPasswordLayout = 'crazywin';
|
|
3
4
|
export interface ForgotPasswordProps {
|
|
4
5
|
logo: ImageProps['src'];
|
|
5
6
|
children?: ReactNode;
|
|
6
7
|
className?: string;
|
|
8
|
+
layout?: ForgotPasswordLayout;
|
|
7
9
|
}
|
|
8
10
|
export declare function ForgotPassword(props: ForgotPasswordProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -8,12 +8,17 @@ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
|
|
|
8
8
|
import { XIcon } from '../../icons/XIcon.js';
|
|
9
9
|
import { Dialog } from '../../ui/Dialog/index.js';
|
|
10
10
|
import { Portal } from '../../ui/Portal/index.js';
|
|
11
|
+
import CrazywinForgotPassword from './Crazywin/CWForgotPassword.js';
|
|
11
12
|
import { ForgotPasswordForm } from './ForgotPasswordForm.js';
|
|
12
13
|
export function ForgotPassword(props) {
|
|
13
14
|
const globalStore = useGlobalStore(useShallow((ctx) => ({
|
|
14
15
|
forgotPassword: ctx.forgotPassword,
|
|
15
16
|
})));
|
|
17
|
+
const Body = {
|
|
18
|
+
crazywin: (_jsx(CrazywinForgotPassword, { logo: props.logo })),
|
|
19
|
+
default: (_jsxs(Dialog.Content, { className: twMerge('mx-auto h-full w-full items-start bg-bg-primary-alt p-3xl pb-4xl lg:h-auto lg:w-[400px] lg:rounded-xl', props.className), children: [_jsx(Dialog.CloseTrigger, { children: _jsx(XIcon, {}) }), _jsx(Image, { src: props.logo, alt: "", width: 200, height: 100, className: "mx-auto h-auto w-[120px]", draggable: false }), _jsx(Suspense, { children: _jsx(ForgotPasswordForm, {}) })] }))
|
|
20
|
+
};
|
|
16
21
|
return (_jsx(Dialog.Root, { open: globalStore.forgotPassword.open, onOpenChange: (details) => {
|
|
17
22
|
globalStore.forgotPassword.setOpen(details.open);
|
|
18
|
-
}, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { children:
|
|
23
|
+
}, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { children: Body[props.layout ?? 'default'] })] }) }));
|
|
19
24
|
}
|
|
@@ -14,9 +14,9 @@ import treasureChestBg from '../../../images/chest-bg.webp';
|
|
|
14
14
|
import star from '../../../images/star.webp';
|
|
15
15
|
import treasureChest from '../../../images/treasure.webp';
|
|
16
16
|
import { formatNumber } from '../../../utils/formatNumber.js';
|
|
17
|
-
import {
|
|
17
|
+
import { getPercentage } from '../../../utils/getPercentage.js';
|
|
18
18
|
import styles from '../Jackpots.module.css';
|
|
19
|
-
import { CRAZYWIN_JACKPOTS_VARIATIONS } from '../utils.js';
|
|
19
|
+
import { CRAZYWIN_JACKPOTS_VARIATIONS, getAccumulatingJackpotDescription } from '../utils.js';
|
|
20
20
|
import { useJackpotsCarouselItemContext } from './JackpotsCarouselContext.js';
|
|
21
21
|
export function JackpotsCarouselItemCrazyWin({ index, }) {
|
|
22
22
|
const [ref] = useIntersectionObserver({
|
|
@@ -111,19 +111,19 @@ export function JackpotsCarouselItemCrazyWin({ index, }) {
|
|
|
111
111
|
styles['flicker-scale-fade-2'],
|
|
112
112
|
'absolute right-[50%] top-[55%] h-4 w-4',
|
|
113
113
|
],
|
|
114
|
-
].map(([animationClass, positionClass], i) => (_jsx(Image, { src: star, alt: "star", draggable: "false", className: twMerge(animationClass, positionClass) }, i))), _jsx("div", { className: "flex h-full flex-col justify-between", children: _jsx("div", { className: "flex w-full justify-between", children: _jsx("div", { className: "flex w-full flex-col", children: _jsxs("div", { className: "relative flex w-full justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-2 flex gap-1 font-medium", children: _jsxs("div", { className: twMerge('flex w-fit items-center justify-center gap-1 rounded-[10px] border border-[#82F0D0] px-[10px] py-1 text-[#82F0D0] text-xs lg:text-sm'), children: [_jsx("div", { className: twMerge('h-[6px] w-[6px] animate-color rounded-full', isPayingOut
|
|
114
|
+
].map(([animationClass, positionClass], i) => (_jsx(Image, { src: star, alt: "star", draggable: "false", className: twMerge(animationClass, positionClass), unoptimized: true }, i))), _jsx("div", { className: "flex h-full flex-col justify-between", children: _jsx("div", { className: "flex w-full justify-between", children: _jsx("div", { className: "flex w-full flex-col", children: _jsxs("div", { className: "relative flex w-full justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-2 flex gap-1 font-medium", children: _jsxs("div", { className: twMerge('flex w-fit items-center justify-center gap-1 rounded-[10px] border border-[#82F0D0] px-[10px] py-1 text-[#82F0D0] text-xs lg:text-sm'), children: [_jsx("div", { className: twMerge('h-[6px] w-[6px] animate-color rounded-full', isPayingOut
|
|
115
115
|
? styles['pulse-error']
|
|
116
116
|
: styles['pulse-success']) }), _jsx("div", { className: twMerge('rounded text-[#CECFD2]'), children: isPayingOut ? 'Paying Out' : 'Accumulating' })] }) }), _jsx("div", { className: "mb-2 text-left font-semibold text-[18px] text-white lg:mb-0 lg:text-2xl", children: jackpot?.name }), _jsx("div", { className: `${variation.poolBg} ${variation.textColor} flex w-fit rounded-lg px-2 font-semibold text-[26px] lg:text-[36px]`, children: formatNumber(jackpotAmount, {
|
|
117
117
|
currency: localeInfo.currency.code,
|
|
118
118
|
minDecimalPlaces: 2,
|
|
119
119
|
maxDecimalPlaces: 2,
|
|
120
|
-
}) })] }), _jsx(Image, { width: 175, height: 175, src: treasureChest, alt: "treasure chest", className: twMerge('absolute top-[0px] right-[-3px] h-[124px] w-[124px] md:top-0 lg:top-[-30px] lg:h-[175px] lg:w-[175px]'), priority: false, loading: "lazy" })] }) }) }) }), _jsxs("div", { className: "mt-3 lg:mt-4", children: [_jsxs("div", { className: "mb-1 flex justify-between", children: [_jsx("div", { className: "font-semibold text-text-primary-900 text-xs", "aria-live": "polite", children: formatNumber(0, {
|
|
120
|
+
}) })] }), _jsx(Image, { width: 175, height: 175, src: treasureChest, alt: "treasure chest", className: twMerge('absolute top-[0px] right-[-3px] h-[124px] w-[124px] md:top-0 lg:top-[-30px] lg:h-[175px] lg:w-[175px]'), priority: false, loading: "lazy", unoptimized: true })] }) }) }) }), _jsxs("div", { className: "mt-3 lg:mt-4", children: [_jsxs("div", { className: "mb-1 flex justify-between", children: [_jsx("div", { className: "font-semibold text-text-primary-900 text-xs", "aria-live": "polite", children: formatNumber(0, {
|
|
121
121
|
currency: localeInfo.currency.code,
|
|
122
122
|
compact: true,
|
|
123
123
|
}) }), _jsxs("div", { className: "relative flex items-center justify-end gap-1.5", children: [isPayingOut ? (_jsx("div", { className: "flex w-6 items-center", children: [0, 1.5, 3].map((left, i) => (_jsx("div", { className: twMerge(`absolute left-${left}`, styles[`animate-arrow-red-flash-${i + 1}`]), children: _jsx(ChevronLeftIcon, { className: "size-4.5" }) }, i))) })) : (_jsx("div", { className: "flex w-6 items-center", children: [0, 1.5, 3].map((left, i) => (_jsx("div", { className: twMerge(`absolute left-${left}`, styles[`animate-arrow-green-flash-${i + 1}`]), children: _jsx(ChevronRightIcon, { className: "size-4.5" }) }, i))) })), _jsx("div", { className: "font-semibold text-text-primary-900 text-xs", children: formatNumber(jackpot?.maximumJackpotPoolLimit, {
|
|
124
124
|
currency: localeInfo.currency.code,
|
|
125
125
|
compact: true,
|
|
126
|
-
}) })] })] }), _jsx(Progress.Root, { className: "h-2 w-full rounded-full bg-bg-primary lg:h-4", max: 100, value: getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuenow": getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuemax": 100, "aria-label": "Jackpot progress", children: _jsx(Progress.Track, { className: twMerge('h-full overflow-hidden rounded-full', variation.progressBg), children: _jsx(Progress.Range, { className: "relative h-full overflow-hidden rounded-full bg-brand-500 pl-1.5", children: _jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-start pl-1.5", "aria-hidden": "true", children: arrowImages }) }) }) }), _jsx("div", { className: "mt-2 h-2 text-left text-[#F5F5F6] text-xs lg:h-auto lg:text-sm", dangerouslySetInnerHTML: { __html: getInfoBlocks()[infoIndex] } }, infoIndex)] })] }), isPayingOut ? (_jsx("div", { className: twMerge(styles['light-rays'], variation.raysColor, 'rounded-t-2xl [--light-rays-left:90%] [--light-rays-top:100px]') })) : (_jsx(Image, { width: 175, height: 175, src: treasureChestBg, alt: "treasure chest background", className: twMerge('absolute top-0 right-0 h-full w-[380px] object-cover opacity-50'), priority: false, loading: "lazy" }))] }), _jsxs("div", { className: "relative flex h-[56px] min-h-[40px] w-full flex-1 items-center justify-between rounded-b-2xl bg-[#171b26] px-4 py-[10px]", children: [showSeeDetailsButton ? (_jsxs("button", { type: "button", className: "flex items-center gap-1 font-medium text-[#fff] text-sm", children: ["See details", _jsx(ArrowNarrowUpRightIcon, { className: "h-5 w-5" })] })) : (_jsxs("div", { className: "w-full text-white text-xs opacity-100 transition-opacity duration-500 ease-in-out", children: [_jsxs("div", { children: ["Minimum bet:", ' ', _jsxs("span", { className: "font-semibold text-[#FFE5AF]", children: ["PHP", ' ', formatNumber(jackpot.minimumBet, {
|
|
126
|
+
}) })] })] }), _jsx(Progress.Root, { className: "h-2 w-full rounded-full bg-bg-primary lg:h-4", max: 100, value: getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuenow": getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuemax": 100, "aria-label": "Jackpot progress", children: _jsx(Progress.Track, { className: twMerge('h-full overflow-hidden rounded-full', variation.progressBg), children: _jsx(Progress.Range, { className: "relative h-full overflow-hidden rounded-full bg-brand-500 pl-1.5", children: _jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-start pl-1.5", "aria-hidden": "true", children: arrowImages }) }) }) }), _jsx("div", { className: "mt-2 h-2 text-left text-[#F5F5F6] text-xs lg:h-auto lg:text-sm", dangerouslySetInnerHTML: { __html: getInfoBlocks()[infoIndex] } }, infoIndex)] })] }), isPayingOut ? (_jsx("div", { className: twMerge(styles['light-rays'], variation.raysColor, 'rounded-t-2xl [--light-rays-left:90%] [--light-rays-top:100px]') })) : (_jsx(Image, { width: 175, height: 175, src: treasureChestBg, alt: "treasure chest background", className: twMerge('absolute top-0 right-0 h-full w-[380px] object-cover opacity-50'), priority: false, loading: "lazy", unoptimized: true }))] }), _jsxs("div", { className: "relative flex h-[56px] min-h-[40px] w-full flex-1 items-center justify-between rounded-b-2xl bg-[#171b26] px-4 py-[10px]", children: [showSeeDetailsButton ? (_jsxs("button", { type: "button", className: "flex items-center gap-1 font-medium text-[#fff] text-sm", children: ["See details", _jsx(ArrowNarrowUpRightIcon, { className: "h-5 w-5" })] })) : (_jsxs("div", { className: "w-full text-white text-xs opacity-100 transition-opacity duration-500 ease-in-out", children: [_jsxs("div", { children: ["Minimum bet:", ' ', _jsxs("span", { className: "font-semibold text-[#FFE5AF]", children: ["PHP", ' ', formatNumber(jackpot.minimumBet, {
|
|
127
127
|
currency: localeInfo.currency.code,
|
|
128
128
|
minDecimalPlaces: 2,
|
|
129
129
|
maxDecimalPlaces: 2,
|
|
@@ -131,14 +131,3 @@ export function JackpotsCarouselItemCrazyWin({ index, }) {
|
|
|
131
131
|
? `${jackpot.minimumMultiplier}X or more`
|
|
132
132
|
: 'N/A' })] })] })), _jsx("button", { type: "button", className: "text-nowrap text-[#FFE5AF] text-sm underline underline-offset-4", children: "Jackpot Rules" })] })] }));
|
|
133
133
|
}
|
|
134
|
-
const getAccumulatingJackpotDescription = (part, total) => {
|
|
135
|
-
const percentage = total === 0 ? 0 : (part / total) * 100;
|
|
136
|
-
return percentage <= 90
|
|
137
|
-
? 'The jackpot is heating up! Keep playing to stay in the action and watch it grow!'
|
|
138
|
-
: '🔥 It’s about to pop! Stay in the game for your shot at the prize!';
|
|
139
|
-
};
|
|
140
|
-
function getPercentage(value, total) {
|
|
141
|
-
const v = parseDecimal(value, 0);
|
|
142
|
-
const t = parseDecimal(total, 0);
|
|
143
|
-
return t === 0 ? 0 : (v / t) * 100;
|
|
144
|
-
}
|
|
@@ -6,4 +6,3 @@ export interface JackpotsCarouselItemHappyBingoProps {
|
|
|
6
6
|
viewAllUrl?: string;
|
|
7
7
|
}
|
|
8
8
|
export declare function JackpotsCarouselItemHappyBingo({ index, }: JackpotsCarouselItemHappyBingoProps): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
-
export declare const getAccumulatingJackpotDescription: (part: number, total: number) => string;
|
|
@@ -19,7 +19,7 @@ import treasureChest from '../../../images/treasure.webp';
|
|
|
19
19
|
import { formatNumber } from '../../../utils/formatNumber.js';
|
|
20
20
|
import { getPercentage } from '../../../utils/getPercentage.js';
|
|
21
21
|
import styles from '../Jackpots.module.css';
|
|
22
|
-
import { HAPPYBINGO_JACKPOTS_VARIATIONS, maskName } from '../utils.js';
|
|
22
|
+
import { getAccumulatingJackpotDescription, HAPPYBINGO_JACKPOTS_VARIATIONS, maskName } from '../utils.js';
|
|
23
23
|
import { useJackpotsCarouselItemContext } from './JackpotsCarouselContext.js';
|
|
24
24
|
export function JackpotsCarouselItemHappyBingo({ index, }) {
|
|
25
25
|
// 1. Hooks (Context, Data, State, Refs)
|
|
@@ -144,7 +144,7 @@ export function JackpotsCarouselItemHappyBingo({ index, }) {
|
|
|
144
144
|
currency: localeInfo.currency.code,
|
|
145
145
|
minDecimalPlaces: 2,
|
|
146
146
|
maxDecimalPlaces: 2,
|
|
147
|
-
}) })] })] })] })) : (_jsxs("div", { className: "flex h-full w-full flex-row-reverse items-center justify-between", children: [_jsx(Image, { src: coins, alt: "coins", className: "ml-2", unoptimized: true }), _jsxs("div", { children: [_jsx("p", { className: "mt-1 font-semibold text-lg leading-6", children: "No one has won big yet" }), _jsxs("p", { className: "mt-1 text-[0.75rem] leading-[1.125rem]", children: ["You could be the first to win the ", _jsx("br", {}), " jackpot!"] })] })] })) })] }), isPayingOut ? (_jsx("div", { className: twMerge(styles['light-rays'], variation.raysColor, 'rounded-t-2xl [--light-rays-left:90%] [--light-rays-top:100px]') })) : (_jsx(Image, { width: 175, height: 175, src: treasureChestBg, alt: "treasure chest background", className: twMerge('absolute top-0 right-0 h-full w-[380px] object-cover opacity-50'), priority: false, loading: "lazy", unoptimized: true }))] }), _jsxs("div", { className: "relative flex h-[56px] min-h-[40px] w-full flex-1 items-center justify-between rounded-b-2xl bg-white px-4 py-[10px] text-[#475467] dark:bg-[#161B26] dark:text-[#94969C]", children: [showSeeDetailsButton ? (_jsxs("button", { type: "button", className:
|
|
147
|
+
}) })] })] })] })) : (_jsxs("div", { className: "flex h-full w-full flex-row-reverse items-center justify-between", children: [_jsx(Image, { src: coins, alt: "coins", className: "ml-2", unoptimized: true }), _jsxs("div", { children: [_jsx("p", { className: "mt-1 font-semibold text-lg leading-6", children: "No one has won big yet" }), _jsxs("p", { className: "mt-1 text-[0.75rem] leading-[1.125rem]", children: ["You could be the first to win the ", _jsx("br", {}), " jackpot!"] })] })] })) })] }), isPayingOut ? (_jsx("div", { className: twMerge(styles['light-rays'], variation.raysColor, 'rounded-t-2xl [--light-rays-left:90%] [--light-rays-top:100px]') })) : (_jsx(Image, { width: 175, height: 175, src: treasureChestBg, alt: "treasure chest background", className: twMerge('absolute top-0 right-0 h-full w-[380px] object-cover opacity-50'), priority: false, loading: "lazy", unoptimized: true }))] }), _jsxs("div", { className: "relative flex h-[56px] min-h-[40px] w-full flex-1 items-center justify-between rounded-b-2xl bg-white px-4 py-[10px] text-[#475467] dark:bg-[#161B26] dark:text-[#94969C]", children: [showSeeDetailsButton ? (_jsxs("button", { type: "button", className: 'flex items-center gap-1 font-medium text-sm', children: ["See details", _jsx(ArrowNarrowUpRightIcon, { className: "h-5 w-5" })] })) : (_jsxs("div", { className: "w-full text-xs transition-opacity duration-500 ease-in-out", children: [_jsxs("div", { children: ["Minimum bet:", ' ', _jsxs("span", { className: "font-semibold text-[#A15C07] dark:text-[#EAAA08]", children: ["PHP", ' ', formatNumber(jackpot.minimumBet, {
|
|
148
148
|
currency: localeInfo.currency.code,
|
|
149
149
|
minDecimalPlaces: 2,
|
|
150
150
|
maxDecimalPlaces: 2,
|
|
@@ -152,9 +152,3 @@ export function JackpotsCarouselItemHappyBingo({ index, }) {
|
|
|
152
152
|
? `${jackpot.minimumMultiplier}X or more`
|
|
153
153
|
: 'N/A' })] })] })), _jsx("button", { type: "button", className: "inline-flex h-9 items-center justify-center gap-1.5 text-nowrap rounded-lg border border-[#EAAA08] bg-white px-4 py-2.5 font-semibold text-[#A15C07] text-sm text-sm shadow-xs transition-colors duration-200 hover:border-[#FDE272] hover:bg-[#FEFBE8] disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-[#EAAA08] disabled:hover:bg-white dark:border-[#333741] dark:bg-[#161B26] dark:text-[#CECFD2] dark:disabled:hover:border-[#333741] dark:disabled:hover:bg-[#161B26]", children: "Jackpot Rules" })] })] }));
|
|
154
154
|
}
|
|
155
|
-
export const getAccumulatingJackpotDescription = (part, total) => {
|
|
156
|
-
const percentage = total === 0 ? 0 : (part / total) * 100;
|
|
157
|
-
return percentage <= 90
|
|
158
|
-
? 'The jackpot is heating up! Keep playing to stay in the action and watch it grow!'
|
|
159
|
-
: '🔥 It’s about to pop! Stay in the game for your shot at the prize!';
|
|
160
|
-
};
|
|
@@ -10,6 +10,7 @@ import { isStyleEntries } from '../../../utils/isStyleEntries.js';
|
|
|
10
10
|
import { JackpotsListNext } from '../JackpotsListNext/JackpotsList.js';
|
|
11
11
|
import { JackpotsListItemContext, JackpotsListPropsContext, } from './JackpotsListContext.js';
|
|
12
12
|
import { JackpotsListItemCrazyWin } from './JackpotsListItem.CrazyWin.js';
|
|
13
|
+
import { JackpotsListItemHappyBingo } from './JackpotsListItem.HappyBingo.js';
|
|
13
14
|
import { JackpotsListItemDesktop } from './JackpotsListItemDesktop.js';
|
|
14
15
|
import { JackpotsListItemMobile } from './JackpotsListItemMobile.js';
|
|
15
16
|
export function JackpotsList(props) {
|
|
@@ -44,5 +45,5 @@ export function JackpotsList(props) {
|
|
|
44
45
|
future.enabled) {
|
|
45
46
|
return _jsx(JackpotsListNext, { ...props });
|
|
46
47
|
}
|
|
47
|
-
return (_jsx(JackpotsListPropsContext, { value: props, children: _jsxs("div", { ref: ref, style: styles.root, className: classNames.root, children: [_jsx("div", { className: "mb-3 font-semibold text-lg lg:mb-4.5", children: props.heading ?? 'Jackpots' }), jackpots.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden flex-col gap-6 lg:flex", children: jackpots.map((jackpot, index) => (_jsx(JackpotsListItemContext, { value: jackpot, children: props.variant === 'crazywin' ? (_jsx(JackpotsListItemCrazyWin, { index: index, className: classNames })) : (_jsx(JackpotsListItemDesktop, { style: styles.itemRoot, className: classNames, animate: props.animate, customJackpotChestImage: props.customJackpotChestImage, jackpotProfileShape: props.jackpotProfileShape, chestImagesByTier: props.chestImagesByTier })) }, index))) }), _jsx("div", { className: "flex flex-col gap-6 lg:hidden", children: jackpots.map((jackpot, index) => (_jsx(JackpotsListItemContext, { value: jackpot, children: props.variant === 'crazywin' ? (_jsx(JackpotsListItemCrazyWin, { index: index, className: classNames })) : (_jsx(JackpotsListItemMobile, { style: styles.itemRoot, className: classNames, animate: props.animate, customJackpotChestImage: props.customJackpotChestImage, jackpotProfileShape: props.jackpotProfileShape, chestImagesByTier: props.chestImagesByTier })) }, index))) })] })) : (_jsxs("div", { className: "mt-5 flex h-fit flex-col items-center justify-center lg:mt-0 lg:h-62", children: [_jsx(Image, { width: 100, height: 100, src: closeChest, alt: "closeChest", className: "size-full h-29.5 w-29.5 mix-blend-luminosity lg:h-25 lg:w-25" }), _jsx("div", { className: "mt-4 font-semibold text-base text-text-primary-900", children: "No Jackpots" }), _jsxs("div", { className: "mt-1 text-center text-sm text-text-tertiary-600", children: ["No jackpots are running at the moment. ", _jsx("br", {}), "Please check back later!"] })] }))] }) }));
|
|
48
|
+
return (_jsx(JackpotsListPropsContext, { value: props, children: _jsxs("div", { ref: ref, style: styles.root, className: classNames.root, children: [_jsx("div", { className: "mb-3 font-semibold text-lg lg:mb-4.5", children: props.heading ?? 'Jackpots' }), jackpots.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden flex-col gap-6 lg:flex", children: jackpots.map((jackpot, index) => (_jsx(JackpotsListItemContext, { value: jackpot, children: props.variant === 'crazywin' ? (_jsx(JackpotsListItemCrazyWin, { index: index, className: classNames })) : props.variant === 'happybingo' ? (_jsx(JackpotsListItemHappyBingo, { index: index, className: classNames })) : (_jsx(JackpotsListItemDesktop, { style: styles.itemRoot, className: classNames, animate: props.animate, customJackpotChestImage: props.customJackpotChestImage, jackpotProfileShape: props.jackpotProfileShape, chestImagesByTier: props.chestImagesByTier })) }, index))) }), _jsx("div", { className: "flex flex-col gap-6 lg:hidden", children: jackpots.map((jackpot, index) => (_jsx(JackpotsListItemContext, { value: jackpot, children: props.variant === 'crazywin' ? (_jsx(JackpotsListItemCrazyWin, { index: index, className: classNames })) : props.variant === 'happybingo' ? (_jsx(JackpotsListItemHappyBingo, { index: index, className: classNames })) : (_jsx(JackpotsListItemMobile, { style: styles.itemRoot, className: classNames, animate: props.animate, customJackpotChestImage: props.customJackpotChestImage, jackpotProfileShape: props.jackpotProfileShape, chestImagesByTier: props.chestImagesByTier })) }, index))) })] })) : (_jsxs("div", { className: "mt-5 flex h-fit flex-col items-center justify-center lg:mt-0 lg:h-62", children: [_jsx(Image, { width: 100, height: 100, src: closeChest, alt: "closeChest", className: "size-full h-29.5 w-29.5 mix-blend-luminosity lg:h-25 lg:w-25" }), _jsx("div", { className: "mt-4 font-semibold text-base text-text-primary-900", children: "No Jackpots" }), _jsxs("div", { className: "mt-1 text-center text-sm text-text-tertiary-600", children: ["No jackpots are running at the moment. ", _jsx("br", {}), "Please check back later!"] })] }))] }) }));
|
|
48
49
|
}
|
|
@@ -22,7 +22,7 @@ import treasureChest from '../../../images/treasure.webp';
|
|
|
22
22
|
import { formatNumber } from '../../../utils/formatNumber.js';
|
|
23
23
|
import { getPercentage } from '../../../utils/getPercentage.js';
|
|
24
24
|
import styles from '../Jackpots.module.css';
|
|
25
|
-
import { CRAZYWIN_JACKPOTS_VARIATIONS, maskName } from '../utils.js';
|
|
25
|
+
import { CRAZYWIN_JACKPOTS_VARIATIONS, formatProviderName, maskName } from '../utils.js';
|
|
26
26
|
import { useJackpotsListItemContext } from './JackpotsListContext.js';
|
|
27
27
|
import { JackpotsListItemGameProviders } from './JackpotsListItemGameProviders.js';
|
|
28
28
|
import { useJackpotsListItemData } from './useJackpotsListItemData.js';
|
|
@@ -133,23 +133,23 @@ export function JackpotsListItemCrazyWin({ index, }) {
|
|
|
133
133
|
styles['flicker-scale-fade-2'],
|
|
134
134
|
'absolute right-[50%] top-[55%] h-4 w-4',
|
|
135
135
|
],
|
|
136
|
-
].map(([animationClass, positionClass], i) => (_jsx(Image, { src: star, alt: "star", draggable: "false", className: twMerge(animationClass, positionClass) }, i))), _jsx("div", { className: "flex h-full flex-col justify-between", children: _jsx("div", { className: "flex w-full justify-between", children: _jsx("div", { className: "flex w-full flex-col", children: _jsxs("div", { className: "relative flex w-full justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-2 flex gap-1 font-medium", children: _jsxs("div", { className: twMerge('flex w-fit items-center justify-center gap-1 rounded-[10px] border border-[#82F0D0] px-[10px] py-1 text-[#82F0D0] text-xs lg:text-sm'), children: [_jsx("div", { className: twMerge('h-[6px] w-[6px] animate-color rounded-full', isPayingOut
|
|
136
|
+
].map(([animationClass, positionClass], i) => (_jsx(Image, { src: star, alt: "star", draggable: "false", className: twMerge(animationClass, positionClass), unoptimized: true }, i))), _jsx("div", { className: "flex h-full flex-col justify-between", children: _jsx("div", { className: "flex w-full justify-between", children: _jsx("div", { className: "flex w-full flex-col", children: _jsxs("div", { className: "relative flex w-full justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-2 flex gap-1 font-medium", children: _jsxs("div", { className: twMerge('flex w-fit items-center justify-center gap-1 rounded-[10px] border border-[#82F0D0] px-[10px] py-1 text-[#82F0D0] text-xs lg:text-sm'), children: [_jsx("div", { className: twMerge('h-[6px] w-[6px] animate-color rounded-full', isPayingOut
|
|
137
137
|
? styles['pulse-error']
|
|
138
138
|
: styles['pulse-success']) }), _jsx("div", { className: twMerge('rounded text-[#CECFD2]'), children: isPayingOut ? 'Paying Out' : 'Accumulating' })] }) }), _jsx("div", { className: "mb-2 text-left font-semibold text-[18px] text-white lg:mb-0 lg:text-2xl", children: jackpot?.name }), _jsx("div", { className: `${variation.poolBg} ${variation.textColor} flex w-fit rounded-lg px-2 font-semibold text-[26px] lg:text-[36px]`, children: formatNumber(jackpotAmount, {
|
|
139
139
|
currency: localeInfo.currency.code,
|
|
140
140
|
minDecimalPlaces: 2,
|
|
141
141
|
maxDecimalPlaces: 2,
|
|
142
|
-
}) })] }), _jsx(Image, { width: 175, height: 175, src: treasureChest, alt: "treasure chest", className: twMerge('absolute top-[0px] right-[-3px] h-[124px] w-[124px] md:top-0 lg:top-[-30px] lg:h-[175px] lg:w-[175px]'), priority: false, loading: "lazy" })] }) }) }) }), _jsxs("div", { className: "mt-3 lg:mt-4", children: [_jsxs("div", { className: "mb-1 flex justify-between", children: [_jsx("div", { className: "font-semibold text-text-primary-900 text-xs", "aria-live": "polite", children: formatNumber(0, {
|
|
142
|
+
}) })] }), _jsx(Image, { width: 175, height: 175, src: treasureChest, alt: "treasure chest", className: twMerge('absolute top-[0px] right-[-3px] h-[124px] w-[124px] md:top-0 lg:top-[-30px] lg:h-[175px] lg:w-[175px]'), priority: false, loading: "lazy", unoptimized: true })] }) }) }) }), _jsxs("div", { className: "mt-3 lg:mt-4", children: [_jsxs("div", { className: "mb-1 flex justify-between", children: [_jsx("div", { className: "font-semibold text-text-primary-900 text-xs", "aria-live": "polite", children: formatNumber(0, {
|
|
143
143
|
currency: localeInfo.currency.code,
|
|
144
144
|
compact: true,
|
|
145
145
|
}) }), _jsxs("div", { className: "relative flex items-center justify-end gap-1.5", children: [isPayingOut ? (_jsx("div", { className: "flex w-6 items-center", children: [0, 1.5, 3].map((left, i) => (_jsx("div", { className: twMerge(`absolute left-${left}`, styles[`animate-arrow-red-flash-${i + 1}`]), children: _jsx(ChevronLeftIcon, { className: "size-4.5" }) }, i))) })) : (_jsx("div", { className: "flex w-6 items-center", children: [0, 1.5, 3].map((left, i) => (_jsx("div", { className: twMerge(`absolute left-${left}`, styles[`animate-arrow-green-flash-${i + 1}`]), children: _jsx(ChevronRightIcon, { className: "size-4.5" }) }, i))) })), _jsx("div", { className: "font-semibold text-text-primary-900 text-xs", children: formatNumber(jackpot?.maximumJackpotPoolLimit, {
|
|
146
146
|
currency: localeInfo.currency.code,
|
|
147
147
|
compact: true,
|
|
148
|
-
}) })] })] }), _jsx(Progress.Root, { className: "h-2 w-full rounded-full bg-bg-primary lg:h-4", max: 100, value: getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuenow": getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuemax": 100, "aria-label": "Jackpot progress", children: _jsx(Progress.Track, { className: twMerge('h-full overflow-hidden rounded-full', variation.progressBg), children: _jsx(Progress.Range, { className: "relative h-full overflow-hidden rounded-full bg-brand-500 pl-1.5", children: _jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-start pl-1.5", "aria-hidden": "true", children: arrowImages }) }) }) }), _jsx("div", { className: "mt-2 h-2 text-left text-[#F5F5F6] text-xs lg:h-auto lg:text-sm", dangerouslySetInnerHTML: { __html: getInfoBlocks()[infoIndex] } }, infoIndex)] })] }), _jsx("div", { className: "flex items-start gap-5 text-white", children: jackpotPayouts.length ? (_jsxs("div", { className: "flex h-full w-full flex-row items-center justify-between gap-3 lg:w-[280px] lg:flex-col lg:justify-center", children: [_jsx("p", { className: "hidden font-bold text-lg lg:block", children: "Recent Payout \uD83C\uDF89" }), _jsxs("div", { children: [_jsx("p", { className: "mb-1 block font-bold text-[14px] lg:hidden lg:text-lg", children: "Recent Payout \uD83C\uDF89" }), _jsxs("p", { className: "block text-xs leading-[18px] tracking-wider lg:hidden", children: ["Massive payout unlocked! ", _jsx("br", {}), " Who's next? \uD83D\uDCB0"] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: `${variation.topPayoutImgBorderColor} relative flex h-[54px] w-[54px] items-center justify-center rounded-full object-contain p-[3.5px] lg:h-[74px] lg:w-[74px]`, children: [_jsx("div", { className: `flex h-full w-full items-center justify-center rounded-full ${variation.topPayoutImgBg}`, children: _jsx(User02Icon, { className: "h-[34px] w-auto lg:h-[44px]" }) }), _jsx("div", { className: `${variation.topPayoutImgBorderColor} absolute right-[-6px] bottom-[-5px] flex h-8 w-8 items-center justify-center rounded-full p-[2px] lg:right-0 lg:bottom-0`, children: _jsxs("div", { className: `flex h-full w-full items-center justify-center rounded-full font-bold text-[10px] ${variation.topPayoutImgBorderColor} ${variation.textColor} ${variation.multiplierBg} ${variation.multiplierColor}`, children: [jackpotPayouts[0].multiplier, "x"] }) })] }), _jsxs("div", { children: [_jsx("p", { className: "font-semibold text-2xl", children: maskName(jackpotPayouts[0].member.name) }), _jsx("p", { className: `${variation.poolBg} rounded-lg px-2 font-semibold text-[22px] ${variation.textColor}`, children: formatNumber(jackpotPayouts[0].amount, {
|
|
148
|
+
}) })] })] }), _jsx(Progress.Root, { className: "h-2 w-full rounded-full bg-bg-primary lg:h-4", max: 100, value: getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuenow": getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuemax": 100, "aria-label": "Jackpot progress", children: _jsx(Progress.Track, { className: twMerge('h-full overflow-hidden rounded-full', variation.progressBg), children: _jsx(Progress.Range, { className: "relative h-full overflow-hidden rounded-full bg-brand-500 pl-1.5", children: _jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-start pl-1.5", "aria-hidden": "true", children: arrowImages }) }) }) }), _jsx("div", { className: "mt-2 h-2 text-left text-[#F5F5F6] text-xs lg:h-auto lg:text-sm", dangerouslySetInnerHTML: { __html: getInfoBlocks()[infoIndex] } }, infoIndex)] })] }), _jsx("div", { className: "z-1 flex items-start gap-5 text-white", children: jackpotPayouts.length ? (_jsxs("div", { className: "flex h-full w-full flex-row items-center justify-between gap-3 lg:w-[280px] lg:flex-col lg:justify-center", children: [_jsx("p", { className: "hidden font-bold text-lg lg:block", children: "Recent Payout \uD83C\uDF89" }), _jsxs("div", { children: [_jsx("p", { className: "mb-1 block font-bold text-[14px] lg:hidden lg:text-lg", children: "Recent Payout \uD83C\uDF89" }), _jsxs("p", { className: "block text-xs leading-[18px] tracking-wider lg:hidden", children: ["Massive payout unlocked! ", _jsx("br", {}), " Who's next? \uD83D\uDCB0"] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: `${variation.topPayoutImgBorderColor} relative flex h-[54px] w-[54px] items-center justify-center rounded-full object-contain p-[3.5px] lg:h-[74px] lg:w-[74px]`, children: [_jsx("div", { className: `flex h-full w-full items-center justify-center rounded-full ${variation.topPayoutImgBg}`, children: _jsx(User02Icon, { className: "h-[34px] w-auto lg:h-[44px]" }) }), _jsx("div", { className: `${variation.topPayoutImgBorderColor} absolute right-[-6px] bottom-[-5px] flex h-8 w-8 items-center justify-center rounded-full p-[2px] lg:right-0 lg:bottom-0`, children: _jsxs("div", { className: `flex h-full w-full items-center justify-center rounded-full font-bold text-[10px] ${variation.topPayoutImgBorderColor} ${variation.textColor} ${variation.multiplierBg} ${variation.multiplierColor}`, children: [jackpotPayouts[0].multiplier, "x"] }) })] }), _jsxs("div", { children: [_jsx("p", { className: "font-semibold text-2xl", children: maskName(jackpotPayouts[0].member.name) }), _jsx("p", { className: `${variation.poolBg} rounded-lg px-2 font-semibold text-[22px] ${variation.textColor}`, children: formatNumber(jackpotPayouts[0].amount, {
|
|
149
149
|
currency: localeInfo.currency.code,
|
|
150
150
|
minDecimalPlaces: 2,
|
|
151
151
|
maxDecimalPlaces: 2,
|
|
152
|
-
}) })] })] }), _jsxs("p", { className: "hidden text-center text-xs leading-[18px] tracking-wider lg:block", children: ["Massive payout unlocked! ", _jsx("br", {}), " Who's next? \uD83D\uDCB0"] })] })) : (_jsxs("div", { className: "flex h-full w-full flex-row-reverse items-center justify-between lg:w-[280px] lg:flex-col lg:justify-center", children: [_jsx(Image, { src: coins, alt: "coins", className: "ml-2" }), _jsxs("div", { children: [_jsx("p", { className: "mt-1 font-semibold text-lg leading-6", children: "No one has won big yet" }), _jsxs("p", { className: "mt-1 text-start text-[0.75rem] leading-[1.125rem] lg:text-center", children: ["You could be the first to win the ", _jsx("br", {}), " jackpot!"] })] })] })) })] }), isPayingOut ? (_jsx("div", { className: twMerge(styles['light-rays'], variation.raysColor, 'rounded-t-2xl [--light-rays-left:
|
|
152
|
+
}) })] })] }), _jsxs("p", { className: "hidden text-center text-xs leading-[18px] tracking-wider lg:block", children: ["Massive payout unlocked! ", _jsx("br", {}), " Who's next? \uD83D\uDCB0"] })] })) : (_jsxs("div", { className: "flex h-full w-full flex-row-reverse items-center justify-between lg:w-[280px] lg:flex-col lg:justify-center", children: [_jsx(Image, { src: coins, alt: "coins", className: "ml-2", unoptimized: true }), _jsxs("div", { children: [_jsx("p", { className: "mt-1 font-semibold text-lg leading-6", children: "No one has won big yet" }), _jsxs("p", { className: "mt-1 text-start text-[0.75rem] leading-[1.125rem] lg:text-center", children: ["You could be the first to win the ", _jsx("br", {}), " jackpot!"] })] })] })) })] }), isPayingOut ? (_jsx("div", { className: twMerge(styles['light-rays'], variation.raysColor, 'rounded-t-2xl [--light-rays-left:70%] [--light-rays-top:100px]') })) : (_jsx(Image, { width: 175, height: 175, src: treasureChestBg, alt: "treasure chest background", className: twMerge('absolute top-0 right-0 h-full w-[380px] object-cover opacity-50'), priority: false, loading: "lazy", unoptimized: true }))] }), _jsxs("div", { className: "relative flex w-full flex-col items-center rounded-b-2xl bg-[#171b26] px-4", children: [_jsxs("div", { className: "flex w-full justify-between py-4", children: [_jsxs("button", { onClick: () => setSeeDetails((v) => !v), type: "button", className: "flex items-center gap-1 font-medium text-[#fff] text-sm", children: ["See details", ' ', seeDetails ? (_jsx(ChevronUpIcon, { className: "h-5" })) : (_jsx(ChevronDownIcon, { className: "h-5" }))] }), _jsx("button", { type: "button", className: "text-nowrap text-[#FFE5AF] text-sm underline underline-offset-4", children: "Jackpot Rules" })] }), seeDetails && (_jsxs("div", { className: "w-full", children: [_jsxs("div", { children: [_jsx("div", { className: "mt-[6px] flex justify-between text-[#CECFD2] text-lg", children: _jsxs("div", { className: "flex items-center gap-3 font-semibold", children: [_jsx(Image, { src: coin, alt: "coin", className: "h-6", unoptimized: true }), "Recent Payouts"] }) }), _jsx("div", { className: "mt-[1.25rem] mb-[2rem] gap-[0.625rem]", children: _jsx("div", { className: "flex-1 overflow-x-auto rounded-lg border border-[#1F242F]", children: _jsxs("table", { className: "w-full min-w-[700px]", children: [_jsx("thead", { children: _jsx("tr", { className: "h-[44px] bg-[#0C111D] text-[#94969C] text-xs", children: [
|
|
153
153
|
'Player',
|
|
154
154
|
'Game Provider',
|
|
155
155
|
'Multiplier',
|
|
@@ -163,11 +163,5 @@ export function JackpotsListItemCrazyWin({ index, }) {
|
|
|
163
163
|
minDecimalPlaces: 2,
|
|
164
164
|
maxDecimalPlaces: 2,
|
|
165
165
|
}) }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: format(new Date(jp.dateTimeCreated), 'dd MMM yyyy h:mm a') })] }, jp.id)))
|
|
166
|
-
: Array.from({ length: 5 }).map((_, i) => (_jsxs("tr", { className: "h-[44px] bg-[#0C111D] text-left text-[#94969C] text-sm", children: [_jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" })] }, i))) })] }) }) })] }), _jsx("div", { className: "w-full", children: Boolean(filteredGameProviders.length) && (_jsx(JackpotsListItemGameProviders, { gameProviders: filteredGameProviders, heading: _jsxs("div", { className: "flex items-center gap-3 font-semibold", children: [_jsx(Image, { src: treasureChest, alt: "treasure chest", className: "size-6" }), "Game Providers"] }) })) })] }))] })] }));
|
|
167
|
-
}
|
|
168
|
-
function formatProviderName(provider) {
|
|
169
|
-
return provider
|
|
170
|
-
.split('_')
|
|
171
|
-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
172
|
-
.join(' ');
|
|
166
|
+
: Array.from({ length: 5 }).map((_, i) => (_jsxs("tr", { className: "h-[44px] bg-[#0C111D] text-left text-[#94969C] text-sm", children: [_jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" }), _jsx("td", { className: "border-[#1F242F] border-b px-6 py-2", children: "-" })] }, i))) })] }) }) })] }), _jsx("div", { className: "w-full", children: Boolean(filteredGameProviders.length) && (_jsx(JackpotsListItemGameProviders, { gameProviders: filteredGameProviders, heading: _jsxs("div", { className: "flex items-center gap-3 font-semibold", children: [_jsx(Image, { src: treasureChest, alt: "treasure chest", className: "size-6", unoptimized: true }), "Game Providers"] }) })) })] }))] })] }));
|
|
173
167
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ClassNameEntries } from './JackpotsList';
|
|
2
|
+
export interface JackpotsListItemDesktopHappyBingoProps {
|
|
3
|
+
index: number;
|
|
4
|
+
className?: ClassNameEntries;
|
|
5
|
+
}
|
|
6
|
+
export declare function JackpotsListItemHappyBingo({ index, }: JackpotsListItemDesktopHappyBingoProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Progress } from '@ark-ui/react/progress';
|
|
4
|
+
import { format } from 'date-fns';
|
|
5
|
+
import isMobile from 'is-mobile';
|
|
6
|
+
import Image from 'next/image';
|
|
7
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
8
|
+
import { twMerge } from 'tailwind-merge';
|
|
9
|
+
import { useIntersectionObserver } from 'usehooks-ts';
|
|
10
|
+
import { useJackpotPayoutsQuery } from '../../../client/hooks/useJackpotPayoutsQuery.js';
|
|
11
|
+
import { useLocaleInfo } from '../../../client/hooks/useLocaleInfo.js';
|
|
12
|
+
import { ChevronDownIcon } from '../../../icons/ChevronDownIcon.js';
|
|
13
|
+
import { ChevronLeftIcon } from '../../../icons/ChevronLeftIcon.js';
|
|
14
|
+
import { ChevronRightIcon } from '../../../icons/ChevronRightIcon.js';
|
|
15
|
+
import { ChevronUpIcon } from '../../../icons/ChevronUpIcon.js';
|
|
16
|
+
import { User02Icon } from '../../../icons/User02Icon.js';
|
|
17
|
+
import starTwo from '../../../images/3d-star.webp';
|
|
18
|
+
import treasureChestBg from '../../../images/chest-bg.webp';
|
|
19
|
+
import coins from '../../../images/happy-bingo-coins.webp';
|
|
20
|
+
import star from '../../../images/star.webp';
|
|
21
|
+
import treasureChest from '../../../images/treasure.webp';
|
|
22
|
+
import { formatNumber } from '../../../utils/formatNumber.js';
|
|
23
|
+
import { getPercentage } from '../../../utils/getPercentage.js';
|
|
24
|
+
import styles from '../Jackpots.module.css';
|
|
25
|
+
import { formatProviderName, HAPPYBINGO_JACKPOTS_VARIATIONS, maskName } from '../utils.js';
|
|
26
|
+
import { useJackpotsListItemContext } from './JackpotsListContext.js';
|
|
27
|
+
import { JackpotsListItemGameProviders } from './JackpotsListItemGameProviders.js';
|
|
28
|
+
import { useJackpotsListItemData } from './useJackpotsListItemData.js';
|
|
29
|
+
export function JackpotsListItemHappyBingo({ index, }) {
|
|
30
|
+
const jackpot = useJackpotsListItemContext();
|
|
31
|
+
const localeInfo = useLocaleInfo();
|
|
32
|
+
const { getAccumulatingJackpotDescription, filteredGameProviders } = useJackpotsListItemData();
|
|
33
|
+
const jackpotPayoutsQuery = useJackpotPayoutsQuery({
|
|
34
|
+
first: 30,
|
|
35
|
+
filter: {
|
|
36
|
+
jackpot: {
|
|
37
|
+
equal: jackpot.id,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const [ref] = useIntersectionObserver({
|
|
42
|
+
threshold: 0.5,
|
|
43
|
+
rootMargin: '50px',
|
|
44
|
+
});
|
|
45
|
+
const [infoIndex, setInfoIndex] = useState(0);
|
|
46
|
+
const [seeDetails, setSeeDetails] = useState(false);
|
|
47
|
+
const [mainTooltipOpen, setMainTooltipOpen] = useState(false);
|
|
48
|
+
const isPayingOut = jackpot.drawing;
|
|
49
|
+
const jackpotAmount = jackpot.pool;
|
|
50
|
+
const jackpotPayouts = jackpotPayoutsQuery.data?.pages[0].edges.map((edge) => edge.node) ?? [];
|
|
51
|
+
const variation = HAPPYBINGO_JACKPOTS_VARIATIONS[index % HAPPYBINGO_JACKPOTS_VARIATIONS.length];
|
|
52
|
+
const isMobileDevice = useMemo(() => isMobile(), []);
|
|
53
|
+
const getInfoBlocks = useCallback(() => {
|
|
54
|
+
return [
|
|
55
|
+
`Current Jackpot: <b>${formatNumber(jackpotAmount, {
|
|
56
|
+
currency: localeInfo.currency.code,
|
|
57
|
+
minDecimalPlaces: 2,
|
|
58
|
+
maxDecimalPlaces: 2,
|
|
59
|
+
})}</b>`,
|
|
60
|
+
`Minimum Payout Limit: <b>${formatNumber(jackpot.minimumJackpotPoolDrawingLimit, {
|
|
61
|
+
currency: localeInfo.currency.code,
|
|
62
|
+
minDecimalPlaces: 2,
|
|
63
|
+
maxDecimalPlaces: 2,
|
|
64
|
+
})}</b>`,
|
|
65
|
+
`Maximum Payout Limit: <b>${formatNumber(jackpot.maximumJackpotPoolLimit, {
|
|
66
|
+
currency: localeInfo.currency.code,
|
|
67
|
+
minDecimalPlaces: 2,
|
|
68
|
+
maxDecimalPlaces: 2,
|
|
69
|
+
})}</b>`,
|
|
70
|
+
isPayingOut
|
|
71
|
+
? `The pot has hit <b>${formatNumber(jackpot.maximumJackpotPoolLimit, {
|
|
72
|
+
currency: localeInfo.currency.code,
|
|
73
|
+
minDecimalPlaces: 2,
|
|
74
|
+
maxDecimalPlaces: 2,
|
|
75
|
+
})}</b> Play now for your chance to win big! 🔥`
|
|
76
|
+
: getAccumulatingJackpotDescription(Number(jackpot.pool), Number(jackpot.maximumJackpotPoolLimit)),
|
|
77
|
+
];
|
|
78
|
+
}, [
|
|
79
|
+
isPayingOut,
|
|
80
|
+
jackpot,
|
|
81
|
+
jackpotAmount,
|
|
82
|
+
localeInfo,
|
|
83
|
+
getAccumulatingJackpotDescription,
|
|
84
|
+
]);
|
|
85
|
+
const Arrow = useCallback(({ index }) => {
|
|
86
|
+
const Icon = isPayingOut ? ChevronLeftIcon : ChevronRightIcon;
|
|
87
|
+
return (_jsx(Icon, { className: twMerge('min-w-2.5 scale-400 text-brand-300 lg:min-w-4 lg:scale-250', isPayingOut
|
|
88
|
+
? styles['animate-wave-color-error']
|
|
89
|
+
: styles['animate-wave-color-success']), style: {
|
|
90
|
+
animationDelay: isPayingOut
|
|
91
|
+
? `${(40 - index - 1) * 0.1}s`
|
|
92
|
+
: `${index * 0.1}s`,
|
|
93
|
+
} }));
|
|
94
|
+
}, [isPayingOut]);
|
|
95
|
+
const arrowImages = useMemo(() => Array.from({ length: 40 }, (_, i) => _jsx(Arrow, { index: i }, i)), [Arrow]);
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const interval = setInterval(() => {
|
|
98
|
+
setInfoIndex((i) => (i + 1) % getInfoBlocks().length);
|
|
99
|
+
}, 4000);
|
|
100
|
+
return () => clearInterval(interval);
|
|
101
|
+
}, [getInfoBlocks]);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (isMobileDevice && mainTooltipOpen) {
|
|
104
|
+
const timeout = setTimeout(() => setMainTooltipOpen(false), 3000);
|
|
105
|
+
return () => clearTimeout(timeout);
|
|
106
|
+
}
|
|
107
|
+
}, [mainTooltipOpen, isMobileDevice]);
|
|
108
|
+
if (jackpot.status === 'DISABLED' && jackpot.drawing !== true) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return (_jsxs("div", { className: "w-full shrink-0", children: [_jsxs("div", { ref: ref, className: twMerge('relative flex w-full shrink-0 rounded-t-2xl p-3 text-center lg:gap-4 lg:p-5', variation.background), children: [_jsxs("div", { className: "flex w-full flex-col gap-6 lg:flex-row lg:gap-0", children: [_jsxs("div", { className: "relative z-1 flex flex-1 flex-col", children: [[
|
|
112
|
+
[
|
|
113
|
+
styles['flicker-scale-fade-2'],
|
|
114
|
+
'absolute right-[38%] top-[2%] h-2 w-2 delay-75',
|
|
115
|
+
],
|
|
116
|
+
[
|
|
117
|
+
styles['flicker-scale-fade'],
|
|
118
|
+
'absolute right-[20%] top-[10%] h-3 w-3',
|
|
119
|
+
],
|
|
120
|
+
[
|
|
121
|
+
styles['flicker-scale-fade-2'],
|
|
122
|
+
'absolute right-[30%] top-[10%] h-5 w-5',
|
|
123
|
+
],
|
|
124
|
+
[
|
|
125
|
+
styles['flicker-scale-fade'],
|
|
126
|
+
'absolute right-[36%] top-[35%] h-3 w-3',
|
|
127
|
+
],
|
|
128
|
+
[
|
|
129
|
+
styles['flicker-scale-fade'],
|
|
130
|
+
'absolute right-[15%] top-[56%] h-3 w-3',
|
|
131
|
+
],
|
|
132
|
+
[
|
|
133
|
+
styles['flicker-scale-fade-2'],
|
|
134
|
+
'absolute right-[50%] top-[55%] h-4 w-4',
|
|
135
|
+
],
|
|
136
|
+
].map(([animationClass, positionClass], i) => (_jsx(Image, { src: star, alt: "star", draggable: "false", className: twMerge(animationClass, positionClass), unoptimized: true }, i))), _jsx("div", { className: "flex h-full flex-col justify-between", children: _jsx("div", { className: "flex w-full justify-between", children: _jsx("div", { className: "flex w-full flex-col", children: _jsxs("div", { className: "relative flex w-full justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-2 flex gap-1 font-medium", children: _jsxs("div", { className: twMerge('flex w-fit items-center justify-center gap-1 rounded-[10px] border border-[#FECDCA] bg-[#FEF3F2] px-2.5 py-1 text-sm'), children: [_jsx("div", { className: twMerge('h-[6px] w-[6px] animate-color rounded-full', isPayingOut
|
|
137
|
+
? styles['pulse-error']
|
|
138
|
+
: styles['pulse-success']) }), _jsx("div", { className: twMerge('rounded text-[#344054]'), children: isPayingOut ? 'Paying Out' : 'Accumulating' })] }) }), _jsx("div", { className: "mb-2 text-left font-semibold text-[18px] text-white lg:mb-0 lg:text-2xl", children: jackpot?.name }), _jsx("div", { className: `${variation.poolBg} ${variation.textColor} flex w-fit rounded-lg px-2 font-semibold text-[26px] lg:text-[36px]`, children: formatNumber(jackpotAmount, {
|
|
139
|
+
currency: localeInfo.currency.code,
|
|
140
|
+
minDecimalPlaces: 2,
|
|
141
|
+
maxDecimalPlaces: 2,
|
|
142
|
+
}) })] }), _jsx(Image, { width: 175, height: 175, src: treasureChest, alt: "treasure chest", className: twMerge('absolute top-[0px] right-[-3px] h-[124px] w-[124px] md:top-0 lg:top-[-30px] lg:h-[175px] lg:w-[175px]'), priority: false, loading: "lazy", unoptimized: true })] }) }) }) }), _jsxs("div", { className: "mt-3 lg:mt-4", children: [_jsxs("div", { className: "mb-1 flex justify-between", children: [_jsx("div", { className: "font-semibold text-text-primary-900 text-xs", "aria-live": "polite", children: formatNumber(0, {
|
|
143
|
+
currency: localeInfo.currency.code,
|
|
144
|
+
compact: true,
|
|
145
|
+
}) }), _jsxs("div", { className: "relative flex items-center justify-end gap-1.5", children: [isPayingOut ? (_jsx("div", { className: "flex w-6 items-center", children: [0, 1.5, 3].map((left, i) => (_jsx("div", { className: twMerge(`absolute left-${left}`, styles[`animate-arrow-red-flash-${i + 1}`]), children: _jsx(ChevronLeftIcon, { className: "size-4.5" }) }, i))) })) : (_jsx("div", { className: "flex w-6 items-center", children: [0, 1.5, 3].map((left, i) => (_jsx("div", { className: twMerge(`absolute left-${left}`, styles[`animate-arrow-green-flash-${i + 1}`]), children: _jsx(ChevronRightIcon, { className: "size-4.5" }) }, i))) })), _jsx("div", { className: "font-semibold text-text-primary-900 text-xs", children: formatNumber(jackpot?.maximumJackpotPoolLimit, {
|
|
146
|
+
currency: localeInfo.currency.code,
|
|
147
|
+
compact: true,
|
|
148
|
+
}) })] })] }), _jsx(Progress.Root, { className: "h-2 w-full rounded-full bg-bg-primary lg:h-4", max: 100, value: getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuenow": getPercentage(jackpot.pool, jackpot.maximumJackpotPoolLimit), "aria-valuemax": 100, "aria-label": "Jackpot progress", children: _jsx(Progress.Track, { className: twMerge('h-full overflow-hidden rounded-full', variation.progressBg), children: _jsx(Progress.Range, { className: "relative h-full overflow-hidden rounded-full bg-brand-500 pl-1.5", children: _jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-start pl-1.5", "aria-hidden": "true", children: arrowImages }) }) }) }), _jsx("div", { className: "mt-2 h-2 text-left text-[#F5F5F6] text-xs lg:h-auto lg:text-sm", dangerouslySetInnerHTML: { __html: getInfoBlocks()[infoIndex] } }, infoIndex)] })] }), _jsx("div", { className: "z-1 flex items-start gap-5 text-white", children: jackpotPayouts.length ? (_jsxs("div", { className: "flex h-full w-full flex-row items-center justify-between gap-3 lg:w-[280px] lg:flex-col lg:justify-center", children: [_jsx("p", { className: "hidden font-bold text-lg lg:block", children: "Recent Payout \uD83C\uDF89" }), _jsxs("div", { children: [_jsx("p", { className: "mb-1 block font-bold text-[14px] lg:hidden lg:text-lg", children: "Recent Payout \uD83C\uDF89" }), _jsxs("p", { className: "block text-xs leading-[18px] tracking-wider lg:hidden", children: ["Massive payout unlocked! ", _jsx("br", {}), " Who's next? \uD83D\uDCB0"] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: `${variation.topPayoutImgBorderColor} relative flex h-[54px] w-[54px] items-center justify-center rounded-full object-contain p-[3.5px] lg:h-[74px] lg:w-[74px]`, children: [_jsx("div", { className: `flex h-full w-full items-center justify-center rounded-full ${variation.topPayoutImgBg}`, children: _jsx(User02Icon, { className: "h-[34px] w-auto lg:h-[44px]" }) }), _jsx("div", { className: `${variation.topPayoutImgBorderColor} absolute right-[-6px] bottom-[-5px] flex h-8 w-8 items-center justify-center rounded-full p-[2px] lg:right-0 lg:bottom-0`, children: _jsxs("div", { className: `flex h-full w-full items-center justify-center rounded-full font-bold text-[10px] ${variation.topPayoutImgBorderColor} ${variation.textColor} ${variation.multiplierBg} ${variation.multiplierColor}`, children: [jackpotPayouts[0].multiplier, "x"] }) })] }), _jsxs("div", { children: [_jsx("p", { className: "font-semibold text-2xl", children: maskName(jackpotPayouts[0].member.name) }), _jsx("p", { className: `${variation.poolBg} rounded-lg px-2 font-semibold text-[22px] ${variation.textColor}`, children: formatNumber(jackpotPayouts[0].amount, {
|
|
149
|
+
currency: localeInfo.currency.code,
|
|
150
|
+
minDecimalPlaces: 2,
|
|
151
|
+
maxDecimalPlaces: 2,
|
|
152
|
+
}) })] })] }), _jsxs("p", { className: "hidden text-center text-xs leading-[18px] tracking-wider lg:block", children: ["Massive payout unlocked! ", _jsx("br", {}), " Who's next? \uD83D\uDCB0"] })] })) : (_jsxs("div", { className: "flex h-full w-full flex-row-reverse items-center justify-between lg:w-[280px] lg:flex-col lg:justify-center", children: [_jsx(Image, { src: coins, alt: "coins", className: "ml-2", unoptimized: true }), _jsxs("div", { children: [_jsx("p", { className: "mt-1 font-semibold text-lg leading-6", children: "No one has won big yet" }), _jsxs("p", { className: "mt-1 text-start text-[0.75rem] leading-[1.125rem] lg:text-center", children: ["You could be the first to win the ", _jsx("br", {}), " jackpot!"] })] })] })) })] }), isPayingOut ? (_jsx("div", { className: twMerge(styles['light-rays'], variation.raysColor, 'rounded-t-2xl [--light-rays-left:70%] [--light-rays-top:100px]') })) : (_jsx(Image, { width: 175, height: 175, src: treasureChestBg, alt: "treasure chest background", className: twMerge('absolute top-0 right-0 h-full w-[380px] object-cover opacity-50'), priority: false, loading: "lazy", unoptimized: true }))] }), _jsxs("div", { className: "relative flex w-full flex-col items-center rounded-b-2xl bg-white px-4 text-[#475467] dark:bg-[#161B26] dark:text-[#94969C]", children: [_jsxs("div", { className: "flex w-full justify-between py-3", children: [_jsxs("button", { onClick: () => setSeeDetails((v) => !v), type: "button", className: "flex items-center gap-1 font-medium text-sm", children: ["See details", ' ', seeDetails ? (_jsx(ChevronUpIcon, { className: "h-5" })) : (_jsx(ChevronDownIcon, { className: "h-5" }))] }), _jsx("button", { type: "button", className: "inline-flex h-9 items-center justify-center gap-1.5 text-nowrap rounded-lg border border-[#EAAA08] bg-white px-4 py-2.5 font-semibold text-[#A15C07] text-sm text-sm shadow-xs transition-colors duration-200 hover:border-[#FDE272] hover:bg-[#FEFBE8] disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-[#EAAA08] disabled:hover:bg-white dark:border-[#333741] dark:bg-[#161B26] dark:text-[#CECFD2] dark:disabled:hover:border-[#333741] dark:disabled:hover:bg-[#161B26]", children: "Jackpot Rules" })] }), seeDetails && (_jsxs("div", { className: "w-full", children: [_jsxs("div", { children: [_jsx("div", { className: "mt-[6px] flex justify-between text-[#344054] text-lg dark:text-[#CECFD2]", children: _jsxs("div", { className: "flex items-center gap-3 font-semibold", children: [_jsx(Image, { src: starTwo, alt: "3d star", className: "size-6", unoptimized: true }), "Recent Payouts"] }) }), _jsx("div", { className: "mt-[1.25rem] mb-[2rem] gap-[0.625rem]", children: _jsx("div", { className: "w-full max-w-full overflow-x-auto overflow-y-hidden whitespace-nowrap rounded-xl border border-[#eaecf0] dark:border-[#1f242f]", children: _jsxs("table", { className: "w-full min-w-[700px]", children: [_jsx("thead", { className: "border-[#EAECF0] border-b dark:border-[#1F242F]", children: _jsx("tr", { className: "border-[#EAECF0] border-b bg-white px-0 last:border-b-0 odd:bg-[#F9FAFB] dark:border-[#1F242F] dark:bg-[#0C111D] dark:odd:bg-[#0C111D]", children: [
|
|
153
|
+
'Player',
|
|
154
|
+
'Game Provider',
|
|
155
|
+
'Multiplier',
|
|
156
|
+
'Prize',
|
|
157
|
+
'Timestamp',
|
|
158
|
+
].map((label) => (_jsx("th", { className: "bg-white px-3xl py-lg text-left font-medium text-[#475467] text-xs dark:bg-[#0C111D] dark:text-[#94969C]", children: label }, label))) }) }), _jsx("tbody", { children: jackpotPayouts.length
|
|
159
|
+
? jackpotPayouts
|
|
160
|
+
.filter((jp) => jp.id !== '5HMmGqAZDPqqeFHBmv')
|
|
161
|
+
.map((jp) => (_jsxs("tr", { className: "border-[#EAECF0] border-b bg-white last:border-b-0 odd:bg-[#F9FAFB] dark:border-[#1F242F] dark:bg-[#0C111D] dark:odd:bg-[#0C111D]", children: [_jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: maskName(jp?.member?.name) }), _jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: formatProviderName(jp?.game.provider ?? '-') }), _jsxs("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: [jp?.multiplier, "x"] }), _jsx("td", { className: "px-3xl py-xl text-left text-[#079455] text-sm dark:text-[#47CD89]", children: formatNumber(jp?.amount ?? 0, {
|
|
162
|
+
currency: localeInfo.currency.code,
|
|
163
|
+
minDecimalPlaces: 2,
|
|
164
|
+
maxDecimalPlaces: 2,
|
|
165
|
+
}) }), _jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: format(new Date(jp.dateTimeCreated), 'dd MMM yyyy h:mm a') })] }, jp.id)))
|
|
166
|
+
: Array.from({ length: 5 }).map((_, i) => (_jsxs("tr", { className: "h-[44px] bg-[#0C111D] text-left text-[#94969C] text-sm", children: [_jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: "-" }), _jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: "-" }), _jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: "-" }), _jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: "-" }), _jsx("td", { className: "px-3xl py-xl text-left text-[#475467] text-sm dark:text-[#94969C]", children: "-" })] }, i))) })] }) }) })] }), _jsx("div", { className: "w-full", children: Boolean(filteredGameProviders.length) && (_jsx(JackpotsListItemGameProviders, { gameProviders: filteredGameProviders, heading: _jsxs("div", { className: "flex items-center gap-3 font-semibold text-[#344054] dark:text-[#CECFD2]", children: [_jsx(Image, { src: treasureChest, alt: "treasure chest", className: "size-6", unoptimized: true }), "Jackpot Game Provider"] }) })) })] }))] })] }));
|
|
167
|
+
}
|
|
@@ -22,3 +22,4 @@ export declare const HAPPYBINGO_JACKPOTS_VARIATIONS: {
|
|
|
22
22
|
}[];
|
|
23
23
|
export declare function formatProviderName(provider: string): string;
|
|
24
24
|
export declare const maskName: (name: string) => string;
|
|
25
|
+
export declare const getAccumulatingJackpotDescription: (part: number, total: number) => string;
|
|
@@ -88,3 +88,9 @@ export const maskName = (name) => {
|
|
|
88
88
|
const maskedPart = '*'.repeat(7);
|
|
89
89
|
return visiblePart + maskedPart;
|
|
90
90
|
};
|
|
91
|
+
export const getAccumulatingJackpotDescription = (part, total) => {
|
|
92
|
+
const percentage = total === 0 ? 0 : (part / total) * 100;
|
|
93
|
+
return percentage <= 90
|
|
94
|
+
? 'The jackpot is heating up! Keep playing to stay in the action and watch it grow!'
|
|
95
|
+
: '🔥 It’s about to pop! Stay in the game for your shot at the prize!';
|
|
96
|
+
};
|
|
@@ -2,6 +2,9 @@ import type { Cashback as TCashback } from '../../types';
|
|
|
2
2
|
interface CashbackProps {
|
|
3
3
|
data: TCashback;
|
|
4
4
|
viewDetailsUrl: string;
|
|
5
|
+
hasPromotionPeriod?: boolean;
|
|
6
|
+
roundedButtons?: boolean;
|
|
7
|
+
textOrientation?: 'left' | 'center';
|
|
5
8
|
}
|
|
6
|
-
export declare function Cashback({ data, viewDetailsUrl }: CashbackProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function Cashback({ data, viewDetailsUrl, hasPromotionPeriod, roundedButtons, textOrientation, }: CashbackProps): import("react/jsx-runtime").JSX.Element;
|
|
7
10
|
export {};
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import Image from 'next/image';
|
|
3
3
|
import Link from 'next/link';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
5
|
import { useShallow } from 'zustand/shallow';
|
|
5
6
|
import { useAvailablePromosQuery } from '../../client/hooks/useAvailablePromosQuery.js';
|
|
6
7
|
import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
|
|
7
8
|
import { Button } from '../../ui/Button/index.js';
|
|
8
|
-
|
|
9
|
+
import { formatPromotionPeriod } from './utils.js';
|
|
10
|
+
export function Cashback({ data, viewDetailsUrl, hasPromotionPeriod, roundedButtons, textOrientation = 'center', }) {
|
|
9
11
|
const globalStore = useGlobalStore(useShallow((ctx) => ({
|
|
10
12
|
depositWithdrawal: ctx.depositWithdrawal,
|
|
11
13
|
})));
|
|
12
14
|
const claimablePromos = useAvailablePromosQuery().data ?? [];
|
|
13
15
|
const claimable = claimablePromos.find((availablePromo) => availablePromo.id === data.id);
|
|
14
|
-
|
|
16
|
+
const promotionPeriod = formatPromotionPeriod(data.activationStartDateTime, data.activationEndDateTime);
|
|
17
|
+
return (_jsxs("div", { className: "relative flex h-full flex-col overflow-hidden rounded-2xl border border-border-secondary bg-accent-50 bg-bg-primary-alt", children: [data.banner?.url && (_jsx(Image, { src: data.banner.url, alt: data.name, width: 400, height: 202, loading: "lazy", unoptimized: true, className: "block aspect-[365/180] w-full object-cover" })), hasPromotionPeriod && (_jsxs("div", { className: "bg-black py-1.5 text-center font-bold text-3xs uppercase", children: ["PROMOTION PERIOD: ", promotionPeriod] })), _jsxs("div", { className: "flex flex-grow flex-col px-4 pt-2xl pb-3xl", children: [_jsx("div", { className: twMerge('w-full grow font-semibold text-xl', textOrientation === 'center' ? 'text-center' : 'text-left'), children: data.name }), _jsxs("div", { className: "mt-auto flex flex-col gap-3 pt-4 lg:flex-row", children: [claimable && (_jsx(Button, { size: "sm", onClick: () => {
|
|
15
18
|
globalStore.depositWithdrawal.setOpen(true);
|
|
16
19
|
globalStore.depositWithdrawal.setPromo(data.id);
|
|
17
|
-
}, children: "Get bonus" })), _jsx(Button, { size: "sm", variant: "outline", asChild: true, children: _jsxs(Link, { href: `${viewDetailsUrl}/${data.id}`, children: ["Read more", _jsxs("span", { className: "sr-only", children: [" about ", data.name] })] }) })] })] })] }));
|
|
20
|
+
}, children: "Get bonus" })), _jsx(Button, { size: "sm", variant: "outline", asChild: true, className: roundedButtons ? 'rounded-full' : '', children: _jsxs(Link, { href: `${viewDetailsUrl}/${data.id}`, children: ["Read more", _jsxs("span", { className: "sr-only", children: [" about ", data.name] })] }) })] })] })] }));
|
|
18
21
|
}
|
|
@@ -2,6 +2,8 @@ import type { CustomPromo as TCustomPromo } from '../../types';
|
|
|
2
2
|
interface CustomPromoProps {
|
|
3
3
|
data: TCustomPromo;
|
|
4
4
|
viewDetailsUrl: string;
|
|
5
|
+
roundedButtons?: boolean;
|
|
6
|
+
textOrientation?: 'left' | 'center';
|
|
5
7
|
}
|
|
6
|
-
export declare function CustomPromo({ data, viewDetailsUrl }: CustomPromoProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare function CustomPromo({ data, viewDetailsUrl, roundedButtons, textOrientation, }: CustomPromoProps): import("react/jsx-runtime").JSX.Element;
|
|
7
9
|
export {};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import Image from 'next/image';
|
|
3
3
|
import Link from 'next/link';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
5
|
import { Button } from '../../ui/Button/index.js';
|
|
5
|
-
export function CustomPromo({ data, viewDetailsUrl }) {
|
|
6
|
-
return (_jsxs("div", { className: "relative flex h-full flex-col overflow-hidden rounded-2xl border border-border-secondary bg-accent-50 bg-bg-primary-alt", children: [_jsx(Image, { src: data.banner, alt: data.name, width: 400, height: 202, loading: "lazy", unoptimized: true, className: "block aspect-[365/180] w-full object-cover" }), _jsxs("div", { className: "flex flex-grow flex-col px-4 pt-2xl pb-3xl", children: [_jsx("div", { className:
|
|
6
|
+
export function CustomPromo({ data, viewDetailsUrl, roundedButtons, textOrientation = 'center', }) {
|
|
7
|
+
return (_jsxs("div", { className: "relative flex h-full flex-col overflow-hidden rounded-2xl border border-border-secondary bg-accent-50 bg-bg-primary-alt", children: [_jsx(Image, { src: data.banner, alt: data.name, width: 400, height: 202, loading: "lazy", unoptimized: true, className: "block aspect-[365/180] w-full object-cover" }), _jsxs("div", { className: "flex flex-grow flex-col px-4 pt-2xl pb-3xl", children: [_jsx("div", { className: twMerge('w-full grow font-semibold text-xl', textOrientation === 'center' ? 'text-center' : 'text-left'), children: data.name }), _jsx("div", { className: "mt-auto flex flex-col gap-3 pt-4 lg:flex-row", children: _jsx(Button, { size: "sm", variant: "outline", asChild: true, className: roundedButtons ? 'rounded-full' : '', children: _jsxs(Link, { href: `${viewDetailsUrl}/${data.id}`, children: ["Read more", _jsxs("span", { className: "sr-only", children: [" about ", data.name] })] }) }) })] })] }));
|
|
7
8
|
}
|
|
@@ -2,6 +2,9 @@ import type { Promo as TPromo } from '../../types';
|
|
|
2
2
|
interface PromoProps {
|
|
3
3
|
data: TPromo;
|
|
4
4
|
viewDetailsUrl: string;
|
|
5
|
+
hasPromotionPeriod?: boolean;
|
|
6
|
+
roundedButtons?: boolean;
|
|
7
|
+
textOrientation?: 'left' | 'center';
|
|
5
8
|
}
|
|
6
|
-
export declare function Promo({ data, viewDetailsUrl }: PromoProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function Promo({ data, viewDetailsUrl, hasPromotionPeriod, roundedButtons, textOrientation, }: PromoProps): import("react/jsx-runtime").JSX.Element;
|
|
7
10
|
export {};
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import Image from 'next/image';
|
|
3
3
|
import Link from 'next/link';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
5
|
import { useShallow } from 'zustand/shallow';
|
|
5
6
|
import { useAvailablePromosQuery } from '../../client/hooks/useAvailablePromosQuery.js';
|
|
6
7
|
import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
|
|
7
8
|
import { Button } from '../../ui/Button/index.js';
|
|
8
|
-
|
|
9
|
+
import { formatPromotionPeriod } from './utils.js';
|
|
10
|
+
export function Promo({ data, viewDetailsUrl, hasPromotionPeriod, roundedButtons, textOrientation = 'center', }) {
|
|
9
11
|
const globalStore = useGlobalStore(useShallow((ctx) => ({
|
|
10
12
|
depositWithdrawal: ctx.depositWithdrawal,
|
|
11
13
|
})));
|
|
12
14
|
const claimablePromos = useAvailablePromosQuery().data ?? [];
|
|
13
15
|
const claimable = claimablePromos.find((availablePromo) => availablePromo.id === data.id);
|
|
14
|
-
|
|
16
|
+
const promotionPeriod = formatPromotionPeriod(data.activationStartDateTime, data.activationEndDateTime);
|
|
17
|
+
return (_jsxs("div", { className: "relative flex h-full flex-col overflow-hidden rounded-2xl border border-border-secondary bg-accent-50 bg-bg-primary-alt", children: [data.banner?.url && (_jsx(Image, { src: data.banner.url, alt: data.name, width: 400, height: 202, loading: "lazy", unoptimized: true, className: "block aspect-[365/180] w-full object-cover" })), hasPromotionPeriod && (_jsxs("div", { className: "bg-black py-1.5 text-center font-bold text-3xs uppercase", children: ["PROMOTION PERIOD: ", promotionPeriod] })), _jsxs("div", { className: "flex flex-grow flex-col px-4 pt-2xl pb-3xl", children: [_jsx("div", { className: twMerge('w-full grow font-semibold text-xl', textOrientation === 'center' ? 'text-center' : 'text-left'), children: data.name }), _jsxs("div", { className: "mt-auto flex flex-col gap-3 pt-4 lg:flex-row", children: [claimable && (_jsx(Button, { size: "sm", onClick: () => {
|
|
15
18
|
globalStore.depositWithdrawal.setOpen(true);
|
|
16
19
|
globalStore.depositWithdrawal.setPromo(data.id);
|
|
17
|
-
}, children: "Get bonus" })), _jsx(Button, { size: "sm", variant: "outline", asChild: true, children: _jsxs(Link, { href: `${viewDetailsUrl}/${data.id}`, children: ["Read more", _jsxs("span", { className: "sr-only", children: [" about ", data.name] })] }) })] })] })] }));
|
|
20
|
+
}, children: "Get bonus" })), _jsx(Button, { size: "sm", variant: "outline", asChild: true, className: roundedButtons ? 'rounded-full' : '', children: _jsxs(Link, { href: `${viewDetailsUrl}/${data.id}`, children: ["Read more", _jsxs("span", { className: "sr-only", children: [" about ", data.name] })] }) })] })] })] }));
|
|
18
21
|
}
|
|
@@ -9,6 +9,9 @@ export interface PromosGridProps {
|
|
|
9
9
|
/** @default "/promos/cashback" */
|
|
10
10
|
viewCashbackDetailsUrl?: string;
|
|
11
11
|
customPromos?: TCustomPromo[];
|
|
12
|
+
hasPromotionPeriod?: boolean;
|
|
13
|
+
roundedButtons?: boolean;
|
|
14
|
+
textOrientation?: 'left' | 'center';
|
|
12
15
|
exclude?: string[];
|
|
13
16
|
className?: string;
|
|
14
17
|
}
|
|
@@ -15,5 +15,5 @@ export function PromosGrid(props) {
|
|
|
15
15
|
const cashbacks = cashbacksQuery.data?.filter((item) => !blacklist.includes(item.id)) ?? [];
|
|
16
16
|
const customPromos = props.customPromos?.filter((item) => !blacklist.includes(item.id)) ?? [];
|
|
17
17
|
const empty = promos.length <= 0 && cashbacks.length <= 0 && customPromos.length <= 0;
|
|
18
|
-
return (_jsxs("div", { className: props.className, children: [_jsxs("div", { className: "flex items-center", children: [_jsx("h2", { className: "font-semibold text-lg", children: props.heading ?? 'Promos' }), _jsx("div", { className: "grow" })] }), empty && (_jsx(Empty, { icon: Gift01Icon, title: "No Promos", message: "No promo is currently available.", className: "mt-8" })), !empty && (_jsx("div", { className: "relative mt-lg lg:overflow-hidden", children: _jsxs("div", { className: "grid gap-3xl lg:grid-cols-3 lg:gap-2xl", children: [promos.map((promo) => (_jsx(Promo, { data: promo, viewDetailsUrl: props.viewPromoDetailsUrl ?? '/promos' }, promo.id))), cashbacks.map((cashback) => (_jsx(Cashback, { data: cashback, viewDetailsUrl: props.viewCashbackDetailsUrl ?? '/promos/cashback' }, cashback.id))), customPromos.map((customPromo) => (_jsx(CustomPromo, { data: customPromo, viewDetailsUrl: props.viewCashbackDetailsUrl ?? '/promos/custom' }, customPromo.id)))] }) }))] }));
|
|
18
|
+
return (_jsxs("div", { className: props.className, children: [_jsxs("div", { className: "flex items-center", children: [_jsx("h2", { className: "font-semibold text-lg", children: props.heading ?? 'Promos' }), _jsx("div", { className: "grow" })] }), empty && (_jsx(Empty, { icon: Gift01Icon, title: "No Promos", message: "No promo is currently available.", className: "mt-8" })), !empty && (_jsx("div", { className: "relative mt-lg lg:overflow-hidden", children: _jsxs("div", { className: "grid gap-3xl lg:grid-cols-3 lg:gap-2xl", children: [promos.map((promo) => (_jsx(Promo, { data: promo, viewDetailsUrl: props.viewPromoDetailsUrl ?? '/promos', hasPromotionPeriod: props.hasPromotionPeriod, roundedButtons: props.roundedButtons, textOrientation: props.textOrientation }, promo.id))), cashbacks.map((cashback) => (_jsx(Cashback, { data: cashback, viewDetailsUrl: props.viewCashbackDetailsUrl ?? '/promos/cashback', hasPromotionPeriod: props.hasPromotionPeriod, roundedButtons: props.roundedButtons, textOrientation: props.textOrientation }, cashback.id))), customPromos.map((customPromo) => (_jsx(CustomPromo, { data: customPromo, viewDetailsUrl: props.viewCashbackDetailsUrl ?? '/promos/custom', roundedButtons: props.roundedButtons, textOrientation: props.textOrientation }, customPromo.id)))] }) }))] }));
|
|
19
19
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatPromotionPeriod(start: string | null | undefined, until: string | null | undefined): string | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { format } from 'date-fns';
|
|
2
|
+
export function formatPromotionPeriod(start, until) {
|
|
3
|
+
if (!start)
|
|
4
|
+
return null;
|
|
5
|
+
if (!until)
|
|
6
|
+
return null;
|
|
7
|
+
const s = format(start, 'd/MM/yyyy hh:mm a');
|
|
8
|
+
const u = format(until, 'd/MM/yyyy hh:mm a');
|
|
9
|
+
return `${s} - ${u}`;
|
|
10
|
+
}
|
|
@@ -9,7 +9,9 @@ import { Field } from '../../ui/Field/index.js';
|
|
|
9
9
|
import { getAllUniqueCountries, getCountryDetails, } from '../../utils/countries/getAllCountries.js';
|
|
10
10
|
export const MobileNumberField = ({ enabledCountries, mobileNumber, onMobileNumberChange, setAreaCode, error, mobileNumberRegistration, }) => {
|
|
11
11
|
const localeInfo = useLocaleInfo();
|
|
12
|
-
const [selectedCountry, setSelectedCountry] = useState(getCountryDetails(localeInfo.country.code)
|
|
12
|
+
const [selectedCountry, setSelectedCountry] = useState(getCountryDetails(enabledCountries.includes(localeInfo.country.code)
|
|
13
|
+
? localeInfo.country.code
|
|
14
|
+
: 'AE'));
|
|
13
15
|
const [search, setSearch] = useState('');
|
|
14
16
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
15
17
|
const allCountries = useMemo(() => getAllUniqueCountries(enabledCountries), [enabledCountries]);
|
|
@@ -51,13 +53,17 @@ export const MobileNumberField = ({ enabledCountries, mobileNumber, onMobileNumb
|
|
|
51
53
|
if (isPopoverOpen && !details.open) {
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
|
-
}, openOnClick: true, children: [_jsx(Combobox.Control, { className: "rounded-lg border-1 shadow-none outline-none", children: _jsx(Combobox.Input, { placeholder: "Search country..." }) }), _jsx(Portal, { children: _jsx(Combobox.Positioner, { style: { zIndex: 9999 }, children: _jsx(Combobox.Content, { className: "w-full", style: { zIndex: 9999 }, children: _jsx(Combobox.ItemGroup, { children:
|
|
55
|
-
.filter((country) => search === '' ||
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
}, openOnClick: true, children: [_jsx(Combobox.Control, { className: "rounded-lg border-1 shadow-none outline-none", children: _jsx(Combobox.Input, { placeholder: "Search country..." }) }), _jsx(Portal, { children: _jsx(Combobox.Positioner, { style: { zIndex: 9999 }, children: _jsx(Combobox.Content, { className: "w-full", style: { zIndex: 9999 }, children: _jsx(Combobox.ItemGroup, { children: (() => {
|
|
57
|
+
const filteredCountries = countriesCollection.items.filter((country) => search === '' ||
|
|
58
|
+
country.name
|
|
59
|
+
.toLowerCase()
|
|
60
|
+
.includes(search.toLowerCase()) ||
|
|
61
|
+
country.areaCode.includes(search));
|
|
62
|
+
if (filteredCountries.length === 0) {
|
|
63
|
+
return (_jsx("div", { className: "p-3 text-center text-text-placeholder", children: "No countries found" }));
|
|
64
|
+
}
|
|
65
|
+
return filteredCountries.map((country) => (_jsxs(Combobox.Item, { item: country, children: [_jsxs(Combobox.ItemText, { children: [_jsx(country.flag, { className: "mr-2 inline-block size-5" }), country.name, " (", country.areaCode, ")"] }), _jsx(Combobox.ItemIndicator, { asChild: true, children: _jsx(CheckIcon, {}) })] }, country.code)));
|
|
66
|
+
})() }) }) }) })] }) }) }) })] }), _jsx(Field.Input, { ...(mobileNumberRegistration || {}), style: { paddingLeft: '0.5rem' }, value: mobileNumber, onChange: handleMobileChange, placeholder: "Enter mobile number" })] }), _jsx(Field.ErrorText, { children: error })] }));
|
|
61
67
|
};
|
|
62
68
|
const countriesListCollection = (countries) => createListCollection({
|
|
63
69
|
items: countries,
|
|
Binary file
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
type MobileNumberParser = {
|
|
3
|
+
validate: (val: unknown) => val is string;
|
|
4
|
+
};
|
|
5
|
+
export declare const createForgotPasswordSchema: (mobileNumberParser: MobileNumberParser) => z.ZodEffects<z.ZodObject<{
|
|
6
|
+
password: z.ZodString;
|
|
7
|
+
confirmPassword: z.ZodString;
|
|
8
|
+
mobileNumber: z.ZodEffects<z.ZodString, string, string>;
|
|
9
|
+
verificationCode: z.ZodEffects<z.ZodString, string, string>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
password: string;
|
|
12
|
+
confirmPassword: string;
|
|
13
|
+
mobileNumber: string;
|
|
14
|
+
verificationCode: string;
|
|
15
|
+
}, {
|
|
16
|
+
password: string;
|
|
17
|
+
confirmPassword: string;
|
|
18
|
+
mobileNumber: string;
|
|
19
|
+
verificationCode: string;
|
|
20
|
+
}>, {
|
|
21
|
+
password: string;
|
|
22
|
+
confirmPassword: string;
|
|
23
|
+
mobileNumber: string;
|
|
24
|
+
verificationCode: string;
|
|
25
|
+
}, {
|
|
26
|
+
password: string;
|
|
27
|
+
confirmPassword: string;
|
|
28
|
+
mobileNumber: string;
|
|
29
|
+
verificationCode: string;
|
|
30
|
+
}>;
|
|
31
|
+
export type ForgotPasswordSchema = z.infer<ReturnType<typeof createForgotPasswordSchema>>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const createForgotPasswordSchema = (mobileNumberParser) => z.object({
|
|
3
|
+
password: z.string().min(8, 'Password must be 8 or more characters').max(20, 'Password must not be more than 20 characters'),
|
|
4
|
+
confirmPassword: z.string().min(8, 'Password must be 8 or more characters').max(20, 'Password must not be more than 20 characters'),
|
|
5
|
+
mobileNumber: z.string().superRefine((v, ctx) => {
|
|
6
|
+
if (!mobileNumberParser.validate(v)) {
|
|
7
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid mobile number' });
|
|
8
|
+
}
|
|
9
|
+
}),
|
|
10
|
+
verificationCode: z.string().refine((v) => /^\d{4,6}$/.test(v), 'Invalid OTP'),
|
|
11
|
+
}).superRefine((val, ctx) => {
|
|
12
|
+
if (val.password !== val.confirmPassword) {
|
|
13
|
+
ctx.addIssue({ path: ['confirmPassword'], code: z.ZodIssueCode.custom, message: 'Passwords do not match' });
|
|
14
|
+
}
|
|
15
|
+
});
|
package/dist/services/game.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface GameSessionQueryVariables__Legacy {
|
|
|
9
9
|
}
|
|
10
10
|
export declare const getGameSession__legacy: (id: string, options?: GraphQLRequestOptions) => Promise<GameSession | null>;
|
|
11
11
|
export type CreateGameSessionError__Legacy = {
|
|
12
|
-
name: 'GameDoesNotExistError';
|
|
12
|
+
name: 'GameDoesNotExistError' | 'GameProviderNotEnabledError' | 'GameTypeNotEnabledError';
|
|
13
13
|
message: string;
|
|
14
14
|
};
|
|
15
15
|
export interface CreateGameSessionMutation__Legacy {
|
package/dist/services/game.js
CHANGED
|
@@ -36,4 +36,6 @@ const ERROR_CODES_MESSAGE_MAP = {
|
|
|
36
36
|
GameProviderError: 'Game provider error',
|
|
37
37
|
GameSessionAlreadyClosedError: 'Game session is already closed',
|
|
38
38
|
GameSessionDoesNotExistError: 'Game session does not exist',
|
|
39
|
+
GameProviderNotEnabledError: 'Game provider is not enabled',
|
|
40
|
+
GameTypeNotEnabledError: 'Game type is not enabled',
|
|
39
41
|
};
|
|
@@ -9,7 +9,7 @@ export declare const REDEEM_POINTS_TO_CASH = "\n mutation RedeemPointsToCash($i
|
|
|
9
9
|
export declare const POINTS_WALLET_TRANSACTIONS = "\n query PointsWalletTransactions(\n $first: Int\n $after: Cursor\n $filter: MemberPointsWalletTransactionFilterInput\n ) {\n member {\n pointsWalletTransactions(first: $first, after: $after, filter: $filter) {\n edges {\n cursor\n node {\n ... on PointsWalletTransaction {\n id\n type\n amount\n balance\n dateTimeCreated\n }\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n }\n";
|
|
10
10
|
export declare const GAME_SESSION = "\n query GameSession($id: ObjectId!) {\n node(id: $id) {\n ... on GameSession {\n id\n game\n status\n launchUrl\n launchOptions\n }\n }\n }\n";
|
|
11
11
|
export declare const GAME_SESSION__LEGACY = "\n query GameSession($id: ObjectId!) {\n node(id: $id) {\n ... on GameSession {\n id\n game {\n id\n }\n status\n launchUrl\n dateTimeCreated\n dateTimeLastUpdated\n }\n }\n }\n";
|
|
12
|
-
export declare const CREATE_GAME_SESSION = "\n mutation CreateGameSession($input: CreateGameSessionInput!) {\n createGameSession(input: $input) {\n ... on GameDoesNotExistError {\n name: __typename\n message\n }\n }\n }\n";
|
|
12
|
+
export declare const CREATE_GAME_SESSION = "\n mutation CreateGameSession($input: CreateGameSessionInput!) {\n createGameSession(input: $input) {\n ... on GameDoesNotExistError {\n name: __typename\n message\n }\n ... on GameProviderNotEnabledError {\n name: __typename\n message\n }\n ... on GameTypeNotEnabledError {\n name: __typename\n message\n }\n }\n }\n";
|
|
13
13
|
export declare const END_GAME_SESSION = "\n mutation EndGameSession($input: EndGameSessionInput!) {\n endGameSession(input: $input)\n }\n";
|
|
14
14
|
export declare const END_GAME_SESSION__LEGACY = "\n mutation EndGameSession($input: EndGameSessionInput!) {\n endGameSession(input: $input) {\n ... on GameSessionDoesNotExistError {\n name: __typename\n message\n }\n ... on GameSessionAlreadyClosedError {\n name: __typename\n message\n }\n ... on GameProviderError {\n name: __typename\n message\n }\n }\n }\n";
|
|
15
15
|
export declare const RECOMMENDED_GAMES = "\n query RecommendedGames {\n recommendedGames {\n id\n name\n type\n provider\n }\n }\n";
|
package/dist/services/queries.js
CHANGED
|
@@ -167,6 +167,14 @@ export const CREATE_GAME_SESSION = /* GraphQL */ `
|
|
|
167
167
|
name: __typename
|
|
168
168
|
message
|
|
169
169
|
}
|
|
170
|
+
... on GameProviderNotEnabledError {
|
|
171
|
+
name: __typename
|
|
172
|
+
message
|
|
173
|
+
}
|
|
174
|
+
... on GameTypeNotEnabledError {
|
|
175
|
+
name: __typename
|
|
176
|
+
message
|
|
177
|
+
}
|
|
170
178
|
}
|
|
171
179
|
}
|
|
172
180
|
`;
|
|
@@ -556,7 +556,7 @@ export interface GameSessionQueryVariables {
|
|
|
556
556
|
}
|
|
557
557
|
export declare const getGameSession: (id: string, options?: GraphQLRequestOptions) => Promise<GameSession | null>;
|
|
558
558
|
export type CreateGameSessionError = {
|
|
559
|
-
name: 'GameDoesNotExistError';
|
|
559
|
+
name: 'GameDoesNotExistError' | 'GameProviderNotEnabledError' | 'GameTypeNotEnabledError';
|
|
560
560
|
message: string;
|
|
561
561
|
};
|
|
562
562
|
export interface CreateGameSessionMutation {
|
package/dist/services/wallet.js
CHANGED
|
@@ -550,6 +550,8 @@ const ERROR_CODES_MESSAGE_MAP = {
|
|
|
550
550
|
DepositPromoMaximumAmountExceededError: 'Deposit amount exceeds maximum amount for selected promo',
|
|
551
551
|
DepositPromoMinimumAmountNotMetError: 'Deposit amount does not meet minimum amount for selected promo',
|
|
552
552
|
GameDoesNotExistError: 'Game does not exist',
|
|
553
|
+
GameProviderNotEnabledError: 'Game provider is not enabled',
|
|
554
|
+
GameTypeNotEnabledError: 'Game type is not enabled',
|
|
553
555
|
InsufficientPointsError: 'Insufficient points',
|
|
554
556
|
InvalidTransactionPasswordError: 'Invalid transaction password',
|
|
555
557
|
InvalidWithdrawalAmountError: 'Invalid withdrawal amount',
|