@opexa/portal-components 0.0.904 → 0.0.906

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 (69) hide show
  1. package/dist/client/hooks/useSignInSSOMutation.d.ts +3 -6
  2. package/dist/client/hooks/useSignInSSOMutation.js +7 -13
  3. package/dist/client/hooks/useVerifyMobileNumber.d.ts +3 -0
  4. package/dist/client/hooks/useVerifyMobileNumber.js +20 -0
  5. package/dist/client/services/signIn.d.ts +0 -1
  6. package/dist/client/services/signIn.js +0 -19
  7. package/dist/components/GamesSearch/GamesSearch.d.ts +2 -0
  8. package/dist/components/GamesSearch/GamesSearch.js +6 -3
  9. package/dist/components/Search/Search.lazy.d.ts +2 -0
  10. package/dist/components/Search/Search.lazy.js +2 -2
  11. package/dist/components/SingleSignOn/SingleSignOn.d.ts +4 -0
  12. package/dist/components/SingleSignOn/SingleSignOn.js +185 -0
  13. package/dist/components/SingleSignOn/index.d.ts +1 -0
  14. package/dist/components/SingleSignOn/index.js +1 -0
  15. package/dist/constants/GameProvider.js +12 -0
  16. package/dist/images/close-chest.png +0 -0
  17. package/dist/images/open-chest.png +0 -0
  18. package/dist/images/tournament-bg-1.webp +0 -0
  19. package/dist/images/tournament-bg-2.webp +0 -0
  20. package/dist/images/tournament-bg-3.webp +0 -0
  21. package/dist/images/trophy.png +0 -0
  22. package/dist/schemas/forgotPasswordSchema.d.ts +4 -4
  23. package/dist/services/account.d.ts +3 -0
  24. package/dist/services/auth.d.ts +5 -0
  25. package/dist/services/auth.js +26 -0
  26. package/dist/types/index.d.ts +1 -1
  27. package/dist/ui/AlertDialog/AlertDialog.d.ts +88 -88
  28. package/dist/ui/AlertDialog/alertDialog.recipe.d.ts +8 -8
  29. package/dist/ui/Badge/Badge.d.ts +12 -12
  30. package/dist/ui/Badge/badge.anatomy.d.ts +1 -1
  31. package/dist/ui/Badge/badge.recipe.d.ts +3 -3
  32. package/dist/ui/Carousel/Carousel.d.ts +72 -72
  33. package/dist/ui/Carousel/carousel.recipe.d.ts +8 -8
  34. package/dist/ui/Checkbox/Checkbox.d.ts +23 -23
  35. package/dist/ui/Checkbox/checkbox.recipe.d.ts +3 -3
  36. package/dist/ui/Clipboard/Clipboard.d.ts +18 -18
  37. package/dist/ui/Clipboard/clipboard.recipe.d.ts +3 -3
  38. package/dist/ui/Collapsible/Collapsible.d.ts +20 -20
  39. package/dist/ui/Collapsible/collapsible.recipe.d.ts +5 -5
  40. package/dist/ui/Combobox/Combobox.d.ts +42 -42
  41. package/dist/ui/Combobox/combobox.recipe.d.ts +3 -3
  42. package/dist/ui/DatePicker/DatePicker.d.ts +72 -72
  43. package/dist/ui/DatePicker/datePicker.recipe.d.ts +3 -3
  44. package/dist/ui/Dialog/Dialog.d.ts +33 -33
  45. package/dist/ui/Dialog/dialog.recipe.d.ts +3 -3
  46. package/dist/ui/Drawer/Drawer.d.ts +33 -33
  47. package/dist/ui/Drawer/drawer.recipe.d.ts +3 -3
  48. package/dist/ui/Field/Field.d.ts +21 -21
  49. package/dist/ui/Field/field.recipe.d.ts +3 -3
  50. package/dist/ui/Menu/Menu.d.ts +360 -360
  51. package/dist/ui/Menu/menu.recipe.d.ts +20 -20
  52. package/dist/ui/Popover/Popover.d.ts +88 -88
  53. package/dist/ui/Popover/popover.recipe.d.ts +8 -8
  54. package/dist/ui/Progress/Progress.d.ts +27 -27
  55. package/dist/ui/Progress/progress.recipe.d.ts +3 -3
  56. package/dist/ui/SegmentGroup/SegmentGroup.d.ts +18 -18
  57. package/dist/ui/SegmentGroup/segmentGroup.recipe.d.ts +3 -3
  58. package/dist/ui/Select/Select.d.ts +45 -45
  59. package/dist/ui/Select/select.recipe.d.ts +3 -3
  60. package/dist/ui/Table/Table.d.ts +21 -21
  61. package/dist/ui/Table/table.anatomy.d.ts +1 -1
  62. package/dist/ui/Table/table.recipe.d.ts +3 -3
  63. package/dist/ui/Tabs/Tabs.d.ts +15 -15
  64. package/dist/ui/Tabs/tabs.recipe.d.ts +3 -3
  65. package/dist/ui/Tooltip/Tooltip.d.ts +30 -30
  66. package/dist/ui/Tooltip/tooltip.recipe.d.ts +5 -5
  67. package/dist/utils/mutationKeys.d.ts +1 -0
  68. package/dist/utils/mutationKeys.js +4 -0
  69. package/package.json +1 -1
@@ -1,6 +1,3 @@
1
- import type { Authenticator, Mutation } from '../../types';
2
- export interface SignInSSOInput {
3
- partnerId: string;
4
- token: string;
5
- }
6
- export declare const useSignInSSOMutation: Mutation<Authenticator | null, SignInSSOInput>;
1
+ import { type CreateSessionMutation_next, type SignInSSOInput } from '../../services/auth';
2
+ import type { Mutation } from '../../types';
3
+ export declare const useSignInSSOMutation: Mutation<CreateSessionMutation_next, SignInSSOInput>;
@@ -1,27 +1,21 @@
1
1
  import { useMutation } from '@tanstack/react-query';
2
+ import { signInSSO, } from '../../services/auth.js';
2
3
  import { getQueryClient } from '../../utils/getQueryClient.js';
3
4
  import { getSignInSSOMutationKey } from '../../utils/mutationKeys.js';
4
5
  import { getSessionQueryKey } from '../../utils/queryKeys.js';
5
- import { signInSSO } from '../services/signIn.js';
6
6
  export const useSignInSSOMutation = (config) => {
7
7
  const queryClient = getQueryClient();
8
8
  return useMutation({
9
9
  ...config,
10
10
  mutationKey: getSignInSSOMutationKey(),
11
11
  mutationFn: async (input) => {
12
- try {
13
- const { partnerId, token } = input;
14
- const authenticator = await signInSSO(partnerId, token);
15
- if (!authenticator) {
16
- await queryClient.invalidateQueries({
17
- queryKey: getSessionQueryKey(),
18
- });
19
- }
20
- return authenticator;
21
- }
22
- catch (error) {
23
- throw error;
12
+ const authenticator = await signInSSO(input);
13
+ if (!authenticator) {
14
+ await queryClient.invalidateQueries({
15
+ queryKey: getSessionQueryKey(),
16
+ });
24
17
  }
18
+ return authenticator;
25
19
  },
26
20
  });
27
21
  };
@@ -0,0 +1,3 @@
1
+ import { type VerifyMobileNumberInput } from '../../services/account';
2
+ import type { Mutation } from '../../types';
3
+ export declare const useVerifyMobileNumber: Mutation<void, VerifyMobileNumberInput>;
@@ -0,0 +1,20 @@
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
+ };
@@ -3,4 +3,3 @@ import { type HttpRequestOptions } from '../../services/httpRequest';
3
3
  import type { Authenticator } from '../../types';
4
4
  export type SignInInput = CreateSessionInput;
5
5
  export declare function signIn(input: SignInInput, options?: HttpRequestOptions): Promise<Authenticator | null>;
6
- export declare function signInSSO(partnerId: string, token: string, options?: HttpRequestOptions): Promise<Authenticator | null>;
@@ -21,22 +21,3 @@ export async function signIn(input, options) {
21
21
  }
22
22
  return res.data ?? null;
23
23
  }
24
- export async function signInSSO(partnerId, token, options) {
25
- // Create base64 encoded authorization
26
- const authString = btoa(`${partnerId}:${token}`);
27
- const res = await httpRequest.json('/api/v3/sessions', {
28
- ...options,
29
- method: 'POST',
30
- headers: {
31
- Authorization: `OPEXA_SINGLE_SIGN_ON ${authString}`,
32
- 'Platform-Code': process.env.NEXT_PUBLIC_PLATFORM_CODE || '',
33
- },
34
- });
35
- if (!res.ok) {
36
- const error = new Error();
37
- error.name = 'SSOSignInError';
38
- error.message = 'Single sign-on authentication failed';
39
- throw error;
40
- }
41
- return res.data ?? null;
42
- }
@@ -5,6 +5,7 @@ export interface ClassNameEntries {
5
5
  thumbnailRoot?: string;
6
6
  thumbnailTitle?: string;
7
7
  loadMoreButton?: string;
8
+ gameSearchResult?: string;
8
9
  }
9
10
  interface GamesSearchProps {
10
11
  first?: number;
@@ -13,6 +14,7 @@ interface GamesSearchProps {
13
14
  className?: string | ClassNameEntries;
14
15
  placeholder?: string;
15
16
  bypassDomains?: BypassDomainConfig[];
17
+ variant?: string;
16
18
  }
17
19
  export declare function GamesSearch(props: GamesSearchProps): import("react/jsx-runtime").JSX.Element;
18
20
  export {};
@@ -20,7 +20,9 @@ export function GamesSearch(props) {
20
20
  const [searchInput, setSearchInput] = useState('');
21
21
  const sanitizedSearch = sanitizeGamesSearch(searchInput);
22
22
  const trimmedInputLength = searchInput.trim().length;
23
- const showMinLengthWarning = trimmedInputLength > 0 && trimmedInputLength < 3 && sanitizedSearch.length < 3;
23
+ const showMinLengthWarning = trimmedInputLength > 0 &&
24
+ trimmedInputLength < 3 &&
25
+ sanitizedSearch.length < 3;
24
26
  const gamesQuery = useGamesQuery({
25
27
  first: props.first ?? 18,
26
28
  filter: props.filter,
@@ -50,13 +52,14 @@ export function GamesSearch(props) {
50
52
  api.setInputValue('');
51
53
  api.focus();
52
54
  }, children: "Clear" }));
53
- } })] }), _jsx(Portal, { children: _jsx(Combobox.Context, { children: (api) => (_jsxs(_Fragment, { children: [_jsx(Presence, { present: api.open, children: _jsx("div", { className: "fixed inset-0 z-40 bg-black/50 backdrop-blur-sm", onClick: () => api.setOpen(false) }) }), _jsx(Combobox.Positioner, { children: searchInput.trim().length > 0 && (_jsx(Combobox.Content, { className: "z-50 max-h-[33.25rem] overflow-y-auto p-0", children: showMinLengthWarning ? (_jsx(Alert, { message: "Search requires at least 3 characters." })) : (_jsxs(_Fragment, { children: [games.length <= 0 && (_jsx(Alert, { message: "No results found" })), games.length > 0 && (_jsxs("div", { className: "p-xl", children: [_jsx(Combobox.Context, { children: (api) => (_jsx("div", { className: "grid grid-cols-3 gap-1.5 lg:grid-cols-9 lg:gap-3.5", children: games.map((game) => (_jsxs(GameLaunchTrigger, { bypassKycCheck: isBypass, game: game, onClick: () => {
55
+ } })] }), _jsx(Portal, { children: _jsx(Combobox.Context, { children: (api) => (_jsxs(_Fragment, { children: [_jsx(Presence, { present: api.open, children: _jsx("div", { className: "fixed inset-0 z-40 bg-black/50 backdrop-blur-sm", onClick: () => api.setOpen(false) }) }), _jsx(Combobox.Positioner, { children: searchInput.trim().length > 0 && (_jsx(Combobox.Content, { className: "z-50 max-h-[33.25rem] overflow-y-auto p-0", children: showMinLengthWarning ? (_jsx(Alert, { message: "Search requires at least 3 characters." })) : (_jsxs(_Fragment, { children: [games.length <= 0 && (_jsx(Alert, { message: "No results found" })), games.length > 0 && (_jsxs("div", { className: "p-xl", children: [_jsx(Combobox.Context, { children: (api) => (_jsx("div", { className: twMerge('grid grid-cols-3 gap-1.5 lg:grid-cols-9 lg:gap-3.5', classNames.gameSearchResult), children: games.map((game) => (_jsxs(GameLaunchTrigger, { bypassKycCheck: isBypass, game: game, onClick: () => {
54
56
  api.setOpen(false);
55
57
  }, className: twMerge('block w-full shadow-sm', classNames.thumbnailRoot), children: [_jsx(Image, { src: getGameImageUrl({
56
58
  reference: game.reference,
57
59
  provider: game.provider,
58
60
  image: game.image,
59
- }), alt: "", width: 200, height: 200, loading: "lazy", unoptimized: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('block w-full truncate rounded-b-md bg-bg-tertiary px-2 py-2.5 text-center font-semibold text-text-primary-brand text-xs', classNames.thumbnailTitle), children: game.name })] }, game.id))) })) }), _jsx(Presence, { present: gamesQuery.hasNextPage, children: _jsx(Button, { variant: "outline", className: twMerge('mx-auto mt-4xl w-fit', classNames.loadMoreButton), onClick: () => gamesQuery.fetchNextPage(), children: "Load More" }) })] }))] })) })) })] })) }) })] }) }));
61
+ }), alt: "", width: 200, height: 200, loading: "lazy", unoptimized: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('block w-full rounded-b-md bg-bg-tertiary px-2 py-2.5 text-center font-semibold text-text-primary-brand text-xs', props.variant !== '88play' &&
62
+ 'truncate', classNames.thumbnailTitle), children: game.name })] }, game.id))) })) }), _jsx(Presence, { present: gamesQuery.hasNextPage, children: _jsx(Button, { variant: "outline", className: twMerge('mx-auto mt-4xl w-fit', classNames.loadMoreButton), onClick: () => gamesQuery.fetchNextPage(), children: "Load More" }) })] }))] })) })) })] })) }) })] }) }));
60
63
  }
61
64
  function Alert({ message }) {
62
65
  return (_jsxs("div", { className: "py-lg", role: "alert", "aria-live": "polite", children: [_jsx("div", { className: "mx-auto flex size-12 items-center justify-center rounded-lg border border-border-primary bg-bg-secondary shadow-xs", children: _jsx(SearchLgIcon, { className: "size-6 text-text-secondary-700" }) }), _jsx("p", { className: "mt-4 text-center text-text-secondary-700", children: message })] }));
@@ -5,6 +5,7 @@ export interface ClassNameEntries {
5
5
  root?: string;
6
6
  gameThumbnailRoot?: string;
7
7
  gameThumbnailTitle?: string;
8
+ gameSearchResult?: string;
8
9
  providerThumbnailRoot?: string;
9
10
  providerThumbnailImage?: string;
10
11
  loadMoreButton?: string;
@@ -28,5 +29,6 @@ export interface SearchProps {
28
29
  gameProviderImages?: Partial<Record<GameProvider, ImageProps['src']>>;
29
30
  placeholder?: string;
30
31
  bypassDomains?: BypassDomainConfig[];
32
+ variant?: string;
31
33
  }
32
34
  export declare function Search(props: SearchProps): import("react/jsx-runtime").JSX.Element;
@@ -79,13 +79,13 @@ export function Search(props) {
79
79
  }, children: "Clear" }) })] }) }), _jsx("div", { className: "flex max-h-[85dvh] min-h-0 flex-1 flex-col", children: _jsx("div", { className: "mt-2xl p-xl pb-3xl lg:mt-2 lg:max-h-[41rem] lg:overflow-y-auto lg:rounded-xl lg:border lg:border-border-primary lg:bg-bg-primary", children: search.length <= 0 ? (_jsx(Alert, { message: "Search for your favorite game or provider." })) : search.length === 1 ? (_jsx(Alert, { message: "Search requires at least 2 characters." })) : (_jsxs(_Fragment, { children: [empty && _jsx(Alert, { message: "No results found" }), !empty && (_jsxs(_Fragment, { children: [gameProviders.length > 0 && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "font-semibold text-lg", children: "Providers" }), _jsx("div", { className: "mt-3.5 mb-3xl grid grid-cols-3 gap-1.5 lg:grid-cols-9 lg:gap-3.5", children: gameProviders.map((provider) => (_jsx(Link, { href: viewGamesUrl(provider), "aria-label": `View ${provider.name} games`, className: twMerge('flex h-14 w-full items-center rounded-md bg-brand-800', classNames.providerThumbnailRoot), onClick: () => {
80
80
  globalStore.search.setOpen(false);
81
81
  }, children: _jsx(Image, { src: props.gameProviderImages?.[provider.id] ??
82
- provider.logo, alt: "", width: 100, height: 50, className: twMerge('mx-auto h-auto w-full', classNames.providerThumbnailImage) }) }, provider.id))) })] })), games.length > 0 && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "font-semibold text-lg", children: "Games" }), _jsx("div", { className: "mt-3.5 grid grid-cols-3 gap-1.5 lg:grid-cols-9 lg:gap-3.5", children: games.map((game) => (_jsxs(GameLaunchTrigger, { bypassKycCheck: isBypass, game: game, className: twMerge('block w-full shadow-sm', classNames.gameThumbnailRoot), onClick: () => {
82
+ provider.logo, alt: "", width: 100, height: 50, className: twMerge('mx-auto h-auto w-full', classNames.providerThumbnailImage) }) }, provider.id))) })] })), games.length > 0 && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "font-semibold text-lg", children: "Games" }), _jsx("div", { className: twMerge('mt-3.5 grid grid-cols-3 gap-1.5 lg:grid-cols-9 lg:gap-3.5', classNames.gameSearchResult), children: games.map((game) => (_jsxs(GameLaunchTrigger, { bypassKycCheck: isBypass, game: game, className: twMerge('block w-full shadow-sm', classNames.gameThumbnailRoot), onClick: () => {
83
83
  globalStore.search.setOpen(false);
84
84
  }, children: [_jsx(Image, { src: getGameImageUrl({
85
85
  reference: game.reference,
86
86
  provider: game.provider,
87
87
  image: game.image,
88
- }), alt: "", width: 200, height: 200, loading: "lazy", unoptimized: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('block w-full truncate rounded-b-md bg-bg-tertiary px-2 py-2.5 text-center font-semibold text-text-primary-brand text-xs', classNames.gameThumbnailTitle), children: game.name })] }, game.id))) })] })), _jsx(Presence, { present: gamesQuery.hasNextPage, children: _jsx(Button, { variant: "outline", className: twMerge('mx-auto mt-12 w-fit', classNames.loadMoreButton), onClick: () => gamesQuery.fetchNextPage(), children: "Load More" }) })] }))] })) }) })] }) })] }) }));
88
+ }), alt: "", width: 200, height: 200, loading: "lazy", unoptimized: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('block w-full rounded-b-md bg-bg-tertiary px-2 py-2.5 text-center font-semibold text-text-primary-brand text-xs', props.variant !== '88play' && 'truncate', classNames.gameThumbnailTitle), children: game.name })] }, game.id))) })] })), _jsx(Presence, { present: gamesQuery.hasNextPage, children: _jsx(Button, { variant: "outline", className: twMerge('mx-auto mt-12 w-fit', classNames.loadMoreButton), onClick: () => gamesQuery.fetchNextPage(), children: "Load More" }) })] }))] })) }) })] }) })] }) }));
89
89
  }
90
90
  function DebouncedInput(props) {
91
91
  const [value, setValue] = useControllableState({
@@ -0,0 +1,4 @@
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;
@@ -0,0 +1,185 @@
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 cinePopLogo from '../../../lib/images/cinepop-logo.png';
10
+ import dearUtolLogo from '../../../lib/images/dear-utol-logo.png';
11
+ import inplayLogo from '../../../lib/images/inplay-logo.png';
12
+ import lightBg from '../../../lib/images/light-bg.png';
13
+ import mariasDiary from '../../../lib/images/marias-diary-logo.png';
14
+ import secretConfessionsLogo from '../../../lib/images/secret-confessions-logo.png';
15
+ import { useCooldown } from '../../client/hooks/useCooldown.js';
16
+ import { useLocaleInfo } from '../../client/hooks/useLocaleInfo.js';
17
+ import { useMobileNumberParser } from '../../client/hooks/useMobileNumberParser.js';
18
+ import { useSendVerificationCodeMutation } from '../../client/hooks/useSendVerificationCodeMutation.js';
19
+ import { useSignInSSOMutation } from '../../client/hooks/useSignInSSOMutation.js';
20
+ import { useVerifyMobileNumber } from '../../client/hooks/useVerifyMobileNumber.js';
21
+ import { toaster } from '../../client/utils/toaster.js';
22
+ import { ArrowLeftIcon } from '../../icons/ArrowLeftIcon.js';
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
+ }
@@ -0,0 +1 @@
1
+ export * from './SingleSignOn';
@@ -0,0 +1 @@
1
+ export * from './SingleSignOn.js';
@@ -290,6 +290,12 @@ export const GAME_PROVIDER_DATA = {
290
290
  slug: 'evolution-netent',
291
291
  logo: evolutionNetent,
292
292
  },
293
+ EVOLUTIONNETENT: {
294
+ id: 'EVOLUTIONNETENT',
295
+ name: 'Evolution Netent',
296
+ slug: 'evolution-netent',
297
+ logo: evolutionNetent,
298
+ },
293
299
  DIGITAIN: {
294
300
  id: 'DIGITAIN',
295
301
  name: 'Digitain',
@@ -332,6 +338,12 @@ export const GAME_PROVIDER_DATA = {
332
338
  slug: 'oneapi-spadegaming',
333
339
  logo: spadegaming,
334
340
  },
341
+ TEST: {
342
+ id: 'TEST',
343
+ name: 'Test',
344
+ slug: 'test',
345
+ logo: '',
346
+ },
335
347
  };
336
348
  export const GAME_PROVIDERS = Object.values(GAME_PROVIDER_DATA).map(({ id }) => id);
337
349
  export const LEGACY_GAME_PROVIDERS = [
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -8,23 +8,23 @@ export declare const createForgotPasswordSchema: (mobileNumberParser: MobileNumb
8
8
  mobileNumber: z.ZodEffects<z.ZodString, string, string>;
9
9
  verificationCode: z.ZodEffects<z.ZodString, string, string>;
10
10
  }, "strip", z.ZodTypeAny, {
11
- password: string;
12
11
  verificationCode: string;
12
+ password: string;
13
13
  mobileNumber: string;
14
14
  confirmPassword: string;
15
15
  }, {
16
- password: string;
17
16
  verificationCode: string;
17
+ password: string;
18
18
  mobileNumber: string;
19
19
  confirmPassword: string;
20
20
  }>, {
21
- password: string;
22
21
  verificationCode: string;
22
+ password: string;
23
23
  mobileNumber: string;
24
24
  confirmPassword: string;
25
25
  }, {
26
- password: string;
27
26
  verificationCode: string;
27
+ password: string;
28
28
  mobileNumber: string;
29
29
  confirmPassword: string;
30
30
  }>;
@@ -222,6 +222,9 @@ export type VerifyMobileNumberError = {
222
222
  export interface VerifyMobileNumberMutation {
223
223
  verifyMobileNumber?: null | VerifyMobileNumberError;
224
224
  }
225
+ export type VerifyMobileNumberInput = {
226
+ verificationCode: string;
227
+ };
225
228
  export interface VerifyMobileNumberMutationVariables {
226
229
  input: {
227
230
  verificationCode: string;
@@ -97,3 +97,8 @@ export interface CreateSingleUseTokenMutation {
97
97
  token: string;
98
98
  }
99
99
  export declare function createSingleUseToken(options?: HttpRequestOptions): Promise<CreateSingleUseTokenMutation>;
100
+ export interface SignInSSOInput {
101
+ partnerId: string;
102
+ token: string;
103
+ }
104
+ export declare function signInSSO(input: SignInSSOInput, options?: HttpRequestOptions): Promise<CreateSessionMutation_next>;
@@ -169,3 +169,29 @@ export async function createSingleUseToken(options) {
169
169
  throw error;
170
170
  }
171
171
  }
172
+ export async function signInSSO(input, options) {
173
+ const { partnerId, token } = input;
174
+ const authString = btoa(`${partnerId}:${token}`);
175
+ const headers = new Headers();
176
+ headers.set('Authorization', `OPEXA_SINGLE_SIGN_ON ${authString}`);
177
+ try {
178
+ const response = await httpRequest.json(`${AUTH_ENDPOINT}/v3/sessions`, {
179
+ ...options,
180
+ method: 'POST',
181
+ headers,
182
+ });
183
+ return response;
184
+ }
185
+ catch (e) {
186
+ if (e instanceof Error) {
187
+ throw e;
188
+ }
189
+ else {
190
+ const error = new Error();
191
+ error.name = 'AccountNotFoundError';
192
+ error.message = 'Account not found';
193
+ Error.captureStackTrace?.(error, createSession);
194
+ throw error;
195
+ }
196
+ }
197
+ }
@@ -157,7 +157,7 @@ export interface Announcement {
157
157
  dateTimeLastUpdated: string;
158
158
  }
159
159
  export type GameType = 'SLOTS' | 'SPORTS' | 'FISHING' | 'BINGO' | 'LIVE' | 'GAMES' | 'TABLE' | 'SPECIALTY' | 'NUMERICAL' | 'NUMERIC' | 'ARCADE';
160
- export type GameProvider = 'JILI' | 'JILI_BINGO' | 'PGSOFT' | 'FACHAI' | 'BTI' | 'DG' | 'PLAYTECH' | 'E2E' | 'ONEAPI_EVOLUTION' | 'EVOLUTION' | 'EVOLUTION_NETENT' | 'EVOLUTION_REDTIGER' | 'MEGABALL' | 'MEGA2SPIN' | 'DARWIN' | 'RTG' | 'DRBINGO' | 'HOLLYWOODTV' | 'CQ9' | 'JDB' | 'HABANERO' | 'SPINIX' | 'JOKER' | 'HACKSAW' | 'JDBGTF' | 'JDBSPRIBE' | 'MICROGAMING' | 'RELAXGAMING' | 'EVOPLAY' | 'BOOONGO' | 'BGAMING' | 'KINGMAKER' | 'KINGMIDAS' | 'YELLOWBAT' | 'ETENGJUE' | 'SABA' | 'PRAGMATICPLAY' | 'SPRIBE' | 'EZUGI' | 'ALIZE' | 'DIGITAIN' | 'BNG' | 'NO_LIMIT_CITY' | 'BIG_TIME_GAMING' | 'SAGAMING' | 'ONEAPI_SPADEGAMING' | 'JK8' | 'RUBYPLAY';
160
+ export type GameProvider = 'JILI' | 'JILI_BINGO' | 'PGSOFT' | 'FACHAI' | 'BTI' | 'DG' | 'PLAYTECH' | 'E2E' | 'ONEAPI_EVOLUTION' | 'EVOLUTION' | 'EVOLUTION_NETENT' | 'EVOLUTION_REDTIGER' | 'MEGABALL' | 'MEGA2SPIN' | 'DARWIN' | 'RTG' | 'DRBINGO' | 'HOLLYWOODTV' | 'CQ9' | 'JDB' | 'HABANERO' | 'SPINIX' | 'JOKER' | 'HACKSAW' | 'JDBGTF' | 'JDBSPRIBE' | 'MICROGAMING' | 'RELAXGAMING' | 'EVOPLAY' | 'BOOONGO' | 'BGAMING' | 'KINGMAKER' | 'KINGMIDAS' | 'YELLOWBAT' | 'ETENGJUE' | 'SABA' | 'PRAGMATICPLAY' | 'SPRIBE' | 'EZUGI' | 'ALIZE' | 'DIGITAIN' | 'BNG' | 'NO_LIMIT_CITY' | 'BIG_TIME_GAMING' | 'SAGAMING' | 'ONEAPI_SPADEGAMING' | 'JK8' | 'RUBYPLAY' | 'EVOLUTIONNETENT' | 'TEST';
161
161
  export type GameStatus = 'ACTIVE' | 'INACTIVE';
162
162
  export type GameTag = 'HOT' | 'hot' | 'NEW' | 'new' | 'TOP' | 'top' | 'POPULAR' | 'popular' | (string & {});
163
163
  export interface Game {