@opexa/portal-components 0.0.1114 → 0.0.1116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DigitainLauncher/DigitainContainer.d.ts +0 -4
- package/dist/components/DigitainLauncher/DigitainContainer.js +45 -100
- package/dist/components/DigitainLauncher/DigitainLauncher.js +2 -2
- package/dist/components/DigitainLauncher/DigitainLoadingPanel.d.ts +0 -1
- package/dist/components/DigitainLauncher/DigitainLoadingPanel.js +3 -4
- package/dist/components/DigitainLauncher/DigitainLoadingView.d.ts +0 -3
- package/dist/components/DigitainLauncher/DigitainLoadingView.js +1 -4
- package/dist/components/DigitainLauncher/Fallback.js +8 -8
- package/dist/components/Games/GamesList.client.js +1 -1
- package/package.json +1 -1
|
@@ -4,8 +4,4 @@ export interface DigitainContainerProps {
|
|
|
4
4
|
params: DigitainBootstrapperParams;
|
|
5
5
|
fallbackBackgroundImage?: ImageProps['src'] | null;
|
|
6
6
|
}
|
|
7
|
-
/**
|
|
8
|
-
* Assumes `bootstrapper.min.js` is already included by `DigitainLauncher` (any auth state).
|
|
9
|
-
* Watches for `window.Bootstrapper`, then boots. MutationObserver + rAF backstops onLoad timing.
|
|
10
|
-
*/
|
|
11
7
|
export declare function DigitainContainer(props: DigitainContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,116 +1,61 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import isMobile from 'is-mobile';
|
|
4
4
|
import { useRouter } from 'next/navigation';
|
|
5
|
-
import {
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
|
+
import { twJoin } from 'tailwind-merge';
|
|
6
7
|
import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
|
|
7
8
|
import { toaster } from '../../client/utils/toaster.js';
|
|
8
9
|
import { DigitainLoadingView } from './DigitainLoadingView.js';
|
|
9
|
-
const SCRIPT_FAIL_TIMEOUT_MS = 20_000;
|
|
10
|
-
/**
|
|
11
|
-
* Assumes `bootstrapper.min.js` is already included by `DigitainLauncher` (any auth state).
|
|
12
|
-
* Watches for `window.Bootstrapper`, then boots. MutationObserver + rAF backstops onLoad timing.
|
|
13
|
-
*/
|
|
14
10
|
export function DigitainContainer(props) {
|
|
15
11
|
const session = useSessionQuery();
|
|
16
|
-
const
|
|
17
|
-
const paramsRef = useRef(props.params);
|
|
18
|
-
paramsRef.current = props.params;
|
|
19
|
-
const bootedRef = useRef(false);
|
|
20
|
-
const waitingForScriptRef = useRef(true);
|
|
21
|
-
const hasRefreshedRef = useRef(false);
|
|
22
|
-
const failTimeoutRef = useRef(undefined);
|
|
23
|
-
const [isBooting, setIsBooting] = useState(true);
|
|
12
|
+
const [isLoading, setLoading] = useState(false);
|
|
24
13
|
const [progress, setProgress] = useState(0);
|
|
25
14
|
const [stepIndex, setStepIndex] = useState(0);
|
|
26
|
-
const
|
|
27
|
-
if (bootedRef.current)
|
|
28
|
-
return;
|
|
29
|
-
bootedRef.current = true;
|
|
30
|
-
waitingForScriptRef.current = false;
|
|
31
|
-
setIsBooting(false);
|
|
32
|
-
toaster.error({ title: 'Error', description });
|
|
33
|
-
}, []);
|
|
34
|
-
const runBoot = useCallback(() => {
|
|
35
|
-
if (bootedRef.current)
|
|
36
|
-
return true;
|
|
37
|
-
const B = window.Bootstrapper;
|
|
38
|
-
if (!B)
|
|
39
|
-
return false;
|
|
40
|
-
bootedRef.current = true;
|
|
41
|
-
waitingForScriptRef.current = false;
|
|
42
|
-
setStepIndex(1);
|
|
43
|
-
setProgress(88);
|
|
44
|
-
void B.boot(paramsRef.current, {
|
|
45
|
-
name: isMobile() ? 'Mobile' : 'AsianView',
|
|
46
|
-
})
|
|
47
|
-
.catch(() => {
|
|
48
|
-
/* partner lib may reject; still transition UI */
|
|
49
|
-
})
|
|
50
|
-
.finally(() => {
|
|
51
|
-
setStepIndex(2);
|
|
52
|
-
setProgress(100);
|
|
53
|
-
});
|
|
54
|
-
window.setTimeout(() => setIsBooting(false), 1000);
|
|
55
|
-
return true;
|
|
56
|
-
}, []);
|
|
15
|
+
const router = useRouter();
|
|
57
16
|
useEffect(() => {
|
|
58
|
-
if (session.data?.status === 'authenticated'
|
|
59
|
-
hasRefreshedRef.current = true;
|
|
17
|
+
if (session.data?.status === 'authenticated') {
|
|
60
18
|
router.refresh();
|
|
61
19
|
}
|
|
62
20
|
}, [session.data?.status, router]);
|
|
63
|
-
// Smooth 0% → 45% only while the script is still missing (max ~8s of ramp for UX)
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
const t0 = performance.now();
|
|
66
|
-
let raf;
|
|
67
|
-
const tick = () => {
|
|
68
|
-
if (!waitingForScriptRef.current)
|
|
69
|
-
return;
|
|
70
|
-
const elapsed = performance.now() - t0;
|
|
71
|
-
const cap = 45;
|
|
72
|
-
setProgress((prev) => Math.max(prev, Math.min(cap, (elapsed / 8000) * cap)));
|
|
73
|
-
raf = requestAnimationFrame(tick);
|
|
74
|
-
};
|
|
75
|
-
raf = requestAnimationFrame(tick);
|
|
76
|
-
return () => cancelAnimationFrame(raf);
|
|
77
|
-
}, []);
|
|
78
|
-
// Throttled MutationObserver: re-check for `window.Bootstrapper` on DOM changes (e.g. script tag injection order).
|
|
79
21
|
useEffect(() => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
22
|
+
setLoading(true);
|
|
23
|
+
setProgress(10);
|
|
24
|
+
setStepIndex(0);
|
|
25
|
+
let attempts = 0;
|
|
26
|
+
const maxAttempts = 5;
|
|
27
|
+
function checkAndBoot() {
|
|
28
|
+
if (typeof window !== 'undefined' && window.Bootstrapper) {
|
|
29
|
+
console.log('Bootstrapper found, booting with params:', props.params);
|
|
30
|
+
setStepIndex(1);
|
|
31
|
+
setProgress(88);
|
|
32
|
+
window.Bootstrapper.boot(props.params, {
|
|
33
|
+
name: isMobile() ? 'Mobile' : 'AsianView',
|
|
34
|
+
}).then(() => {
|
|
35
|
+
console.log('Sportsbook booted!');
|
|
36
|
+
});
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
setStepIndex(2);
|
|
39
|
+
setProgress(100);
|
|
40
|
+
setLoading(false);
|
|
41
|
+
}, 1000);
|
|
42
|
+
clearInterval(intervalId);
|
|
43
|
+
}
|
|
44
|
+
else if (++attempts >= maxAttempts) {
|
|
45
|
+
setLoading(false);
|
|
46
|
+
toaster.error({
|
|
47
|
+
title: 'Error',
|
|
48
|
+
description: 'Sportsbook failed to load. Please try again later.',
|
|
49
|
+
});
|
|
50
|
+
console.warn('Bootstrapper did not load in time.');
|
|
51
|
+
clearInterval(intervalId);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
setProgress(Math.min(45, 10 + attempts * 8));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const intervalId = setInterval(checkAndBoot, 500);
|
|
58
|
+
return () => clearInterval(intervalId);
|
|
59
|
+
}, [props.params]);
|
|
60
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: twJoin(!isLoading && 'hidden'), children: _jsx(DigitainLoadingView, { fallbackBackgroundImage: props.fallbackBackgroundImage, loadingProgress: progress, loadingActiveStepIndex: stepIndex }) }), _jsx("div", { id: "digitain-container", className: twJoin(isLoading && 'hidden') })] }));
|
|
116
61
|
}
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import Script from 'next/script';
|
|
3
3
|
import { getSession } from '../../server/services/getSession.js';
|
|
4
4
|
import { Protected } from '../Protected/index.js';
|
|
5
|
-
import { DigitainAuthWall } from './DigitainAuthWall.js';
|
|
6
5
|
import { DigitainContainer } from './DigitainContainer.js';
|
|
6
|
+
import { Fallback } from './Fallback.js';
|
|
7
7
|
import { defaultDigitainParams, getDigitainLaunchToken } from './utils.js';
|
|
8
8
|
export async function DigitainLauncher(props) {
|
|
9
9
|
const session = await getSession();
|
|
@@ -15,5 +15,5 @@ export async function DigitainLauncher(props) {
|
|
|
15
15
|
params.server = props.hostname;
|
|
16
16
|
}
|
|
17
17
|
const finalizedParams = { ...params };
|
|
18
|
-
return (_jsxs(_Fragment, { children: [_jsx(Script, {
|
|
18
|
+
return (_jsxs(_Fragment, { children: [_jsx(Script, { src: `//${props.hostname}/js/partner/bootstrapper.min.js` }), _jsx(Protected, { fallback: _jsx(Fallback, { type: "fallback", signInUrl: props.signInUrl, fallbackBackgroundImage: props.fallbackBackgroundImage }), children: _jsx(DigitainContainer, { params: finalizedParams, fallbackBackgroundImage: props.fallbackBackgroundImage }) })] }));
|
|
19
19
|
}
|
|
@@ -2,5 +2,4 @@ export interface DigitainLoadingPanelProps {
|
|
|
2
2
|
progress: number;
|
|
3
3
|
activeStepIndex: number;
|
|
4
4
|
}
|
|
5
|
-
/** Centered copy + progress only—no card shell; meant to sit on a dark overlay. */
|
|
6
5
|
export declare function DigitainLoadingPanel({ progress, activeStepIndex, }: DigitainLoadingPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -7,13 +7,12 @@ const STEPS = [
|
|
|
7
7
|
'Setting up your session',
|
|
8
8
|
'Launching Sportsbook',
|
|
9
9
|
];
|
|
10
|
-
/** Centered copy + progress only—no card shell; meant to sit on a dark overlay. */
|
|
11
10
|
export function DigitainLoadingPanel({ progress, activeStepIndex, }) {
|
|
12
11
|
const clamped = Math.min(100, Math.max(0, progress));
|
|
13
12
|
const current = Math.min(STEPS.length - 1, Math.max(0, activeStepIndex));
|
|
14
|
-
return (_jsxs("div", { className: "w-full max-w-[22rem]
|
|
13
|
+
return (_jsxs("div", { className: "mx-auto w-full max-w-[22rem] space-y-8 text-center", role: "status", "aria-live": "polite", "aria-busy": "true", "aria-label": "Loading sportsbook", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "font-semibold text-lg text-white drop-shadow-sm sm:text-xl", children: "Sportsbook" }), _jsx("p", { className: "text-sm text-white/80", children: "Please wait while we load the sportsbook." })] }), _jsx("ol", { className: "list-none space-y-2 pl-0 text-left text-sm sm:text-base", children: STEPS.map((label, i) => {
|
|
15
14
|
const isCurrent = i === current;
|
|
16
15
|
const isDone = i < current;
|
|
17
|
-
return (_jsxs("li", { className: twMerge(isCurrent && 'font-medium text-button-tertiary-fg', !isCurrent && isDone && 'text-white/90', !isCurrent && !isDone && 'text-white/45'), children: [_jsxs("span", { className: "tabular-nums", children: [i + 1, "."] }), " ", label, isCurrent && (_jsx("span", { className: "text-button-tertiary-fg", children: "
|
|
18
|
-
}) }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-white/70 text-xs sm:text-sm", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { className: "font-medium tabular-nums
|
|
16
|
+
return (_jsxs("li", { className: twMerge(isCurrent && 'font-medium text-button-tertiary-fg', !isCurrent && isDone && 'text-white/90', !isCurrent && !isDone && 'text-white/45'), children: [_jsxs("span", { className: "tabular-nums", children: [i + 1, "."] }), " ", label, isCurrent && (_jsx("span", { className: "text-button-tertiary-fg", children: " - in progress" }))] }, label));
|
|
17
|
+
}) }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-white/70 text-xs sm:text-sm", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { className: "font-medium text-white tabular-nums", children: [Math.round(clamped), "%"] })] }), _jsx(Progress.Root, { min: 0, max: 100, value: clamped, variant: "solid", className: "w-full", "aria-label": "Loading progress", children: _jsx(Progress.Track, { className: "!rounded-full h-2 bg-white/20", children: _jsx(Progress.Range, { className: "!bg-button-tertiary-fg" }) }) })] })] }));
|
|
19
18
|
}
|
|
@@ -4,7 +4,4 @@ export interface DigitainLoadingViewProps {
|
|
|
4
4
|
loadingProgress: number;
|
|
5
5
|
loadingActiveStepIndex: number;
|
|
6
6
|
}
|
|
7
|
-
/**
|
|
8
|
-
* Dimmed full-area overlay (below the app header) with optional hero image behind it.
|
|
9
|
-
*/
|
|
10
7
|
export declare function DigitainLoadingView(props: DigitainLoadingViewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import Image from 'next/image';
|
|
4
4
|
import { DigitainLoadingPanel } from './DigitainLoadingPanel.js';
|
|
5
|
-
/**
|
|
6
|
-
* Dimmed full-area overlay (below the app header) with optional hero image behind it.
|
|
7
|
-
*/
|
|
8
5
|
export function DigitainLoadingView(props) {
|
|
9
|
-
return (_jsxs("div", { className: "
|
|
6
|
+
return (_jsxs("div", { className: "min-h-[calc(100dvh-4rem)] w-full", children: [props.fallbackBackgroundImage ? (_jsx("div", { className: "relative min-h-[calc(100dvh-4rem)] w-full overflow-hidden rounded-xl", children: _jsx(Image, { src: props.fallbackBackgroundImage, alt: "", fill: true, className: "object-cover", sizes: "100vw" }) })) : null, _jsx("div", { className: "fixed inset-x-0 top-16 bottom-0 z-[1000] flex min-h-0 items-center justify-center overflow-y-auto overscroll-contain bg-black/65 px-4 py-6 backdrop-blur-md sm:px-10 sm:py-10", children: _jsx("div", { className: "my-auto w-full max-w-[22rem] py-2 pb-[max(1.5rem,env(safe-area-inset-bottom))]", children: _jsx(DigitainLoadingPanel, { progress: props.loadingProgress, activeStepIndex: props.loadingActiveStepIndex }) }) })] }));
|
|
10
7
|
}
|
|
@@ -8,12 +8,12 @@ export function Fallback({ type, signInUrl, fallbackBackgroundImage, }) {
|
|
|
8
8
|
const globalStore = useGlobalStore(useShallow((ctx) => ({
|
|
9
9
|
signIn: ctx.signIn,
|
|
10
10
|
})));
|
|
11
|
-
return (_jsxs("div", { className: "relative h-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
return (_jsxs("div", { className: "relative min-h-[calc(100dvh-4rem)] w-full", children: [fallbackBackgroundImage && (_jsx(Image, { src: fallbackBackgroundImage, alt: "Background", fill: true, className: "rounded-xl object-cover" })), _jsx("div", { className: "absolute right-0 bottom-safe-area-inset-bottom left-0 h-1/2 rounded-xl bg-gradient-to-b from-[#00000000] to-bg-primary-alt" }), _jsx("div", { className: "absolute right-0 bottom-5 left-0 z-10 m-auto flex max-w-[42.5rem] flex-col items-center justify-center px-4 lg:bottom-15", children: type === 'loading' ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "mb-4 h-10 w-10 animate-spin rounded-full border-4 border-bg-tertiary border-t-button-tertiary-fg" }), _jsx("p", { className: "font-medium text-gray-700 text-lg", children: "Please wait while we load the Sports Book..." })] })) : (_jsxs("div", { className: "text-center", children: [_jsxs("div", { className: "mb-8 space-y-3", children: [_jsx("h2", { className: "font-bold text-gray-900 text-xl uppercase lg:text-[40px]", children: "Sports Book Login Required" }), _jsx("p", { className: "text-gray-600 text-xs leading-relaxed lg:text-lg", children: "The Sports Book is our online platform where you can explore real-time betting odds, place bets on a wide range of sports, and track your activity." }), _jsx("p", { className: "text-gray-600 text-xs leading-relaxed lg:text-lg", children: "Access is restricted to authenticated users. Please login to continue and unlock full access to the platform." })] }), _jsx(Button, { className: "mx-auto w-fit", onClick: () => {
|
|
12
|
+
if (signInUrl) {
|
|
13
|
+
window.location.href = signInUrl;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
globalStore.signIn.setOpen(true);
|
|
17
|
+
}
|
|
18
|
+
}, children: "Login" })] })) })] }));
|
|
19
19
|
}
|
|
@@ -69,5 +69,5 @@ export function GamesList__client(props) {
|
|
|
69
69
|
} }) }, game.id));
|
|
70
70
|
}) }), _jsx("div", { className: "mt-2xl flex flex-col items-center lg:mt-3xl", children: pagination === 'paginated' && sortedRows.length > 0 ? (_jsx(GamesPagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (page) => {
|
|
71
71
|
setCurrentPage(page);
|
|
72
|
-
} })) : (_jsxs(_Fragment, { children: [_jsx(Progress.Root, { min: 0, max:
|
|
72
|
+
} })) : (_jsxs(_Fragment, { children: [_jsx(Progress.Root, { min: 0, max: totalRows || sortedRows.length, value: sortedRows.length, onValueChange: noop, className: twMerge('w-[12.5rem]', classNames.progressRoot), children: _jsx(Progress.Track, { className: twMerge('bg-bg-tertiary', classNames.progressTrack), children: _jsx(Progress.Range, {}) }) }), _jsx("p", { className: "mt-md text-button-tertiary-fg text-sm", children: `Displaying ${sortedRows.length} of ${totalRows || sortedRows.length}` }), hasNextPage && (_jsx(Button, { size: "sm", variant: "outline", fullWidth: false, onClick: next, className: twMerge('mt-lg', classNames.loadMoreButton), children: "Load More" }))] })) })] }))] }) }));
|
|
73
73
|
}
|