@opexa/portal-components 0.0.735 → 0.0.737

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.
@@ -80,25 +80,22 @@ export function GameLaunchTrigger(props) {
80
80
  return;
81
81
  }
82
82
  try {
83
- console.log('Signing in using biometric credentials');
84
83
  await signIn({
85
84
  type: 'SINGLE_USE_TOKEN',
86
85
  token: credentials.password,
87
86
  });
88
87
  }
89
- catch {
88
+ catch (err) {
89
+ console.log(err);
90
90
  toaster.error({
91
- title: 'Biometric sign-in token has expired.',
91
+ title: 'Biometric removed or token expired.',
92
92
  description: 'Please sign in with your mobile number or username to re-enable biometric login.',
93
93
  });
94
94
  deleteBiometricCredentials();
95
95
  globalStore.signIn.setOpen(!globalStore.signIn.open);
96
96
  }
97
- getQueryClient().invalidateQueries({
98
- queryKey: getSessionQueryKey(),
99
- });
100
- const session = await getSession();
101
97
  const pushToken = localStorage.getItem(LOCALSTORAGE_PUSH_NOTIFICATION_TOKEN_KEY);
98
+ const session = await getSession();
102
99
  await unregisterFCMDevice({
103
100
  type: ['IOS', 'ANDROID'],
104
101
  }, {
@@ -116,6 +113,9 @@ export function GameLaunchTrigger(props) {
116
113
  },
117
114
  });
118
115
  }
116
+ getQueryClient().invalidateQueries({
117
+ queryKey: getSessionQueryKey(),
118
+ });
119
119
  const r = await createSingleUseToken({
120
120
  headers: {
121
121
  Authorization: `Bearer ${session.token}`,
@@ -140,45 +140,6 @@ export function GameLaunchTrigger(props) {
140
140
  }
141
141
  }
142
142
  else {
143
- // still update biometric credentials if user has cancelled biometric once
144
- if (hasCancelledBiometric) {
145
- const credentials = await getBiometricCredentials();
146
- if (!credentials) {
147
- toaster.error({ description: 'Biometric verification failed' });
148
- globalStore.signIn.setOpen(!globalStore.signIn.open);
149
- return;
150
- }
151
- await signIn({
152
- type: 'SINGLE_USE_TOKEN',
153
- token: credentials.password,
154
- });
155
- getQueryClient().invalidateQueries({
156
- queryKey: getSessionQueryKey(),
157
- });
158
- const session = await getSession();
159
- const r = await createSingleUseToken({
160
- headers: {
161
- Authorization: `Bearer ${session.token}`,
162
- },
163
- });
164
- if (r.token) {
165
- const saved = await saveBiometricCredentials({
166
- username: credentials.username,
167
- password: r.token,
168
- });
169
- if (saved) {
170
- console.info('Biometric credentials has been updated');
171
- }
172
- else {
173
- console.warn('Failed to updated biometric credentials');
174
- globalStore.signIn.setOpen(!globalStore.signIn.open);
175
- }
176
- }
177
- else {
178
- console.error('Failed to create token');
179
- globalStore.signIn.setOpen(!globalStore.signIn.open);
180
- }
181
- }
182
143
  globalStore.signIn.setOpen(!globalStore.signIn.open);
183
144
  }
184
145
  return props.onClick?.(e);
@@ -46,7 +46,7 @@ export function GamesList__client(props) {
46
46
  const classNames = isString(props.className)
47
47
  ? { root: props.className }
48
48
  : (props.className ?? {});
49
- return (_jsx(GamesPropsContext, { value: props, children: _jsxs("div", { className: classNames.root, id: "games-list", children: [_jsxs("div", { className: "flex flex-col lg:flex-row lg:items-center lg:justify-between", children: [_jsx("h2", { className: "order-2 mt-4xl font-semibold text-lg lg:order-none lg:mt-0", children: props.heading ?? 'Games' }), props.viewGameProvidersUrl && (_jsxs(Link, { href: props.viewGameProvidersUrl, className: "order-1 flex items-center gap-sm font-semibold text-button-tertiary-fg text-lg lg:order-none lg:text-sm", children: [_jsx(ChevronLeftIcon, { className: "size-5" }), "Back to all Providers"] }))] }), totalRows <= 0 && (_jsx(Empty, { icon: loading ? SpinnerIcon : GamingPad01Icon, title: loading ? 'Just a moment' : 'No games', message: loading
49
+ return (_jsx(GamesPropsContext, { value: props, children: _jsxs("div", { className: classNames.root, id: "games-list", children: [_jsxs("div", { className: "flex flex-col lg:flex-row lg:items-center lg:justify-between", children: [_jsx("h2", { className: "order-2 mt-md font-semibold text-lg lg:order-none lg:mt-0", children: props.heading ?? 'Games' }), props.viewGameProvidersUrl && (_jsxs(Link, { href: props.viewGameProvidersUrl, className: "order-1 flex items-center gap-sm font-semibold text-button-tertiary-fg text-lg lg:order-none lg:text-sm", children: [_jsx(ChevronLeftIcon, { className: "size-5" }), "Back to all Providers"] }))] }), totalRows <= 0 && (_jsx(Empty, { icon: loading ? SpinnerIcon : GamingPad01Icon, title: loading ? 'Just a moment' : 'No games', message: loading
50
50
  ? 'Fetching latest games...'
51
51
  : 'No game is currently available. Please check back later', className: "mt-lg" })), totalRows >= 1 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "mt-lg grid grid-cols-3 gap-1.5 lg:grid-cols-6 lg:gap-2.5", children: (pagination === 'paginated' ? paginatedRows : availableRows).map((game) => (_jsx(GameContext, { value: game, children: _jsx(Game, { badge: props.badge, className: {
52
52
  root: classNames.thumbnailRoot,
@@ -1,5 +1,11 @@
1
+ import { type ImageProps } from 'next/image';
1
2
  import type { GameProviderData } from '../../../types';
3
+ interface JackpotGameProvider extends GameProviderData {
4
+ redirectUrl: string;
5
+ providedLogo?: ImageProps['src'];
6
+ }
2
7
  export interface JackpotsListItemGameProvidersProps {
3
- gameProviders: GameProviderData[];
8
+ gameProviders: JackpotGameProvider[];
4
9
  }
5
10
  export declare function JackpotsListItemGameProviders({ gameProviders, }: JackpotsListItemGameProvidersProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -1,24 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import useEmblaCarousel from 'embla-carousel-react';
3
3
  import { isString } from 'lodash-es';
4
- import Image from 'next/image';
4
+ import Image, {} from 'next/image';
5
5
  import Link from 'next/link';
6
6
  import { useCallback, useEffect, useState } from 'react';
7
7
  import { twMerge } from 'tailwind-merge';
8
8
  import { ArrowLeftIcon } from '../../../icons/ArrowLeftIcon.js';
9
9
  import { ArrowRightIcon } from '../../../icons/ArrowRightIcon.js';
10
10
  import { Button } from '../../../ui/Button/index.js';
11
- import { callIfFn } from '../../../utils/callIfFn.js';
12
11
  import { useJackpotsListPropsContext } from './JackpotsListContext.js';
13
12
  export function JackpotsListItemGameProviders({ gameProviders, }) {
14
13
  const jackpotsProps = useJackpotsListPropsContext();
15
- const viewGamesUrl = (data) => {
16
- return jackpotsProps.viewGamesUrl
17
- ? callIfFn(jackpotsProps.viewGamesUrl, data)
18
- .replace(':id', data.id)
19
- .replace(':slug', data.slug)
20
- : `/providers/${data.slug}`;
21
- };
22
14
  const classNames = isString(jackpotsProps.className)
23
15
  ? { root: jackpotsProps.className }
24
16
  : (jackpotsProps.className ?? {});
@@ -49,6 +41,5 @@ export function JackpotsListItemGameProviders({ gameProviders, }) {
49
41
  emblaApi.on('select', onSelect);
50
42
  emblaApi.on('reInit', onSelect);
51
43
  }, [emblaApi, onSelect]);
52
- return (_jsxs("div", { className: twMerge('p-4 pb-8', classNames.providerRoot), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: twMerge('font-semibold text-lg text-text-primary-900', classNames.providerHeading), children: "Jackpot Game Providers" }), _jsxs("div", { className: "hidden lg:flex", children: [_jsx(Button, { disabled: !canScrollPrev, onClick: scrollPrev, variant: "outline", colorScheme: "gray", className: twMerge('rounded-r-none border-r-0', classNames.providerNavigationButton), "aria-label": "Previous", children: _jsx(ArrowLeftIcon, { className: "size-5" }) }), _jsxs(Button, { disabled: !canScrollNext, onClick: scrollNext, variant: "outline", colorScheme: "gray", className: twMerge('rounded-l-none', classNames.providerNavigationButton), "aria-label": "Next", children: [_jsx("span", { className: "sr-only", children: "Next" }), _jsx(ArrowRightIcon, { className: "size-5" })] })] })] }), _jsx("div", { className: "relative mt-3 overflow-hidden", ref: emblaRef, children: _jsx("div", { className: "flex gap-3.5", children: gameProviders.map((provider) => (_jsx(Link, { href: viewGamesUrl(provider), className: twMerge('min-w-27.5 rounded-md bg-brand-800 lg:bg-bg-primary-900', classNames.providerThumbnailRoot), children: _jsx(Image, { src: jackpotsProps.gameProviderImages?.[provider.id] ??
53
- provider.logo, alt: "provider", className: twMerge('size-full', classNames.providerThumbnailImage), width: 300, height: 150 }) }, provider.slug))) }) })] }));
44
+ return (_jsxs("div", { className: twMerge('p-4 pb-8', classNames.providerRoot), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: twMerge('font-semibold text-lg text-text-primary-900', classNames.providerHeading), children: "Jackpot Game Providers" }), _jsxs("div", { className: "hidden lg:flex", children: [_jsx(Button, { disabled: !canScrollPrev, onClick: scrollPrev, variant: "outline", colorScheme: "gray", className: twMerge('rounded-r-none border-r-0', classNames.providerNavigationButton), "aria-label": "Previous", children: _jsx(ArrowLeftIcon, { className: "size-5" }) }), _jsxs(Button, { disabled: !canScrollNext, onClick: scrollNext, variant: "outline", colorScheme: "gray", className: twMerge('rounded-l-none', classNames.providerNavigationButton), "aria-label": "Next", children: [_jsx("span", { className: "sr-only", children: "Next" }), _jsx(ArrowRightIcon, { className: "size-5" })] })] })] }), _jsx("div", { className: "relative mt-3 overflow-hidden", ref: emblaRef, children: _jsx("div", { className: "flex gap-3.5", children: gameProviders.map((provider) => (_jsx(Link, { href: provider.redirectUrl, className: twMerge('min-w-27.5 rounded-md bg-brand-800 lg:bg-bg-primary-900', classNames.providerThumbnailRoot), children: _jsx(Image, { src: provider.providedLogo ?? provider.logo, alt: "provider", className: twMerge('size-full', classNames.providerThumbnailImage), width: 300, height: 150 }) }, provider.slug))) }) })] }));
54
45
  }
@@ -17,12 +17,13 @@ import { useMobileNumberParser } from '../../client/hooks/useMobileNumberParser.
17
17
  import { useSendVerificationCodeMutation } from '../../client/hooks/useSendVerificationCodeMutation.js';
18
18
  import { useSignInMutation } from '../../client/hooks/useSignInMutation.js';
19
19
  import { getSession } from '../../client/services/getSession.js';
20
- import { hasSavedBiometry } from '../../client/utils/biometric.js';
20
+ import { deleteBiometricCredentials, getBiometricCredentials, hasSavedBiometry, saveBiometricCredentials, } from '../../client/utils/biometric.js';
21
21
  import { toaster } from '../../client/utils/toaster.js';
22
22
  import { ArrowLeftIcon } from '../../icons/ArrowLeftIcon.js';
23
23
  import { CheckIcon } from '../../icons/CheckIcon.js';
24
24
  import pagcorLogo from '../../images/pagcor-round-icon.png';
25
25
  import responsibleGamingLogo from '../../images/responsible-gaming-gold.png';
26
+ import { createSingleUseToken } from '../../services/auth.js';
26
27
  import { registerFCMDevice, unregisterFCMDevice } from '../../services/trigger.js';
27
28
  import { Button } from '../../ui/Button/index.js';
28
29
  import { Checkbox } from '../../ui/Checkbox/index.js';
@@ -84,9 +85,40 @@ export function MobileNumberSignIn() {
84
85
  if (signInProps.shouldShowDisclaimer) {
85
86
  globalStore.disclaimer.setOpen(true);
86
87
  }
87
- console.log('hasSavedBiometry', hasSavedBiometry());
88
- if (!hasSavedBiometry()) {
89
- globalStore.registerBiometrics.setOpen(true);
88
+ if (Capacitor.isNativePlatform()) {
89
+ if (!hasSavedBiometry()) {
90
+ globalStore.registerBiometrics.setOpen(true);
91
+ }
92
+ else {
93
+ const r = await createSingleUseToken({
94
+ headers: {
95
+ Authorization: `Bearer ${session.token}`,
96
+ },
97
+ });
98
+ if (r.token) {
99
+ const credentials = await getBiometricCredentials();
100
+ if (!credentials) {
101
+ console.error({ description: 'Biometric verification failed' });
102
+ deleteBiometricCredentials();
103
+ return;
104
+ }
105
+ const saved = await saveBiometricCredentials({
106
+ username: credentials.username,
107
+ password: r.token,
108
+ });
109
+ if (saved) {
110
+ console.info('Biometric credentials has been updated');
111
+ }
112
+ else {
113
+ console.warn('Failed to updated biometric credentials');
114
+ globalStore.signIn.setOpen(!globalStore.signIn.open);
115
+ }
116
+ }
117
+ else {
118
+ console.error('Failed to create token');
119
+ globalStore.signIn.setOpen(!globalStore.signIn.open);
120
+ }
121
+ }
90
122
  }
91
123
  },
92
124
  onError: (err) => {
@@ -14,7 +14,7 @@ import { useAuthenticateMutation } from '../../client/hooks/useAuthenticateMutat
14
14
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
15
15
  import { useSignInMutation } from '../../client/hooks/useSignInMutation.js';
16
16
  import { getSession } from '../../client/services/getSession.js';
17
- import { hasSavedBiometry } from '../../client/utils/biometric.js';
17
+ import { deleteBiometricCredentials, getBiometricCredentials, hasSavedBiometry, saveBiometricCredentials, } from '../../client/utils/biometric.js';
18
18
  import { toaster } from '../../client/utils/toaster.js';
19
19
  import { SECRET_QUESTIONS, SECRET_QUESTIONS_MAP } from '../../constants/index.js';
20
20
  import { CheckIcon } from '../../icons/CheckIcon.js';
@@ -22,6 +22,7 @@ import { EyeIcon } from '../../icons/EyeIcon.js';
22
22
  import { EyeOffIcon } from '../../icons/EyeOffIcon.js';
23
23
  import pagcorLogo from '../../images/pagcor-round-icon.png';
24
24
  import responsibleGamingLogo from '../../images/responsible-gaming-gold.png';
25
+ import { createSingleUseToken } from '../../services/auth.js';
25
26
  import { registerFCMDevice, unregisterFCMDevice } from '../../services/trigger.js';
26
27
  import { Button } from '../../ui/Button/index.js';
27
28
  import { Checkbox } from '../../ui/Checkbox/index.js';
@@ -78,8 +79,40 @@ export function NameAndPasswordSignIn() {
78
79
  });
79
80
  }
80
81
  }
81
- if (!hasSavedBiometry()) {
82
- globalStore.registerBiometrics.setOpen(true);
82
+ if (Capacitor.isNativePlatform()) {
83
+ if (!hasSavedBiometry()) {
84
+ globalStore.registerBiometrics.setOpen(true);
85
+ }
86
+ else {
87
+ const r = await createSingleUseToken({
88
+ headers: {
89
+ Authorization: `Bearer ${session.token}`,
90
+ },
91
+ });
92
+ if (r.token) {
93
+ const credentials = await getBiometricCredentials();
94
+ if (!credentials) {
95
+ console.error({ description: 'Biometric verification failed' });
96
+ deleteBiometricCredentials();
97
+ return;
98
+ }
99
+ const saved = await saveBiometricCredentials({
100
+ username: credentials.username,
101
+ password: r.token,
102
+ });
103
+ if (saved) {
104
+ console.info('Biometric credentials has been updated');
105
+ }
106
+ else {
107
+ console.warn('Failed to updated biometric credentials');
108
+ globalStore.signIn.setOpen(!globalStore.signIn.open);
109
+ }
110
+ }
111
+ else {
112
+ console.error('Failed to create token');
113
+ globalStore.signIn.setOpen(!globalStore.signIn.open);
114
+ }
115
+ }
83
116
  }
84
117
  globalStore.signIn.setOpen(false);
85
118
  authenticateMutation.reset();
@@ -136,8 +169,40 @@ export function NameAndPasswordSignIn() {
136
169
  if (signInProps.shouldShowDisclaimer) {
137
170
  globalStore.disclaimer.setOpen(true);
138
171
  }
139
- if (!hasSavedBiometry()) {
140
- globalStore.registerBiometrics.setOpen(true);
172
+ if (Capacitor.isNativePlatform()) {
173
+ if (!hasSavedBiometry()) {
174
+ globalStore.registerBiometrics.setOpen(true);
175
+ }
176
+ else {
177
+ const r = await createSingleUseToken({
178
+ headers: {
179
+ Authorization: `Bearer ${session.token}`,
180
+ },
181
+ });
182
+ if (r.token) {
183
+ const credentials = await getBiometricCredentials();
184
+ if (!credentials) {
185
+ console.error({ description: 'Biometric verification failed' });
186
+ deleteBiometricCredentials();
187
+ return;
188
+ }
189
+ const saved = await saveBiometricCredentials({
190
+ username: credentials.username,
191
+ password: r.token,
192
+ });
193
+ if (saved) {
194
+ console.info('Biometric credentials has been updated');
195
+ }
196
+ else {
197
+ console.warn('Failed to updated biometric credentials');
198
+ globalStore.signIn.setOpen(!globalStore.signIn.open);
199
+ }
200
+ }
201
+ else {
202
+ console.error('Failed to create token');
203
+ globalStore.signIn.setOpen(!globalStore.signIn.open);
204
+ }
205
+ }
141
206
  }
142
207
  },
143
208
  onError(error) {
@@ -112,45 +112,6 @@ export function SignInTrigger(props) {
112
112
  }
113
113
  }
114
114
  else {
115
- // still update biometric credentials if user has cancelled biometric once
116
- if (hasCancelledBiometric) {
117
- const credentials = await getBiometricCredentials();
118
- if (!credentials) {
119
- toaster.error({ description: 'Biometric verification failed' });
120
- globalStore.signIn.setOpen(!globalStore.signIn.open);
121
- return;
122
- }
123
- await signIn({
124
- type: 'SINGLE_USE_TOKEN',
125
- token: credentials.password,
126
- });
127
- getQueryClient().invalidateQueries({
128
- queryKey: getSessionQueryKey(),
129
- });
130
- const session = await getSession();
131
- const r = await createSingleUseToken({
132
- headers: {
133
- Authorization: `Bearer ${session.token}`,
134
- },
135
- });
136
- if (r.token) {
137
- const saved = await saveBiometricCredentials({
138
- username: credentials.username,
139
- password: r.token,
140
- });
141
- if (saved) {
142
- console.info('Biometric credentials has been updated');
143
- }
144
- else {
145
- console.warn('Failed to updated biometric credentials');
146
- globalStore.signIn.setOpen(!globalStore.signIn.open);
147
- }
148
- }
149
- else {
150
- console.error('Failed to create token');
151
- globalStore.signIn.setOpen(!globalStore.signIn.open);
152
- }
153
- }
154
115
  globalStore.signIn.setOpen(!globalStore.signIn.open);
155
116
  }
156
117
  return props.onClick?.(e);
@@ -156,7 +156,7 @@ export async function sendVerificationCode(input, options) {
156
156
  }
157
157
  export async function createSingleUseToken(options) {
158
158
  try {
159
- return await httpRequest.json(`${AUTH_ENDPOINT}/token`, {
159
+ return await httpRequest.json(`${AUTH_ENDPOINT}/token?ttl=30d`, {
160
160
  ...options,
161
161
  method: 'POST',
162
162
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opexa/portal-components",
3
- "version": "0.0.735",
3
+ "version": "0.0.737",
4
4
  "exports": {
5
5
  "./ui/*": {
6
6
  "types": "./dist/ui/*/index.d.ts",