@opexa/portal-components 0.0.1122 → 0.0.1125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/__tests__/utils/mocks.d.ts +1 -1
  2. package/dist/client/hooks/useSignInMutation.d.ts +1 -0
  3. package/dist/client/hooks/useSignInMutation.js +8 -2
  4. package/dist/components/KYC/KYCReview.js +4 -33
  5. package/dist/components/SignIn/CrazyWin/MobileNumberSignIn.js +1 -1
  6. package/dist/components/SignIn/CrazyWin/NameAndPasswordSignIn.js +1 -0
  7. package/dist/components/SignIn/HappyBingo/MobileNumberSignIn.js +1 -1
  8. package/dist/components/SignIn/HappyBingo/NameAndPasswordSignIn.js +1 -0
  9. package/dist/components/SignIn/MobileNumberSignIn.js +1 -1
  10. package/dist/components/SignIn/MobileNumberSignInternational.js +1 -1
  11. package/dist/components/SignIn/NameAndPasswordSignIn.js +1 -0
  12. package/dist/components/SignIn/SignIn.lazy.d.ts +5 -0
  13. package/dist/components/UpdateMobilePhoneNumber/UpdateMobilePhoneNumber.js +3 -3
  14. package/dist/constants/HeaderKey.d.ts +1 -0
  15. package/dist/constants/HeaderKey.js +1 -0
  16. package/dist/handlers/postSession.js +5 -1
  17. package/dist/services/auth.js +36 -2
  18. package/package.json +1 -1
  19. package/dist/client/hooks/useVerifyMobileNumber.d.ts +0 -3
  20. package/dist/client/hooks/useVerifyMobileNumber.js +0 -20
  21. package/dist/components/DepositWithdrawal/Deposit/AurixPayPayMayaDeposit/AurixPayGrabPayDeposit.d.ts +0 -1
  22. package/dist/components/DepositWithdrawal/Deposit/AurixPayPayMayaDeposit/AurixPayGrabPayDeposit.js +0 -241
  23. package/dist/components/SingleSignOn/SingleSignOn.d.ts +0 -4
  24. package/dist/components/SingleSignOn/SingleSignOn.js +0 -185
  25. package/dist/components/SingleSignOn/index.d.ts +0 -1
  26. package/dist/components/SingleSignOn/index.js +0 -1
  27. package/dist/components/UpdateMobileNumber/UpdateMobileNumber.d.ts +0 -3
  28. package/dist/components/UpdateMobileNumber/UpdateMobileNumber.js +0 -141
  29. package/dist/components/UpdateMobileNumber/index.d.ts +0 -1
  30. package/dist/components/UpdateMobileNumber/index.js +0 -1
  31. package/dist/lib/components/UpdateMobileNumber/UpdateMobileNumber.d.ts +0 -1
  32. package/dist/lib/components/UpdateMobileNumber/UpdateMobileNumber.js +0 -154
  33. package/dist/lib/components/UpdateMobileNumber/index.d.ts +0 -1
  34. package/dist/lib/components/UpdateMobileNumber/index.js +0 -1
@@ -165,7 +165,7 @@ export declare function createMockSignOutMutation(): {
165
165
  */
166
166
  export declare function createMockMemberVerificationQuery(status?: 'VERIFIED' | 'PENDING' | 'REJECTED' | 'MISSING' | 'APPROVED', isLoading?: boolean): {
167
167
  data: {
168
- status: "VERIFIED" | "PENDING" | "REJECTED" | "MISSING" | "APPROVED";
168
+ status: "PENDING" | "APPROVED" | "REJECTED" | "VERIFIED" | "MISSING";
169
169
  };
170
170
  isLoading: boolean;
171
171
  isError: boolean;
@@ -4,5 +4,6 @@ import type { Authenticator, MutationConfig } from '../../types';
4
4
  import { type SignInInput } from '../services/signIn';
5
5
  export interface UseSignInMutationOptions extends MutationConfig<Authenticator | null, SignInInput> {
6
6
  versionSession?: VersionSession;
7
+ fingerprint?: () => Promise<string | null> | string | null;
7
8
  }
8
9
  export declare const useSignInMutation: (options?: UseSignInMutationOptions) => UseMutationResult<Authenticator | null, Error, SignInInput>;
@@ -1,7 +1,7 @@
1
1
  import { Capacitor } from '@capacitor/core';
2
2
  import { useMutation } from '@tanstack/react-query';
3
3
  import { useReCaptcha } from 'next-recaptcha-v3';
4
- import { RECAPTCHA_HEADER_KEY } from '../../constants/index.js';
4
+ import { FINGERPRINT_HEADER_KEY, RECAPTCHA_HEADER_KEY, } from '../../constants/index.js';
5
5
  import { getQueryClient } from '../../utils/getQueryClient.js';
6
6
  import { getSignInMutationKey } from '../../utils/mutationKeys.js';
7
7
  import { getSessionQueryKey } from '../../utils/queryKeys.js';
@@ -10,7 +10,7 @@ import { signIn } from '../services/signIn.js';
10
10
  export const useSignInMutation = (options) => {
11
11
  const queryClient = getQueryClient();
12
12
  const recaptcha = useReCaptcha();
13
- const { versionSession, ...config } = options ?? {};
13
+ const { fingerprint, versionSession, ...config } = options ?? {};
14
14
  return useMutation({
15
15
  ...config,
16
16
  mutationKey: getSignInMutationKey(),
@@ -19,6 +19,9 @@ export const useSignInMutation = (options) => {
19
19
  const token = recaptcha.reCaptchaKey
20
20
  ? await recaptcha.executeRecaptcha('submit')
21
21
  : null;
22
+ const fingerprintValue = versionSession === 'Inplay' && input.type === 'NAME_AND_PASSWORD'
23
+ ? await Promise.resolve(fingerprint?.()).catch(() => null)
24
+ : null;
22
25
  const authenticator = await signIn(input, {
23
26
  headers: {
24
27
  ...(token && {
@@ -27,6 +30,9 @@ export const useSignInMutation = (options) => {
27
30
  ...(session.domain && {
28
31
  Domain: session.domain,
29
32
  }),
33
+ ...(fingerprintValue && {
34
+ [FINGERPRINT_HEADER_KEY]: fingerprintValue,
35
+ }),
30
36
  ...(Capacitor.getPlatform() === 'android'
31
37
  ? { Channel: 'ANDROID' }
32
38
  : { Channel: 'IOS' }),
@@ -1,12 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import Image from 'next/image';
4
- import { useState } from 'react';
5
4
  import { useShallow } from 'zustand/shallow';
6
- import { useFeatureFlag } from '../../client/hooks/useFeatureFlag.js';
7
5
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
8
- import { getSession } from '../../client/services/getSession.js';
9
- import { toaster } from '../../client/utils/toaster.js';
10
6
  import cinePopLogo from '../../images/cinepop-logo.png';
11
7
  import dearUtolLogo from '../../images/dear-utol-logo.png';
12
8
  import mariasDiary from '../../images/marias-diary-logo.png';
@@ -15,35 +11,10 @@ import { Dialog } from '../../ui/Dialog/index.js';
15
11
  import { Portal } from '../../ui/Portal/index.js';
16
12
  export function KYCReview() {
17
13
  const { kycReview } = useGlobalStore(useShallow((s) => ({ kycReview: s.kycReview })));
18
- const [isLoading, setIsLoading] = useState(false);
19
- const featureFlag = useFeatureFlag();
20
- const isDialogOpen = kycReview.open && featureFlag.enabled;
21
- return (_jsx(Dialog.Root, { open: isDialogOpen, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { className: "flex items-center", children: _jsxs(Dialog.Content, { className: "flex w-[375px] flex-col items-center justify-between space-y-4 rounded-lg bg-[#232443] p-6 text-center", children: [_jsxs("div", { className: "flex flex-col items-center", children: [_jsx("div", { className: "mb-4 h-7 w-7 animate-spin rounded-full border-4 border-[#101730] border-t-[#F05027]" }), _jsx("div", { className: "font-semibold text-[#F5F5F6] text-lg", children: "Thanks for your submission." }), _jsxs("div", { className: "mt-1 text-[#CECFD2] text-sm", children: ["We\u2019re now ", '', _jsxs("span", { className: "text-[#F96B47]", children: ["reviewing your KYC information ", ''] }), "and will notify you once the verification is complete."] }), _jsx("div", { className: "mt-6 text-[#CECFD2] text-sm", children: "In the meantime, you can watch your favorite series on CinePop!" })] }), _jsxs("div", { className: "pt-3", children: [_jsx(Image, { src: cinePopLogo, alt: "cine poplogo", width: 151, height: 24, className: "mx-auto mb-2 h-auto w-[151px]" }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Image, { src: secretConfessionsLogo, alt: "secret confessions logo", width: 104, height: 53, className: "h-auto w-[104px]" }), _jsx(Image, { src: dearUtolLogo, alt: "dear utol logo", width: 105, height: 53, className: "h-auto w-[105px]" }), _jsx(Image, { src: mariasDiary, alt: "maria's diary logo", width: 104, height: 53, className: "h-auto w-[104px]" })] })] }), _jsx("button", { disabled: isLoading, type: "button", className: "h-[44px] w-full rounded-md font-semibold", style: {
14
+ return (_jsx(Dialog.Root, { open: kycReview.open, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { className: "flex items-center", children: _jsxs(Dialog.Content, { className: "flex w-[375px] flex-col items-center justify-between space-y-4 border bg-[#232443] p-6 text-center", children: [_jsxs("div", { className: "flex flex-col items-center", children: [_jsx("div", { className: "mb-4 h-7 w-7 animate-spin rounded-full border-4 border-[#101730] border-t-[#F05027]" }), _jsx("div", { className: "font-semibold text-[#F5F5F6] text-lg", children: "Thanks for your submission." }), _jsxs("div", { className: "mt-1 text-[#CECFD2] text-sm", children: ["We\u2019re now ", '', _jsxs("span", { className: "text-[#F96B47]", children: ["reviewing your KYC information ", ''] }), "and will notify you once the verification is complete."] }), _jsx("div", { className: "mt-6 text-[#CECFD2] text-sm", children: "In the meantime, you can watch your favorite series on CinePop!" })] }), _jsxs("div", { className: "pt-3", children: [_jsx(Image, { src: cinePopLogo, alt: "cine poplogo", width: 151, height: 24, className: "mx-auto mb-2 h-auto w-[151px]" }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Image, { src: secretConfessionsLogo, alt: "secret confessions logo", width: 104, height: 53, className: "h-auto w-[104px]" }), _jsx(Image, { src: dearUtolLogo, alt: "dear utol logo", width: 105, height: 53, className: "h-auto w-[105px]" }), _jsx(Image, { src: mariasDiary, alt: "maria's diary logo", width: 104, height: 53, className: "h-auto w-[104px]" })] })] }), _jsx("button", { type: "button", className: "h-[44px] w-full rounded-md font-semibold", style: {
22
15
  background: 'linear-gradient(90deg, #9333E8 0%, #D92778 100%)',
23
- }, onClick: async () => {
24
- const session = await getSession();
25
- setIsLoading(true);
26
- try {
27
- const response = await fetch('https://auth.development.opexa.io/v1/sso/cinepop', {
28
- method: 'POST',
29
- headers: {
30
- AUTHORIZATION: `Bearer ${session.token}`,
31
- 'PLATFORM-ID': 'Z892',
32
- 'Content-Type': 'application/json',
33
- },
34
- });
35
- const data = (await response.json());
36
- window.open(data.data.redirectionUrl, '_blank');
37
- }
38
- catch {
39
- toaster.error({
40
- title: 'Failed to redirect',
41
- description: 'Unable to open CinePop. Please try again.',
42
- });
43
- }
44
- finally {
45
- setIsLoading(false);
46
- kycReview.setOpen(false);
47
- }
16
+ }, onClick: () => {
17
+ window.open('https://cinepop.film/', '_blank');
18
+ kycReview.setOpen(false);
48
19
  }, children: "Watch Cinepop" })] }) })] }) }));
49
20
  }
@@ -45,7 +45,7 @@ export function MobileNumberSignIn() {
45
45
  disclaimer: ctx.disclaimer,
46
46
  })));
47
47
  const signInMutation = useSignInMutation({
48
- versionSession: signInProps.versionSession,
48
+ // versionSession intentionally omitted: only applies to NAME_AND_PASSWORD
49
49
  onSuccess: async () => {
50
50
  step1Form.reset();
51
51
  step2Form.reset();
@@ -45,6 +45,7 @@ export function NameAndPasswordSignIn() {
45
45
  disclaimer: ctx.disclaimer,
46
46
  })));
47
47
  const signInMutation = useSignInMutation({
48
+ fingerprint: signInProps.fingerprint,
48
49
  versionSession: signInProps.versionSession,
49
50
  onSuccess: async (authenticator) => {
50
51
  if (authenticator) {
@@ -46,7 +46,7 @@ export function MobileNumberSignIn() {
46
46
  disclaimer: ctx.disclaimer,
47
47
  })));
48
48
  const signInMutation = useSignInMutation({
49
- versionSession: signInProps.versionSession,
49
+ // versionSession intentionally omitted: only applies to NAME_AND_PASSWORD
50
50
  onSuccess: async () => {
51
51
  step1Form.reset();
52
52
  step2Form.reset();
@@ -42,6 +42,7 @@ export function NameAndPasswordSignIn() {
42
42
  disclaimer: ctx.disclaimer,
43
43
  })));
44
44
  const signInMutation = useSignInMutation({
45
+ fingerprint: signInProps.fingerprint,
45
46
  versionSession: signInProps.versionSession,
46
47
  onSuccess: async (authenticator) => {
47
48
  if (authenticator) {
@@ -53,7 +53,7 @@ export function MobileNumberSignIn() {
53
53
  termsOfUse: ctx.termsOfUse,
54
54
  })));
55
55
  const signInMutation = useSignInMutation({
56
- versionSession: signInProps.versionSession,
56
+ // versionSession intentionally omitted: only applies to NAME_AND_PASSWORD
57
57
  onSuccess: async () => {
58
58
  step1Form.reset();
59
59
  step2Form.reset();
@@ -80,7 +80,7 @@ export function MobileNumberSignInInternational() {
80
80
  disclaimer: ctx.disclaimer,
81
81
  })));
82
82
  const signInMutation = useSignInMutation({
83
- versionSession: signInProps.versionSession,
83
+ // versionSession intentionally omitted: only applies to NAME_AND_PASSWORD
84
84
  onSuccess: async () => {
85
85
  step1Form.reset();
86
86
  step2Form.reset();
@@ -55,6 +55,7 @@ export function NameAndPasswordSignIn() {
55
55
  })));
56
56
  const [formType, setFormType] = useState('NAME_AND_PASSWORD');
57
57
  const signInMutation = useSignInMutation({
58
+ fingerprint: signInProps.fingerprint,
58
59
  versionSession: signInProps.versionSession,
59
60
  onSuccess: async (authenticator) => {
60
61
  if (authenticator) {
@@ -31,5 +31,10 @@ export interface SignInProps extends UseSignInProps {
31
31
  * - `Inplay`: `${AUTH_ENDPOINT}/v3/inplay/sessions`
32
32
  */
33
33
  versionSession?: VersionSession;
34
+ /**
35
+ * Optional browser fingerprint provider. For Inplay NAME_AND_PASSWORD
36
+ * sign-ins, pass `() => sdk.fingerprint()` from the consuming app.
37
+ */
38
+ fingerprint?: () => Promise<string | null> | string | null;
34
39
  }
35
40
  export declare function SignIn(props: SignInProps): import("react/jsx-runtime").JSX.Element;
@@ -30,11 +30,11 @@ export function UpdateMobilePhoneNumber() {
30
30
  const accountQuery = useAccountQuery();
31
31
  const account = accountQuery.data;
32
32
  const isAccountLoading = accountQuery.isLoading;
33
- const hasMobileNumber = !!account?.mobileNumber;
33
+ const isMobileNumberVerified = account?.mobileNumberVerified === true;
34
34
  const hasExecuted = useRef(false);
35
35
  useEffect(() => {
36
36
  if (!isAccountLoading && !!account && !hasExecuted.current) {
37
- if (!hasMobileNumber) {
37
+ if (!isMobileNumberVerified) {
38
38
  globalStore.updateMobilePhoneNumber.setOpen(true);
39
39
  }
40
40
  else {
@@ -45,7 +45,7 @@ export function UpdateMobilePhoneNumber() {
45
45
  }, [
46
46
  isAccountLoading,
47
47
  account,
48
- hasMobileNumber,
48
+ isMobileNumberVerified,
49
49
  globalStore.updateMobilePhoneNumber,
50
50
  ]);
51
51
  const [step, setStep] = useState(1);
@@ -2,3 +2,4 @@ export declare const RECAPTCHA_HEADER_KEY: string;
2
2
  export declare const TEST_PASS_HEADER_KEY: string;
3
3
  export declare const DOMAIN_HEADER_KEY: string;
4
4
  export declare const SESSION_VERSION_HEADER_KEY: string;
5
+ export declare const FINGERPRINT_HEADER_KEY: string;
@@ -2,3 +2,4 @@ export const RECAPTCHA_HEADER_KEY = 'Google-Recaptcha-Response';
2
2
  export const TEST_PASS_HEADER_KEY = 'Test-Pass';
3
3
  export const DOMAIN_HEADER_KEY = 'Domain';
4
4
  export const SESSION_VERSION_HEADER_KEY = 'X-Session-Version';
5
+ export const FINGERPRINT_HEADER_KEY = 'Fingerprint';
@@ -1,7 +1,7 @@
1
1
  import { addDays, addMinutes, subMinutes } from 'date-fns';
2
2
  import { NextResponse } from 'next/server';
3
3
  import { z } from 'zod';
4
- import { ACCESS_TOKEN_COOKIE_NAME, DOMAIN_HEADER_KEY, RECAPTCHA_HEADER_KEY, REFRESH_TOKEN_COOKIE_NAME, SESSION_VERSION_HEADER_KEY, } from '../constants/index.js';
4
+ import { ACCESS_TOKEN_COOKIE_NAME, DOMAIN_HEADER_KEY, FINGERPRINT_HEADER_KEY, RECAPTCHA_HEADER_KEY, REFRESH_TOKEN_COOKIE_NAME, SESSION_VERSION_HEADER_KEY, } from '../constants/index.js';
5
5
  import { createSession } from '../services/auth.js';
6
6
  const CreateSessionDefinition = z.union([
7
7
  z.object({
@@ -41,6 +41,7 @@ export async function postSession(request) {
41
41
  }
42
42
  const recaptcha = request.headers.get(RECAPTCHA_HEADER_KEY);
43
43
  const domain = request.headers.get(DOMAIN_HEADER_KEY);
44
+ const fingerprint = request.headers.get(FINGERPRINT_HEADER_KEY);
44
45
  const versionSessionHeader = request.headers.get(SESSION_VERSION_HEADER_KEY);
45
46
  const versionSession = versionSessionHeader === 'Inplay' ? 'Inplay' : 'default';
46
47
  try {
@@ -52,6 +53,9 @@ export async function postSession(request) {
52
53
  ...(domain && {
53
54
  [DOMAIN_HEADER_KEY]: domain,
54
55
  }),
56
+ ...(fingerprint && {
57
+ [FINGERPRINT_HEADER_KEY]: fingerprint,
58
+ }),
55
59
  ...(userAgent && {
56
60
  'User-Agent': userAgent,
57
61
  }),
@@ -1,4 +1,4 @@
1
- import { AUTH_ENDPOINT } from '../constants/index.js';
1
+ import { AUTH_ENDPOINT, FINGERPRINT_HEADER_KEY } from '../constants/index.js';
2
2
  import { httpRequest } from './httpRequest.js';
3
3
  import { sha256 } from './sha256.js';
4
4
  const SESSION_ENDPOINTS = {
@@ -29,8 +29,42 @@ export async function createSession(input, options, versionSession = 'default')
29
29
  new Headers(options?.headers).forEach((value, key) => {
30
30
  headers.set(key, value);
31
31
  });
32
+ // `versionSession` only applies to NAME_AND_PASSWORD sign-ins. All other
33
+ // auth types (MOBILE_NUMBER, MAYA, SOCIALS, CABINET, SINGLE_USE_TOKEN) are
34
+ // forced to the default `/sessions` endpoint.
35
+ const effectiveVersionSession = input.type === 'NAME_AND_PASSWORD' ? versionSession : 'default';
36
+ // The `Fingerprint` header is only meaningful for the Inplay
37
+ // NAME_AND_PASSWORD endpoint (`/v3/inplay/sessions`). Strip it for any
38
+ // other combination to avoid leaking it to upstream endpoints that don't
39
+ // expect it.
40
+ if (effectiveVersionSession !== 'Inplay' ||
41
+ input.type !== 'NAME_AND_PASSWORD') {
42
+ headers.delete(FINGERPRINT_HEADER_KEY);
43
+ }
32
44
  try {
33
- return await httpRequest.json(`${AUTH_ENDPOINT}${SESSION_ENDPOINTS[versionSession]}`, {
45
+ // The Inplay `/v3/inplay/sessions` endpoint wraps its payload in
46
+ // `{ data: { ... } }` (same shape as `/v2/sessions`), while the
47
+ // default `/sessions` endpoint returns the flat shape directly.
48
+ // Unwrap the Inplay response so callers can treat both consistently
49
+ // via the existing `CreateSessionMutation` union.
50
+ if (effectiveVersionSession === 'Inplay') {
51
+ const wrapped = await httpRequest.json(`${AUTH_ENDPOINT}${SESSION_ENDPOINTS[effectiveVersionSession]}`, {
52
+ ...options,
53
+ method: 'POST',
54
+ headers,
55
+ });
56
+ if (wrapped.data.authenticator) {
57
+ return {
58
+ authenticator: wrapped.data.authenticator,
59
+ };
60
+ }
61
+ return {
62
+ session: wrapped.data.session,
63
+ accessToken: wrapped.data.accessToken,
64
+ refreshToken: wrapped.data.refreshToken,
65
+ };
66
+ }
67
+ return await httpRequest.json(`${AUTH_ENDPOINT}${SESSION_ENDPOINTS[effectiveVersionSession]}`, {
34
68
  ...options,
35
69
  method: 'POST',
36
70
  headers,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opexa/portal-components",
3
- "version": "0.0.1122",
3
+ "version": "0.0.1125",
4
4
  "exports": {
5
5
  "./ui/*": {
6
6
  "types": "./dist/ui/*/index.d.ts",
@@ -1,3 +0,0 @@
1
- import { type VerifyMobileNumberInput } from '../../services/account';
2
- import type { Mutation } from '../../types';
3
- export declare const useVerifyMobileNumber: Mutation<void, VerifyMobileNumberInput>;
@@ -1,20 +0,0 @@
1
- import { useMutation } from '@tanstack/react-query';
2
- import invariant from 'tiny-invariant';
3
- import { verifyMobileNumber, } from '../../services/account.js';
4
- import { getVerifyMobileNumberMutationKey } from '../../utils/mutationKeys.js';
5
- import { getSession } from '../services/getSession.js';
6
- export const useVerifyMobileNumber = (config) => {
7
- return useMutation({
8
- ...config,
9
- mutationKey: getVerifyMobileNumberMutationKey(),
10
- mutationFn: async (input) => {
11
- const session = await getSession();
12
- invariant(session.status === 'authenticated');
13
- await verifyMobileNumber(input.verificationCode, {
14
- headers: {
15
- Authorization: `Bearer ${session.token}`,
16
- },
17
- });
18
- },
19
- });
20
- };
@@ -1 +0,0 @@
1
- export declare function AurixPayGrabPayDeposit(): import("react/jsx-runtime").JSX.Element;
@@ -1,241 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { zodResolver } from '@hookform/resolvers/zod';
3
- import { ObjectId } from '@opexa/object-id';
4
- import Link from 'next/link';
5
- import { useEffect, useState } from 'react';
6
- import { Controller, useForm } from 'react-hook-form';
7
- import invariant from 'tiny-invariant';
8
- import { useBoolean } from 'usehooks-ts';
9
- import { z } from 'zod';
10
- import { useShallow } from 'zustand/shallow';
11
- import { useAvailablePromosQuery } from '../../../../client/hooks/useAvailablePromosQuery.js';
12
- import { useCreateAurixPayGrabPayDepositMutation } from '../../../../client/hooks/useCreateAurixPayGrabPayDepositMutation.js';
13
- import { useDepositQuery } from '../../../../client/hooks/useDepositQuery.js';
14
- import { useDepositsCountQuery } from '../../../../client/hooks/useDepositsCountQuery.js';
15
- import { useDisclosure } from '../../../../client/hooks/useDisclosure.js';
16
- import { useGlobalStore } from '../../../../client/hooks/useGlobalStore.js';
17
- import { useMemberVerificationQuery } from '../../../../client/hooks/useMemberVerificationQuery.js';
18
- import { usePaymentSettingsQuery } from '../../../../client/hooks/usePaymentSettingsQuery.js';
19
- import { AlertCircleIcon } from '../../../../icons/AlertCircleIcon.js';
20
- import { ChevronDownIcon } from '../../../../icons/ChevronDownIcon.js';
21
- import { ChevronUpIcon } from '../../../../icons/ChevronUpIcon.js';
22
- import { RefreshCcw01Icon } from '../../../../icons/RefreshCcw01Icon.js';
23
- import { SpinnerIcon } from '../../../../icons/SpinnerIcon.js';
24
- import { XIcon } from '../../../../icons/XIcon.js';
25
- import { ObjectType } from '../../../../services/ObjectType.js';
26
- import { AlertDialog } from '../../../../ui/AlertDialog/index.js';
27
- import { Button } from '../../../../ui/Button/index.js';
28
- import { Field } from '../../../../ui/Field/index.js';
29
- import { NumberInput } from '../../../../ui/NumberInput/index.js';
30
- import { Portal } from '../../../../ui/Portal/index.js';
31
- import { getQueryClient } from '../../../../utils/getQueryClient.js';
32
- import { parseDecimal } from '../../../../utils/parseDecimal.js';
33
- import { getDepositsCountQueryKey } from '../../../../utils/queryKeys.js';
34
- import { AmountChoices } from '../../AmountChoices.js';
35
- import { useDepositWithdrawalPropsContext } from '../../DepositWithdrawalContext.js';
36
- import { AvailablePromos } from '../AvailablePromos.js';
37
- export function AurixPayGrabPayDeposit() {
38
- const depositWithdrawalProps = useDepositWithdrawalPropsContext();
39
- const disclosure = useDisclosure({
40
- onOpenChange(open) {
41
- if (!open) {
42
- form.reset();
43
- }
44
- },
45
- });
46
- const globalStore = useGlobalStore(useShallow((ctx) => ({
47
- depositWithdrawal: ctx.depositWithdrawal,
48
- kycVerificationStatus: ctx.kycVerificationStatus,
49
- })));
50
- const verificationQuery = useMemberVerificationQuery();
51
- const verificationStatus = verificationQuery.data?.status ?? 'UNVERIFIED';
52
- const [status, setStatus] = useState('waiting');
53
- const [errorMessage, setErrorMessage] = useState(null);
54
- const createDepositMutation = useCreateAurixPayGrabPayDepositMutation({
55
- onMutate() {
56
- disclosure.setOpen(true);
57
- setStatus('processing');
58
- },
59
- onSuccess(data) {
60
- const queryClient = getQueryClient();
61
- invariant(data.checkoutUrl);
62
- window.open(data.checkoutUrl, '_blank', 'noopener,noreferrer');
63
- queryClient.invalidateQueries({
64
- queryKey: getDepositsCountQueryKey(),
65
- });
66
- setStatus('success');
67
- },
68
- onError(data) {
69
- setStatus('failed');
70
- setErrorMessage({
71
- name: data.name,
72
- message: data.message,
73
- });
74
- },
75
- });
76
- const warn = useBoolean();
77
- const depositQuery = useDepositQuery(createDepositMutation.data?.id, {
78
- enabled: !warn.value && status === 'success',
79
- refetchInterval: (ctx) => ctx.state.data?.status === 'CONFIRMED' ||
80
- ctx.state.data?.status === 'REJECTED' ||
81
- ctx.state.data?.status === 'CANCELLED'
82
- ? false
83
- : 1000,
84
- });
85
- useEffect(() => {
86
- if (depositQuery.data?.status === 'CONFIRMED') {
87
- setStatus('confirmed');
88
- return;
89
- }
90
- if (depositQuery.data?.status === 'REJECTED' ||
91
- depositQuery.data?.status === 'CANCELLED') {
92
- setStatus('failed');
93
- return;
94
- }
95
- }, [depositQuery.data?.status]);
96
- const depositsCountQuery = useDepositsCountQuery();
97
- const depositsCount = depositsCountQuery.data ?? 0;
98
- const paymentSettingsQuery = usePaymentSettingsQuery();
99
- const paymentSettings = paymentSettingsQuery.data;
100
- const gatewaySettings = paymentSettings?.aioGCashDepositGatewaySettings;
101
- const maximumAmount = parseDecimal(gatewaySettings?.maximumAmount, 0);
102
- const minimumAmount = depositsCount <= 0
103
- ? parseDecimal(paymentSettingsQuery.data?.minimumFirstDepositAmount, 0)
104
- : parseDecimal(gatewaySettings?.minimumAmount, 0);
105
- const promosQuery = useAvailablePromosQuery();
106
- const promos = promosQuery.data ?? [];
107
- const definition = z
108
- .object({
109
- amount: z.string().superRefine((val, ctx) => {
110
- const n = parseDecimal(val, 0);
111
- if (n < minimumAmount) {
112
- ctx.addIssue({
113
- type: 'number',
114
- code: z.ZodIssueCode.too_small,
115
- inclusive: true,
116
- minimum: minimumAmount,
117
- message: `Please enter ${minimumAmount.toLocaleString()} or more to proceed with your deposit.`,
118
- });
119
- }
120
- if (n > maximumAmount) {
121
- ctx.addIssue({
122
- type: 'number',
123
- code: z.ZodIssueCode.too_big,
124
- inclusive: true,
125
- maximum: maximumAmount,
126
- message: `Maximum amount is ${maximumAmount.toLocaleString()}`,
127
- });
128
- }
129
- }),
130
- promo: z.string().optional().nullable(),
131
- accountNumber: z
132
- .string()
133
- .min(1, 'Account number is required')
134
- .min(8, 'Account number must be 8 or more characters')
135
- .max(32, 'Account number must not be more than 32 characters'),
136
- })
137
- .superRefine((value, ctx) => {
138
- const promo = promos.find((o) => o.id === value.promo);
139
- const promoMinAmount = parseDecimal(promo?.minimumDepositAmount, 0);
140
- const promoMaxAmount = parseDecimal(promo?.maximumDepositAmount, 0);
141
- const amount = parseDecimal(value.amount, 0);
142
- if (promo && amount < promoMinAmount) {
143
- ctx.addIssue({
144
- path: ['amount'],
145
- code: z.ZodIssueCode.custom,
146
- message: `Minimum amount for this promo is ${promoMinAmount.toLocaleString()}`,
147
- });
148
- }
149
- if (promo && amount > promoMaxAmount) {
150
- ctx.addIssue({
151
- path: ['amount'],
152
- code: z.ZodIssueCode.custom,
153
- message: `Maximum amount for this promo is ${promoMaxAmount}`,
154
- });
155
- }
156
- });
157
- const form = useForm({
158
- mode: 'all',
159
- resolver: zodResolver(definition),
160
- defaultValues: {
161
- amount: '0',
162
- promo: globalStore.depositWithdrawal.promo ?? null,
163
- accountNumber: '',
164
- },
165
- });
166
- useEffect(() => {
167
- if (minimumAmount) {
168
- form.reset({
169
- amount: minimumAmount.toString(),
170
- promo: form.getValues('promo') ?? null,
171
- accountNumber: form.getValues('accountNumber') ?? '',
172
- });
173
- }
174
- }, [form, minimumAmount]);
175
- const redirectUrl = (() => {
176
- const path = depositWithdrawalProps.depositSuccessPageUrl ?? '/deposits/:id/status';
177
- const origin = window.location.origin.includes('localhost')
178
- ? 'https://uat.powerplay.ph' +
179
- depositWithdrawalProps.depositSuccessPageUrl
180
- : window.location.origin;
181
- return `${origin}${path}`;
182
- })();
183
- return (_jsxs("form", { onSubmit: form.handleSubmit(async (data) => {
184
- if (!depositWithdrawalProps.bypassDepositKycCheck &&
185
- (verificationStatus === 'PENDING' ||
186
- verificationStatus === 'UNVERIFIED' ||
187
- verificationStatus === 'REJECTED' ||
188
- verificationStatus === 'CREATED')) {
189
- globalStore.kycVerificationStatus.setOpen(true);
190
- return;
191
- }
192
- else {
193
- const id = ObjectId.generate(ObjectType.Deposit).toString();
194
- createDepositMutation.reset();
195
- createDepositMutation.mutate({
196
- id,
197
- amount: data.amount.toString(),
198
- promo: data.promo ?? undefined,
199
- redirectUrl: redirectUrl.replace(':id', id),
200
- accountNumber: data.accountNumber,
201
- });
202
- }
203
- }), noValidate: true, children: [_jsxs(Field.Root, { invalid: !!form.formState.errors.accountNumber, children: [_jsx(Field.Label, { children: "Account number" }), _jsx(Field.Input, { ...form.register('accountNumber') }), _jsx(Field.ErrorText, { children: form.formState.errors.accountNumber?.message })] }), _jsx(Controller, { control: form.control, name: "amount", render: (o) => (_jsxs(Field.Root, { invalid: !!form.formState.errors.amount, className: "mt-lg", children: [_jsxs(NumberInput.Root, { min: 0, step: 1, value: o.field.value, onValueChange: (details) => {
204
- o.field.onChange(details.value);
205
- }, allowMouseWheel: true, children: [_jsx(NumberInput.Label, { children: "Enter amount you want to deposit" }), _jsxs(NumberInput.Control, { children: [_jsx(NumberInput.Input, {}), _jsx(NumberInput.IncrementTrigger, { children: _jsx(ChevronUpIcon, {}) }), _jsx(NumberInput.DecrementTrigger, { children: _jsx(ChevronDownIcon, {}) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.amount?.message })] })) }), _jsx(AmountChoices, { value: parseDecimal(form.watch('amount'), 0), onChange: (value) => {
206
- form.setValue('amount', value.toString(), {
207
- shouldTouch: true,
208
- shouldDirty: true,
209
- shouldValidate: true,
210
- });
211
- }, min: minimumAmount, max: maximumAmount, className: "mt-lg" }), _jsx(Controller, { control: form.control, name: "promo", render: (o) => (_jsx(AvailablePromos, { value: o.field.value, onChange: (value) => {
212
- o.field.onChange(value);
213
- globalStore.depositWithdrawal.setPromo(null);
214
- }, className: "mt-3xl" })) }), _jsx(Button, { type: "submit", className: "mt-3xl", disabled: createDepositMutation.isPending, children: "Deposit" }), _jsxs("p", { className: "mt-lg text-text-tertiary-600 text-xs", children: ["By depositing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.privacyPolicyUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: disclosure.open, onOpenChange: (details) => {
215
- disclosure.setOpen(details.open);
216
- }, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, onExitComplete: () => {
217
- setStatus('waiting');
218
- setErrorMessage(null);
219
- form.reset();
220
- warn.setFalse();
221
- }, children: _jsxs(Portal, { children: [_jsx(AlertDialog.Backdrop, { className: "!z-[calc(var(--z-dialog)+2)]" }), _jsx(AlertDialog.Positioner, { className: "!z-[calc(var(--z-dialog)+3)]", children: _jsxs(AlertDialog.Content, { children: [_jsx(AlertDialog.Context, { children: (api) => (_jsx("button", { type: "button", className: "absolute top-2.5 right-2.5 flex icon:size-6 size-11 items-center justify-center text-text-quinary", onClick: () => {
222
- if (status === 'success' && !warn.value) {
223
- warn.setTrue();
224
- }
225
- else {
226
- api.setOpen(false);
227
- }
228
- }, children: _jsx(XIcon, {}) })) }), _jsxs(AlertDialog.Header, { children: [status === 'processing' && (_jsx(SpinnerIcon, { className: "size-12 text-text-brand-primary-600" })), status === 'success' && !warn.value && (_jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-bg-brand-secondary text-text-featured-icon-light-brand", children: _jsx(RefreshCcw01Icon, {}) })), status === 'success' && warn.value && (_jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-bg-error-secondary text-text-featured-icon-light-error", children: _jsx(AlertCircleIcon, {}) })), status === 'confirmed' && (_jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-bg-success-secondary text-text-featured-icon-light-success", children: _jsx(AlertCircleIcon, {}) })), status === 'failed' && (_jsx("div", { className: "flex size-12 items-center justify-center rounded-full bg-bg-error-secondary text-text-featured-icon-light-error", children: _jsx(AlertCircleIcon, {}) }))] }), _jsxs(AlertDialog.Body, { children: [_jsxs(AlertDialog.Title, { children: [status === 'processing' && 'Processing Deposit', status === 'success' &&
229
- !warn.value &&
230
- 'Didn’t see the payment window?', status === 'success' && warn.value && (_jsx(_Fragment, { children: "Are you sure you want to close this\u00A0window?" })), status === 'confirmed' && 'Deposit Successful', status === 'failed' && errorMessage?.name] }), _jsxs(AlertDialog.Description, { children: [status === 'processing' &&
231
- "We're verifying your account and amount. Please hold a moment.", status === 'success' &&
232
- !warn.value &&
233
- 'Sometimes the payment pop up doesn’t appear right away. Don’t worry, just click the button below to reopen it and continue your deposit.', status === 'success' &&
234
- warn.value &&
235
- 'Closing this window might cancel your current deposit. Do you want to continue?', status === 'confirmed' &&
236
- 'Your deposit has been successfully processed.', status === 'failed' && errorMessage?.message] })] }), (status === 'failed' ||
237
- status === 'success' ||
238
- status === 'confirmed') && (_jsxs(AlertDialog.Footer, { children: [status === 'success' && !warn.value && (_jsx(Button, { asChild: true, children: _jsx("a", { href: createDepositMutation.data?.checkoutUrl ?? '', target: "_blank", rel: "noopener noreferrer", children: "Try Again" }) })), status === 'success' && warn.value && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", onClick: () => {
239
- warn.setFalse();
240
- }, children: "Go back" }), _jsx(AlertDialog.Context, { children: (api) => (_jsx(Button, { onClick: () => api.setOpen(false), children: "Continue" })) })] })), status !== 'success' && (_jsx(AlertDialog.Context, { children: (api) => (_jsx(Button, { onClick: () => api.setOpen(false), children: "Ok" })) }))] }))] }) })] }) })] }));
241
- }
@@ -1,4 +0,0 @@
1
- export declare function SingleSignOn(): import("react/jsx-runtime").JSX.Element | null;
2
- export declare function VerifyMobileNumber({ onClose }: {
3
- onClose?: () => void;
4
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,185 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { zodResolver } from '@hookform/resolvers/zod';
4
- import Image from 'next/image';
5
- import { useParams, useRouter, useSearchParams } from 'next/navigation';
6
- import { useEffect, useRef, useState } from 'react';
7
- import { Controller, useForm } from 'react-hook-form';
8
- import z from 'zod';
9
- import { useCooldown } from '../../client/hooks/useCooldown.js';
10
- import { useLocaleInfo } from '../../client/hooks/useLocaleInfo.js';
11
- import { useMobileNumberParser } from '../../client/hooks/useMobileNumberParser.js';
12
- import { useSendVerificationCodeMutation } from '../../client/hooks/useSendVerificationCodeMutation.js';
13
- import { useSignInSSOMutation } from '../../client/hooks/useSignInSSOMutation.js';
14
- import { useVerifyMobileNumber } from '../../client/hooks/useVerifyMobileNumber.js';
15
- import { toaster } from '../../client/utils/toaster.js';
16
- import { ArrowLeftIcon } from '../../icons/ArrowLeftIcon.js';
17
- import cinePopLogo from '../../images/cinepop-logo.png';
18
- import dearUtolLogo from '../../images/dear-utol-logo.png';
19
- import inplayLogo from '../../images/inplay-logo.png';
20
- import lightBg from '../../images/light-bg.png';
21
- import mariasDiary from '../../images/marias-diary-logo.png';
22
- import secretConfessionsLogo from '../../images/secret-confessions-logo.png';
23
- import { Button } from '../../ui/Button/index.js';
24
- import { Dialog } from '../../ui/Dialog/index.js';
25
- import { Field } from '../../ui/Field/index.js';
26
- import { PinInput } from '../../ui/PinInput/index.js';
27
- import { Portal } from '../../ui/Portal/index.js';
28
- export function SingleSignOn() {
29
- const params = useParams();
30
- const searchParams = useSearchParams();
31
- const router = useRouter();
32
- const partnerId = params.partnerId;
33
- const token = searchParams.get('token');
34
- const [isSsoOpen, setIsSsoOpen] = useState(true);
35
- const [showVerifyDialog, setShowVerifyDialog] = useState(false);
36
- const ssoMutation = useSignInSSOMutation({
37
- onSuccess: () => {
38
- toaster.success({
39
- description: 'Account created successfully',
40
- });
41
- setIsSsoOpen(false);
42
- setShowVerifyDialog(true);
43
- },
44
- onError: () => {
45
- toaster.error({
46
- description: 'Account creation failed',
47
- });
48
- setIsSsoOpen(false);
49
- router.push('/');
50
- },
51
- });
52
- // biome-ignore lint/correctness/useExhaustiveDependencies: We only want to trigger the mutation when the URL parameters change.
53
- useEffect(() => {
54
- // Trigger SSO login when component mounts
55
- if (partnerId && token && !ssoMutation.isPending) {
56
- ssoMutation.mutate({ partnerId, token });
57
- }
58
- }, [partnerId, token]);
59
- if (ssoMutation.isPending) {
60
- return (_jsx(Dialog.Root, { open: isSsoOpen, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { className: "flex items-center", children: _jsxs(Dialog.Content, { className: "flex h-[333px] w-[375px] flex-col items-center space-y-4 bg-[#111827] p-6 text-center", style: {
61
- backgroundImage: `url(${lightBg.src})`,
62
- }, children: [_jsx(Image, { src: inplayLogo, alt: "inplay logo", width: 82, height: 34, className: "h-auto w-[82px]" }), _jsx("div", { className: "mb-4 h-7 w-7 animate-spin rounded-full border-4 border-[#101730] border-t-[#F05027]" }), _jsx("div", { className: "text-[#CECFD2] text-sm", children: "We\u2019re creating an account for you..." }), _jsx("div", { className: "text-[#CECFD2] text-sm", children: "In the meantime, you can watch your favorite series on CinePop!" }), _jsxs("div", { className: "pt-3", children: [_jsx(Image, { src: cinePopLogo, alt: "cine poplogo", width: 151, height: 24, className: "mx-auto mb-2 h-auto w-[151px]" }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Image, { src: secretConfessionsLogo, alt: "secret confessions logo", width: 104, height: 53, className: "h-auto w-[104px]" }), _jsx(Image, { src: dearUtolLogo, alt: "dear utol logo", width: 105, height: 53, className: "h-auto w-[105px]" }), _jsx(Image, { src: mariasDiary, alt: "maria's diary logo", width: 104, height: 53, className: "h-auto w-[104px]" })] })] })] }) })] }) }));
63
- }
64
- if (showVerifyDialog) {
65
- return (_jsx(VerifyMobileNumber, { onClose: () => {
66
- setShowVerifyDialog(false);
67
- router.push('/');
68
- } }));
69
- }
70
- return null;
71
- }
72
- export function VerifyMobileNumber({ onClose }) {
73
- const [step, setStep] = useState(1);
74
- const sendVerificationCodeMutation = useSendVerificationCodeMutation({
75
- onSuccess: () => {
76
- setStep(2);
77
- cooldown.start();
78
- },
79
- onError: (err) => {
80
- toaster.error({
81
- title: 'Sign In Failed',
82
- description: err.message,
83
- });
84
- },
85
- });
86
- const verifyMobileNumberMutation = useVerifyMobileNumber({
87
- onSuccess: async () => {
88
- step1Form.reset();
89
- step2Form.reset();
90
- setStep(1);
91
- toaster.success({
92
- title: 'Verification Successful',
93
- description: 'Your mobile number has been verified.',
94
- });
95
- onClose?.();
96
- },
97
- onError: (err) => {
98
- const errorMessage = err.name === 'Forbidden'
99
- ? 'Please enter the correct verification code'
100
- : err.message;
101
- toaster.error({
102
- title: 'Sign In Failed',
103
- description: errorMessage,
104
- });
105
- },
106
- });
107
- const localeInfo = useLocaleInfo();
108
- const mobileNumberParser = useMobileNumberParser();
109
- const Step1Definition = z.object({
110
- mobileNumber: z
111
- .string()
112
- .min(1, 'Mobile number is required')
113
- .superRefine((v, ctx) => {
114
- if (!mobileNumberParser.validate(v)) {
115
- ctx.addIssue({
116
- code: z.ZodIssueCode.custom,
117
- message: 'Invalid mobile number',
118
- });
119
- }
120
- }),
121
- });
122
- const Step2Definition = z.object({
123
- verificationCode: z.array(z.string()).superRefine((val, ctx) => {
124
- if (val.length !== 6 || val.some((v) => v.length !== 1)) {
125
- ctx.addIssue({
126
- code: z.ZodIssueCode.custom,
127
- message: 'Please enter your 6-digit verification code.',
128
- });
129
- }
130
- }),
131
- });
132
- const step1Form = useForm({
133
- resolver: zodResolver(Step1Definition),
134
- defaultValues: {
135
- mobileNumber: '',
136
- },
137
- });
138
- const step2Form = useForm({
139
- resolver: zodResolver(Step2Definition),
140
- defaultValues: {
141
- verificationCode: Array.from({ length: 6 }).fill(''),
142
- },
143
- });
144
- const cooldown = useCooldown({
145
- max: 60,
146
- duration: 1000 * 60,
147
- });
148
- const formRef = useRef(null);
149
- return (_jsx(Dialog.Root, { open: true, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { className: "flex items-center", children: _jsxs(Dialog.Content, { className: "flex w-[375px] flex-col items-center space-y-4 rounded-xl bg-[#111827] p-6 text-center", style: {
150
- backgroundImage: `url(${lightBg.src})`,
151
- }, children: [_jsx(Image, { src: inplayLogo, alt: "inplay logo", width: 82, height: 34, className: "h-auto w-[82px]" }), _jsxs("div", { children: [step === 1 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "font-bold text-sm", children: ["Get ", _jsx("span", { className: "text-[#F05127]", children: "\u20B150 Bonus" }), " when you verify your account and play."] }), _jsxs("form", { className: "mt-3xl", onSubmit: step1Form.handleSubmit(async (data) => {
152
- sendVerificationCodeMutation.mutateAsync({
153
- channel: 'SMS',
154
- recipient: mobileNumberParser.format(data.mobileNumber),
155
- strict: true,
156
- });
157
- }), children: [_jsxs(Field.Root, { invalid: !!step1Form.formState.errors.mobileNumber, className: "text-left", children: [_jsx(Field.Label, { children: "Mobile Number" }), _jsxs("div", { className: "relative", children: [_jsx("div", { className: "-translate-y-1/2 absolute top-1/2 left-3.5 flex shrink-0 items-center gap-md", children: _jsx("span", { className: "text-text-placeholder", children: localeInfo.mobileNumber.areaCode }) }), _jsx(Field.Input, { style: {
158
- paddingLeft: `calc(1.25rem + ${localeInfo.mobileNumber.areaCode.length}ch)`,
159
- }, ...step1Form.register('mobileNumber') })] }), _jsx(Field.ErrorText, { children: step1Form.formState.errors.mobileNumber?.message })] }), _jsx(Button, { type: "submit", className: "mt-3xl", disabled: step1Form.formState.isSubmitting, children: "Send Code" })] })] })), step === 2 && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "mt-xl text-center font-semibold text-lg", children: "Check your Phone" }), _jsxs("p", { className: "mt-xs text-center text-sm text-text-secondary-700", children: ["We\u2019ve sent a verification code to your mobile number", ' ', _jsx("span", { className: "font-semibold text-[#F05127]", children: mobileNumberParser.format(step1Form.getValues('mobileNumber')) }), ' ', "via text"] }), _jsxs("form", { ref: formRef, className: "mt-5", onSubmit: step2Form.handleSubmit(async ({ verificationCode }) => {
160
- verifyMobileNumberMutation.mutateAsync({
161
- verificationCode: verificationCode.join(''),
162
- });
163
- }), children: [_jsx(Controller, { name: "verificationCode", control: step2Form.control, render: (o) => (_jsxs(Field.Root, { invalid: o.fieldState.invalid, children: [_jsxs(PinInput.Root, { placeholder: "0", onKeyDown: (e) => {
164
- if (e.key === 'Backspace') {
165
- step2Form.reset();
166
- }
167
- }, value: o.field.value, onValueChange: (details) => {
168
- o.field.onChange(details.value);
169
- o.field.onBlur();
170
- }, otp: true, onValueComplete: () => {
171
- formRef.current?.requestSubmit();
172
- }, blurOnComplete: true, readOnly: step2Form.formState.isSubmitting, type: "numeric", children: [_jsxs(PinInput.Control, { className: "grid-cols-[1fr_1fr_1fr_auto_1fr_1fr_1fr] items-center gap-md", children: [_jsx(PinInput.Input, { index: 0 }), _jsx(PinInput.Input, { index: 1 }), _jsx(PinInput.Input, { index: 2 }), _jsx("span", { className: "font-medium text-2xl text-text-placeholder-subtle", children: "\u2013" }), _jsx(PinInput.Input, { index: 3 }), _jsx(PinInput.Input, { index: 4 }), _jsx(PinInput.Input, { index: 5 })] }), _jsx(PinInput.HiddenInput, {})] }), _jsx(Field.ErrorText, { children: o.fieldState.error?.message })] })) }), _jsx(Button, { type: "submit", className: "mt-4xl", disabled: step2Form.formState.isSubmitting, children: "Verify" }), _jsxs("div", { className: "mt-4 flex w-full items-center justify-center gap-xs text-xs", children: [_jsx("span", { className: "text-[#9CA3AF]", children: "Didn't receive the code?" }), _jsx("button", { type: "button", className: "font-semibold text-[#C084FC]", disabled: cooldown.cooling, onClick: async () => {
173
- await sendVerificationCodeMutation.mutateAsync({
174
- channel: 'SMS',
175
- recipient: mobileNumberParser.format(step1Form.getValues('mobileNumber')),
176
- });
177
- cooldown.start();
178
- }, children: cooldown.cooling
179
- ? `Resend in ${cooldown.countdown}s`
180
- : 'Resend' })] }), _jsx("button", { type: "button", className: "absolute top-0 left-6 mx-auto mt-3xl flex h-8 w-8 items-center gap-1 rounded-full bg-[#1f2638] font-semibold text-sm text-text-tertiary-600", onClick: () => {
181
- setStep(1);
182
- step2Form.reset();
183
- cooldown.stop();
184
- }, children: _jsx(ArrowLeftIcon, { className: "mx-auto size-5" }) })] })] }))] })] }) })] }) }));
185
- }
@@ -1 +0,0 @@
1
- export * from './SingleSignOn';
@@ -1 +0,0 @@
1
- export * from './SingleSignOn.js';
@@ -1,3 +0,0 @@
1
- export declare function UpdateMobileNumber({ onClose }: {
2
- onClose?: () => void;
3
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,141 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { zodResolver } from '@hookform/resolvers/zod';
4
- import Image from 'next/image';
5
- import { useRef, useState } from 'react';
6
- import { Controller, useForm } from 'react-hook-form';
7
- import z from 'zod';
8
- import { useAccountQuery } from '../../client/hooks/useAccountQuery.js';
9
- import { useCooldown } from '../../client/hooks/useCooldown.js';
10
- import { useLocaleInfo } from '../../client/hooks/useLocaleInfo.js';
11
- import { useMobileNumberParser } from '../../client/hooks/useMobileNumberParser.js';
12
- import { useSendVerificationCodeMutation } from '../../client/hooks/useSendVerificationCodeMutation.js';
13
- import { useUpdateMobileNumber } from '../../client/hooks/useUpdateMobileNumber.js';
14
- import { toaster } from '../../client/utils/toaster.js';
15
- import { ArrowLeftIcon } from '../../icons/ArrowLeftIcon.js';
16
- import inplayLogo from '../../images/inplay-logo.png';
17
- import lightBg from '../../images/light-bg.png';
18
- import { Button } from '../../ui/Button/index.js';
19
- import { Dialog } from '../../ui/Dialog/index.js';
20
- import { Field } from '../../ui/Field/index.js';
21
- import { PinInput } from '../../ui/PinInput/index.js';
22
- import { Portal } from '../../ui/Portal/index.js';
23
- export function UpdateMobileNumber({ onClose }) {
24
- const accountQuery = useAccountQuery();
25
- const account = accountQuery.data;
26
- const isAccountLoading = accountQuery.isLoading;
27
- const hasMobileNumber = !!account?.mobileNumber;
28
- const isDialogOpen = !isAccountLoading && !!account && !hasMobileNumber;
29
- const [step, setStep] = useState(1);
30
- const sendVerificationCodeMutation = useSendVerificationCodeMutation({
31
- onSuccess: () => {
32
- setStep(2);
33
- cooldown.start();
34
- },
35
- onError: (err) => {
36
- toaster.error({
37
- title: 'Sign In Failed',
38
- description: err.message,
39
- });
40
- },
41
- });
42
- const updateMobileNumberMutation = useUpdateMobileNumber({
43
- onSuccess: async () => {
44
- step1Form.reset();
45
- step2Form.reset();
46
- setStep(1);
47
- toaster.success({
48
- title: 'Verification Successful',
49
- description: 'Your mobile number has been verified.',
50
- });
51
- onClose?.();
52
- },
53
- onError: (err) => {
54
- const errorMessage = err.message === 'Internal Server Error'
55
- ? `mobile number ${mobileNumberParser.format(step1Form.getValues('mobileNumber'))} is not available`
56
- : err.message;
57
- toaster.error({
58
- title: 'Sign In Failed',
59
- description: errorMessage,
60
- });
61
- },
62
- });
63
- const localeInfo = useLocaleInfo();
64
- const mobileNumberParser = useMobileNumberParser();
65
- const Step1Definition = z.object({
66
- mobileNumber: z
67
- .string()
68
- .min(1, 'Mobile number is required')
69
- .superRefine((v, ctx) => {
70
- if (!mobileNumberParser.validate(v)) {
71
- ctx.addIssue({
72
- code: z.ZodIssueCode.custom,
73
- message: 'Invalid mobile number',
74
- });
75
- }
76
- }),
77
- });
78
- const Step2Definition = z.object({
79
- verificationCode: z.array(z.string()).superRefine((val, ctx) => {
80
- if (val.length !== 6 || val.some((v) => v.length !== 1)) {
81
- ctx.addIssue({
82
- code: z.ZodIssueCode.custom,
83
- message: 'Please enter your 6-digit verification code.',
84
- });
85
- }
86
- }),
87
- });
88
- const step1Form = useForm({
89
- resolver: zodResolver(Step1Definition),
90
- defaultValues: {
91
- mobileNumber: '',
92
- },
93
- });
94
- const step2Form = useForm({
95
- resolver: zodResolver(Step2Definition),
96
- defaultValues: {
97
- verificationCode: Array.from({ length: 6 }).fill(''),
98
- },
99
- });
100
- const cooldown = useCooldown({
101
- max: 60,
102
- duration: 1000 * 60,
103
- });
104
- const formRef = useRef(null);
105
- return (_jsx(Dialog.Root, { open: isDialogOpen, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { className: "flex items-center", children: _jsxs(Dialog.Content, { className: "flex w-[375px] flex-col items-center space-y-4 rounded-xl bg-[#111827] p-6 text-center", style: {
106
- backgroundImage: `url(${lightBg.src})`,
107
- }, children: [_jsx(Image, { src: inplayLogo, alt: "inplay logo", width: 82, height: 34, className: "h-auto w-[82px]" }), _jsxs("div", { children: [step === 1 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "font-bold text-sm", children: ["Get ", _jsx("span", { className: "text-[#F05127]", children: "\u20B150 Bonus" }), " when you verify your account and play."] }), _jsxs("form", { className: "mt-3xl", onSubmit: step1Form.handleSubmit(async (data) => {
108
- sendVerificationCodeMutation.mutateAsync({
109
- channel: 'SMS',
110
- recipient: mobileNumberParser.format(data.mobileNumber),
111
- });
112
- }), children: [_jsxs(Field.Root, { invalid: !!step1Form.formState.errors.mobileNumber, className: "text-left", children: [_jsx(Field.Label, { children: "Mobile Number" }), _jsxs("div", { className: "relative", children: [_jsx("div", { className: "-translate-y-1/2 absolute top-1/2 left-3.5 flex shrink-0 items-center gap-md", children: _jsx("span", { className: "text-text-placeholder", children: localeInfo.mobileNumber.areaCode }) }), _jsx(Field.Input, { style: {
113
- paddingLeft: `calc(1.25rem + ${localeInfo.mobileNumber.areaCode.length}ch)`,
114
- }, ...step1Form.register('mobileNumber') })] }), _jsx(Field.ErrorText, { children: step1Form.formState.errors.mobileNumber?.message })] }), _jsx(Button, { type: "submit", className: "mt-3xl", disabled: step1Form.formState.isSubmitting, children: "Send Code" })] })] })), step === 2 && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "mt-xl text-center font-semibold text-lg", children: "Check your Phone" }), _jsxs("p", { className: "mt-xs text-center text-sm text-text-secondary-700", children: ["We\u2019ve sent a verification code to your mobile number", ' ', _jsx("span", { className: "font-semibold text-[#F05127]", children: mobileNumberParser.format(step1Form.getValues('mobileNumber')) }), ' ', "via text"] }), _jsxs("form", { ref: formRef, className: "mt-5", onSubmit: step2Form.handleSubmit(async ({ verificationCode }) => {
115
- updateMobileNumberMutation.mutateAsync({
116
- mobileNumber: mobileNumberParser.format(step1Form.getValues('mobileNumber')),
117
- verificationCode: verificationCode.join(''),
118
- });
119
- }), children: [_jsx(Controller, { name: "verificationCode", control: step2Form.control, render: (o) => (_jsxs(Field.Root, { invalid: o.fieldState.invalid, children: [_jsxs(PinInput.Root, { placeholder: "0", onKeyDown: (e) => {
120
- if (e.key === 'Backspace') {
121
- step2Form.reset();
122
- }
123
- }, value: o.field.value, onValueChange: (details) => {
124
- o.field.onChange(details.value);
125
- o.field.onBlur();
126
- }, otp: true, onValueComplete: () => {
127
- formRef.current?.requestSubmit();
128
- }, blurOnComplete: true, readOnly: step2Form.formState.isSubmitting, type: "numeric", children: [_jsxs(PinInput.Control, { className: "grid-cols-[1fr_1fr_1fr_auto_1fr_1fr_1fr] items-center gap-md", children: [_jsx(PinInput.Input, { index: 0 }), _jsx(PinInput.Input, { index: 1 }), _jsx(PinInput.Input, { index: 2 }), _jsx("span", { className: "font-medium text-2xl text-text-placeholder-subtle", children: "\u2013" }), _jsx(PinInput.Input, { index: 3 }), _jsx(PinInput.Input, { index: 4 }), _jsx(PinInput.Input, { index: 5 })] }), _jsx(PinInput.HiddenInput, {})] }), _jsx(Field.ErrorText, { children: o.fieldState.error?.message })] })) }), _jsx(Button, { type: "submit", className: "mt-4xl", disabled: step2Form.formState.isSubmitting, children: "Verify" }), _jsxs("div", { className: "mt-4 flex w-full items-center justify-center gap-xs text-xs", children: [_jsx("span", { className: "text-[#9CA3AF]", children: "Didn't receive the code?" }), _jsx("button", { type: "button", className: "font-semibold text-[#C084FC]", disabled: cooldown.cooling, onClick: async () => {
129
- await sendVerificationCodeMutation.mutateAsync({
130
- channel: 'SMS',
131
- recipient: mobileNumberParser.format(step1Form.getValues('mobileNumber')),
132
- });
133
- cooldown.start();
134
- }, children: cooldown.cooling
135
- ? `Resend in ${cooldown.countdown}s`
136
- : 'Resend' })] }), _jsx("button", { type: "button", className: "absolute top-0 left-6 mx-auto mt-3xl flex h-8 w-8 items-center gap-1 rounded-full bg-[#1f2638] font-semibold text-sm text-text-tertiary-600", onClick: () => {
137
- setStep(1);
138
- step2Form.reset();
139
- cooldown.stop();
140
- }, children: _jsx(ArrowLeftIcon, { className: "mx-auto size-5" }) })] })] }))] })] }) })] }) }));
141
- }
@@ -1 +0,0 @@
1
- export * from './UpdateMobileNumber';
@@ -1 +0,0 @@
1
- export * from './UpdateMobileNumber.js';
@@ -1 +0,0 @@
1
- export declare function UpdateMobileNumber(): import("react/jsx-runtime").JSX.Element;
@@ -1,154 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { zodResolver } from '@hookform/resolvers/zod';
4
- import Image from 'next/image';
5
- import { useEffect, useRef, useState } from 'react';
6
- import { Controller, useForm } from 'react-hook-form';
7
- import z from 'zod';
8
- import { useAccountQuery } from '../../client/hooks/useAccountQuery.js';
9
- import { useCooldown } from '../../client/hooks/useCooldown.js';
10
- import { useLocaleInfo } from '../../client/hooks/useLocaleInfo.js';
11
- import { useMobileNumberParser } from '../../client/hooks/useMobileNumberParser.js';
12
- import { useSendVerificationCodeMutation } from '../../client/hooks/useSendVerificationCodeMutation.js';
13
- import { useUpdateMobileNumber } from '../../client/hooks/useUpdateMobileNumber.js';
14
- import { toaster } from '../../client/utils/toaster.js';
15
- import { ArrowLeftIcon } from '../../icons/ArrowLeftIcon.js';
16
- import inplayLogo from '../../images/inplay-logo.png';
17
- import lightBg from '../../images/light-bg.png';
18
- import { Button } from '../../ui/Button/index.js';
19
- import { Dialog } from '../../ui/Dialog/index.js';
20
- import { Field } from '../../ui/Field/index.js';
21
- import { PinInput } from '../../ui/PinInput/index.js';
22
- import { Portal } from '../../ui/Portal/index.js';
23
- export function UpdateMobileNumber() {
24
- const accountQuery = useAccountQuery();
25
- const account = accountQuery.data;
26
- const isAccountLoading = accountQuery.isLoading;
27
- const hasMobileNumber = !!account?.mobileNumber;
28
- const [isDialogOpen, setIsDialogOpen] = useState(false);
29
- console.log('isDialogOpen', isDialogOpen);
30
- // biome-ignore lint/correctness/useExhaustiveDependencies: We only want to open the dialog when the account data loads, not on every hasMobileNumber change
31
- useEffect(() => {
32
- if (!isAccountLoading && !!account && !hasMobileNumber) {
33
- setIsDialogOpen(true);
34
- }
35
- else if (!isAccountLoading && !!account && hasMobileNumber) {
36
- setIsDialogOpen(false);
37
- }
38
- }, [isAccountLoading, account?.mobileNumber]);
39
- const [step, setStep] = useState(1);
40
- const sendVerificationCodeMutation = useSendVerificationCodeMutation({
41
- onSuccess: () => {
42
- setStep(2);
43
- cooldown.start();
44
- },
45
- onError: (err) => {
46
- toaster.error({
47
- title: 'Sign In Failed',
48
- description: err.message,
49
- });
50
- },
51
- });
52
- const updateMobileNumberMutation = useUpdateMobileNumber({
53
- onSuccess: async () => {
54
- step1Form.reset();
55
- step2Form.reset();
56
- setStep(1);
57
- toaster.success({
58
- title: 'Verification Successful',
59
- description: 'Your mobile number has been verified.',
60
- });
61
- setIsDialogOpen(false);
62
- console.log('close dialog');
63
- },
64
- onError: (err) => {
65
- console.log('err', err);
66
- console.log('error updating mobile number');
67
- const errorMessage = err.message === 'Internal Server Error'
68
- ? `mobile number ${mobileNumberParser.format(step1Form.getValues('mobileNumber'))} is not available`
69
- : err.message;
70
- toaster.error({
71
- title: 'Sign In Failed',
72
- description: errorMessage,
73
- });
74
- },
75
- });
76
- const localeInfo = useLocaleInfo();
77
- const mobileNumberParser = useMobileNumberParser();
78
- const Step1Definition = z.object({
79
- mobileNumber: z
80
- .string()
81
- .min(1, 'Mobile number is required')
82
- .superRefine((v, ctx) => {
83
- if (!mobileNumberParser.validate(v)) {
84
- ctx.addIssue({
85
- code: z.ZodIssueCode.custom,
86
- message: 'Invalid mobile number',
87
- });
88
- }
89
- }),
90
- });
91
- const Step2Definition = z.object({
92
- verificationCode: z.array(z.string()).superRefine((val, ctx) => {
93
- if (val.length !== 6 || val.some((v) => v.length !== 1)) {
94
- ctx.addIssue({
95
- code: z.ZodIssueCode.custom,
96
- message: 'Please enter your 6-digit verification code.',
97
- });
98
- }
99
- }),
100
- });
101
- const step1Form = useForm({
102
- resolver: zodResolver(Step1Definition),
103
- defaultValues: {
104
- mobileNumber: '',
105
- },
106
- });
107
- const step2Form = useForm({
108
- resolver: zodResolver(Step2Definition),
109
- defaultValues: {
110
- verificationCode: Array.from({ length: 6 }).fill(''),
111
- },
112
- });
113
- const cooldown = useCooldown({
114
- max: 60,
115
- duration: 1000 * 60,
116
- });
117
- const formRef = useRef(null);
118
- return (_jsx(Dialog.Root, { open: isDialogOpen, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { className: "flex items-center", children: _jsxs(Dialog.Content, { className: "flex w-[375px] flex-col items-center space-y-4 rounded-xl bg-[#111827] p-6 text-center", style: {
119
- backgroundImage: `url(${lightBg.src})`,
120
- }, children: [_jsx(Image, { src: inplayLogo, alt: "inplay logo", width: 82, height: 34, className: "h-auto w-[82px]" }), _jsxs("div", { children: [step === 1 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "font-bold text-sm", children: ["Get ", _jsx("span", { className: "text-[#F05127]", children: "\u20B150 Bonus" }), " when you verify your account and play."] }), _jsxs("form", { className: "mt-3xl", onSubmit: step1Form.handleSubmit(async (data) => {
121
- sendVerificationCodeMutation.mutateAsync({
122
- channel: 'SMS',
123
- recipient: mobileNumberParser.format(data.mobileNumber),
124
- });
125
- }), children: [_jsxs(Field.Root, { invalid: !!step1Form.formState.errors.mobileNumber, className: "text-left", children: [_jsx(Field.Label, { children: "Mobile Number" }), _jsxs("div", { className: "relative", children: [_jsx("div", { className: "-translate-y-1/2 absolute top-1/2 left-3.5 flex shrink-0 items-center gap-md", children: _jsx("span", { className: "text-text-placeholder", children: localeInfo.mobileNumber.areaCode }) }), _jsx(Field.Input, { style: {
126
- paddingLeft: `calc(1.25rem + ${localeInfo.mobileNumber.areaCode.length}ch)`,
127
- }, ...step1Form.register('mobileNumber') })] }), _jsx(Field.ErrorText, { children: step1Form.formState.errors.mobileNumber?.message })] }), _jsx(Button, { type: "submit", className: "mt-3xl", disabled: step1Form.formState.isSubmitting, children: "Send Code" })] })] })), step === 2 && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "mt-xl text-center font-semibold text-lg", children: "Check your Phone" }), _jsxs("p", { className: "mt-xs text-center text-sm text-text-secondary-700", children: ["We\u2019ve sent a verification code to your mobile number", ' ', _jsx("span", { className: "font-semibold text-[#F05127]", children: mobileNumberParser.format(step1Form.getValues('mobileNumber')) }), ' ', "via text"] }), _jsxs("form", { ref: formRef, className: "mt-5", onSubmit: step2Form.handleSubmit(async ({ verificationCode }) => {
128
- updateMobileNumberMutation.mutateAsync({
129
- mobileNumber: mobileNumberParser.format(step1Form.getValues('mobileNumber')),
130
- verificationCode: verificationCode.join(''),
131
- });
132
- }), children: [_jsx(Controller, { name: "verificationCode", control: step2Form.control, render: (o) => (_jsxs(Field.Root, { invalid: o.fieldState.invalid, children: [_jsxs(PinInput.Root, { placeholder: "0", onKeyDown: (e) => {
133
- if (e.key === 'Backspace') {
134
- step2Form.reset();
135
- }
136
- }, value: o.field.value, onValueChange: (details) => {
137
- o.field.onChange(details.value);
138
- o.field.onBlur();
139
- }, otp: true, onValueComplete: () => {
140
- formRef.current?.requestSubmit();
141
- }, blurOnComplete: true, readOnly: step2Form.formState.isSubmitting, type: "numeric", children: [_jsxs(PinInput.Control, { className: "grid-cols-[1fr_1fr_1fr_auto_1fr_1fr_1fr] items-center gap-md", children: [_jsx(PinInput.Input, { index: 0 }), _jsx(PinInput.Input, { index: 1 }), _jsx(PinInput.Input, { index: 2 }), _jsx("span", { className: "font-medium text-2xl text-text-placeholder-subtle", children: "\u2013" }), _jsx(PinInput.Input, { index: 3 }), _jsx(PinInput.Input, { index: 4 }), _jsx(PinInput.Input, { index: 5 })] }), _jsx(PinInput.HiddenInput, {})] }), _jsx(Field.ErrorText, { children: o.fieldState.error?.message })] })) }), _jsx(Button, { type: "submit", className: "mt-4xl", disabled: step2Form.formState.isSubmitting, children: "Verify" }), _jsxs("div", { className: "mt-4 flex w-full items-center justify-center gap-xs text-xs", children: [_jsx("span", { className: "text-[#9CA3AF]", children: "Didn't receive the code?" }), _jsx("button", { type: "button", className: "font-semibold text-[#C084FC]", disabled: cooldown.cooling, onClick: async () => {
142
- await sendVerificationCodeMutation.mutateAsync({
143
- channel: 'SMS',
144
- recipient: mobileNumberParser.format(step1Form.getValues('mobileNumber')),
145
- });
146
- cooldown.start();
147
- }, children: cooldown.cooling
148
- ? `Resend in ${cooldown.countdown}s`
149
- : 'Resend' })] }), _jsx("button", { type: "button", className: "absolute top-0 left-6 mx-auto mt-3xl flex h-8 w-8 items-center gap-1 rounded-full bg-[#1f2638] font-semibold text-sm text-text-tertiary-600", onClick: () => {
150
- setStep(1);
151
- step2Form.reset();
152
- cooldown.stop();
153
- }, children: _jsx(ArrowLeftIcon, { className: "mx-auto size-5" }) })] })] }))] })] }) })] }) }));
154
- }
@@ -1 +0,0 @@
1
- export * from './UpdateMobileNumber';
@@ -1 +0,0 @@
1
- export * from './UpdateMobileNumber.js';