@opexa/portal-components 0.1.28 → 0.1.29

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.
@@ -7,6 +7,7 @@ import Link from 'next/link';
7
7
  import { useEffect, useRef, useState } from 'react';
8
8
  import { useShallow } from 'zustand/shallow';
9
9
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
10
+ import { setDisclaimerAccepted } from '../../utils/disclaimer-cooldown.js';
10
11
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
11
12
  import { CheckIcon } from '../../icons/CheckIcon.js';
12
13
  import pagcorLogo from '../../images/pagcor.png';
@@ -50,6 +51,7 @@ export function DisclaimerV1(props) {
50
51
  // Reset terms and responsible gaming acceptance states
51
52
  // so users must re-accept in SignIn forms
52
53
  globalStore.termsAndConditions.setAccepted(false);
54
+ setDisclaimerAccepted();
53
55
  disclaimer.close();
54
56
  }, disabled: !checked, "data-testid": "disclaimer-v1-accept-btn", children: "Accept" }), _jsx(Button, { variant: "outline", type: "button", className: "mt-lg", "data-testid": "disclaimer-v1-exit-btn", onClick: () => {
55
57
  if (Capacitor.isNativePlatform()) {
@@ -12,7 +12,8 @@ import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
12
12
  import { useSignOutMutation } from '../../client/hooks/useSignOutMutation.js';
13
13
  import { getSession } from '../../client/services/getSession.js';
14
14
  import { BIOMETRIC_STORAGE_KEY } from '../../client/utils/biometric.js';
15
- import { DISCLAIMER_ACCEPTED_KEY, TERMS_OF_USE_PENDING_STORAGE_KEY, } from '../../constants/index.js';
15
+ import { TERMS_OF_USE_PENDING_STORAGE_KEY } from '../../constants/index.js';
16
+ import { setDisclaimerAccepted } from '../../utils/disclaimer-cooldown.js';
16
17
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
17
18
  import { CheckIcon } from '../../icons/CheckIcon.js';
18
19
  import pagcorLogo from '../../images/pagcor2.png';
@@ -115,10 +116,10 @@ export function DisclaimerV2(props) {
115
116
  // so users must re-accept in SignIn forms
116
117
  globalStore.termsAndConditions.setAccepted(false);
117
118
  globalStore.responsibleGaming.setAccepted(false);
119
+ setDisclaimerAccepted();
118
120
  disclaimer.close();
119
121
  if (isAuthenticated) {
120
122
  sessionStorage.setItem(TERMS_OF_USE_PENDING_STORAGE_KEY, 'true');
121
- sessionStorage.setItem(DISCLAIMER_ACCEPTED_KEY, 'true');
122
123
  globalStore.termsOfUse.setOpen(true);
123
124
  return;
124
125
  }
@@ -9,7 +9,7 @@ import { useShallow } from 'zustand/shallow';
9
9
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
10
10
  import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
11
11
  import { useSignOutMutation } from '../../client/hooks/useSignOutMutation.js';
12
- import { DISCLAIMER_ACCEPTED_KEY, TERMS_OF_USE_PENDING_STORAGE_KEY, } from '../../constants/index.js';
12
+ import { TERMS_OF_USE_PENDING_STORAGE_KEY, } from '../../constants/index.js';
13
13
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
14
14
  import { CheckIcon } from '../../icons/CheckIcon.js';
15
15
  import pagcorLogo from '../../images/pagcor2.png';
@@ -18,6 +18,7 @@ import { Button } from '../../ui/Button/index.js';
18
18
  import { Checkbox } from '../../ui/Checkbox/index.js';
19
19
  import { Dialog } from '../../ui/Dialog/index.js';
20
20
  import { Portal } from '../../ui/Portal/index.js';
21
+ import { setDisclaimerAccepted } from '../../utils/disclaimer-cooldown.js';
21
22
  import { useDisclaimer } from './useDisclaimer.js';
22
23
  export function DisclaimerV3(props) {
23
24
  const disclaimer = useDisclaimer({
@@ -83,10 +84,10 @@ export function DisclaimerV3(props) {
83
84
  // so users must re-accept in SignIn forms
84
85
  globalStore.termsAndConditions.setAccepted(false);
85
86
  globalStore.responsibleGaming.setAccepted(false);
87
+ setDisclaimerAccepted();
86
88
  disclaimer.close();
87
89
  if (isAuthenticated) {
88
90
  sessionStorage.setItem(TERMS_OF_USE_PENDING_STORAGE_KEY, 'true');
89
- sessionStorage.setItem(DISCLAIMER_ACCEPTED_KEY, 'true');
90
91
  globalStore.termsOfUse.setOpen(true);
91
92
  return;
92
93
  }
@@ -3,34 +3,41 @@ import { useTimeout } from 'usehooks-ts';
3
3
  import { useShallow } from 'zustand/shallow';
4
4
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
5
5
  import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
6
- import { DISCLAIMER_ACCEPTED_KEY } from '../../constants/index.js';
6
+ import { isDisclaimerCooldownActive } from '../../utils/disclaimer-cooldown.js';
7
7
  export function useDisclaimer({ showInLogin = false, } = {}) {
8
8
  'use no memo';
9
9
  const sessionQuery = useSessionQuery();
10
10
  const searchParams = useSearchParams();
11
11
  const pathname = usePathname();
12
- const disclaimerStore = useGlobalStore(useShallow((state) => state.disclaimer));
12
+ const store = useGlobalStore(useShallow((state) => ({
13
+ disclaimer: state.disclaimer,
14
+ termsOfUse: state.termsOfUse,
15
+ })));
13
16
  // Check if we're on an SSO route (like /login/[partnerId])
14
17
  const isSsoRoute = pathname?.startsWith('/login/') && pathname.includes('/');
15
18
  const shouldShowDisclaimer = searchParams.get('game-exit') !== 'true' && !isSsoRoute;
16
19
  const isAuthenticated = sessionQuery.data?.status === 'authenticated';
20
+ const isCooldownActive = isDisclaimerCooldownActive();
17
21
  // Auto-open logic
18
22
  useTimeout(() => {
19
- const isDisclaimerAccepted = sessionStorage.getItem(DISCLAIMER_ACCEPTED_KEY) === 'true';
20
- if (shouldShowDisclaimer &&
21
- (!isAuthenticated || showInLogin) &&
22
- !isDisclaimerAccepted) {
23
- disclaimerStore.setOpen(true);
23
+ if (!shouldShowDisclaimer || isCooldownActive) {
24
+ return;
25
+ }
26
+ if (!isAuthenticated) {
27
+ store.disclaimer.setOpen(true);
28
+ }
29
+ else if (showInLogin) {
30
+ store.termsOfUse.setOpen(true);
24
31
  }
25
32
  }, 0);
26
33
  return {
27
34
  open: sessionQuery.isLoading
28
35
  ? false
29
36
  : shouldShowDisclaimer &&
30
- (!isAuthenticated || // guest: always allowed
31
- (showInLogin && isAuthenticated)) && // logged-in: only if allowed
32
- disclaimerStore.open,
33
- setOpen: (v) => disclaimerStore.setOpen(v),
34
- close: () => disclaimerStore.setOpen(false),
37
+ !isAuthenticated &&
38
+ !isCooldownActive &&
39
+ store.disclaimer.open,
40
+ setOpen: (v) => store.disclaimer.setOpen(v),
41
+ close: () => store.disclaimer.setOpen(false),
35
42
  };
36
43
  }
@@ -169,7 +169,7 @@ export function PersonalInformation() {
169
169
  globalStore.kycAccountVerificationRequired.setOpen(false);
170
170
  globalStore.kycReminder.setOpen(true);
171
171
  if (globalStore.firstTimeSignUp) {
172
- globalStore.disclaimer.setOpen(true);
172
+ // globalStore.disclaimer.setOpen(true);
173
173
  globalStore.setFirstTimeSignUp(false);
174
174
  }
175
175
  toaster.success({
@@ -10,6 +10,7 @@ import secondStepBackground from '../../images/second-step-background.png';
10
10
  import thirdStepBackground from '../../images/third-step-background.png';
11
11
  import { Dialog } from '../../ui/Dialog/index.js';
12
12
  import { Portal } from '../../ui/Portal/index.js';
13
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
13
14
  const AnimatedHeader = ({ text }) => {
14
15
  if (text === '88PLAY') {
15
16
  return (_jsx("div", { className: "relative", children: _jsxs("h1", { className: "venus-rising flex items-center font-bold text-4xl drop-shadow-lg", children: [_jsx("span", { className: "text-transparent", style: {
@@ -120,7 +121,7 @@ export function Onboarding() {
120
121
  globalStore.signUp.setOpen(true);
121
122
  }
122
123
  if (globalStore.onboarding.next === 'DISCLAIMER') {
123
- globalStore.disclaimer.setOpen(true);
124
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
124
125
  }
125
126
  globalStore.onboarding.setNext(null);
126
127
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsx(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: _jsx(OnboardingCarousel, {}) }) })] }) }));
@@ -13,6 +13,7 @@ import { createSingleUseToken } from '../../services/auth.js';
13
13
  import { Button } from '../../ui/Button/index.js';
14
14
  import { Dialog } from '../../ui/Dialog/index.js';
15
15
  import { Portal } from '../../ui/Portal/index.js';
16
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
16
17
  import { getQueryClient } from '../../utils/getQueryClient.js';
17
18
  import { getSessionQueryKey } from '../../utils/queryKeys.js';
18
19
  export function RegisterBiometrics() {
@@ -91,7 +92,7 @@ export function RegisterBiometrics() {
91
92
  description: 'Biometric setup successful',
92
93
  });
93
94
  registerBiometricStore.setOpen(false);
94
- kycModals.disclaimer.setOpen(true);
95
+ openDisclaimerIfAllowed(kycModals.disclaimer.setOpen);
95
96
  }, className: "text-sm", children: "Sure" }), _jsx(Button, { className: "border-border-dark text-sm text-text-primary-900", variant: "outline", onClick: () => {
96
97
  registerBiometricStore.setOpen(false);
97
98
  }, children: "Not now" })] })] }) }) }) }));
@@ -8,6 +8,7 @@ import responsibleGamingLogo from '../../images/responsible-gaming.png';
8
8
  import { Button } from '../../ui/Button/index.js';
9
9
  import { Dialog } from '../../ui/Dialog/index.js';
10
10
  import { Portal } from '../../ui/Portal/index.js';
11
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
11
12
  export function ResponsibleGaming(props) {
12
13
  const globalStore = useGlobalStore(useShallow((ctx) => ({
13
14
  signIn: ctx.signIn,
@@ -30,7 +31,7 @@ export function ResponsibleGaming(props) {
30
31
  globalStore.signUp.setOpen(true);
31
32
  }
32
33
  if (globalStore.responsibleGaming.next === 'DISCLAIMER') {
33
- globalStore.disclaimer.setOpen(true);
34
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
34
35
  }
35
36
  globalStore.responsibleGaming.setNext(null);
36
37
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto p-3xl lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: props.logo, alt: "", width: 200, height: 100, className: "mx-auto h-auto w-[7.5rem]", draggable: false }), _jsxs("div", { className: "w-full grow", children: [_jsx(Dialog.Title, { className: "mt-3xl text-center font-semibold text-brand-400 text-lg", children: "Responsible Gaming" }), _jsx(Dialog.Description, { className: "mt-xs text-sm leading-2xl", children: props.content }), _jsxs("div", { className: "mt-5 flex items-center justify-center gap-3xl", children: [_jsx(Image, { src: pagcorLogo, alt: "", height: 75, width: 88, className: "h-[5.5rem] w-auto shrink-0", draggable: false }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "", height: 62, width: 186, className: "h-[3.875rem] w-auto shrink-0", draggable: false })] })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: "mt-3 py-2.5", onClick: () => {
@@ -9,6 +9,7 @@ import { ScrollToTopIcon } from '../../icons/ScrollToTopIcon.js';
9
9
  import { Button } from '../../ui/Button/index.js';
10
10
  import { Dialog } from '../../ui/Dialog/index.js';
11
11
  import { Portal } from '../../ui/Portal/index.js';
12
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
12
13
  export function ResponsibleGamingV2(props) {
13
14
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
14
15
  const [isAtBottom, setIsAtBottom] = useState(false);
@@ -51,7 +52,7 @@ export function ResponsibleGamingV2(props) {
51
52
  globalStore.signUp.setOpen(true);
52
53
  }
53
54
  if (globalStore.responsibleGaming.next === 'DISCLAIMER') {
54
- globalStore.disclaimer.setOpen(true);
55
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
55
56
  }
56
57
  globalStore.responsibleGaming.setNext(null);
57
58
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: props.logo, alt: "", width: 250, height: 150, className: "mx-auto h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Responsible Gaming Guidelines" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContentRef, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -10,6 +10,7 @@ import decorativebackground from '../../images/decorative-patern.png';
10
10
  import { Button } from '../../ui/Button/index.js';
11
11
  import { Dialog } from '../../ui/Dialog/index.js';
12
12
  import { Portal } from '../../ui/Portal/index.js';
13
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
13
14
  export function ResponsibleGamingV3(props) {
14
15
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
15
16
  const [isAtBottom, setIsAtBottom] = useState(false);
@@ -52,7 +53,7 @@ export function ResponsibleGamingV3(props) {
52
53
  globalStore.signUp.setOpen(true);
53
54
  }
54
55
  if (globalStore.responsibleGaming.next === 'DISCLAIMER') {
55
- globalStore.disclaimer.setOpen(true);
56
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
56
57
  }
57
58
  globalStore.responsibleGaming.setNext(null);
58
59
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: decorativebackground, alt: "", width: 200, height: 200, className: "absolute top-0 left-0" }), _jsx(Image, { src: props.logo, alt: "", width: 250, height: 150, className: "h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Responsible Gaming Guidelines" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContent, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -85,7 +85,7 @@ export function MobileNumberSignIn() {
85
85
  globalStore.responsibleGamingReminder.setOpen(true);
86
86
  }
87
87
  if (signInProps.shouldShowDisclaimer) {
88
- globalStore.disclaimer.setOpen(true);
88
+ globalStore.termsOfUse.setOpen(true);
89
89
  }
90
90
  if (Capacitor.isNativePlatform()) {
91
91
  if (!hasSavedBiometry()) {
@@ -115,7 +115,7 @@ export function MobileNumberSignIn() {
115
115
  console.warn('Failed to updated biometric credentials');
116
116
  globalStore.signIn.setOpen(!globalStore.signIn.open);
117
117
  }
118
- globalStore.disclaimer.setOpen(true);
118
+ globalStore.termsOfUse.setOpen(true);
119
119
  }
120
120
  else {
121
121
  console.error('Failed to create token');
@@ -78,6 +78,7 @@ export function MobileNumberSignInInternational() {
78
78
  kyc: ctx.kyc,
79
79
  registerBiometrics: ctx.registerBiometrics,
80
80
  disclaimer: ctx.disclaimer,
81
+ termsOfUse: ctx.termsOfUse,
81
82
  })));
82
83
  const signInMutation = useSignInMutation({
83
84
  // versionSession intentionally omitted: only applies to NAME_AND_PASSWORD
@@ -112,7 +113,7 @@ export function MobileNumberSignInInternational() {
112
113
  globalStore.responsibleGamingReminder.setOpen(true);
113
114
  }
114
115
  if (signInProps.shouldShowDisclaimer) {
115
- globalStore.disclaimer.setOpen(true);
116
+ globalStore.termsOfUse.setOpen(true);
116
117
  }
117
118
  if (Capacitor.isNativePlatform()) {
118
119
  if (!hasSavedBiometry()) {
@@ -111,7 +111,7 @@ export function NameAndPasswordSignIn() {
111
111
  else {
112
112
  console.warn('Failed to update biometric credentials');
113
113
  }
114
- globalStore.disclaimer.setOpen(true);
114
+ globalStore.termsOfUse.setOpen(true);
115
115
  }
116
116
  else {
117
117
  console.error('Failed to create token');
@@ -128,7 +128,7 @@ export function NameAndPasswordSignIn() {
128
128
  globalStore.responsibleGamingReminder.setOpen(true);
129
129
  }
130
130
  if (signInProps.shouldShowDisclaimer) {
131
- globalStore.disclaimer.setOpen(true);
131
+ globalStore.termsOfUse.setOpen(true);
132
132
  }
133
133
  }
134
134
  },
@@ -174,7 +174,7 @@ export function NameAndPasswordSignIn() {
174
174
  globalStore.responsibleGamingReminder.setOpen(true);
175
175
  }
176
176
  if (signInProps.shouldShowDisclaimer) {
177
- globalStore.disclaimer.setOpen(true);
177
+ globalStore.termsOfUse.setOpen(true);
178
178
  }
179
179
  if (Capacitor.isNativePlatform()) {
180
180
  if (!hasSavedBiometry()) {
@@ -205,7 +205,7 @@ export function NameAndPasswordSignIn() {
205
205
  else {
206
206
  console.warn('Failed to update biometric credentials');
207
207
  }
208
- globalStore.disclaimer.setOpen(true);
208
+ globalStore.termsOfUse.setOpen(true);
209
209
  }
210
210
  else {
211
211
  // globalStore.signIn.setOpen(!globalStore.signIn.open);
@@ -18,6 +18,7 @@ export function SignInTrigger(props) {
18
18
  signIn: ctx.signIn,
19
19
  registerBiometrics: ctx.registerBiometrics,
20
20
  disclaimer: ctx.disclaimer,
21
+ termsOfUse: ctx.termsOfUse,
21
22
  })));
22
23
  return (_jsx(ark.button, { type: "button", "aria-label": "Sign in", "data-state": globalStore.signIn.open ? 'open' : 'closed', ...props, onClick: async (e) => {
23
24
  if (hasSavedBiometry()) {
@@ -87,7 +88,7 @@ export function SignInTrigger(props) {
87
88
  queryKey: getSessionQueryKey(),
88
89
  });
89
90
  if (Capacitor.isNativePlatform()) {
90
- globalStore.disclaimer.setOpen(true);
91
+ globalStore.termsOfUse.setOpen(true);
91
92
  }
92
93
  const r = await createSingleUseToken({
93
94
  headers: {
@@ -35,6 +35,7 @@ import { Field } from '../../../ui/Field/index.js';
35
35
  import { PinInput } from '../../../ui/PinInput/index.js';
36
36
  import { Select } from '../../../ui/Select/index.js';
37
37
  import { createPoll } from '../../../utils/createPoll.js';
38
+ import { openDisclaimerIfAllowed } from '../../../utils/disclaimer-cooldown.js';
38
39
  import { getQueryClient } from '../../../utils/getQueryClient.js';
39
40
  import { getMemberVerificationQueryKey } from '../../../utils/queryKeys.js';
40
41
  import DateOfBirthField from '../../DateOfBirthField.js';
@@ -196,7 +197,7 @@ export default function SignUpLongForm() {
196
197
  step1Form.reset();
197
198
  step2Form.reset();
198
199
  setStep(1);
199
- globalStore.disclaimer.setOpen(true);
200
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
200
201
  toaster.success({
201
202
  title: 'Member Created!',
202
203
  description: 'Member created successfully',
@@ -8,6 +8,7 @@ import responsibleGamingLogo from '../../images/responsible-gaming.png';
8
8
  import { Button } from '../../ui/Button/index.js';
9
9
  import { Dialog } from '../../ui/Dialog/index.js';
10
10
  import { Portal } from '../../ui/Portal/index.js';
11
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
11
12
  export function TermsAndConditions({ logo, siteName, content, ...props }) {
12
13
  const globalStore = useGlobalStore(useShallow((ctx) => ({
13
14
  signIn: ctx.signIn,
@@ -30,7 +31,7 @@ export function TermsAndConditions({ logo, siteName, content, ...props }) {
30
31
  globalStore.signUp.setOpen(true);
31
32
  }
32
33
  if (globalStore.termsAndConditions.next === 'DISCLAIMER') {
33
- globalStore.disclaimer.setOpen(true);
34
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
34
35
  }
35
36
  globalStore.termsAndConditions.setNext(null);
36
37
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto p-3xl lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: logo, alt: "", width: 200, height: 100, className: "mx-auto h-auto w-[120px]", draggable: false }), _jsxs("div", { className: "w-full grow", children: [_jsxs(Dialog.Title, { className: "mt-3xl text-center font-semibold text-brand-400 text-lg", children: [siteName, " Terms of Use"] }), _jsx(Dialog.Description, { className: "mt-xs text-sm leading-2xl", children: content }), _jsxs("div", { className: "mt-5 flex items-center justify-center gap-3xl", children: [_jsx(Image, { src: pagcorLogo, alt: "", height: 75, width: 88, className: "h-[5.5rem] w-auto shrink-0", draggable: false }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "", height: 62, width: 186, className: "h-[3.875rem] w-auto shrink-0", draggable: false })] })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: "mt-3 py-2.5", onClick: () => {
@@ -9,6 +9,7 @@ import responsibleGamingLogo from '../../images/responsible-gaming.png';
9
9
  import { Button } from '../../ui/Button/index.js';
10
10
  import { Dialog } from '../../ui/Dialog/index.js';
11
11
  import { Portal } from '../../ui/Portal/index.js';
12
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
12
13
  export function TermsOfUse({ logo, siteName, content, ...props }) {
13
14
  const globalStore = useGlobalStore(useShallow((ctx) => ({
14
15
  signIn: ctx.signIn,
@@ -32,7 +33,7 @@ export function TermsOfUse({ logo, siteName, content, ...props }) {
32
33
  globalStore.signUp.setOpen(true);
33
34
  }
34
35
  if (globalStore.termsOfUse.next === 'DISCLAIMER') {
35
- globalStore.disclaimer.setOpen(true);
36
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
36
37
  }
37
38
  globalStore.termsOfUse.setNext(null);
38
39
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto p-3xl lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: logo, alt: "", width: 200, height: 100, className: "mx-auto h-auto w-[120px]", draggable: false }), _jsxs("div", { className: "w-full grow", children: [_jsxs(Dialog.Title, { className: "mt-3xl text-center font-semibold text-brand-400 text-lg", children: [siteName, " Terms of Use"] }), _jsx(Dialog.Description, { className: "mt-xs text-sm leading-2xl", children: content }), _jsxs("div", { className: "mt-5 flex items-center justify-center gap-3xl", children: [_jsx(Image, { src: pagcorLogo, alt: "", height: 75, width: 88, className: "h-[5.5rem] w-auto shrink-0", draggable: false }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "", height: 62, width: 186, className: "h-[3.875rem] w-auto shrink-0", draggable: false })] })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: "mt-3 py-2.5", onClick: () => {
@@ -10,6 +10,7 @@ import { ScrollToTopIcon } from '../../icons/ScrollToTopIcon.js';
10
10
  import { Button } from '../../ui/Button/index.js';
11
11
  import { Dialog } from '../../ui/Dialog/index.js';
12
12
  import { Portal } from '../../ui/Portal/index.js';
13
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
13
14
  export function TermsOfUseV2({ logo, content }) {
14
15
  const scrollableContentRef = useRef(null);
15
16
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
@@ -54,7 +55,7 @@ export function TermsOfUseV2({ logo, content }) {
54
55
  globalStore.signUp.setOpen(true);
55
56
  }
56
57
  if (globalStore.termsOfUse.next === 'DISCLAIMER') {
57
- globalStore.disclaimer.setOpen(true);
58
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
58
59
  }
59
60
  globalStore.termsOfUse.setNext(null);
60
61
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "!z-[calc(var(--z-dialog)+1)]" }), _jsx(Dialog.Positioner, { className: "!z-[calc(var(--z-dialog)+3)]", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden bg-bg-primary p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: logo, alt: "", width: 250, height: 150, className: "mx-auto h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Terms of Use" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContentRef, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -11,6 +11,7 @@ import decorativebackground from '../../images/decorative-patern.png';
11
11
  import { Button } from '../../ui/Button/index.js';
12
12
  import { Dialog } from '../../ui/Dialog/index.js';
13
13
  import { Portal } from '../../ui/Portal/index.js';
14
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
14
15
  export function TermsOfUseV3({ logo, content }) {
15
16
  const scrollableContentRef = useRef(null);
16
17
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
@@ -54,7 +55,7 @@ export function TermsOfUseV3({ logo, content }) {
54
55
  globalStore.signUp.setOpen(true);
55
56
  }
56
57
  if (globalStore.termsOfUse.next === 'DISCLAIMER') {
57
- globalStore.disclaimer.setOpen(true);
58
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
58
59
  }
59
60
  globalStore.termsOfUse.setNext(null);
60
61
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden bg-bg-primary p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: decorativebackground, alt: "", width: 200, height: 200, className: "absolute top-safe-area-inset-top left-0" }), _jsx(Image, { src: logo, alt: "", width: 250, height: 150, className: "h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Terms of Use" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContentRef, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -0,0 +1,4 @@
1
+ /** Whether the disclaimer was accepted within the last 24 hours. */
2
+ export declare function isDisclaimerCooldownActive(): boolean;
3
+ export declare function setDisclaimerAccepted(): void;
4
+ export declare function openDisclaimerIfAllowed(setOpen: (open: boolean) => void): void;
@@ -0,0 +1,32 @@
1
+ import { DISCLAIMER_ACCEPTED_KEY } from '../constants/index.js';
2
+ const DISCLAIMER_COOLDOWN_MS = 24 * 60 * 60 * 1000;
3
+ function getDisclaimerAcceptedAt() {
4
+ if (typeof window === 'undefined') {
5
+ return null;
6
+ }
7
+ const raw = localStorage.getItem(DISCLAIMER_ACCEPTED_KEY);
8
+ if (!raw) {
9
+ return null;
10
+ }
11
+ if (raw === 'true') {
12
+ return Date.now();
13
+ }
14
+ const acceptedAt = Number(raw);
15
+ return Number.isFinite(acceptedAt) ? acceptedAt : null;
16
+ }
17
+ /** Whether the disclaimer was accepted within the last 24 hours. */
18
+ export function isDisclaimerCooldownActive() {
19
+ const acceptedAt = getDisclaimerAcceptedAt();
20
+ if (acceptedAt === null) {
21
+ return false;
22
+ }
23
+ return Date.now() - acceptedAt < DISCLAIMER_COOLDOWN_MS;
24
+ }
25
+ export function setDisclaimerAccepted() {
26
+ localStorage.setItem(DISCLAIMER_ACCEPTED_KEY, String(Date.now()));
27
+ }
28
+ export function openDisclaimerIfAllowed(setOpen) {
29
+ if (!isDisclaimerCooldownActive()) {
30
+ setOpen(true);
31
+ }
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opexa/portal-components",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "exports": {
5
5
  "./ui/*": {
6
6
  "types": "./dist/ui/*/index.d.ts",