├── .gitattributes
├── src
├── react-app-env.d.ts
├── store
│ ├── constant.ts
│ ├── reducers
│ │ ├── persistReducer.tsx
│ │ ├── index.ts
│ │ ├── menu.ts
│ │ ├── sports.ts
│ │ ├── snackbar.ts
│ │ └── auth.ts
│ └── index.ts
├── assets
│ ├── images
│ │ ├── games
│ │ │ ├── boom.png
│ │ │ ├── fire.png
│ │ │ ├── limbo1.png
│ │ │ ├── limbo2.png
│ │ │ ├── rocket.png
│ │ │ ├── darkPanel.png
│ │ │ ├── mountain.png
│ │ │ ├── chip.svg
│ │ │ └── back.svg
│ │ ├── icons
│ │ │ ├── SOL.png
│ │ │ ├── phantom-logo.png
│ │ │ ├── coinbase.svg
│ │ │ └── wallet.svg
│ │ ├── logo
│ │ │ ├── logo.png
│ │ │ └── 200xlogo.png
│ │ ├── payments
│ │ │ ├── 1.png
│ │ │ └── 2.png
│ │ ├── sports
│ │ │ └── trophy.png
│ │ ├── users
│ │ │ └── avatar.png
│ │ ├── landing
│ │ │ ├── header-bg.jpg
│ │ │ └── img-contact-mail.svg
│ │ └── maintenance
│ │ │ ├── img-error-text.svg
│ │ │ ├── img-error-purple.svg
│ │ │ ├── img-error-bg.svg
│ │ │ └── img-error-bg-dark.svg
│ ├── fonts
│ │ ├── Unlock-Regular.ttf
│ │ ├── fa-solid-900.woff2
│ │ ├── sportsicons.woff2
│ │ ├── Silkscreen-Bold.ttf
│ │ ├── Silkscreen-Regular.ttf
│ │ └── OFL.txt
│ └── scss
│ │ ├── fontawesome.scss
│ │ ├── sportsicon.scss
│ │ └── _themes-vars.module.scss
├── types
│ ├── menu.ts
│ ├── overrides
│ │ ├── Alert.d.ts
│ │ ├── createTheme.d.ts
│ │ ├── createPalette.d.ts
│ │ └── createTypography.d.ts
│ ├── snackbar.ts
│ ├── config.ts
│ ├── payment.ts
│ ├── index.ts
│ ├── auth.ts
│ ├── sports.ts
│ └── default-theme.ts
├── hooks
│ ├── useConfig.ts
│ ├── useApi.ts
│ ├── useScriptRef.ts
│ └── useLocalStorage.ts
├── navigation
│ ├── index.tsx
│ ├── pages.tsx
│ └── main.tsx
├── ui-component
│ ├── Logo.tsx
│ ├── Loader.tsx
│ ├── Loadable.tsx
│ ├── Locales.tsx
│ ├── extended
│ │ ├── Avatar.tsx
│ │ ├── AnimateButton.tsx
│ │ ├── Transitions.tsx
│ │ └── Snackbar.tsx
│ └── cards
│ │ ├── SubCard.tsx
│ │ └── MainCard.tsx
├── views
│ ├── mybets
│ │ └── history
│ │ │ └── index.tsx
│ ├── casino
│ │ └── Blackjack
│ │ │ ├── Card.tsx
│ │ │ ├── Deal.tsx
│ │ │ └── Model.tsx
│ ├── auth
│ │ ├── Login.tsx
│ │ ├── ResetPassword.tsx
│ │ ├── ForgotPassword.tsx
│ │ ├── auth-forms
│ │ │ └── AuthLogin.tsx
│ │ └── Register.tsx
│ ├── sports
│ │ └── component
│ │ │ ├── OddNum.tsx
│ │ │ └── Betslip
│ │ │ └── index.tsx
│ ├── profile
│ │ └── Wallet
│ │ │ ├── index.tsx
│ │ │ └── DepositCoinpayment.tsx
│ └── pages
│ │ └── Error.tsx
├── layout
│ ├── CasinoLayout
│ │ └── index.tsx
│ ├── MainLayout
│ │ ├── LogoSection
│ │ │ └── index.tsx
│ │ ├── Sidebar
│ │ │ └── MenuList
│ │ │ │ ├── index.tsx
│ │ │ │ └── NavGroup
│ │ │ │ └── index.tsx
│ │ ├── Advertisement
│ │ │ └── index.tsx
│ │ ├── Header
│ │ │ ├── BetslipSection
│ │ │ │ └── index.tsx
│ │ │ └── SearchSection
│ │ │ │ └── index.tsx
│ │ ├── MobileMenu
│ │ │ └── index.tsx
│ │ └── index.tsx
│ ├── NavigationScroll.tsx
│ ├── AuthLayout
│ │ └── index.tsx
│ ├── UserLayout
│ │ ├── index.tsx
│ │ └── NavItem.tsx
│ ├── MinimalLayout
│ │ └── index.tsx
│ ├── MyBetsLayout
│ │ └── index.tsx
│ └── Footer.tsx
├── utils
│ ├── getlibrary.ts
│ ├── snackbar.ts
│ ├── AuthGuard.tsx
│ ├── number.tsx
│ ├── games.ts
│ ├── Icons.tsx
│ ├── password-strength.ts
│ ├── axios.ts
│ └── connectors.ts
├── reportWebVitals.ts
├── routes
│ ├── index.tsx
│ ├── AuthenticationRoutes.tsx
│ ├── MyBetsRoutes.tsx
│ ├── ProfileRoutes.tsx
│ ├── MainRoutes.tsx
│ └── CasinoRoutes.tsx
├── config.ts
├── themes
│ ├── shadows.tsx
│ ├── index.tsx
│ ├── typography.tsx
│ └── palette.tsx
├── contexts
│ └── ConfigContext.tsx
├── index.tsx
└── serviceWorker.tsx
├── public
├── logo.png
├── favicon.ico
└── index.html
├── .prettierrc
├── .eslintrc.js
├── tsconfig.json
├── config-overrides.js
└── .gitignore
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | declare module 'oddslib';
3 |
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/public/logo.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/store/constant.ts:
--------------------------------------------------------------------------------
1 | export const gridSpacing = 3;
2 | export const drawerWidth = 280;
3 | export const appDrawerWidth = 320;
4 |
--------------------------------------------------------------------------------
/src/assets/images/games/boom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/games/boom.png
--------------------------------------------------------------------------------
/src/assets/images/games/fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/games/fire.png
--------------------------------------------------------------------------------
/src/assets/images/icons/SOL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/icons/SOL.png
--------------------------------------------------------------------------------
/src/assets/images/logo/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/logo/logo.png
--------------------------------------------------------------------------------
/src/assets/images/payments/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/payments/1.png
--------------------------------------------------------------------------------
/src/assets/images/payments/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/payments/2.png
--------------------------------------------------------------------------------
/src/types/menu.ts:
--------------------------------------------------------------------------------
1 | export type MenuProps = {
2 | selectedItem: string[];
3 | drawerOpen: boolean;
4 | page: string;
5 | };
6 |
--------------------------------------------------------------------------------
/src/assets/fonts/Unlock-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/fonts/Unlock-Regular.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/fonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/sportsicons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/fonts/sportsicons.woff2
--------------------------------------------------------------------------------
/src/assets/images/games/limbo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/games/limbo1.png
--------------------------------------------------------------------------------
/src/assets/images/games/limbo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/games/limbo2.png
--------------------------------------------------------------------------------
/src/assets/images/games/rocket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/games/rocket.png
--------------------------------------------------------------------------------
/src/assets/images/logo/200xlogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/logo/200xlogo.png
--------------------------------------------------------------------------------
/src/assets/images/sports/trophy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/sports/trophy.png
--------------------------------------------------------------------------------
/src/assets/images/users/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/users/avatar.png
--------------------------------------------------------------------------------
/src/assets/fonts/Silkscreen-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/fonts/Silkscreen-Bold.ttf
--------------------------------------------------------------------------------
/src/assets/images/games/darkPanel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/games/darkPanel.png
--------------------------------------------------------------------------------
/src/assets/images/games/mountain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/games/mountain.png
--------------------------------------------------------------------------------
/src/assets/fonts/Silkscreen-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/fonts/Silkscreen-Regular.ttf
--------------------------------------------------------------------------------
/src/assets/images/icons/phantom-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/icons/phantom-logo.png
--------------------------------------------------------------------------------
/src/assets/images/landing/header-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fairrustana/Sports-Betting-Sportsbook/HEAD/src/assets/images/landing/header-bg.jpg
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "bracketSpacing": true,
3 | "printWidth": 140,
4 | "singleQuote": true,
5 | "trailingComma": "none",
6 | "tabWidth": 4,
7 | "useTabs": false
8 | }
9 |
--------------------------------------------------------------------------------
/src/hooks/useConfig.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import { ConfigContext } from 'contexts/ConfigContext';
3 |
4 | const useConfig = () => useContext(ConfigContext);
5 |
6 | export default useConfig;
7 |
--------------------------------------------------------------------------------
/src/navigation/index.tsx:
--------------------------------------------------------------------------------
1 | import main from './main';
2 | import { NavItemType } from 'types';
3 |
4 | const menuItems: { items: NavItemType[] } = {
5 | items: [main]
6 | };
7 |
8 | export default menuItems;
9 |
--------------------------------------------------------------------------------
/src/types/overrides/Alert.d.ts:
--------------------------------------------------------------------------------
1 | import * as Alert from '@mui/material/Alert';
2 |
3 | declare module '@mui/material/Alert' {
4 | interface AlertPropsColorOverrides {
5 | primary;
6 | secondary;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ui-component/Logo.tsx:
--------------------------------------------------------------------------------
1 | import LogoImg from 'assets/images/logo/logo.png';
2 |
3 | const Logo = () =>
;
4 |
5 | export default Logo;
6 |
--------------------------------------------------------------------------------
/src/views/mybets/history/index.tsx:
--------------------------------------------------------------------------------
1 | import { Grid } from "@mui/material";
2 |
3 | const SportsBetsList = () => {
4 | return (
5 |
6 |
7 | );
8 | };
9 |
10 | export default SportsBetsList;
11 |
--------------------------------------------------------------------------------
/src/layout/CasinoLayout/index.tsx:
--------------------------------------------------------------------------------
1 | import { Outlet } from 'react-router-dom';
2 | import History from 'views/casino/History';
3 |
4 | const CasinoLayout = () => (
5 | <>
6 |
7 |
8 | >
9 | );
10 |
11 | export default CasinoLayout;
12 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/LogoSection/index.tsx:
--------------------------------------------------------------------------------
1 | import { HOME_PATH } from 'config';
2 | import Logo from 'ui-component/Logo';
3 |
4 | const LogoSection = () => (
5 |
6 |
7 |
8 | );
9 |
10 | export default LogoSection;
11 |
--------------------------------------------------------------------------------
/src/ui-component/Loader.tsx:
--------------------------------------------------------------------------------
1 | import LinearProgress from '@mui/material/LinearProgress';
2 | import { LoaderWrapper } from 'ui-component';
3 |
4 | const Loader = () => (
5 |
6 |
7 |
8 | );
9 |
10 | export default Loader;
11 |
--------------------------------------------------------------------------------
/src/utils/getlibrary.ts:
--------------------------------------------------------------------------------
1 | import { Web3Provider, JsonRpcFetchFunc } from '@ethersproject/providers';
2 |
3 | const getLibrary = (provider: JsonRpcFetchFunc) => {
4 | const library = new Web3Provider(provider, 'any');
5 | library.pollingInterval = 15000;
6 | return library;
7 | };
8 |
9 | export default getLibrary;
10 |
--------------------------------------------------------------------------------
/src/hooks/useApi.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import APIContext from 'contexts/ApiContext';
3 |
4 | const useApi = () => {
5 | const context = useContext(APIContext);
6 |
7 | if (!context) throw new Error('context must be use inside provider');
8 |
9 | return context;
10 | };
11 |
12 | export default useApi;
13 |
--------------------------------------------------------------------------------
/src/hooks/useScriptRef.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | const useScriptRef = () => {
4 | const scripted = useRef(true);
5 |
6 | useEffect(
7 | () => () => {
8 | scripted.current = false;
9 | },
10 | []
11 | );
12 |
13 | return scripted;
14 | };
15 |
16 | export default useScriptRef;
17 |
--------------------------------------------------------------------------------
/src/store/reducers/persistReducer.tsx:
--------------------------------------------------------------------------------
1 | import { persistReducer } from 'redux-persist';
2 | import storage from 'redux-persist/lib/storage';
3 |
4 | const persistConfig = {
5 | key: 'boi-book-v1',
6 | storage,
7 | whitelist: ['auth']
8 | };
9 |
10 | const persist = (reducers: any) => persistReducer(persistConfig, reducers);
11 |
12 | export default persist;
13 |
--------------------------------------------------------------------------------
/src/types/snackbar.ts:
--------------------------------------------------------------------------------
1 | import { AlertProps, SnackbarOrigin } from '@mui/material';
2 |
3 | export interface SnackbarProps {
4 | action: boolean;
5 | open: boolean;
6 | message: string;
7 | anchorOrigin: SnackbarOrigin;
8 | variant: string;
9 | alert: AlertProps;
10 | transition: string;
11 | close: boolean;
12 | actionButton: boolean;
13 | }
14 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | node: true,
4 | es6: true,
5 | browser: true
6 | },
7 | parserOptions: {
8 | ecmaVersion: 6,
9 | sourceType: 'module',
10 | ecmaFeatures: {
11 | jsx: true,
12 | modules: true,
13 | experimentalObjectRestSpread: true
14 | }
15 | },
16 | rules: {
17 | }
18 | }
--------------------------------------------------------------------------------
/src/store/reducers/index.ts:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 |
3 | import authReducer from './auth';
4 | import menuReducer from './menu';
5 | import sportsReducer from './sports';
6 | import snackbarReducer from './snackbar';
7 |
8 | const reducer = combineReducers({
9 | auth: authReducer,
10 | menu: menuReducer,
11 | sports: sportsReducer,
12 | snackbar: snackbarReducer
13 | });
14 |
15 | export default reducer;
16 |
--------------------------------------------------------------------------------
/src/utils/snackbar.ts:
--------------------------------------------------------------------------------
1 | import { store } from 'store';
2 | import { openSnackbar } from 'store/reducers/snackbar';
3 |
4 | const snackbar = (message: any, color: string = 'success') => {
5 | store.dispatch(
6 | openSnackbar({
7 | open: true,
8 | message,
9 | variant: 'alert',
10 | transition: 'SlideLeft',
11 | alert: { color },
12 | anchorOrigin: { vertical: 'top', horizontal: 'right' }
13 | })
14 | );
15 | };
16 |
17 | export default snackbar;
18 |
--------------------------------------------------------------------------------
/src/layout/NavigationScroll.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, ReactElement } from 'react';
2 | import { useLocation } from 'react-router-dom';
3 |
4 | const NavigationScroll = ({ children }: { children: ReactElement | null }) => {
5 | const { pathname } = useLocation();
6 |
7 | useEffect(() => {
8 | window.scrollTo({
9 | top: 0,
10 | left: 0,
11 | behavior: 'smooth'
12 | });
13 | }, [pathname]);
14 |
15 | return children || null;
16 | };
17 |
18 | export default NavigationScroll;
19 |
--------------------------------------------------------------------------------
/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | };
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/src/ui-component/Loadable.tsx:
--------------------------------------------------------------------------------
1 | import { Suspense, LazyExoticComponent, ComponentType } from 'react';
2 |
3 | import { LinearProgressProps } from '@mui/material';
4 |
5 | import Loader from './Loader';
6 |
7 | interface LoaderProps extends LinearProgressProps {}
8 |
9 | const Loadable = (Component: LazyExoticComponent<() => JSX.Element> | ComponentType | any) => (props: LoaderProps) =>
10 | (
11 | }>
12 |
13 |
14 | );
15 |
16 | export default Loadable;
17 |
--------------------------------------------------------------------------------
/src/utils/AuthGuard.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { useNavigate } from 'react-router-dom';
3 | import { GuardProps } from 'types';
4 | import { HOME_PATH } from 'config';
5 | import { useSelector } from 'store';
6 |
7 | const AuthGuard = ({ children }: GuardProps) => {
8 | const navigate = useNavigate();
9 | const { isLoggedIn } = useSelector((state) => state.auth);
10 |
11 | useEffect(() => {
12 | if (!isLoggedIn) {
13 | navigate(HOME_PATH, { replace: true });
14 | }
15 | }, [isLoggedIn, navigate]);
16 |
17 | return children;
18 | };
19 |
20 | export default AuthGuard;
21 |
--------------------------------------------------------------------------------
/src/routes/index.tsx:
--------------------------------------------------------------------------------
1 | import { useRoutes } from 'react-router-dom';
2 |
3 | import MainRoutes from './MainRoutes';
4 | import MyBetsRoutes from './MyBetsRoutes';
5 | // import CasinoRoutes from './CasinoRoutes';
6 | import ProfileRoutes from './ProfileRoutes';
7 | import AuthenticationRoutes from './AuthenticationRoutes';
8 | import Error from 'views/pages/Error';
9 |
10 | export default function ThemeRoutes() {
11 | return useRoutes([
12 | MainRoutes,
13 | // CasinoRoutes,
14 | ProfileRoutes,
15 | MyBetsRoutes,
16 | AuthenticationRoutes,
17 | { path: '*', element: }
18 | ]);
19 | }
20 |
--------------------------------------------------------------------------------
/src/types/overrides/createTheme.d.ts:
--------------------------------------------------------------------------------
1 | import * as createTheme from '@mui/material/styles';
2 | import { customShadows } from 'themes/shadows';
3 |
4 | declare module '@mui/material/styles' {
5 | export interface ThemeOptions {
6 | customShadows?: customShadows;
7 | customization?: TypographyOptions | ((palette: Palette) => TypographyOptions);
8 | darkTextSecondary?: string;
9 | textDark?: string;
10 | darkTextPrimary?: string;
11 | grey500?: string;
12 | }
13 | interface Theme {
14 | customShadows: customShadows;
15 | customization: Typography;
16 | darkTextSecondary: string;
17 | textDark: string;
18 | grey500: string;
19 | darkTextPrimary: string;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/utils/number.tsx:
--------------------------------------------------------------------------------
1 | import NumberFormat from 'react-number-format';
2 |
3 | export const toNumber = (number: number | undefined, fixed = 5, status = false) => {
4 | if (!number || isNaN(number)) {
5 | if (status) {
6 | return Number(0).toFixed(fixed);
7 | }
8 | return '0.00';
9 | }
10 | if (status) {
11 | return Number(number).toFixed(fixed).toLocaleString();
12 | }
13 | return Number(Number(number).toFixed(fixed)).toLocaleString();
14 | };
15 |
16 | export const toNumberTag = (number = 0, fixed = 5) => {
17 | if (!number || isNaN(number)) {
18 | return '0.00';
19 | }
20 | return ;
21 | };
22 |
--------------------------------------------------------------------------------
/src/layout/AuthLayout/index.tsx:
--------------------------------------------------------------------------------
1 | import { useSelector } from 'store';
2 |
3 | import Login from 'views/auth/Login';
4 | import Register from 'views/auth/Register';
5 | import Forgot from 'views/auth/ForgotPassword';
6 | import ResetPassword from 'views/auth/ResetPassword';
7 | import Bets from 'views/mybets/bets';
8 |
9 | const AuthLayout = () => {
10 | const { page } = useSelector((state) => state.menu);
11 | return (
12 | <>
13 | {page === 'login' && }
14 | {page === 'register' && }
15 | {page === 'forgot' && }
16 | {page === 'reset-password' && }
17 | {page === 'bets' && }
18 | >
19 | );
20 | };
21 |
22 | export default AuthLayout;
23 |
--------------------------------------------------------------------------------
/src/assets/images/icons/coinbase.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/store/reducers/menu.ts:
--------------------------------------------------------------------------------
1 | import { MenuProps } from 'types/menu';
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const initialState: MenuProps = {
5 | selectedItem: ['dashboard'],
6 | drawerOpen: false,
7 | page: ''
8 | };
9 |
10 | const menu = createSlice({
11 | name: 'menu',
12 | initialState,
13 | reducers: {
14 | activeItem(state, action) {
15 | state.selectedItem = action.payload;
16 | },
17 |
18 | openDrawer(state, action) {
19 | state.drawerOpen = action.payload;
20 | },
21 |
22 | ChangePage(state, action: any) {
23 | state.page = action.payload;
24 | }
25 | }
26 | });
27 |
28 | export default menu.reducer;
29 |
30 | export const { activeItem, openDrawer, ChangePage } = menu.actions;
31 |
--------------------------------------------------------------------------------
/src/types/overrides/createPalette.d.ts:
--------------------------------------------------------------------------------
1 | import * as createPalette from '@mui/material/styles/createPalette';
2 |
3 | declare module '@mui/material/styles/createPalette' {
4 | interface PaletteColor {
5 | 100: string;
6 | 200: string;
7 | 300: string;
8 | 400: string;
9 | 500: string;
10 | 600: string;
11 | 700: string;
12 | 800: string;
13 | 900: string;
14 | }
15 |
16 | export interface TypeText {
17 | dark: string;
18 | hint: string;
19 | }
20 |
21 | interface PaletteOptions {
22 | orange?: PaletteColorOptions;
23 | dark?: PaletteColorOptions;
24 | icon?: IconPaletteColorOptions;
25 | }
26 | interface Palette {
27 | orange: PaletteColor;
28 | dark: PaletteColor;
29 | icon: IconPaletteColor;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/views/casino/Blackjack/Card.tsx:
--------------------------------------------------------------------------------
1 | import { CardProp } from './Model';
2 |
3 | class Card {
4 | card: CardProp;
5 |
6 | constructor(card: CardProp) {
7 | this.card = card;
8 | }
9 |
10 | getIndex() {
11 | return this.card.index;
12 | }
13 |
14 | getType() {
15 | return this.card.type;
16 | }
17 |
18 | getRank() {
19 | return this.card.rank;
20 | }
21 |
22 | getSuit() {
23 | return this.card.suit;
24 | }
25 |
26 | getValue() {
27 | switch (this.getRank()) {
28 | case 'A':
29 | return 11;
30 | case 'K':
31 | case 'Q':
32 | case 'J':
33 | return 10;
34 | default:
35 | return Math.floor(Number(this.getRank()));
36 | }
37 | }
38 | }
39 |
40 | export default Card;
41 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/Sidebar/MenuList/index.tsx:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 |
3 | import { Typography } from '@mui/material';
4 |
5 | import { FormattedMessage } from 'react-intl';
6 |
7 | import menuItem from 'navigation';
8 | import NavGroup from './NavGroup';
9 |
10 | const MenuList = () => {
11 | const navItems = menuItem.items.map((item) => {
12 | switch (item.type) {
13 | case 'group':
14 | return ;
15 | default:
16 | return (
17 |
18 |
19 |
20 | );
21 | }
22 | });
23 |
24 | return <>{navItems}>;
25 | };
26 |
27 | export default memo(MenuList);
28 |
--------------------------------------------------------------------------------
/src/views/auth/Login.tsx:
--------------------------------------------------------------------------------
1 | import Dialog from '@mui/material/Dialog';
2 | import DialogContent from '@mui/material/DialogContent';
3 |
4 | import { useDispatch } from 'store';
5 | import { ChangePage } from 'store/reducers/menu';
6 |
7 | import AuthMetamask from './auth-forms/AuthMetamask';
8 |
9 | const Login = () => {
10 | const dispatch = useDispatch();
11 |
12 | return (
13 |
24 | );
25 | };
26 |
27 | export default Login;
28 |
--------------------------------------------------------------------------------
/src/assets/images/games/chip.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "jsx": "react-jsx",
6 | "strict": true,
7 | "esModuleInterop": true,
8 | "skipLibCheck": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "lib": ["dom", "dom.iterable", "esnext"],
11 | "allowJs": true,
12 | "noUnusedLocals": false,
13 | "allowSyntheticDefaultImports": true,
14 | "noFallthroughCasesInSwitch": true,
15 | "moduleResolution": "node",
16 | "resolveJsonModule": true,
17 | "isolatedModules": true,
18 | "noEmit": true,
19 | "noImplicitAny": true,
20 | "noImplicitThis": true,
21 | "strictNullChecks": true,
22 | "types": ["node", "webpack-env"],
23 | "typeRoots": ["./types"],
24 | "baseUrl": "src"
25 | },
26 | "include": ["src"]
27 | }
28 |
--------------------------------------------------------------------------------
/src/routes/AuthenticationRoutes.tsx:
--------------------------------------------------------------------------------
1 | import { lazy } from 'react';
2 |
3 | import Loadable from 'ui-component/Loadable';
4 | import MinimalLayout from 'layout/MinimalLayout';
5 |
6 | const PagesTerms = Loadable(lazy(() => import('views/pages/Terms')));
7 | const PagesContactUS = Loadable(lazy(() => import('views/pages/contact-us')));
8 | const PagesPrivacyPolicy = Loadable(lazy(() => import('views/pages/PrivacyPolicy')));
9 |
10 | const AuthenticationRoutes = {
11 | path: '/pages',
12 | element: ,
13 | children: [
14 | {
15 | path: '/pages/terms',
16 | element:
17 | },
18 | {
19 | path: '/pages/contact-us',
20 | element:
21 | },
22 | {
23 | path: '/pages/privacy-policy',
24 | element:
25 | }
26 | ]
27 | };
28 |
29 | export default AuthenticationRoutes;
30 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import { persistStore } from 'redux-persist';
2 | import { configureStore } from '@reduxjs/toolkit';
3 | import { useDispatch as useAppDispatch, useSelector as useAppSelector, TypedUseSelectorHook } from 'react-redux';
4 |
5 | import rootReducer from './reducers';
6 | import persistReducer from './reducers/persistReducer';
7 |
8 | const store = configureStore({
9 | reducer: persistReducer(rootReducer),
10 | middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false, immutableCheck: false })
11 | });
12 |
13 | const persister = persistStore(store);
14 |
15 | export type RootState = ReturnType;
16 |
17 | export type AppDispatch = typeof store.dispatch;
18 |
19 | const { dispatch } = store;
20 |
21 | const useDispatch = () => useAppDispatch();
22 | const useSelector: TypedUseSelectorHook = useAppSelector;
23 |
24 | export { store, persister, dispatch, useSelector, useDispatch };
25 |
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
1 | import { ConfigProps } from 'types/config';
2 |
3 | export const BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:2020';
4 | export const BASE_PATH = '';
5 | export const HOME_PATH = '/sports';
6 |
7 | const config: ConfigProps = {
8 | fontFamily: `'Roboto', sans-serif`,
9 | borderRadius: 8,
10 | boxShadow: 'rgba(0, 0, 0, 0.2) 0px 1px 3px 0px, rgba(0, 0, 0, 0.12) 0px 1px 2px 0px, rgba(255, 255, 255, 0.04) 0px 1px 0px 0px inset',
11 | outlinedFilled: true,
12 | navType: 'dark',
13 | presetColor: 'default',
14 | dark1: '#191919',
15 | dark2: '#272727',
16 | dark3: '#1c1c1c',
17 | grey2: '#8c8c8c',
18 | locale: 'en',
19 | rtlLayout: false,
20 | timer1: 5000,
21 | timer2: 900000,
22 | RECAPTCHA_SITE_KEY: '6LeRhsIeAAAAADY6KUkpQaIqPTKsXy2sa7u4JBAb',
23 | adminSolanaWallet: '8Myhky6nWVJFeNkcBH3FE9i29KqV4qsD8reook3AUqYk',
24 | adminMetamaskWallet: '0x9FbCF8e7a61c734869FC3d00e17c4c616EDBbd98'
25 | };
26 |
27 | export default config;
28 |
--------------------------------------------------------------------------------
/src/types/config.ts:
--------------------------------------------------------------------------------
1 | import { PaletteMode } from '@mui/material';
2 |
3 | export type ConfigProps = {
4 | fontFamily: string;
5 | borderRadius: number;
6 | outlinedFilled: boolean;
7 | navType: PaletteMode;
8 | presetColor: string;
9 | grey2: string;
10 | dark1: string;
11 | dark2: string;
12 | dark3: string;
13 | boxShadow: string;
14 | locale: string;
15 | rtlLayout: boolean;
16 | timer1: number;
17 | timer2: number;
18 | RECAPTCHA_SITE_KEY: string;
19 | adminSolanaWallet: string;
20 | adminMetamaskWallet: string;
21 | };
22 |
23 | export type CustomizationProps = {
24 | fontFamily: string;
25 | borderRadius: number;
26 | outlinedFilled: boolean;
27 | navType: PaletteMode;
28 | presetColor: string;
29 | boxShadow: string;
30 | locale: string;
31 | rtlLayout: boolean;
32 | onChangeLocale: (locale: string) => void;
33 | };
34 |
35 | export enum ModeTypes {
36 | pro = 'pro',
37 | _dev = '_dev',
38 | dev = 'dev'
39 | }
40 |
--------------------------------------------------------------------------------
/src/views/sports/component/OddNum.tsx:
--------------------------------------------------------------------------------
1 | import { Typography } from '@mui/material';
2 | import * as oddslib from 'oddslib';
3 | import { useSelector } from 'store';
4 |
5 | const OddNum = ({ odd, color }: { odd: number; color?: string }) => {
6 | const { user } = useSelector((state) => state.auth);
7 |
8 | const oddFormat = (params: number) => {
9 | if (user?.oddsformat === undefined || user?.oddsformat === 'decimal') {
10 | return Number(params).toFixed(2);
11 | }
12 | try {
13 | const number = oddslib.from('decimal', params).to(user.oddsformat);
14 | if (user.oddsformat === 'moneyline') {
15 | return Math.floor(number);
16 | }
17 | return Number(number).toFixed(2);
18 | } catch (error) {
19 | return 0;
20 | }
21 | };
22 |
23 | return (
24 |
25 | {oddFormat(odd)}
26 |
27 | );
28 | };
29 |
30 | export default OddNum;
31 |
--------------------------------------------------------------------------------
/src/routes/MyBetsRoutes.tsx:
--------------------------------------------------------------------------------
1 | import { lazy } from 'react';
2 | import MainLayout from 'layout/MainLayout';
3 | import MyBetsLayout from 'layout/MyBetsLayout';
4 | import Loadable from 'ui-component/Loadable';
5 | import AuthGuard from 'utils/AuthGuard';
6 |
7 | const MybetsActive = Loadable(lazy(() => import('views/mybets')));
8 | const MybetsSettled = Loadable(lazy(() => import('views/mybets/settled')));
9 | const MybetsHistory = Loadable(lazy(() => import('views/mybets/history/')));
10 |
11 | const ProfileRoutes = {
12 | path: '/my-bets',
13 | element: (
14 |
15 |
16 |
17 |
18 |
19 | ),
20 | children: [
21 | {
22 | path: '/my-bets',
23 | element:
24 | },
25 | {
26 | path: '/my-bets/settled',
27 | element:
28 | },
29 | {
30 | path: '/my-bets/history',
31 | element:
32 | }
33 | ]
34 | };
35 |
36 | export default ProfileRoutes;
37 |
--------------------------------------------------------------------------------
/src/assets/scss/fontawesome.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Font Awesome 5 Pro';
3 | font-style: normal;
4 | font-weight: 900;
5 | font-display: block;
6 | src: url(../fonts/fa-solid-900.woff2) format('woff2');
7 | }
8 |
9 | .fas {
10 | font-family: 'Font Awesome 5 Pro';
11 | font-weight: 900;
12 | -moz-osx-font-smoothing: grayscale;
13 | -webkit-font-smoothing: antialiased;
14 | display: inline-block;
15 | font-style: normal;
16 | font-variant: normal;
17 | text-rendering: auto;
18 | line-height: 1;
19 | }
20 |
21 | .fa-spade:before {
22 | content: '\f2f4';
23 | }
24 |
25 | .fa-heart:before {
26 | content: '\f004';
27 | }
28 |
29 | .fa-club:before {
30 | content: '\f327';
31 | }
32 |
33 | .fa-diamond:before {
34 | content: '\f219';
35 | }
36 |
37 | .fa-gem:before {
38 | content: '\f3a5';
39 | }
40 |
41 | .fa-square:before {
42 | content: '\f0c8';
43 | }
44 |
45 | .fa-coin:before {
46 | content: '\f85c';
47 | }
48 |
49 | .fa-bullseye:before {
50 | content: '\f140';
51 | }
52 |
53 | .fa-dice-d20:before {
54 | content: '\f6cf';
55 | }
56 |
57 | .fa-rocket:before {
58 | content: '\f135';
59 | }
60 |
--------------------------------------------------------------------------------
/src/hooks/useLocalStorage.ts:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from 'react';
2 |
3 | export default function useLocalStorage(key: string, defaultValue: ValueType) {
4 | const [value, setValue] = useState(() => {
5 | const storedValue = localStorage.getItem(key);
6 | return storedValue === null ? defaultValue : JSON.parse(storedValue);
7 | });
8 |
9 | useEffect(() => {
10 | const listener = (e: StorageEvent) => {
11 | if (e.storageArea === localStorage && e.key === key) {
12 | setValue(e.newValue ? JSON.parse(e.newValue) : e.newValue);
13 | }
14 | };
15 | window.addEventListener('storage', listener);
16 |
17 | return () => {
18 | window.removeEventListener('storage', listener);
19 | };
20 | }, [key, defaultValue]);
21 |
22 | const setValueInLocalStorage = (newValue: ValueType) => {
23 | setValue((currentValue: any) => {
24 | const result = typeof newValue === 'function' ? newValue(currentValue) : newValue;
25 | localStorage.setItem(key, JSON.stringify(result));
26 | return result;
27 | });
28 | };
29 |
30 | return [value, setValueInLocalStorage];
31 | }
32 |
--------------------------------------------------------------------------------
/src/types/payment.ts:
--------------------------------------------------------------------------------
1 | export interface CurrencyProps {
2 | _id: string;
3 | symbol: string;
4 | name?: string;
5 | betLimit?: number;
6 | maxBet?: number;
7 | minBet?: number;
8 | minDeposit?: number;
9 | minWithdraw?: number;
10 | icon?: string;
11 | status?: boolean;
12 | deposit?: boolean;
13 | withdrawal?: boolean;
14 | network?: string;
15 | tokenMintAccount?: string;
16 | }
17 |
18 | export interface BalanceProps {
19 | _id: string;
20 | balance: number;
21 | currency: CurrencyProps;
22 | disabled: boolean;
23 | status: boolean;
24 | userId: string;
25 | }
26 |
27 | export interface TransactionsProps {
28 | _id: string;
29 | amount: number;
30 | currencyId: CurrencyProps;
31 | ipn_type: string;
32 | status_text: string;
33 | status: number;
34 | createdAt: Date;
35 | updatedAt: Date;
36 | }
37 |
38 | export interface GameProps {
39 | icon: string;
40 | name: string;
41 | }
42 |
43 | export interface HistoryProps {
44 | _id: string;
45 | amount: number;
46 | currency: string;
47 | game: GameProps;
48 | profit: number;
49 | status: string;
50 | username: string;
51 | createdAt: Date;
52 | }
53 |
--------------------------------------------------------------------------------
/src/utils/games.ts:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 | import { toNumber } from './number';
3 |
4 | export const resultPopup = (game: any) => {
5 | const status = game.status.toLowerCase();
6 | const popup = $(`
11 | `);
12 | $('.game-content').append(popup);
13 | popup.hide().fadeIn('fast');
14 | setTimeout(() => {
15 | // eslint-disable-next-line
16 | popup.fadeOut('fast', function () {
17 | $(this).remove();
18 | });
19 | }, 2000);
20 | };
21 |
22 | export const Random = (min: number, max: number, floor = true) => {
23 | const r = Math.random() * max + min;
24 | return floor ? Math.floor(r) : r;
25 | };
26 |
27 | export const chain = (times: number, ms: number, cb: Function) => {
28 | let i = 0;
29 | const next = () => {
30 | if (i < times) {
31 | setTimeout(() => {
32 | cb(i);
33 | next();
34 | }, ms);
35 | i += 1;
36 | }
37 | };
38 | next();
39 | };
40 |
--------------------------------------------------------------------------------
/src/utils/Icons.tsx:
--------------------------------------------------------------------------------
1 | import { IconContext } from 'react-icons';
2 | import { IoIosFootball, IoIosBaseball } from 'react-icons/io';
3 | import { GiAmericanFootballBall, GiAmericanFootballHelmet, GiBasketballBall, GiDeathStar } from 'react-icons/gi';
4 | import { RiBoxingFill } from 'react-icons/ri';
5 |
6 | const UseIcons = (icon: string) => {
7 | if (icon) {
8 | return (
9 |
10 | {icon === 'football' ? : null}
11 | {icon === 'icehockey' ? : null}
12 | {icon === 'basketball' ? : null}
13 | {icon === 'americanfootball' ? : null}
14 | {icon === 'boxing' ? : null}
15 | {icon === 'baseball' ? : null}
16 |
17 | );
18 | }
19 | return (
20 |
21 |
22 |
23 |
24 |
25 | );
26 | };
27 |
28 | export default UseIcons;
29 |
--------------------------------------------------------------------------------
/src/routes/ProfileRoutes.tsx:
--------------------------------------------------------------------------------
1 | import { lazy } from 'react';
2 | import MainLayout from 'layout/MainLayout';
3 | import UserLayout from 'layout/UserLayout';
4 | import Loadable from 'ui-component/Loadable';
5 | import AuthGuard from 'utils/AuthGuard';
6 |
7 | const Wallet = Loadable(lazy(() => import('views/profile/Wallet')));
8 | const Account = Loadable(lazy(() => import('views/profile/Account')));
9 | const Referral = Loadable(lazy(() => import('views/profile/Referral')));
10 | const Preferences = Loadable(lazy(() => import('views/profile/Preferences')));
11 |
12 | const ProfileRoutes = {
13 | path: '/user',
14 | element: (
15 |
16 |
17 |
18 |
19 |
20 | ),
21 | children: [
22 | {
23 | path: '/user/wallet',
24 | element:
25 | },
26 | {
27 | path: '/user/account',
28 | element:
29 | },
30 | {
31 | path: '/user/referral',
32 | element:
33 | },
34 | {
35 | path: '/user/preferences',
36 | element:
37 | }
38 | ]
39 | };
40 |
41 | export default ProfileRoutes;
42 |
--------------------------------------------------------------------------------
/src/layout/UserLayout/index.tsx:
--------------------------------------------------------------------------------
1 | import { Outlet } from 'react-router-dom';
2 |
3 | import { CardContent, Grid, useTheme } from '@mui/material';
4 |
5 | import { gridSpacing } from 'store/constant';
6 | import MainCard from 'ui-component/cards/MainCard';
7 | import NavItem from './NavItem';
8 |
9 | const UserLayout = () => {
10 | const theme = useTheme();
11 |
12 | return (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
29 |
30 |
31 |
32 |
33 | );
34 | };
35 |
36 | export default UserLayout;
37 |
--------------------------------------------------------------------------------
/src/themes/shadows.tsx:
--------------------------------------------------------------------------------
1 | import { alpha, Theme } from '@mui/material';
2 |
3 | const createCustomShadow = (theme: Theme, color: string) => {
4 | const transparent = alpha(color, 0.24);
5 | return {
6 | z1: `0 1px 2px 0 ${transparent}`,
7 | z8: `0 8px 16px 0 ${transparent}`,
8 | z12: `0 12px 24px 0 ${transparent} 0 10px 20px 0 ${transparent}`,
9 | z16: `0 0 3px 0 ${transparent} 0 14px 28px -5px ${transparent}`,
10 | z20: `0 0 3px 0 ${transparent} 0 18px 36px -5px ${transparent}`,
11 | z24: `0 0 6px 0 ${transparent} 0 21px 44px 0 ${transparent}`,
12 |
13 | primary: `0px 12px 14px 0px ${alpha(theme.palette.primary.main, 0.3)}`,
14 | secondary: `0px 12px 14px 0px ${alpha(theme.palette.secondary.main, 0.3)}`,
15 | orange: `0px 12px 14px 0px ${alpha(theme.palette.orange.main, 0.3)}`,
16 | success: `0px 12px 14px 0px ${alpha(theme.palette.success.main, 0.3)}`,
17 | warning: `0px 12px 14px 0px ${alpha(theme.palette.warning.main, 0.3)}`,
18 | error: `0px 12px 14px 0px ${alpha(theme.palette.error.main, 0.3)}`
19 | };
20 | };
21 |
22 | export default function customShadows(navType: string, theme: Theme) {
23 | return navType === 'dark' ? createCustomShadow(theme, theme.palette.dark.main) : createCustomShadow(theme, theme.palette.grey[600]);
24 | }
25 |
--------------------------------------------------------------------------------
/src/utils/password-strength.ts:
--------------------------------------------------------------------------------
1 | import { NumbColorFunc, StringBoolFunc, StringNumFunc } from 'types';
2 | import value from 'assets/scss/_themes-vars.module.scss';
3 |
4 | const hasNumber: StringBoolFunc = (number) => new RegExp(/[0-9]/).test(number);
5 |
6 | const hasMixed: StringBoolFunc = (number) => new RegExp(/[a-z]/).test(number) && new RegExp(/[A-Z]/).test(number);
7 |
8 | const hasSpecial: StringBoolFunc = (number) => new RegExp(/[!#@$%^&*)(+=._-]/).test(number);
9 |
10 | export const strengthColor: NumbColorFunc = (count) => {
11 | if (count < 2) return { label: 'Poor', color: value.errorMain };
12 | if (count < 3) return { label: 'Weak', color: value.warningDark };
13 | if (count < 4) return { label: 'Normal', color: value.orangeMain };
14 | if (count < 5) return { label: 'Good', color: value.successMain };
15 | if (count < 6) return { label: 'Strong', color: value.successDark };
16 | return { label: 'Poor', color: value.errorMain };
17 | };
18 |
19 | export const strengthIndicator: StringNumFunc = (number) => {
20 | let strengths = 0;
21 | if (number.length > 5) strengths += 1;
22 | if (number.length > 7) strengths += 1;
23 | if (hasNumber(number)) strengths += 1;
24 | if (hasSpecial(number)) strengths += 1;
25 | if (hasMixed(number)) strengths += 1;
26 | return strengths;
27 | };
28 |
--------------------------------------------------------------------------------
/src/ui-component/Locales.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 |
3 | import { IntlProvider, MessageFormatElement } from 'react-intl';
4 | import useConfig from 'hooks/useConfig';
5 | import Axios from 'utils/axios';
6 | import Loader from './Loader';
7 |
8 | interface LocalsProps {
9 | children: React.ReactNode;
10 | }
11 |
12 | const Locales = ({ children }: LocalsProps) => {
13 | const { locale } = useConfig();
14 | const [loading, setLoading] = useState(true);
15 | const [messages, setMessages] = useState | Record | undefined>();
16 |
17 | useEffect(() => {
18 | setLoading(true);
19 | Axios.post('api/v1/languages/word/', { id: locale || 'es' })
20 | .then(({ data }) => {
21 | setMessages(data);
22 | setLoading(false);
23 | })
24 | .catch(() => {
25 | setLoading(false);
26 | });
27 | }, [locale]);
28 |
29 | if (loading) return ;
30 | return (
31 | <>
32 | {messages && (
33 | {}}>
34 | {children}
35 |
36 | )}
37 | >
38 | );
39 | };
40 |
41 | export default Locales;
42 |
--------------------------------------------------------------------------------
/src/utils/axios.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import { BASE_URL } from 'config';
3 | import { store } from 'store';
4 | import { Logout } from 'store/reducers/auth';
5 | import snackbar from './snackbar';
6 |
7 | const axiosServices = axios.create();
8 |
9 | axiosServices.interceptors.request.use(
10 | (config: any) => {
11 | config.baseURL = BASE_URL;
12 | const state = store.getState() as any;
13 | const accessToken = state.auth.token;
14 | if (accessToken) {
15 | config.headers.authorization = accessToken;
16 | }
17 | return config;
18 | },
19 | (error) => Promise.reject(error)
20 | );
21 |
22 | axiosServices.interceptors.response.use(
23 | (response) => response,
24 | (error) => {
25 | const { response } = error;
26 | if (response && response.status === 400) {
27 | snackbar(response.data, 'error');
28 | } else if (response && response.status === 401) {
29 | store.dispatch(Logout({}));
30 | } else if (response && response.status === 413) {
31 | snackbar(response.data, 'error');
32 | } else if (response && response.status === 429) {
33 | snackbar(response.data, 'error');
34 | } else {
35 | console.log(response);
36 | }
37 | return Promise.reject(error);
38 | }
39 | );
40 |
41 | export default axiosServices;
42 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/Sidebar/MenuList/NavGroup/index.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 |
3 | import { Typography } from '@mui/material';
4 |
5 | import { FormattedMessage } from 'react-intl';
6 |
7 | import { GenericCardProps } from 'types';
8 |
9 | import NavItem from '../NavItem';
10 | import NavCollapse from '../NavCollapse';
11 |
12 | export interface NavGroupProps {
13 | item: {
14 | id?: string;
15 | type?: string;
16 | icon?: GenericCardProps['iconPrimary'];
17 | children?: NavGroupProps['item'][];
18 | title?: ReactNode | string;
19 | caption?: ReactNode | string;
20 | color?: 'primary' | 'secondary' | 'default' | undefined;
21 | };
22 | }
23 |
24 | const NavGroup = ({ item }: NavGroupProps) => {
25 | const items = item.children?.map((menu) => {
26 | switch (menu.type) {
27 | case 'collapse':
28 | return ;
29 | case 'item':
30 | return ;
31 | default:
32 | return (
33 |
34 |
35 |
36 | );
37 | }
38 | });
39 |
40 | return <>{items}>;
41 | };
42 |
43 | export default NavGroup;
44 |
--------------------------------------------------------------------------------
/src/contexts/ConfigContext.tsx:
--------------------------------------------------------------------------------
1 | import { createContext, ReactNode } from 'react';
2 |
3 | import defaultConfig from 'config';
4 | import useLocalStorage from 'hooks/useLocalStorage';
5 |
6 | import { CustomizationProps } from 'types/config';
7 |
8 | const initialState: CustomizationProps = {
9 | ...defaultConfig,
10 | onChangeLocale: () => {}
11 | };
12 |
13 | const ConfigContext = createContext(initialState);
14 |
15 | type ConfigProviderProps = {
16 | children: ReactNode;
17 | };
18 |
19 | function ConfigProvider({ children }: ConfigProviderProps) {
20 | const [config, setConfig] = useLocalStorage('berry-config', {
21 | fontFamily: initialState.fontFamily,
22 | borderRadius: initialState.borderRadius,
23 | outlinedFilled: initialState.outlinedFilled,
24 | navType: initialState.navType,
25 | boxShadow: initialState.boxShadow,
26 | presetColor: initialState.presetColor,
27 | locale: initialState.locale,
28 | rtlLayout: initialState.rtlLayout
29 | });
30 |
31 | const onChangeLocale = (locale: string) => {
32 | setConfig({
33 | ...config,
34 | locale
35 | });
36 | };
37 |
38 | return (
39 |
45 | {children}
46 |
47 | );
48 | }
49 |
50 | export { ConfigProvider, ConfigContext };
51 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom';
2 | import { BrowserRouter } from 'react-router-dom';
3 | import { Provider } from 'react-redux';
4 | import { PersistGate } from 'redux-persist/integration/react';
5 |
6 | import { Web3ReactProvider } from '@web3-react/core';
7 | import * as serviceWorker from 'serviceWorker';
8 | import reportWebVitals from 'reportWebVitals';
9 |
10 | import App from 'App';
11 | import { BASE_PATH } from 'config';
12 | import { store, persister } from 'store';
13 | import getLibrary from 'utils/getlibrary';
14 | import { ConfigProvider } from 'contexts/ConfigContext';
15 |
16 | import 'assets/scss/style.scss';
17 |
18 | import 'moment/locale/ja';
19 | import 'moment/locale/es';
20 | import 'moment/locale/pt';
21 | import 'moment/locale/tr';
22 | import 'moment/locale/th';
23 | import 'moment/locale/de';
24 | import 'moment/locale/fr';
25 | import 'moment/locale/vi';
26 | import 'moment/locale/zh-cn';
27 |
28 | ReactDOM.render(
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | ,
40 | document.getElementById('root')
41 | );
42 |
43 | serviceWorker.unregister();
44 | reportWebVitals();
45 |
--------------------------------------------------------------------------------
/src/assets/images/icons/wallet.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/layout/MinimalLayout/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo } from 'react';
2 | import { Outlet } from 'react-router-dom';
3 | import { AppBar, Box, Container, Toolbar } from '@mui/material';
4 |
5 | import PerfectScrollbar from 'react-perfect-scrollbar';
6 |
7 | import useConfig from 'hooks/useConfig';
8 |
9 | import Footer from 'layout/Footer';
10 | import Header from 'layout/MainLayout/Header';
11 |
12 | import Auth from '../AuthLayout';
13 |
14 | const MinimalLayout = () => {
15 | const { navType } = useConfig();
16 |
17 | const header = useMemo(
18 | () => (
19 |
20 |
21 |
22 | ),
23 | []
24 | );
25 | return (
26 |
27 |
28 |
38 | {header}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | );
48 | };
49 |
50 | export default MinimalLayout;
51 |
--------------------------------------------------------------------------------
/src/routes/MainRoutes.tsx:
--------------------------------------------------------------------------------
1 | import { lazy } from 'react';
2 |
3 | import MainLayout from 'layout/MainLayout';
4 | import Loadable from 'ui-component/Loadable';
5 |
6 | const SportsPage = Loadable(lazy(() => import('views/sports')));
7 | const InplayPage = Loadable(lazy(() => import('views/sports/inplay')));
8 | const UpcomingPage = Loadable(lazy(() => import('views/sports/upcoming')));
9 | const EventsPage = Loadable(lazy(() => import('views/sports/events')));
10 |
11 | const MainRoutes = {
12 | path: '/',
13 | element: ,
14 | children: [
15 | {
16 | path: '/',
17 | element:
18 | },
19 | {
20 | path: '/sports',
21 | element:
22 | },
23 | {
24 | path: '/sports/:sportsId',
25 | element:
26 | },
27 | {
28 | path: '/sports/:sportsId/:tabId',
29 | element:
30 | },
31 | {
32 | path: '/inplay',
33 | element:
34 | },
35 | {
36 | path: '/inplay/:sportsId',
37 | element:
38 | },
39 | {
40 | path: '/upcoming',
41 | element:
42 | },
43 | {
44 | path: '/upcoming/:sportsId',
45 | element:
46 | },
47 | {
48 | path: '/events/:id',
49 | element:
50 | }
51 | ]
52 | };
53 |
54 | export default MainRoutes;
55 |
--------------------------------------------------------------------------------
/src/store/reducers/sports.ts:
--------------------------------------------------------------------------------
1 | import { createSlice } from '@reduxjs/toolkit';
2 | import { SportsProps } from 'types/sports';
3 |
4 | const initialState: SportsProps = {
5 | betslipData: [],
6 | liveMatches: [],
7 | recentBets: [],
8 | betAmount: 0,
9 | betslipOpen: false,
10 | search: ''
11 | };
12 |
13 | const sports = createSlice({
14 | name: 'sports',
15 | initialState,
16 | reducers: {
17 | setBetslip(state, action) {
18 | const innerWidth = window.innerWidth;
19 | if (innerWidth > 767 && action.payload.length > state.betslipData.length) {
20 | state.betslipOpen = true;
21 | }
22 | state.betslipData = [...action.payload];
23 | },
24 |
25 | clearAll(state) {
26 | state.betslipData = [];
27 | },
28 |
29 | setLiveMatches(state, action) {
30 | state.liveMatches = action.payload;
31 | },
32 |
33 | setRecentBets(state, action) {
34 | state.recentBets = action.payload;
35 | },
36 |
37 | setBetAmount(state, action) {
38 | state.betAmount = action.payload;
39 | },
40 |
41 | openBetslip(state, action) {
42 | state.betslipOpen = action.payload;
43 | },
44 |
45 | updateSearch(state, action) {
46 | state.search = action.payload;
47 | }
48 | }
49 | });
50 |
51 | export default sports.reducer;
52 |
53 | export const { setBetslip, setRecentBets, setLiveMatches, setBetAmount, clearAll, openBetslip, updateSearch } = sports.actions;
54 |
--------------------------------------------------------------------------------
/src/views/casino/Blackjack/Deal.tsx:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 | import { CardProp } from './Model';
3 |
4 | class Deal {
5 | vm: any;
6 |
7 | constructor(vm: any) {
8 | this.vm = vm;
9 | }
10 | // eslint-disable-next-line
11 | setCard(sender: any, card: CardProp) {
12 | sender.setHand(card);
13 | }
14 |
15 | dealCard(sender: any, card: CardProp, isHidden: boolean) {
16 | const elements = sender.getElements();
17 | const dealerHand = this.vm.dealer.getHand();
18 | const playerHand = this.vm.player.getHand();
19 | if (dealerHand.find((e: CardProp) => e.index === card.index) || playerHand.find((e: CardProp) => e.index === card.index)) return;
20 | this.vm.deal.setCard(sender, card);
21 | this.vm.renderCard(elements.ele, sender, false, isHidden, undefined);
22 | sender.getScore((score: string) => $(elements.score).html(score));
23 | if (playerHand.length < 3) {
24 | if (dealerHand.length > 0 && dealerHand[0].rank === 'A') {
25 | if ($('.insurance').length === 0 && !this.vm.isGameStarted()) {
26 | this.vm.setState({ insurance: true });
27 | }
28 | }
29 | this.vm.player.getScore((score: number) => {
30 | if (score === 21) {
31 | if (this.vm.blackjack) return;
32 | setTimeout(() => this.vm.player.stand(), 500);
33 | this.vm.blackjack = true;
34 | }
35 | });
36 | }
37 | }
38 | }
39 |
40 | export default Deal;
41 |
--------------------------------------------------------------------------------
/src/navigation/pages.tsx:
--------------------------------------------------------------------------------
1 | import { FormattedMessage } from 'react-intl';
2 |
3 | import { IconKey, IconReceipt2, IconBug, IconBellRinging, IconPhoneCall, IconQuestionMark, IconShieldLock } from '@tabler/icons';
4 |
5 | const icons = {
6 | IconKey,
7 | IconReceipt2,
8 | IconBug,
9 | IconBellRinging,
10 | IconPhoneCall,
11 | IconQuestionMark,
12 | IconShieldLock
13 | };
14 |
15 | const pages = {
16 | id: 'pages',
17 | title: 'pages',
18 | type: 'group',
19 | children: [
20 | {
21 | id: 'contact-us',
22 | title: ,
23 | type: 'item',
24 | icon: icons.IconPhoneCall,
25 | url: '/pages/contact-us',
26 | target: true
27 | },
28 | {
29 | id: 'terms',
30 | title: ,
31 | type: 'item',
32 | icon: icons.IconQuestionMark,
33 | url: '/pages/terms',
34 | target: true
35 | },
36 | {
37 | id: 'faqs',
38 | title: ,
39 | type: 'item',
40 | icon: icons.IconQuestionMark,
41 | url: '/pages/faqs',
42 | target: true
43 | },
44 | {
45 | id: 'privacy-policy',
46 | title: ,
47 | type: 'item',
48 | icon: icons.IconShieldLock,
49 | url: '/pages/privacy-policy',
50 | target: true
51 | }
52 | ]
53 | };
54 |
55 | export default pages;
56 |
--------------------------------------------------------------------------------
/src/types/overrides/createTypography.d.ts:
--------------------------------------------------------------------------------
1 | import * as createTypography from '@mui/material/styles/createTypography';
2 |
3 | declare module '@mui/material/styles/createTypography' {
4 | export interface FontStyle
5 | extends Required<{
6 | textTransform: TextTransform;
7 | fontSize: string | number;
8 | }> {}
9 | export interface FontStyleOptions extends Partial {
10 | fontSize?: string | number;
11 | }
12 | export type Variant =
13 | | 'customInput'
14 | | 'mainContent'
15 | | 'menuCaption'
16 | | 'subMenuCaption'
17 | | 'commonAvatar'
18 | | 'smallAvatar'
19 | | 'mediumAvatar'
20 | | 'largeAvatar';
21 |
22 | export interface TypographyOptions extends Partial & FontStyleOptions> {
23 | customInput?: TypographyStyleOptions;
24 | mainContent?: TypographyStyleOptions;
25 | menuCaption?: TypographyStyleOptions;
26 | subMenuCaption?: TypographyStyleOptions;
27 | commonAvatar?: TypographyStyleOptions;
28 | smallAvatar?: TypographyStyleOptions;
29 | mediumAvatar?: TypographyStyleOptions;
30 | largeAvatar?: TypographyStyleOptions;
31 | }
32 |
33 | export interface Typography extends Record, FontStyle, TypographyUtils {
34 | customInput: TypographyStyle;
35 | mainContent: TypographyStyle;
36 | menuCaption: TypographyStyleOptions;
37 | subMenuCaption: TypographyStyleOptions;
38 | commonAvatar: TypographyStyle;
39 | smallAvatar: TypographyStyle;
40 | mediumAvatar: TypographyStyle;
41 | largeAvatar: TypographyStyle;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/config-overrides.js:
--------------------------------------------------------------------------------
1 | /* config-overrides.js */
2 | const webpack = require('webpack');
3 | // const paths = require('react-scripts-ts/config/paths')
4 |
5 | module.exports = function override(config, env) {
6 | //do stuff with the webpack config...]
7 |
8 | config.module.rules.push({
9 | test: /\.tsx?$/,
10 | loader: 'ts-loader',
11 | exclude: /node_modules/,
12 | options: {
13 | transpileOnly: true,
14 | configFile: 'tsconfig.json',
15 | },
16 | })
17 |
18 | config.resolve.extensions = [
19 | '*', '.js', '.jsx', '.ts', '.tsx'
20 | ]
21 |
22 | // config.module.rules.push({
23 | // test: /\.(js|jsx)$/,
24 | // include: paths.appSrc,
25 | // loader: require.resolve('babel-loader'),
26 | // options: {
27 | // babelrc: false,
28 | // presets: [require.resolve('babel-preset-react-app')],
29 | // cacheDirectory: true,
30 | // },
31 | // })
32 |
33 | config.resolve.fallback = {
34 | url: require.resolve('url'),
35 | fs: require.resolve('fs'),
36 | assert: require.resolve('assert/'),
37 | crypto: require.resolve('crypto-browserify'),
38 | http: require.resolve('stream-http'),
39 | https: require.resolve('https-browserify'),
40 | os: require.resolve('os-browserify/browser'),
41 | buffer: require.resolve('buffer'),
42 | stream: require.resolve('stream-browserify'),
43 | path: require.resolve("path-browserify")
44 | };
45 | config.plugins.push(
46 | new webpack.ProvidePlugin({
47 | process: 'process/browser',
48 | Buffer: ['buffer', 'Buffer'],
49 | }),
50 | );
51 |
52 | return config;
53 | }
--------------------------------------------------------------------------------
/src/store/reducers/snackbar.ts:
--------------------------------------------------------------------------------
1 | import { createSlice } from '@reduxjs/toolkit';
2 |
3 | import { SnackbarProps } from 'types/snackbar';
4 |
5 | const initialState: SnackbarProps = {
6 | action: false,
7 | open: false,
8 | message: 'Note archived',
9 | anchorOrigin: {
10 | vertical: 'bottom',
11 | horizontal: 'right'
12 | },
13 | variant: 'default',
14 | alert: {
15 | color: 'primary',
16 | variant: 'filled'
17 | },
18 | transition: 'Fade',
19 | close: true,
20 | actionButton: false
21 | };
22 |
23 | const snackbar = createSlice({
24 | name: 'snackbar',
25 | initialState,
26 | reducers: {
27 | openSnackbar(state, action) {
28 | const { open, message, anchorOrigin, variant, alert, transition, close, actionButton } = action.payload;
29 |
30 | state.action = !state.action;
31 | state.open = open || initialState.open;
32 | state.message = message || initialState.message;
33 | state.anchorOrigin = anchorOrigin || initialState.anchorOrigin;
34 | state.variant = variant || initialState.variant;
35 | state.alert = {
36 | color: alert?.color || initialState.alert.color,
37 | variant: alert?.variant || initialState.alert.variant
38 | };
39 | state.transition = transition || initialState.transition;
40 | state.close = close === false ? close : initialState.close;
41 | state.actionButton = actionButton || initialState.actionButton;
42 | },
43 |
44 | closeSnackbar(state) {
45 | state.open = false;
46 | }
47 | }
48 | });
49 |
50 | export default snackbar.reducer;
51 |
52 | export const { closeSnackbar, openSnackbar } = snackbar.actions;
53 |
--------------------------------------------------------------------------------
/src/utils/connectors.ts:
--------------------------------------------------------------------------------
1 | import { InjectedConnector } from '@web3-react/injected-connector';
2 | import { WalletConnectConnector } from '@web3-react/walletconnect-connector';
3 | import { WalletLinkConnector } from '@web3-react/walletlink-connector';
4 |
5 | export const injected = new InjectedConnector({
6 | supportedChainIds: [1, 56, 97]
7 | });
8 |
9 | export const CoinbaseWallet = new WalletLinkConnector({
10 | url: `https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161`,
11 | appName: 'Boibook',
12 | supportedChainIds: [1, 56, 97]
13 | });
14 |
15 | export const WalletConnect = new WalletConnectConnector({
16 | bridge: 'https://bridge.walletconnect.org',
17 | qrcode: true,
18 | supportedChainIds: [1, 56, 97]
19 | });
20 |
21 | export const switchNetwork = async (network: string, status: boolean = false) => {
22 | try {
23 | const provider = window as any;
24 | if (provider.ethereum) {
25 | const chainId = await provider.ethereum.request({ method: 'eth_chainId' });
26 | let ChainId = '0x1';
27 | if (network === 'ethereum') {
28 | ChainId = '0x1';
29 | } else if (network === 'binance') {
30 | // BSC Test 97
31 | // ChainId = '0x61';
32 | // BSC Main 56
33 | ChainId = '0x38';
34 | }
35 | if (chainId === ChainId) return;
36 | try {
37 | await provider.ethereum.request({
38 | method: 'wallet_switchEthereumChain',
39 | params: [{ chainId: ChainId }]
40 | });
41 | } catch (switchError: any) {
42 | console.log(switchError);
43 | }
44 | } else if (!status) {
45 | window.open('https://metamask.io/download/');
46 | }
47 | } catch (error) {
48 | console.log(error);
49 | }
50 | };
51 |
52 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Boibook
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/layout/MyBetsLayout/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { Outlet, useLocation, useNavigate } from 'react-router-dom';
3 |
4 | import { Stack, Typography } from '@mui/material';
5 |
6 | import { FormattedMessage } from 'react-intl';
7 |
8 | import { WTab, WTabs } from 'ui-component';
9 | import { MyBetsIcon } from 'ui-component/SvgIcon';
10 |
11 | const MyBetsLayout = () => {
12 | const navigate = useNavigate();
13 | const { pathname } = useLocation();
14 | const [activeTab, setActiveTab] = useState(0);
15 |
16 | const tabChangeHandler = (event: React.SyntheticEvent, index: number) => {
17 | const routeContent = ['/my-bets', '/my-bets/settled', '/my-bets/history'];
18 | navigate(routeContent[index]);
19 | setActiveTab(index);
20 | };
21 |
22 | useEffect(() => {
23 | const path = document.location.pathname.toString();
24 | if (path === '/my-bets') {
25 | setActiveTab(0);
26 | }
27 | if (path === '/my-bets/settled') {
28 | setActiveTab(1);
29 | }
30 | }, [pathname]);
31 |
32 | return (
33 | <>
34 |
35 |
36 |
43 |
44 |
45 |
46 |
47 | } iconPosition="start" />
48 | } iconPosition="start" />
49 | } iconPosition="start" />
50 |
51 |
52 | >
53 | );
54 | };
55 |
56 | export default MyBetsLayout;
57 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/Advertisement/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { Box, useMediaQuery } from '@mui/material';
3 | import { Swiper, SwiperSlide } from 'swiper/react';
4 | import SwiperCore, { Autoplay } from 'swiper';
5 | import Axios from 'utils/axios';
6 | import { BASE_URL } from 'config';
7 | // Import Swiper styles
8 | import 'swiper/swiper-bundle.min.css';
9 | import 'swiper/swiper.min.css';
10 |
11 | SwiperCore.use([Autoplay]);
12 |
13 | interface AdvertisementProps {
14 | title: string;
15 | hyperlink: string;
16 | uri: string;
17 | status: boolean;
18 | }
19 |
20 | export default function Advertisement() {
21 | const isMobile = useMediaQuery('(max-width:767px)');
22 | const [advertisements, setAdvertisements] = useState([]);
23 |
24 | useEffect(() => {
25 | Axios.post('api/v3/advertisements/list', {}).then(({ data }) => {
26 | setAdvertisements(data.results);
27 | });
28 | }, []);
29 |
30 | return (
31 |
38 |
46 | {advertisements.map((aditem, index) => (
47 |
48 |
49 |
54 |
55 |
56 | ))}
57 |
58 |
59 | );
60 | }
61 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/Header/BetslipSection/index.tsx:
--------------------------------------------------------------------------------
1 | import { Avatar, Badge, Box, useTheme } from '@mui/material';
2 |
3 | import { IconReceipt } from '@tabler/icons';
4 |
5 | import { useDispatch, useSelector } from 'store';
6 | import { openBetslip } from 'store/reducers/sports';
7 |
8 | const NotificationSection = () => {
9 | const theme = useTheme();
10 | const dispatch = useDispatch();
11 | const { betslipOpen, betslipData } = useSelector((state) => state.sports);
12 |
13 | const handleClick = () => {
14 | dispatch(openBetslip(!betslipOpen));
15 | };
16 |
17 | return (
18 |
26 |
27 |
47 |
48 |
49 |
50 |
51 | );
52 | };
53 |
54 | export default NotificationSection;
55 |
--------------------------------------------------------------------------------
/src/navigation/main.tsx:
--------------------------------------------------------------------------------
1 | import { FormattedMessage } from 'react-intl';
2 | import { SidebarItem } from 'ui-component';
3 | import { CasinoIcon, InplayIcon, SportsIcon, UpcomingIcon } from 'ui-component/SvgIcon';
4 |
5 | interface DashboardMenuProps {
6 | id: string;
7 | title: React.ReactNode | string;
8 | type: string;
9 | children: {
10 | id: string;
11 | title: React.ReactNode | string;
12 | type: string;
13 | url: string;
14 | icon: React.ReactNode;
15 | breadcrumbs: boolean;
16 | }[];
17 | }
18 |
19 | const dashboard: DashboardMenuProps = {
20 | id: 'main',
21 | title: 'main',
22 | type: 'group',
23 | children: [
24 | {
25 | id: 'sports',
26 | title: ,
27 | type: 'item',
28 | url: '/sports',
29 | icon: (
30 |
31 |
32 |
33 | ),
34 | breadcrumbs: false
35 | },
36 | {
37 | id: 'inplay',
38 | title: ,
39 | type: 'item',
40 | url: '/inplay',
41 | icon: (
42 |
43 |
44 |
45 | ),
46 | breadcrumbs: false
47 | },
48 | {
49 | id: 'upcoming',
50 | title: ,
51 | type: 'item',
52 | url: '/upcoming',
53 | icon: (
54 |
55 |
56 |
57 | ),
58 | breadcrumbs: false
59 | }
60 | // {
61 | // id: 'casino',
62 | // title: ,
63 | // type: 'item',
64 | // url: '/casino',
65 | // icon: (
66 | //
67 | //
68 | //
69 | // ),
70 | // breadcrumbs: false
71 | // }
72 | ]
73 | };
74 |
75 | export default dashboard;
76 |
--------------------------------------------------------------------------------
/src/types/index.ts:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent, ReactElement } from 'react';
2 |
3 | import { SvgIconTypeMap, ChipProps } from '@mui/material';
4 | import { OverridableComponent } from '@mui/material/OverridableComponent';
5 |
6 | import { TablerIcon } from '@tabler/icons';
7 |
8 | export type ArrangementOrder = 'asc' | 'desc' | undefined;
9 |
10 | export type GetComparator = (o: ArrangementOrder, o1: string) => (a: KeyedObject, b: KeyedObject) => number;
11 |
12 | export interface GenericCardProps {
13 | title?: string;
14 | primary?: string | number | undefined;
15 | secondary?: string;
16 | content?: string;
17 | image?: string;
18 | dateTime?: string;
19 | iconPrimary?: OverrideIcon;
20 | color?: string;
21 | size?: string;
22 | }
23 |
24 | export type OverrideIcon =
25 | | (OverridableComponent> & {
26 | muiName: string;
27 | })
28 | | React.ComponentClass
29 | | FunctionComponent
30 | | TablerIcon;
31 |
32 | export type LinkTarget = '_blank' | '_self' | '_parent' | '_top';
33 |
34 | export type NavItemTypeObject = { children?: NavItemType[]; items?: NavItemType[]; type?: string };
35 |
36 | export type NavItemType = {
37 | id?: string;
38 | icon?: GenericCardProps['iconPrimary'];
39 | target?: boolean;
40 | external?: string;
41 | url?: string | undefined;
42 | type?: string;
43 | title?: React.ReactNode | string;
44 | color?: 'primary' | 'secondary' | 'default' | undefined;
45 | caption?: React.ReactNode | string;
46 | breadcrumbs?: boolean;
47 | children?: any;
48 | disabled?: boolean;
49 | chip?: ChipProps;
50 | };
51 |
52 | export interface ColorProps {
53 | readonly [key: string]: string;
54 | }
55 |
56 | export type GuardProps = {
57 | children: ReactElement | null;
58 | };
59 |
60 | export interface StringColorProps {
61 | id?: string;
62 | label?: string;
63 | color?: string;
64 | primary?: string;
65 | secondary?: string;
66 | }
67 |
68 | export type StringBoolFunc = (s: string) => boolean;
69 | export type StringNumFunc = (s: string) => number;
70 | export type NumbColorFunc = (n: number) => StringColorProps | undefined;
71 |
72 | export type KeyedObject = {
73 | [key: string]: string | number | KeyedObject | any;
74 | };
75 |
--------------------------------------------------------------------------------
/src/types/auth.ts:
--------------------------------------------------------------------------------
1 | import { CurrencyProps } from './payment';
2 |
3 | export type UserProfile = {
4 | _id: string;
5 | email: string;
6 | username: string;
7 | avatar: string;
8 | iReferral: string;
9 | cryptoAccount?: string;
10 | publicAddress?: string;
11 | oddsformat?: string;
12 | rReferral?: string;
13 | pReferral?: string;
14 | };
15 |
16 | export type APIContextType = {
17 | login: (email: string, password: string, recaptcha: string | null) => Promise;
18 | register: (email: string, username: string, password: string, recaptcha: string) => Promise;
19 | logout: () => void;
20 | checkAddress: (publicAddress: string) => Promise;
21 | signInAddress: (publicAddress: string, signature: string) => Promise;
22 | signInSolana: (publicAddress: string, signature: string) => Promise;
23 | signUpAddress: (publicAddress: string) => Promise;
24 | forgotPassword: (email: string, recaptcha: string) => Promise;
25 | changePassword: (data: any) => Promise;
26 | resetPassword: (email: string) => void;
27 | updateUserInfo: (user: any) => Promise;
28 | getReferral: () => Promise;
29 | getTransactions: () => Promise;
30 | getBalances: () => Promise;
31 | uploadFile: (data: FormData) => Promise;
32 | deleteFile: (uri: string) => Promise;
33 | getCurrency: () => Promise;
34 | addCurrency: (currency: string) => Promise;
35 | changeCurrency: (currency: string) => Promise;
36 | deposit: () => Promise;
37 | depositSolana: (transaction: any) => Promise;
38 | depositMetamask: (transaction: any) => Promise;
39 | withdrawal: (address: string, method: number, amount: number) => Promise;
40 | cancelWithdrawal: (_id: string) => Promise;
41 | betSport: (data: any, type: string, stake: number) => Promise;
42 | getMybets: (status: string) => Promise;
43 | getCasinoHistory: (type: number, perPage: number) => Promise;
44 | };
45 |
46 | export interface InitialLoginContextProps {
47 | isLoggedIn: boolean;
48 | isInitialized?: boolean;
49 | token?: string | undefined;
50 | user: UserProfile;
51 | balance: number;
52 | betsId: string;
53 | balanceId: string;
54 | currencyId: string;
55 | code: string;
56 | currency: CurrencyProps;
57 | }
58 |
--------------------------------------------------------------------------------
/src/assets/scss/sportsicon.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: sportsicons;
3 | src: url(../fonts/sportsicons.woff2) format('woff2');
4 | font-weight: 400;
5 | font-style: normal;
6 | font-display: block;
7 | }
8 |
9 | [class*=' sportsicon-'],
10 | [class^='sportsicon-'] {
11 | font-family: sportsicons !important;
12 | font-style: normal;
13 | font-weight: 400;
14 | font-variant: normal;
15 | text-transform: none;
16 | line-height: 1;
17 | -webkit-font-smoothing: antialiased;
18 | -moz-osx-font-smoothing: grayscale;
19 | }
20 |
21 | .sportsicon-1:before {
22 | content: '';
23 | }
24 |
25 | .sportsicon-18:before {
26 | content: '';
27 | }
28 |
29 | .sportsicon-16:before {
30 | content: '';
31 | }
32 |
33 | .sportsicon-17:before {
34 | content: '';
35 | }
36 |
37 | .sportsicon-91:before {
38 | content: '';
39 | }
40 |
41 | .sportsicon-9:before {
42 | content: '';
43 | }
44 |
45 | .sportsicon-78:before {
46 | content: '';
47 | }
48 |
49 | .sportsicon-3:before {
50 | content: '';
51 | }
52 |
53 | .sportsicon-83:before {
54 | content: '';
55 | }
56 |
57 | .sportsicon-15:before {
58 | content: '';
59 | }
60 |
61 | .sportsicon-8:before {
62 | content: '';
63 | }
64 |
65 | .sportsicon-19:before {
66 | content: '';
67 | }
68 |
69 | .sportsicon-110:before {
70 | content: '';
71 | }
72 |
73 | .sportsicon-151:before {
74 | content: '';
75 | }
76 |
77 | .sportsicon-2:before {
78 | content: '';
79 | }
80 |
81 | .sportsicon-4:before {
82 | content: '';
83 | }
84 |
85 | .sportsicon-14:before {
86 | content: '';
87 | }
88 |
89 | .sportsicon-12:before {
90 | content: '';
91 | }
92 |
93 | .sportsicon-13:before {
94 | content: '';
95 | }
96 |
97 | .sportsicon-94:before {
98 | content: '';
99 | }
100 |
101 | .sportsicon-66:before {
102 | content: '';
103 | }
104 |
105 | .sportsicon-75:before {
106 | content: '';
107 | }
108 |
109 | .sportsicon-90:before {
110 | content: '';
111 | }
112 |
113 | .sportsicon-95:before {
114 | content: '';
115 | }
116 |
117 | .sportsicon-107:before {
118 | content: '';
119 | }
120 |
121 | .sportsicon-36:before {
122 | content: '';
123 | }
124 |
125 | .sportsicon-92:before {
126 | content: '';
127 | }
128 |
--------------------------------------------------------------------------------
/src/assets/images/landing/img-contact-mail.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/src/routes/CasinoRoutes.tsx:
--------------------------------------------------------------------------------
1 | import { lazy } from 'react';
2 |
3 | import MainLayout from 'layout/MainLayout';
4 | import Loadable from 'ui-component/Loadable';
5 | import CasinoLayout from 'layout/CasinoLayout';
6 |
7 | const CasinoPage = Loadable(lazy(() => import('views/casino')));
8 | // const BlackjackPage = Loadable(lazy(() => import('views/casino/Blackjack')));
9 | // const CoinflipPage = Loadable(lazy(() => import('views/casino/Coinflip')));
10 | // const DiamondsPage = Loadable(lazy(() => import('views/casino/Diamonds')));
11 | // const DicePage = Loadable(lazy(() => import('views/casino/Dice')));
12 | // const PlinkoPage = Loadable(lazy(() => import('views/casino/Plinko')));
13 | // const LimboPage = Loadable(lazy(() => import('views/casino/Limbo')));
14 | // const KenoPage = Loadable(lazy(() => import('views/casino/Keno')));
15 | // const WheelPage = Loadable(lazy(() => import('views/casino/Wheel')));
16 | // const RoulettePage = Loadable(lazy(() => import('views/casino/Roulette')));
17 |
18 | const CasinoRoutes = {
19 | path: '/casino',
20 | element: (
21 |
22 |
23 |
24 | ),
25 | children: [
26 | {
27 | path: '/casino',
28 | element:
29 | }
30 | // {
31 | // path: '/casino/blackjack',
32 | // element:
33 | // },
34 | // {
35 | // path: '/casino/coinflip',
36 | // element:
37 | // },
38 | // {
39 | // path: '/casino/diamonds',
40 | // element:
41 | // },
42 | // {
43 | // path: '/casino/dice',
44 | // element:
45 | // },
46 | // {
47 | // path: '/casino/plinko',
48 | // element:
49 | // },
50 | // {
51 | // path: '/casino/limbo',
52 | // element:
53 | // },
54 | // {
55 | // path: '/casino/keno',
56 | // element:
57 | // },
58 | // {
59 | // path: '/casino/wheel',
60 | // element:
61 | // },
62 | // {
63 | // path: '/casino/roulette',
64 | // element:
65 | // }
66 | ]
67 | };
68 |
69 | export default CasinoRoutes;
70 |
--------------------------------------------------------------------------------
/src/views/profile/Wallet/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { Divider, Grid, Typography } from '@mui/material';
3 |
4 | import { FormattedMessage } from 'react-intl';
5 |
6 | // Tx Result
7 | // import axios from 'axios';
8 | // import {
9 | // LAMPORTS_PER_SOL,
10 | // clusterApiUrl,
11 | // } from "@solana/web3.js";
12 | // Tx Result
13 |
14 | import useApi from 'hooks/useApi';
15 | import { gridSpacing } from 'store/constant';
16 | import { TransactionsProps } from 'types/payment';
17 |
18 | import Balances from './Balances';
19 | import Transaction from './Transaction';
20 |
21 | const Wallet = () => {
22 | const Api = useApi();
23 | const [transactions, setTransactions] = useState([]);
24 |
25 | const getTransactions = () => {
26 | Api.getTransactions()
27 | .then(({ data }) => {
28 | setTransactions(data);
29 | })
30 | .catch((error) => {
31 | console.log(error);
32 | });
33 | };
34 |
35 | // const getTxnResult = async () => {
36 | // const param = "mainnet-beta";
37 | // const URL = clusterApiUrl(param);
38 | // const res = await axios(URL, {
39 | // method: "POST",
40 | // headers: { "content-type": "application/json" },
41 | // data: {
42 | // jsonrpc: "2.0",
43 | // id: "get-transaction",
44 | // method: "getTransaction",
45 | // params: ["signature"],
46 | // },
47 | // });
48 | // };
49 |
50 | useEffect(() => {
51 | // getTxnResult();
52 | getTransactions();
53 | // eslint-disable-next-line
54 | }, []);
55 |
56 | return (
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | {/*
68 |
69 | */}
70 |
71 |
72 |
73 |
74 | );
75 | };
76 |
77 | export default Wallet;
78 |
--------------------------------------------------------------------------------
/src/themes/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo, ReactNode } from 'react';
2 |
3 | import {
4 | createTheme,
5 | CssBaseline,
6 | StyledEngineProvider,
7 | Theme,
8 | ThemeOptions,
9 | ThemeProvider,
10 | TypographyVariantsOptions
11 | } from '@mui/material';
12 |
13 | import useConfig from 'hooks/useConfig';
14 | import { CustomShadowProps } from 'types/default-theme';
15 |
16 | import Palette from './palette';
17 | import Typography from './typography';
18 |
19 | import customShadows from './shadows';
20 | import componentStyleOverrides from './compStyleOverride';
21 |
22 | interface Props {
23 | children: ReactNode;
24 | }
25 |
26 | export default function ThemeCustomization({ children }: Props) {
27 | const { borderRadius, fontFamily, navType, outlinedFilled, presetColor, rtlLayout } = useConfig();
28 |
29 | const theme: Theme = useMemo(() => Palette(navType, presetColor), [navType, presetColor]);
30 |
31 | // eslint-disable-next-line
32 | const themeTypography: TypographyVariantsOptions = useMemo(
33 | () => Typography(theme, borderRadius, fontFamily),
34 | [theme, borderRadius, fontFamily]
35 | );
36 | const themeCustomShadows: CustomShadowProps = useMemo(() => customShadows(navType, theme), [navType, theme]);
37 |
38 | const themeOptions: ThemeOptions = useMemo(
39 | () => ({
40 | direction: rtlLayout ? 'rtl' : 'ltr',
41 | palette: theme.palette,
42 | mixins: {
43 | toolbar: {
44 | minHeight: '48px',
45 | padding: '0',
46 | '@media (min-width: 600px)': {
47 | padding: '0',
48 | minHeight: '48px'
49 | }
50 | }
51 | },
52 | typography: themeTypography,
53 | customShadows: themeCustomShadows
54 | }),
55 | [rtlLayout, theme, themeCustomShadows, themeTypography]
56 | );
57 |
58 | const themes: Theme = createTheme(themeOptions);
59 | themes.components = useMemo(
60 | () => componentStyleOverrides(themes, borderRadius, outlinedFilled),
61 | [themes, borderRadius, outlinedFilled]
62 | );
63 |
64 | return (
65 |
66 |
67 |
68 | {children}
69 |
70 |
71 | );
72 | }
73 |
--------------------------------------------------------------------------------
/src/ui-component/extended/Avatar.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 | import { LinkTarget } from 'types';
3 |
4 | import { useTheme, Avatar as MuiAvatar, AvatarProps } from '@mui/material';
5 | import { OverridableComponent } from '@mui/material/OverridableComponent';
6 |
7 | interface avatarProps extends AvatarProps {
8 | alt?: string;
9 | src?: string;
10 | className?: string;
11 | color?: string;
12 | component?: OverridableComponent /** Any component can override */;
13 | target?: LinkTarget;
14 | href?: string;
15 | sx?: AvatarProps['sx'];
16 | children?: ReactNode;
17 | outline?: boolean;
18 | size?: 'badge' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
19 | }
20 |
21 | const Avatar = ({ className, color, outline, size, sx, ...others }: avatarProps) => {
22 | const theme = useTheme();
23 |
24 | const colorSX = color && !outline && { color: theme.palette.background.paper, bgcolor: `${color}.main` };
25 | const outlineSX = outline && {
26 | color: color ? `${color}.main` : `primary.main`,
27 | bgcolor: theme.palette.background.paper,
28 | border: '2px solid',
29 | borderColor: color ? `${color}.main` : `primary.main`
30 | };
31 | let sizeSX = {};
32 | switch (size) {
33 | case 'badge':
34 | sizeSX = {
35 | width: theme.spacing(3.5),
36 | height: theme.spacing(3.5)
37 | };
38 | break;
39 | case 'xs':
40 | sizeSX = {
41 | width: theme.spacing(4.25),
42 | height: theme.spacing(4.25)
43 | };
44 | break;
45 | case 'sm':
46 | sizeSX = {
47 | width: theme.spacing(5),
48 | height: theme.spacing(5)
49 | };
50 | break;
51 | case 'lg':
52 | sizeSX = {
53 | width: theme.spacing(9),
54 | height: theme.spacing(9)
55 | };
56 | break;
57 | case 'xl':
58 | sizeSX = {
59 | width: theme.spacing(10.25),
60 | height: theme.spacing(10.25)
61 | };
62 | break;
63 | case 'md':
64 | sizeSX = {
65 | width: theme.spacing(7.5),
66 | height: theme.spacing(7.5)
67 | };
68 | break;
69 | default:
70 | sizeSX = {};
71 | }
72 |
73 | return ;
74 | };
75 |
76 | export default Avatar;
77 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # Snowpack dependency directory (https://snowpack.dev/)
46 | web_modules/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Optional stylelint cache
58 | .stylelintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variable files
76 | .env
77 | .env.development.local
78 | .env.test.local
79 | .env.production.local
80 | .env.local
81 |
82 | # parcel-bundler cache (https://parceljs.org/)
83 | .cache
84 | .parcel-cache
85 |
86 | # Next.js build output
87 | .next
88 | out
89 |
90 | # Nuxt.js build / generate output
91 | .nuxt
92 | dist
93 |
94 | # Gatsby files
95 | .cache/
96 | # Comment in the public line in if your project uses Gatsby and not Next.js
97 | # https://nextjs.org/blog/next-9-1#public-directory-support
98 | # public
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # vuepress v2.x temp and cache directory
104 | .temp
105 | .cache
106 |
107 | # Serverless directories
108 | .serverless/
109 |
110 | # FuseBox cache
111 | .fusebox/
112 |
113 | # DynamoDB Local files
114 | .dynamodb/
115 |
116 | # TernJS port file
117 | .tern-port
118 |
119 | # Stores VSCode versions used for testing VSCode extensions
120 | .vscode-test
121 |
122 | # yarn v2
123 | .yarn/cache
124 | .yarn/unplugged
125 | .yarn/build-state.yml
126 | .yarn/install-state.gz
127 | .pnp.*
128 |
--------------------------------------------------------------------------------
/src/ui-component/cards/SubCard.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactNode, Ref } from 'react';
2 |
3 | import { Card, CardContent, CardHeader, Divider, Typography, useTheme } from '@mui/material';
4 |
5 | interface SubCardProps {
6 | children: ReactNode | string | null;
7 | content?: boolean;
8 | className?: string;
9 | contentClass?: string;
10 | darkTitle?: boolean;
11 | secondary?: ReactNode | string | {} | any;
12 | sx?: {};
13 | contentSX?: {};
14 | title?: ReactNode | string | {} | any;
15 | }
16 |
17 | const SubCard = React.forwardRef(
18 | (
19 | { children, className, content, contentClass, darkTitle, secondary, sx = {}, contentSX = {}, title, ...others }: SubCardProps,
20 | ref: Ref
21 | ) => {
22 | const theme = useTheme();
23 |
24 | return (
25 |
37 | {/* card header and action */}
38 | {!darkTitle && title && (
39 | {title}} action={secondary} />
40 | )}
41 | {darkTitle && title && (
42 | {title}} action={secondary} />
43 | )}
44 |
45 | {/* content & header divider */}
46 | {title && (
47 |
53 | )}
54 |
55 | {/* card content */}
56 | {content && (
57 |
58 | {children}
59 |
60 | )}
61 | {!content && children}
62 |
63 | );
64 | }
65 | );
66 |
67 | SubCard.defaultProps = {
68 | content: true
69 | };
70 |
71 | export default SubCard;
72 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/MobileMenu/index.tsx:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import { useNavigate } from 'react-router-dom';
3 | import { Badge, Stack, Typography } from '@mui/material';
4 |
5 | import { IconMenu2, IconReceipt } from '@tabler/icons';
6 | import { FormattedMessage } from 'react-intl';
7 |
8 | import { useDispatch, useSelector } from 'store';
9 | import { openDrawer } from 'store/reducers/menu';
10 | import { openBetslip } from 'store/reducers/sports';
11 |
12 | import useConfig from 'hooks/useConfig';
13 | import AnimateButton from 'ui-component/extended/AnimateButton';
14 |
15 | const MobileMenu = () => {
16 | const dispatch = useDispatch();
17 | const navigate = useNavigate();
18 | const { boxShadow } = useConfig();
19 | const { betslipData } = useSelector((state) => state.sports);
20 | return (
21 |
35 |
36 | dispatch(openDrawer(true))}>
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | dispatch(openBetslip(true))}>
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | navigate('/sports')}>
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | );
63 | };
64 |
65 | export default memo(MobileMenu);
66 |
--------------------------------------------------------------------------------
/src/assets/images/maintenance/img-error-text.svg:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/src/ui-component/cards/MainCard.tsx:
--------------------------------------------------------------------------------
1 | import React, { Ref } from 'react';
2 |
3 | import { Card, CardContent, CardHeader, Divider, Typography, CardProps, CardHeaderProps, CardContentProps, useTheme } from '@mui/material';
4 |
5 | import { KeyedObject } from 'types';
6 |
7 | const headerSX = {
8 | '& .MuiCardHeader-action': { mr: 0 }
9 | };
10 |
11 | export interface MainCardProps extends KeyedObject {
12 | border?: boolean;
13 | boxShadow?: boolean;
14 | children: React.ReactNode | string;
15 | style?: React.CSSProperties;
16 | content?: boolean;
17 | className?: string;
18 | contentClass?: string;
19 | contentSX?: CardContentProps['sx'];
20 | darkTitle?: boolean;
21 | divider?: boolean;
22 | sx?: CardProps['sx'];
23 | secondary?: CardHeaderProps['action'];
24 | shadow?: string;
25 | elevation?: number;
26 | title?: React.ReactNode | string;
27 | }
28 |
29 | const MainCard = React.forwardRef(
30 | (
31 | {
32 | border = true,
33 | boxShadow,
34 | children,
35 | content = true,
36 | contentClass = '',
37 | contentSX = {},
38 | darkTitle,
39 | secondary,
40 | shadow,
41 | sx = {},
42 | title,
43 | divider = true,
44 | ...others
45 | }: MainCardProps,
46 | ref: Ref
47 | ) => {
48 | const theme = useTheme();
49 |
50 | return (
51 |
66 | {/* card header and action */}
67 | {!darkTitle && title && }
68 | {darkTitle && title && (
69 | {title}} action={secondary} />
70 | )}
71 |
72 | {/* content & header divider */}
73 | {title && divider && }
74 |
75 | {/* card content */}
76 | {content && (
77 |
78 | {children}
79 |
80 | )}
81 | {!content && children}
82 |
83 | );
84 | }
85 | );
86 |
87 | export default MainCard;
88 |
--------------------------------------------------------------------------------
/src/ui-component/extended/AnimateButton.tsx:
--------------------------------------------------------------------------------
1 | import React, { Ref } from 'react';
2 | import { motion, useCycle } from 'framer-motion';
3 |
4 | interface ScaleProps {
5 | hover: number | string | undefined;
6 | tap: number | string | undefined;
7 | }
8 |
9 | interface AnimateButtonProps {
10 | children?: React.ReactNode;
11 | type?: 'slide' | 'scale' | 'rotate';
12 | direction?: 'up' | 'down' | 'left' | 'right';
13 | offset?: number;
14 | scale?: ScaleProps;
15 | }
16 |
17 | const AnimateButton = React.forwardRef(({ children, type, direction, offset, scale }: AnimateButtonProps, ref: Ref) => {
18 | let offset1;
19 | let offset2;
20 | switch (direction) {
21 | case 'up':
22 | case 'left':
23 | offset1 = offset;
24 | offset2 = 0;
25 | break;
26 | case 'right':
27 | case 'down':
28 | default:
29 | offset1 = 0;
30 | offset2 = offset;
31 | break;
32 | }
33 |
34 | const [x, cycleX] = useCycle(offset1, offset2);
35 | const [y, cycleY] = useCycle(offset1, offset2);
36 |
37 | switch (type) {
38 | case 'rotate':
39 | return (
40 |
50 | {children}
51 |
52 | );
53 | case 'slide':
54 | if (direction === 'up' || direction === 'down') {
55 | return (
56 | cycleY()}
60 | onHoverStart={() => cycleY()}
61 | >
62 | {children}
63 |
64 | );
65 | }
66 | return (
67 | cycleX()} onHoverStart={() => cycleX()}>
68 | {children}
69 |
70 | );
71 |
72 | case 'scale':
73 | default:
74 | if (typeof scale === 'number') {
75 | scale = {
76 | hover: scale,
77 | tap: scale
78 | };
79 | }
80 | return (
81 |
82 | {children}
83 |
84 | );
85 | }
86 | });
87 |
88 | AnimateButton.defaultProps = {
89 | type: 'scale',
90 | offset: 10,
91 | direction: 'right',
92 | scale: {
93 | hover: 1,
94 | tap: 0.9
95 | }
96 | };
97 |
98 | export default AnimateButton;
99 |
--------------------------------------------------------------------------------
/src/store/reducers/auth.ts:
--------------------------------------------------------------------------------
1 | import { InitialLoginContextProps } from 'types/auth';
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | const initialCurrency = {
5 | _id: '',
6 | icon: 'https://boibook.io/SOL.png',
7 | symbol: 'SOL',
8 | minBet: 10,
9 | maxBet: 100000,
10 | price: 0.1,
11 | tokenMintAccount: ''
12 | };
13 |
14 | const initialUser = {
15 | _id: '',
16 | email: '',
17 | username: '',
18 | iReferral: '',
19 | pReferral: '',
20 | avatar: ''
21 | };
22 |
23 | const initialState: InitialLoginContextProps = {
24 | isInitialized: true,
25 | isLoggedIn: false,
26 | code: '',
27 | betsId: '',
28 | token: '',
29 | balance: 0,
30 | balanceId: '',
31 | currencyId: '',
32 | user: initialUser,
33 | currency: initialCurrency
34 | };
35 |
36 | const auth = createSlice({
37 | name: 'auth',
38 | initialState,
39 | reducers: {
40 | Login(state, action: any) {
41 | const { balance, user, session } = action.payload!;
42 | state.user = user;
43 | state.token = session.accessToken;
44 | state.balance = balance.balance;
45 | state.balanceId = balance._id;
46 | state.currency = balance.currency;
47 | state.currencyId = balance.currency._id;
48 | state.isLoggedIn = true;
49 | state.isInitialized = true;
50 | },
51 |
52 | UpdateInfo(state, action: any) {
53 | state.user = action.payload;
54 | },
55 |
56 | UpdateBalance(state, action: any) {
57 | state.balance = action.payload;
58 | },
59 |
60 | UpdateBalances(state, action: any) {
61 | const balance = action.payload!;
62 | state.balance = balance.balance;
63 | state.balanceId = balance._id;
64 | state.currency = balance.currency;
65 | state.currencyId = balance.currency._id;
66 | state = { ...state };
67 | },
68 |
69 | SetCode(state, action: any) {
70 | state.code = action.payload;
71 | },
72 |
73 | SetBetsId(state, action: any) {
74 | state.betsId = action.payload;
75 | },
76 |
77 | Logout(state, action: any) {
78 | state.token = '';
79 | state.balance = 0;
80 | state.balanceId = '';
81 | state.currencyId = '';
82 | state.user = initialUser;
83 | state.currency = initialCurrency;
84 | state.isLoggedIn = false;
85 | state.isInitialized = true;
86 | state = { ...state };
87 | if (
88 | window.location.pathname.toString().indexOf('blackjack') !== -1 ||
89 | window.location.pathname.toString().indexOf('roulette') !== -1
90 | ) {
91 | window.location.reload();
92 | }
93 | }
94 | }
95 | });
96 |
97 | export default auth.reducer;
98 |
99 | export const { Login, Logout, UpdateInfo, UpdateBalances, UpdateBalance, SetCode, SetBetsId } = auth.actions;
100 |
--------------------------------------------------------------------------------
/src/assets/images/games/back.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/ui-component/extended/Transitions.tsx:
--------------------------------------------------------------------------------
1 | import React, { Ref, ExoticComponent, ReactElement } from 'react';
2 | import { Collapse, Fade, Box, Grow, Slide, Zoom } from '@mui/material';
3 |
4 | interface TSProps {
5 | children?: ReactElement;
6 | position?: string;
7 | sx?: React.CSSProperties;
8 | in?: boolean;
9 | type?: string;
10 | direction?: 'up' | 'right' | 'left' | 'down';
11 | [others: string]: any;
12 | }
13 |
14 | const Transitions = React.forwardRef(({ children, position, sx, type, direction, ...others }: TSProps, ref: Ref) => {
15 | let positionSX = {
16 | transformOrigin: '0 0 0'
17 | };
18 |
19 | switch (position) {
20 | case 'top-right':
21 | positionSX = {
22 | transformOrigin: 'top right'
23 | };
24 | break;
25 | case 'top':
26 | positionSX = {
27 | transformOrigin: 'top'
28 | };
29 | break;
30 | case 'bottom-left':
31 | positionSX = {
32 | transformOrigin: 'bottom left'
33 | };
34 | break;
35 | case 'bottom-right':
36 | positionSX = {
37 | transformOrigin: 'bottom right'
38 | };
39 | break;
40 | case 'bottom':
41 | positionSX = {
42 | transformOrigin: 'bottom'
43 | };
44 | break;
45 | case 'top-left':
46 | default:
47 | positionSX = {
48 | transformOrigin: '0 0 0'
49 | };
50 | break;
51 | }
52 |
53 | return (
54 |
55 | {type === 'grow' && (
56 |
57 | {children}
58 |
59 | )}
60 | {type === 'collapse' && (
61 |
62 | {children}
63 |
64 | )}
65 | {type === 'fade' && (
66 |
74 | {children}
75 |
76 | )}
77 | {type === 'slide' && (
78 |
87 | {children}
88 |
89 | )}
90 | {type === 'zoom' && (
91 |
92 | {children}
93 |
94 | )}
95 |
96 | );
97 | });
98 |
99 | Transitions.defaultProps = {
100 | type: 'grow',
101 | position: 'top-left',
102 | direction: 'up'
103 | };
104 |
105 | export default Transitions;
106 |
--------------------------------------------------------------------------------
/src/assets/images/maintenance/img-error-purple.svg:
--------------------------------------------------------------------------------
1 |
43 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo } from 'react';
2 | import { Outlet } from 'react-router-dom';
3 |
4 | import { AppBar, Box, Container, CssBaseline, Grid, Toolbar, useMediaQuery, useTheme } from '@mui/material';
5 |
6 | import useConfig from 'hooks/useConfig';
7 | import { useSelector } from 'store';
8 | import { drawerWidth } from 'store/constant';
9 |
10 | import { Main } from 'ui-component';
11 | import Footer from 'layout/Footer';
12 | // import { isMobile } from 'react-device-detect';
13 |
14 | import Header from './Header';
15 | // import Sidebar from './Sidebar';
16 | import MobileMenu from './MobileMenu';
17 | import Auth from '../AuthLayout';
18 | import Betslip from 'views/sports/component/Betslip';
19 | import Advertisement from './Advertisement';
20 | import RecentBets from './RecentBets';
21 | import LiveMatches from './LiveMatches';
22 |
23 | const MainLayout = ({ children }: any) => {
24 | const theme = useTheme();
25 | const { boxShadow } = useConfig();
26 | const isMobile = useMediaQuery('(max-width:767px)');
27 | const isTablet = useMediaQuery('(max-width:1000px)');
28 | const isDesktop = useMediaQuery('(min-width:1440px)');
29 | const { drawerOpen } = useSelector((state) => state.menu);
30 | const { betslipOpen } = useSelector((state) => state.sports);
31 | const Width = drawerOpen ? drawerWidth : drawerWidth - 210;
32 | const dWidth = betslipOpen ? Width + (isDesktop ? 370 : 0) : Width;
33 |
34 | const header = useMemo(
35 | () => (
36 |
37 |
38 |
39 | ),
40 | []
41 | );
42 |
43 | return (
44 |
45 |
46 |
47 |
59 | {header}
60 |
61 | {/* */}
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | {children && children}
72 | {!children && }
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | {isMobile && }
84 |
85 | );
86 | };
87 |
88 | export default MainLayout;
89 |
--------------------------------------------------------------------------------
/src/layout/Footer.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | import { Box, Grid, Link, Stack, Typography } from '@mui/material';
4 | import { IconBrandTwitter, IconBrandDiscord, IconLink } from '@tabler/icons';
5 |
6 | import { FormattedMessage } from 'react-intl';
7 |
8 | import Axios from 'utils/axios';
9 | import LogoSection from './MainLayout/LogoSection';
10 |
11 | interface Currency {
12 | name: string;
13 | icon: string;
14 | officialLink: string;
15 | }
16 |
17 | const Footer = () => {
18 | const [currencies, setCurrencies] = useState([]);
19 |
20 | useEffect(() => {
21 | Axios.post('api/v1/payments/getPaymentMethod', {}).then(({ data }) => {
22 | setCurrencies(data);
23 | });
24 | }, []);
25 |
26 | return (
27 |
35 |
36 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | {currencies.map((item, key) => (
72 |
73 |
74 |
75 | ))}
76 |
77 |
78 |
79 |
80 |
81 |
82 | );
83 | };
84 |
85 | export default Footer;
86 |
--------------------------------------------------------------------------------
/src/views/auth/ResetPassword.tsx:
--------------------------------------------------------------------------------
1 | import { Close } from '@mui/icons-material';
2 | import { Grid, IconButton, Stack, Typography, useMediaQuery, useTheme } from '@mui/material';
3 |
4 | import { FormattedMessage } from 'react-intl';
5 |
6 | import { useDispatch } from 'store';
7 | import { ChangePage } from 'store/reducers/menu';
8 |
9 | import LogoSection from 'layout/MainLayout/LogoSection';
10 | import { AuthCardWrapper, AuthWrapper } from 'ui-component';
11 | import AuthResetPassword from './auth-forms/AuthResetPassword';
12 |
13 | const ResetPassword = () => {
14 | const theme = useTheme();
15 | const dispatch = useDispatch();
16 | const matchDownSM = useMediaQuery(theme.breakpoints.down('md'));
17 |
18 | return (
19 |
20 |
21 |
22 |
23 |
24 | dispatch(ChangePage(''))}
29 | sx={{ position: 'absolute', right: 0, top: 0, px: 0 }}
30 | >
31 |
32 |
33 |
34 |
35 |
36 |
37 |
43 |
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default ResetPassword;
71 |
--------------------------------------------------------------------------------
/src/themes/typography.tsx:
--------------------------------------------------------------------------------
1 | import { Theme, TypographyVariantsOptions } from '@mui/material';
2 |
3 | const Typography = (theme: Theme, borderRadius: number, fontFamily: string): TypographyVariantsOptions => ({
4 | fontFamily,
5 | h6: {
6 | fontWeight: 500,
7 | color: theme.palette.grey[600],
8 | fontSize: '0.75rem'
9 | },
10 | h5: {
11 | fontSize: '0.875rem',
12 | color: theme.palette.grey[600],
13 | fontWeight: 500
14 | },
15 | h4: {
16 | fontSize: '1rem',
17 | color: theme.palette.grey[600],
18 | fontWeight: 600
19 | },
20 | h3: {
21 | fontSize: '1.1rem',
22 | color: theme.palette.grey[600],
23 | fontWeight: 500
24 | },
25 | h2: {
26 | fontSize: '1.5rem',
27 | color: theme.palette.grey[600],
28 | fontWeight: 700
29 | },
30 | h1: {
31 | fontSize: '2.125rem',
32 | color: theme.palette.grey[600],
33 | fontWeight: 700
34 | },
35 | subtitle1: {
36 | fontSize: '0.875rem',
37 | fontWeight: 500,
38 | color: theme.palette.text.dark
39 | },
40 | subtitle2: {
41 | fontSize: '0.75rem',
42 | fontWeight: 400,
43 | color: theme.palette.text.secondary
44 | },
45 | caption: {
46 | fontSize: '0.75rem',
47 | color: theme.palette.text.secondary,
48 | fontWeight: 400
49 | },
50 | body1: {
51 | fontSize: '0.875rem',
52 | fontWeight: 400,
53 | lineHeight: '1.334em'
54 | },
55 | body2: {
56 | letterSpacing: '0em',
57 | fontWeight: 400,
58 | lineHeight: '1.5em',
59 | color: theme.palette.text.primary
60 | },
61 | button: {
62 | textTransform: 'capitalize'
63 | },
64 | customInput: {
65 | marginTop: 1,
66 | marginBottom: 1,
67 | '& > label': {
68 | top: 13,
69 | left: 0,
70 | color: theme.palette.grey[500],
71 | '&[data-shrink="false"]': {
72 | top: 0
73 | }
74 | },
75 | '& > div > input': {
76 | padding: '20.5px 14px 11.5px !important'
77 | },
78 | '& legend': {
79 | display: 'none'
80 | },
81 | '& fieldset': {
82 | top: 0
83 | }
84 | },
85 | mainContent: {
86 | transition: theme.transitions.create('all'),
87 | backgroundColor: theme.palette.mode === 'dark' ? 'transparent' : theme.palette.primary.light,
88 | height: 'calc(100vh - 80px)',
89 | overflowY: 'auto',
90 | flexGrow: 1,
91 | padding: '0px',
92 | paddingTop: '10px',
93 | marginTop: '80px'
94 | },
95 | menuCaption: {
96 | fontSize: '0.875rem',
97 | fontWeight: 500,
98 | color: theme.palette.grey[600],
99 | padding: '6px',
100 | textTransform: 'capitalize',
101 | marginTop: '10px'
102 | },
103 | subMenuCaption: {
104 | fontSize: '0.6875rem',
105 | fontWeight: 500,
106 | color: theme.palette.text.secondary,
107 | textTransform: 'capitalize'
108 | },
109 | commonAvatar: {
110 | cursor: 'pointer',
111 | borderRadius: '8px'
112 | },
113 | smallAvatar: {
114 | width: '22px',
115 | height: '22px',
116 | fontSize: '1rem'
117 | },
118 | mediumAvatar: {
119 | width: '34px',
120 | height: '34px',
121 | fontSize: '1.2rem'
122 | },
123 | largeAvatar: {
124 | width: '44px',
125 | height: '44px',
126 | fontSize: '1.5rem'
127 | }
128 | });
129 |
130 | export default Typography;
131 |
--------------------------------------------------------------------------------
/src/themes/palette.tsx:
--------------------------------------------------------------------------------
1 | import { createTheme, PaletteMode } from '@mui/material';
2 |
3 | import defaultColor from 'assets/scss/_themes-vars.module.scss';
4 |
5 | import { ColorProps } from 'types';
6 |
7 | const Palette = (navType: PaletteMode, presetColor: string) => {
8 | let colors: ColorProps;
9 | switch (presetColor) {
10 | case 'default':
11 | default:
12 | colors = defaultColor;
13 | }
14 |
15 | return createTheme({
16 | palette: {
17 | mode: navType,
18 | common: {
19 | black: colors.darkPaper
20 | },
21 | primary: {
22 | light: navType === 'dark' ? colors.darkPrimaryLight : colors.primaryLight,
23 | main: navType === 'dark' ? colors.darkPrimaryMain : colors.primaryMain,
24 | dark: navType === 'dark' ? colors.darkPrimaryDark : colors.primaryDark,
25 | 200: navType === 'dark' ? colors.darkPrimary200 : colors.primary200,
26 | 800: navType === 'dark' ? colors.darkPrimary800 : colors.primary800
27 | },
28 | secondary: {
29 | light: navType === 'dark' ? colors.darkSecondaryLight : colors.secondaryLight,
30 | main: navType === 'dark' ? colors.darkSecondaryMain : colors.secondaryMain,
31 | dark: navType === 'dark' ? colors.darkSecondaryDark : colors.secondaryDark,
32 | 200: navType === 'dark' ? colors.darkSecondary200 : colors.secondary200,
33 | 800: navType === 'dark' ? colors.darkSecondary800 : colors.secondary800
34 | },
35 | error: {
36 | light: colors.errorLight,
37 | main: colors.errorMain,
38 | dark: colors.errorDark
39 | },
40 | orange: {
41 | light: colors.orangeLight,
42 | main: colors.orangeMain,
43 | dark: colors.orangeDark
44 | },
45 | warning: {
46 | light: colors.warningLight,
47 | main: colors.warningMain,
48 | dark: colors.warningDark
49 | },
50 | success: {
51 | light: colors.successLight,
52 | 200: colors.success200,
53 | main: colors.successMain,
54 | dark: colors.successDark
55 | },
56 | grey: {
57 | 50: colors.grey50,
58 | 100: colors.grey100,
59 | 500: navType === 'dark' ? colors.darkTextSecondary : colors.grey500,
60 | 600: navType === 'dark' ? colors.darkTextTitle : colors.grey900,
61 | 700: navType === 'dark' ? colors.darkTextPrimary : colors.grey700,
62 | 900: navType === 'dark' ? colors.darkTextPrimary : colors.grey900
63 | },
64 | dark: {
65 | light: colors.darkTextPrimary,
66 | main: colors.darkLevel1,
67 | dark: colors.darkLevel2,
68 | 800: colors.darkBackground,
69 | 900: colors.darkPaper
70 | },
71 | text: {
72 | primary: navType === 'dark' ? colors.darkTextPrimary : colors.grey700,
73 | secondary: navType === 'dark' ? colors.darkTextSecondary : colors.grey500,
74 | dark: navType === 'dark' ? colors.darkTextPrimary : colors.grey900,
75 | hint: colors.grey100
76 | },
77 | divider: navType === 'dark' ? colors.darkTextPrimary : colors.grey200,
78 | background: {
79 | paper: navType === 'dark' ? colors.darkLevel2 : colors.paper,
80 | default: navType === 'dark' ? colors.darkPaper : colors.paper
81 | }
82 | }
83 | });
84 | };
85 |
86 | export default Palette;
87 |
--------------------------------------------------------------------------------
/src/layout/MainLayout/Header/SearchSection/index.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { useTheme, Avatar, Modal, Box, Paper, IconButton, InputBase } from '@mui/material';
3 | import SearchIcon from '@mui/icons-material/Search';
4 | import { useDispatch, useSelector } from 'store';
5 | import { updateSearch } from 'store/reducers/sports';
6 |
7 | const SearchSection = () => {
8 | const theme = useTheme();
9 | const dispacth = useDispatch();
10 | const { search } = useSelector((store) => store.sports);
11 | const [open, setOpen] = useState(false);
12 | const handleOpen = () => setOpen(true);
13 | const handleClose = () => setOpen(false);
14 |
15 | return (
16 | <>
17 |
37 |
38 |
39 |
40 |
55 |
63 | dispacth(updateSearch(e.target.value))}
66 | type="search"
67 | placeholder="Search..."
68 | sx={{
69 | ml: 1,
70 | flex: 1,
71 | fontSize: 18,
72 | 'input::placeholder': {
73 | fontSize: 18
74 | }
75 | }}
76 | />
77 |
78 |
79 |
80 |
81 |
82 |
83 | >
84 | );
85 | };
86 |
87 | export default SearchSection;
88 |
--------------------------------------------------------------------------------
/src/serviceWorker.tsx:
--------------------------------------------------------------------------------
1 | const isLocalhost = Boolean(
2 | window.location.hostname === 'localhost' ||
3 | window.location.hostname === '[::1]' ||
4 | window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
5 | );
6 |
7 | const publicURL = process.env.PUBLIC_URL || '';
8 |
9 | export type SWConfigProps = {
10 | onSuccess: (r: ServiceWorkerRegistration) => void;
11 | onUpdate: (s: ServiceWorkerRegistration) => void;
12 | };
13 |
14 | export function register(config: SWConfigProps) {
15 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
16 | const publicUrl = new URL(publicURL, window.location.href);
17 | if (publicUrl.origin !== window.location.origin) {
18 | return;
19 | }
20 |
21 | window.addEventListener('load', () => {
22 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
23 |
24 | if (isLocalhost) {
25 | checkValidServiceWorker(swUrl, config);
26 |
27 | navigator.serviceWorker.ready.then(() => {
28 | console.log();
29 | });
30 | } else {
31 | registerValidSW(swUrl, config);
32 | }
33 | });
34 | }
35 | }
36 |
37 | function registerValidSW(swUrl: string, config: SWConfigProps) {
38 | navigator.serviceWorker
39 | .register(swUrl)
40 | .then((registration) => {
41 | registration.onupdatefound = () => {
42 | const installingWorker = registration.installing;
43 | if (installingWorker == null) {
44 | return;
45 | }
46 | installingWorker.onstatechange = () => {
47 | if (installingWorker.state === 'installed') {
48 | if (navigator.serviceWorker.controller) {
49 | console.log();
50 |
51 | if (config && config.onUpdate) {
52 | config.onUpdate(registration);
53 | }
54 | } else {
55 | console.log('Content is cached for offline use.');
56 |
57 | if (config && config.onSuccess) {
58 | config.onSuccess(registration);
59 | }
60 | }
61 | }
62 | };
63 | };
64 | })
65 | .catch((error) => {
66 | console.error('Error during service worker registration:', error);
67 | });
68 | }
69 |
70 | function checkValidServiceWorker(swUrl: string, config: SWConfigProps) {
71 | fetch(swUrl, {
72 | headers: { 'Service-Worker': 'script' }
73 | })
74 | .then((response) => {
75 | const contentType = response.headers.get('content-type');
76 | if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) {
77 | navigator.serviceWorker.ready.then((registration) => {
78 | registration.unregister().then(() => {
79 | window.location.reload();
80 | });
81 | });
82 | } else {
83 | registerValidSW(swUrl, config);
84 | }
85 | })
86 | .catch(() => {
87 | console.log('No internet connection found. App is running in offline mode.');
88 | });
89 | }
90 |
91 | export function unregister() {
92 | if ('serviceWorker' in navigator) {
93 | navigator.serviceWorker.ready
94 | .then((registration) => {
95 | registration.unregister();
96 | })
97 | .catch((error) => {
98 | console.error(error.message);
99 | });
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/views/auth/ForgotPassword.tsx:
--------------------------------------------------------------------------------
1 | import { Close } from '@mui/icons-material';
2 | import { Divider, Grid, IconButton, Typography, useMediaQuery, useTheme } from '@mui/material';
3 |
4 | import { FormattedMessage } from 'react-intl';
5 |
6 | import { useDispatch } from 'store';
7 | import { ChangePage } from 'store/reducers/menu';
8 |
9 | import LogoSection from 'layout/MainLayout/LogoSection';
10 | import { AuthCardWrapper, AuthWrapper } from 'ui-component';
11 | import AnimateButton from 'ui-component/extended/AnimateButton';
12 | import AuthForgotPassword from './auth-forms/AuthForgotPassword';
13 |
14 | const ForgotPassword = () => {
15 | const theme = useTheme();
16 | const dispatch = useDispatch();
17 | const matchDownSM = useMediaQuery(theme.breakpoints.down('md'));
18 |
19 | return (
20 |
21 |
22 |
23 |
24 |
25 | dispatch(ChangePage(''))}
30 | sx={{ position: 'absolute', right: 0, top: 0, px: 0 }}
31 | >
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | dispatch(ChangePage('login'))} className="h6" sx={{ cursor: 'pointer' }}>
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | );
72 | };
73 |
74 | export default ForgotPassword;
75 |
--------------------------------------------------------------------------------
/src/views/casino/Blackjack/Model.tsx:
--------------------------------------------------------------------------------
1 | export interface PropsType {}
2 |
3 | export enum CardTypes {
4 | spades = 'spades',
5 | hearts = 'hearts',
6 | clubs = 'clubs',
7 | diamonds = 'diamonds'
8 | }
9 |
10 | export interface CardProps {
11 | type: CardTypes;
12 | value: string;
13 | slot: number;
14 | }
15 |
16 | export interface FlipCardsProps {
17 | rank: string;
18 | suit: string;
19 | value: number;
20 | }
21 |
22 | export interface ResProps {
23 | betting: any;
24 | turn: number;
25 | type: string;
26 | game: any | undefined;
27 | }
28 |
29 | export interface CardProp {
30 | index: number;
31 | rank: string;
32 | suit: string;
33 | type: string;
34 | value: number;
35 | }
36 |
37 | export const deck = {
38 | 1: { type: 'spades', value: 'A', slot: 1 },
39 | 2: { type: 'spades', value: '2', slot: 2 },
40 | 3: { type: 'spades', value: '3', slot: 3 },
41 | 4: { type: 'spades', value: '4', slot: 4 },
42 | 5: { type: 'spades', value: '5', slot: 5 },
43 | 6: { type: 'spades', value: '6', slot: 6 },
44 | 7: { type: 'spades', value: '7', slot: 7 },
45 | 8: { type: 'spades', value: '8', slot: 8 },
46 | 9: { type: 'spades', value: '9', slot: 9 },
47 | 10: { type: 'spades', value: '10', slot: 10 },
48 | 11: { type: 'spades', value: 'J', slot: 11 },
49 | 12: { type: 'spades', value: 'Q', slot: 12 },
50 | 13: { type: 'spades', value: 'K', slot: 13 },
51 | 14: { type: 'hearts', value: 'A', slot: 1 },
52 | 15: { type: 'hearts', value: '2', slot: 2 },
53 | 16: { type: 'hearts', value: '3', slot: 3 },
54 | 17: { type: 'hearts', value: '4', slot: 4 },
55 | 18: { type: 'hearts', value: '5', slot: 5 },
56 | 19: { type: 'hearts', value: '6', slot: 6 },
57 | 20: { type: 'hearts', value: '7', slot: 7 },
58 | 21: { type: 'hearts', value: '8', slot: 8 },
59 | 22: { type: 'hearts', value: '9', slot: 9 },
60 | 23: { type: 'hearts', value: '10', slot: 10 },
61 | 24: { type: 'hearts', value: 'J', slot: 11 },
62 | 25: { type: 'hearts', value: 'Q', slot: 12 },
63 | 26: { type: 'hearts', value: 'K', slot: 13 },
64 | 27: { type: 'clubs', value: 'A', slot: 1 },
65 | 28: { type: 'clubs', value: '2', slot: 2 },
66 | 29: { type: 'clubs', value: '3', slot: 3 },
67 | 30: { type: 'clubs', value: '4', slot: 4 },
68 | 31: { type: 'clubs', value: '5', slot: 5 },
69 | 32: { type: 'clubs', value: '6', slot: 6 },
70 | 33: { type: 'clubs', value: '7', slot: 7 },
71 | 34: { type: 'clubs', value: '8', slot: 8 },
72 | 35: { type: 'clubs', value: '9', slot: 9 },
73 | 36: { type: 'clubs', value: '10', slot: 10 },
74 | 37: { type: 'clubs', value: 'J', slot: 11 },
75 | 38: { type: 'clubs', value: 'Q', slot: 12 },
76 | 39: { type: 'clubs', value: 'K', slot: 13 },
77 | 40: { type: 'diamonds', value: 'A', slot: 1 },
78 | 41: { type: 'diamonds', value: '2', slot: 2 },
79 | 42: { type: 'diamonds', value: '3', slot: 3 },
80 | 43: { type: 'diamonds', value: '4', slot: 4 },
81 | 44: { type: 'diamonds', value: '5', slot: 5 },
82 | 45: { type: 'diamonds', value: '6', slot: 6 },
83 | 46: { type: 'diamonds', value: '7', slot: 7 },
84 | 47: { type: 'diamonds', value: '8', slot: 8 },
85 | 48: { type: 'diamonds', value: '9', slot: 9 },
86 | 49: { type: 'diamonds', value: '10', slot: 10 },
87 | 50: { type: 'diamonds', value: 'J', slot: 11 },
88 | 51: { type: 'diamonds', value: 'Q', slot: 12 },
89 | 52: { type: 'diamonds', value: 'K', slot: 13 },
90 | toIcon: (card: CardProps) => {
91 | const icons = {
92 | spades: 'fas fa-spade',
93 | hearts: 'fas fa-heart',
94 | clubs: 'fas fa-club',
95 | diamonds: 'fas fa-diamond'
96 | };
97 | return card === undefined ? icons.spades : icons[card.type];
98 | },
99 | toString: (card: CardProps) => `${card.value}`
100 | } as any;
101 |
--------------------------------------------------------------------------------
/src/assets/images/maintenance/img-error-bg.svg:
--------------------------------------------------------------------------------
1 |
35 |
--------------------------------------------------------------------------------
/src/assets/images/maintenance/img-error-bg-dark.svg:
--------------------------------------------------------------------------------
1 |
35 |
--------------------------------------------------------------------------------
/src/views/sports/component/Betslip/index.tsx:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import { Box, Drawer, IconButton, Stack, Typography, useMediaQuery, useTheme } from '@mui/material';
3 |
4 | import CloseIcon from '@mui/icons-material/Close';
5 | import { IconReceipt } from '@tabler/icons';
6 |
7 | import { FormattedMessage } from 'react-intl';
8 |
9 | import useConfig from 'hooks/useConfig';
10 |
11 | import { useDispatch, useSelector } from 'store';
12 | import { openBetslip } from 'store/reducers/sports';
13 |
14 | import { StyledBadge } from 'ui-component';
15 |
16 | import Tabs from './Tabs';
17 |
18 | const Betslip = () => {
19 | const theme = useTheme();
20 | const { boxShadow } = useConfig();
21 | const dispatch = useDispatch();
22 | const isMobile = useMediaQuery('(max-width:767px)');
23 | const isDesktop = useMediaQuery('(min-width:1440px)');
24 |
25 | const { betslipData, betslipOpen } = useSelector((state) => state.sports);
26 | const width = isMobile ? '100vw' : '370px';
27 | const dWidth = betslipOpen ? width : 0;
28 |
29 | return (
30 |
43 | dispatch(openBetslip(!betslipOpen))}
48 | sx={{
49 | '& .MuiDrawer-paper': {
50 | width: dWidth,
51 | transition: theme.transitions.create('all'),
52 | background: '#191919',
53 | borderLeft: 'none',
54 | boxShadow
55 | }
56 | }}
57 | >
58 |
71 |
72 |
79 |
80 |
89 |
90 |
91 |
92 |
93 | dispatch(openBetslip(!betslipOpen))}>
94 |
95 |
96 |
97 |
98 |
99 |
100 | );
101 | };
102 |
103 | export default memo(Betslip);
104 |
--------------------------------------------------------------------------------
/src/views/pages/Error.tsx:
--------------------------------------------------------------------------------
1 | import { Link } from 'react-router-dom';
2 |
3 | import { useTheme, styled, Button, Card, CardContent, CardMedia, Grid, Typography } from '@mui/material';
4 | import HomeTwoToneIcon from '@mui/icons-material/HomeTwoTone';
5 |
6 | import { HOME_PATH } from 'config';
7 | import { gridSpacing } from 'store/constant';
8 | import AnimateButton from 'ui-component/extended/AnimateButton';
9 |
10 | import imageBlue from 'assets/images/maintenance/img-error-blue.svg';
11 | import imageText from 'assets/images/maintenance/img-error-text.svg';
12 | import imageBackground from 'assets/images/maintenance/img-error-bg.svg';
13 | import imagePurple from 'assets/images/maintenance/img-error-purple.svg';
14 | import imageDarkBackground from 'assets/images/maintenance/img-error-bg-dark.svg';
15 |
16 | const CardMediaWrapper = styled('div')({
17 | maxWidth: 720,
18 | margin: '0 auto',
19 | position: 'relative'
20 | });
21 |
22 | const ErrorWrapper = styled('div')({
23 | maxWidth: 350,
24 | margin: '0 auto',
25 | textAlign: 'center'
26 | });
27 |
28 | const ErrorCard = styled(Card)({
29 | minHeight: '100vh',
30 | display: 'flex',
31 | alignItems: 'center',
32 | justifyContent: 'center'
33 | });
34 |
35 | const CardMediaBlock = styled('img')({
36 | position: 'absolute',
37 | top: 0,
38 | left: 0,
39 | width: '100%',
40 | animation: '3s bounce ease-in-out infinite'
41 | });
42 |
43 | const CardMediaBlue = styled('img')({
44 | position: 'absolute',
45 | top: 0,
46 | left: 0,
47 | width: '100%',
48 | animation: '15s wings ease-in-out infinite'
49 | });
50 |
51 | const CardMediaPurple = styled('img')({
52 | position: 'absolute',
53 | top: 0,
54 | left: 0,
55 | width: '100%',
56 | animation: '12s wings ease-in-out infinite'
57 | });
58 |
59 | const Error = () => {
60 | const theme = useTheme();
61 |
62 | return (
63 |
64 |
65 |
66 |
67 |
68 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | Something is wrong
84 |
85 |
86 |
87 |
88 | The page you are looking was moved, removed, renamed, or might never exist!{' '}
89 |
90 |
91 |
92 |
93 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | );
105 | };
106 |
107 | export default Error;
108 |
--------------------------------------------------------------------------------
/src/views/auth/auth-forms/AuthLogin.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useState } from 'react';
2 |
3 | import {
4 | Box,
5 | Button,
6 | Checkbox,
7 | Divider,
8 | FormControl,
9 | FormControlLabel,
10 | FormHelperText,
11 | Grid,
12 | IconButton,
13 | InputAdornment,
14 | InputLabel,
15 | CircularProgress,
16 | OutlinedInput,
17 | Stack,
18 | Typography,
19 | useTheme
20 | } from '@mui/material';
21 | import Visibility from '@mui/icons-material/Visibility';
22 | import VisibilityOff from '@mui/icons-material/VisibilityOff';
23 |
24 | import ReCAPTCHA from 'react-google-recaptcha';
25 | import { FormattedMessage, useIntl } from 'react-intl';
26 |
27 | import * as Yup from 'yup';
28 | import { Formik } from 'formik';
29 |
30 | import config from 'config';
31 |
32 | import useApi from 'hooks/useApi';
33 | import useConfig from 'hooks/useConfig';
34 | import useScriptRef from 'hooks/useScriptRef';
35 |
36 | import { useDispatch } from 'store';
37 | import { Login } from 'store/reducers/auth';
38 | import { ChangePage } from 'store/reducers/menu';
39 |
40 | import snackbar from 'utils/snackbar';
41 | import AnimateButton from 'ui-component/extended/AnimateButton';
42 | import AuthMetamask from './AuthMetamask';
43 |
44 | const AuthLogin = ({ loginProp, ...others }: { loginProp?: number }) => {
45 | const theme = useTheme();
46 | const scriptedRef = useScriptRef();
47 | const { formatMessage } = useIntl();
48 | const recaptchaInputRef = useRef({}) as any;
49 | const { borderRadius, locale } = useConfig();
50 | const dispatch = useDispatch();
51 | const { login } = useApi();
52 | const [checked, setChecked] = useState(true);
53 | const [recaptcha, setRecaptcha] = useState(null);
54 | const [showPassword, setShowPassword] = useState(false);
55 |
56 | const loginHandler = async (values: { email: string; password: string }, { setErrors, setStatus, setSubmitting }: any) => {
57 | try {
58 | await login(values.email, values.password, recaptcha)
59 | .then(
60 | ({ data }) => onLogin(data),
61 | (err: any) => {
62 | if (scriptedRef.current) {
63 | setStatus({ success: false });
64 | setErrors({ submit: err.message });
65 | setSubmitting(false);
66 | }
67 | if (recaptchaInputRef.current) {
68 | recaptchaInputRef.current.reset();
69 | }
70 | }
71 | )
72 | .catch((error) => {
73 | if (recaptchaInputRef.current) {
74 | recaptchaInputRef.current.reset();
75 | }
76 | });
77 | } catch (err: any) {
78 | if (scriptedRef.current) {
79 | setStatus({ success: false });
80 | setErrors({ submit: err.message });
81 | setSubmitting(false);
82 | }
83 | if (recaptchaInputRef.current) {
84 | recaptchaInputRef.current.reset();
85 | }
86 | }
87 | };
88 |
89 | const handleClickShowPassword = () => {
90 | setShowPassword(!showPassword);
91 | };
92 |
93 | const handleMouseDownPassword = (event: React.SyntheticEvent) => {
94 | event.preventDefault();
95 | };
96 |
97 | const onLogin = (user: any) => {
98 | dispatch(Login(user));
99 | dispatch(ChangePage(''));
100 | snackbar(
101 | <>
102 | You have successfully logged in as a user to {process.env.REACT_APP_NAME}.
103 |
104 | Now you can start to play. Enjoy!
105 | >
106 | );
107 | if (
108 | window.location.pathname.toString().indexOf('blackjack') !== -1 ||
109 | window.location.pathname.toString().indexOf('roulette') !== -1
110 | ) {
111 | window.location.reload();
112 | }
113 | };
114 |
115 | return (
116 |
117 |
118 |
119 | );
120 | };
121 |
122 | export default AuthLogin;
123 |
--------------------------------------------------------------------------------
/src/views/auth/Register.tsx:
--------------------------------------------------------------------------------
1 | import { Close } from '@mui/icons-material';
2 | import { Divider, Grid, IconButton, Stack, Typography, useMediaQuery, useTheme } from '@mui/material';
3 |
4 | import { FormattedMessage } from 'react-intl';
5 |
6 | import { useDispatch } from 'store';
7 | import { ChangePage } from 'store/reducers/menu';
8 |
9 | import LogoSection from 'layout/MainLayout/LogoSection';
10 | import { AuthCardWrapper, AuthWrapper } from 'ui-component';
11 | import AnimateButton from 'ui-component/extended/AnimateButton';
12 | import AuthRegister from './auth-forms/AuthRegister';
13 |
14 | const Register = () => {
15 | const theme = useTheme();
16 | const dispatch = useDispatch();
17 | const matchDownSM = useMediaQuery(theme.breakpoints.down('md'));
18 |
19 | return (
20 |
21 |
22 |
23 |
24 |
25 | dispatch(ChangePage(''))}
30 | sx={{ position: 'absolute', right: 0, top: 0, px: 0 }}
31 | >
32 |
33 |
34 |
35 |
36 |
37 |
38 |
44 |
45 |
46 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | dispatch(ChangePage('login'))} className="h6" sx={{ cursor: 'pointer' }}>
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | );
81 | };
82 |
83 | export default Register;
84 |
--------------------------------------------------------------------------------
/src/assets/fonts/OFL.txt:
--------------------------------------------------------------------------------
1 | Copyright 2001 The Silkscreen Project Authors (https://github.com/googlefonts/silkscreen)
2 |
3 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
4 | This license is copied below, and is also available with a FAQ at:
5 | http://scripts.sil.org/OFL
6 |
7 |
8 | -----------------------------------------------------------
9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10 | -----------------------------------------------------------
11 |
12 | PREAMBLE
13 | The goals of the Open Font License (OFL) are to stimulate worldwide
14 | development of collaborative font projects, to support the font creation
15 | efforts of academic and linguistic communities, and to provide a free and
16 | open framework in which fonts may be shared and improved in partnership
17 | with others.
18 |
19 | The OFL allows the licensed fonts to be used, studied, modified and
20 | redistributed freely as long as they are not sold by themselves. The
21 | fonts, including any derivative works, can be bundled, embedded,
22 | redistributed and/or sold with any software provided that any reserved
23 | names are not used by derivative works. The fonts and derivatives,
24 | however, cannot be released under any other type of license. The
25 | requirement for fonts to remain under this license does not apply
26 | to any document created using the fonts or their derivatives.
27 |
28 | DEFINITIONS
29 | "Font Software" refers to the set of files released by the Copyright
30 | Holder(s) under this license and clearly marked as such. This may
31 | include source files, build scripts and documentation.
32 |
33 | "Reserved Font Name" refers to any names specified as such after the
34 | copyright statement(s).
35 |
36 | "Original Version" refers to the collection of Font Software components as
37 | distributed by the Copyright Holder(s).
38 |
39 | "Modified Version" refers to any derivative made by adding to, deleting,
40 | or substituting -- in part or in whole -- any of the components of the
41 | Original Version, by changing formats or by porting the Font Software to a
42 | new environment.
43 |
44 | "Author" refers to any designer, engineer, programmer, technical
45 | writer or other person who contributed to the Font Software.
46 |
47 | PERMISSION & CONDITIONS
48 | Permission is hereby granted, free of charge, to any person obtaining
49 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
50 | redistribute, and sell modified and unmodified copies of the Font
51 | Software, subject to the following conditions:
52 |
53 | 1) Neither the Font Software nor any of its individual components,
54 | in Original or Modified Versions, may be sold by itself.
55 |
56 | 2) Original or Modified Versions of the Font Software may be bundled,
57 | redistributed and/or sold with any software, provided that each copy
58 | contains the above copyright notice and this license. These can be
59 | included either as stand-alone text files, human-readable headers or
60 | in the appropriate machine-readable metadata fields within text or
61 | binary files as long as those fields can be easily viewed by the user.
62 |
63 | 3) No Modified Version of the Font Software may use the Reserved Font
64 | Name(s) unless explicit written permission is granted by the corresponding
65 | Copyright Holder. This restriction only applies to the primary font name as
66 | presented to the users.
67 |
68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69 | Software shall not be used to promote, endorse or advertise any
70 | Modified Version, except to acknowledge the contribution(s) of the
71 | Copyright Holder(s) and the Author(s) or with their explicit written
72 | permission.
73 |
74 | 5) The Font Software, modified or unmodified, in part or in whole,
75 | must be distributed entirely under this license, and must not be
76 | distributed under any other license. The requirement for fonts to
77 | remain under this license does not apply to any document created
78 | using the Font Software.
79 |
80 | TERMINATION
81 | This license becomes null and void if any of the above conditions are
82 | not met.
83 |
84 | DISCLAIMER
85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93 | OTHER DEALINGS IN THE FONT SOFTWARE.
94 |
--------------------------------------------------------------------------------
/src/views/profile/Wallet/DepositCoinpayment.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef } from 'react';
2 | import { CardContent, Grid, IconButton, CardProps, TextField, InputAdornment, Tooltip, Alert, useTheme } from '@mui/material';
3 | import CloseIcon from '@mui/icons-material/Close';
4 | import ContentCopyTwoToneIcon from '@mui/icons-material/ContentCopyTwoTone';
5 |
6 | import QRCode from 'qrcode.react';
7 | import { FormattedMessage, useIntl } from 'react-intl';
8 | import { CopyToClipboard } from 'react-copy-to-clipboard';
9 |
10 | import snackbar from 'utils/snackbar';
11 |
12 | import { useSelector } from 'store';
13 | import { gridSpacing } from 'store/constant';
14 |
15 | import SubCard from 'ui-component/cards/SubCard';
16 | import MainCard from 'ui-component/cards/MainCard';
17 |
18 | interface Props extends CardProps {
19 | modalStyle: React.CSSProperties;
20 | handleClose: () => void;
21 | depositAddress: string;
22 | }
23 |
24 | const CurrencyList = forwardRef(({ modalStyle, handleClose, depositAddress }: Props, ref: React.Ref) => {
25 | const theme = useTheme();
26 | const { formatMessage } = useIntl();
27 | const { currency } = useSelector((store) => store.auth);
28 | return (
29 |
30 |
44 |
45 |
46 | }
47 | >
48 |
49 |
50 |
51 |
52 |
61 |
62 |
63 |
64 |
72 | snackbar(formatMessage({ id: 'Copied' }))}>
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | )
81 | }}
82 | />
83 |
84 |
85 |
86 | : {currency.minDeposit} {currency.symbol}
87 |
88 |
89 |
90 |
91 |
92 |
93 | );
94 | });
95 |
96 | export default CurrencyList;
97 |
--------------------------------------------------------------------------------
/src/assets/scss/_themes-vars.module.scss:
--------------------------------------------------------------------------------
1 | // paper & background
2 | $paper: #ffffff;
3 |
4 | // primary
5 | $primaryLight: #e3f2fd;
6 | // $primaryMain: #2196f3;
7 | $primaryMain: #384635;
8 | // $primaryDark: #1e88e5;
9 | $primaryDark: #384635;
10 | $primary200: #90caf9;
11 | $primary800: #1565c0;
12 |
13 | // secondary
14 | $secondaryLight: #ede7f6;
15 | $secondaryMain: #673ab7;
16 | $secondaryDark: #5e35b1;
17 | $secondary200: #b39ddb;
18 | $secondary800: #4527a0;
19 |
20 | // success Colors
21 | $successLight: #b9f6ca;
22 | $success200: #69f0ae;
23 | $successMain: #00e676;
24 | $successDark: #00c853;
25 |
26 | // error
27 | $errorLight: #ef9a9a;
28 | $errorMain: #f44336;
29 | $errorDark: #c62828;
30 |
31 | // orange
32 | $orangeLight: #fbe9e7;
33 | $orangeMain: #ffab91;
34 | $orangeDark: #d84315;
35 |
36 | // warning
37 | $warningLight: #fff8e1;
38 | $warningMain: #ffe57f;
39 | $warningDark: #ffc107;
40 |
41 | // grey
42 | $grey50: #fafafa;
43 | $grey100: #f5f5f5;
44 | $grey200: #eeeeee;
45 | $grey300: #e0e0e0;
46 | $grey500: #9e9e9e;
47 | $grey600: #757575;
48 | $grey700: #616161;
49 | $grey900: #212121;
50 |
51 | // ==============================|| DARK THEME VARIANTS ||============================== //
52 |
53 | // paper & background
54 | // $darkBackground: #1a223f; // level 3
55 | // input background
56 | $darkBackground: #202020; // level 3
57 | // $darkPaper: #0a0e16; // level 4
58 | // $darkPaper: #384635; // level 4
59 | $darkPaper: #373636; // level 4
60 |
61 | // dark 800 & 900
62 | // $darkLevel1: #29314f; // level 1
63 | // head button background
64 | $darkLevel1: #191919; // level 1
65 | // $darkLevel2: #212946; // level 2
66 |
67 | // Head Background Color
68 | $darkLevel2: #272727; // level 2
69 |
70 | // primary dark
71 | $darkPrimaryLight: #e3f2fd;
72 | // $darkPrimaryMain: #2196f3;
73 | // button background
74 | $darkPrimaryMain: #8c8c8c;
75 | // $darkPrimaryDark: #1e88e5;
76 | $darkPrimaryDark: #384635;
77 | $darkPrimary200: #90caf9;
78 | $darkPrimary800: #1565c0;
79 |
80 | // secondary dark
81 | $darkSecondaryLight: #d1c4e9;
82 | $darkSecondaryMain: #7c4dff;
83 | $darkSecondaryDark: #651fff;
84 | $darkSecondary200: #b39ddb;
85 | $darkSecondary800: #6200ea;
86 |
87 | // text variants
88 | $darkTextTitle: #d7dcec;
89 | $darkTextPrimary: #bdc8f0;
90 | $darkTextSecondary: #8492c4;
91 |
92 | // ==============================|| JAVASCRIPT ||============================== //
93 |
94 | :export {
95 | // paper & background
96 | paper: $paper;
97 |
98 | // primary
99 | primaryLight: $primaryLight;
100 | primary200: $primary200;
101 | primaryMain: $primaryMain;
102 | primaryDark: $primaryDark;
103 | primary800: $primary800;
104 |
105 | // secondary
106 | secondaryLight: $secondaryLight;
107 | secondary200: $secondary200;
108 | secondaryMain: $secondaryMain;
109 | secondaryDark: $secondaryDark;
110 | secondary800: $secondary800;
111 |
112 | // success
113 | successLight: $successLight;
114 | success200: $success200;
115 | successMain: $successMain;
116 | successDark: $successDark;
117 |
118 | // error
119 | errorLight: $errorLight;
120 | errorMain: $errorMain;
121 | errorDark: $errorDark;
122 |
123 | // orange
124 | orangeLight: $orangeLight;
125 | orangeMain: $orangeMain;
126 | orangeDark: $orangeDark;
127 |
128 | // warning
129 | warningLight: $warningLight;
130 | warningMain: $warningMain;
131 | warningDark: $warningDark;
132 |
133 | // grey
134 | grey50: $grey50;
135 | grey100: $grey100;
136 | grey200: $grey200;
137 | grey300: $grey300;
138 | grey500: $grey500;
139 | grey600: $grey600;
140 | grey700: $grey700;
141 | grey900: $grey900;
142 |
143 | // ==============================|| DARK THEME VARIANTS ||============================== //
144 |
145 | // paper & background
146 | darkPaper: $darkPaper;
147 | darkBackground: $darkBackground;
148 |
149 | // dark 800 & 900
150 | darkLevel1: $darkLevel1;
151 | darkLevel2: $darkLevel2;
152 |
153 | // text variants
154 | darkTextTitle: $darkTextTitle;
155 | darkTextPrimary: $darkTextPrimary;
156 | darkTextSecondary: $darkTextSecondary;
157 |
158 | // primary dark
159 | darkPrimaryLight: $darkPrimaryLight;
160 | darkPrimaryMain: $darkPrimaryMain;
161 | darkPrimaryDark: $darkPrimaryDark;
162 | darkPrimary200: $darkPrimary200;
163 | darkPrimary800: $darkPrimary800;
164 |
165 | // secondary dark
166 | darkSecondaryLight: $darkSecondaryLight;
167 | darkSecondaryMain: $darkSecondaryMain;
168 | darkSecondaryDark: $darkSecondaryDark;
169 | darkSecondary200: $darkSecondary200;
170 | darkSecondary800: $darkSecondary800;
171 | }
172 |
--------------------------------------------------------------------------------
/src/types/sports.ts:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 |
3 | export const inintSportsData = {
4 | _id: '',
5 | SportId: 0,
6 | SportName: '',
7 | color: '',
8 | count: 0,
9 | icon: '',
10 | img: '',
11 | live: true,
12 | upcoming: true
13 | };
14 |
15 | export const initEvents = {
16 | _id: '',
17 | id: 0,
18 | home: {
19 | id: 0,
20 | image_id: 0,
21 | cc: '',
22 | name: ''
23 | },
24 | away: {
25 | id: 0,
26 | image_id: 0,
27 | cc: '',
28 | name: ''
29 | },
30 | league: {
31 | id: 0,
32 | image_id: 0,
33 | cc: '',
34 | name: ''
35 | },
36 | sport_id: 0,
37 | ss: '',
38 | time: Date.now() / 1000,
39 | timer: {},
40 | odds: {},
41 | scores: {},
42 | time_status: 1
43 | };
44 |
45 | export enum OddTypes {
46 | Home = 'home',
47 | Away = 'away',
48 | Draw = 'draw',
49 | Over = 'over',
50 | Under = 'under'
51 | }
52 |
53 | export interface SportsParamsProps {
54 | sportsId?: number;
55 | tabId?: number;
56 | }
57 |
58 | export interface SportsListProps {
59 | _id: string;
60 | SportId: number;
61 | SportName: string;
62 | color: string;
63 | count: number;
64 | icon: string;
65 | img: string;
66 | live: boolean;
67 | upcoming: boolean;
68 | }
69 |
70 | export interface SportsTeamProps {
71 | id: number;
72 | image_id: number;
73 | cc: string;
74 | name: string;
75 | }
76 |
77 | export interface SportsLeagueProps {
78 | id: number;
79 | cc: string;
80 | name: string;
81 | }
82 |
83 | export interface SportsEventProps {
84 | _id: string;
85 | id: number;
86 | home: SportsTeamProps;
87 | away: SportsTeamProps;
88 | league: SportsLeagueProps;
89 | sport_id: number;
90 | time_status: number;
91 | time: number;
92 | odds: any;
93 | timer: any | undefined;
94 | scores: any | undefined;
95 | ss: string | undefined;
96 | }
97 |
98 | export interface SportsMatchProps {
99 | LeagueId: number;
100 | LeagueName: string;
101 | events: SportsEventProps[];
102 | }
103 |
104 | export interface TabProps {
105 | index?: number;
106 | title?: string;
107 | status?: string;
108 | icon?: ReactNode;
109 | }
110 |
111 | export interface LockProps {
112 | item: any;
113 | sports: SportsListProps | undefined;
114 | isLive: boolean;
115 | event: SportsEventProps;
116 | }
117 |
118 | export interface EventProps {
119 | event: SportsEventProps;
120 | activeSports: SportsListProps | undefined;
121 | isLive: boolean;
122 | }
123 |
124 | export interface MarketDataProps {
125 | id: string;
126 | ss: string;
127 | notUpdate: number;
128 | add_time: string;
129 | time_str: string;
130 | home_od?: string | undefined;
131 | away_od?: string | undefined;
132 | draw_od?: string | undefined;
133 | over_od?: string | undefined;
134 | under_od?: string | undefined;
135 | handicap?: string | undefined;
136 | }
137 |
138 | export interface MarketProps {
139 | id: string;
140 | name: string;
141 | home: string;
142 | away: string;
143 | league: string;
144 | marketId: string;
145 | data: MarketDataProps;
146 | }
147 |
148 | export interface BetslipProps {
149 | AwayTeam: string;
150 | HomeTeam: string;
151 | LeagueId: number;
152 | LeagueName: string;
153 | SportId: number;
154 | SportName: string;
155 | Time: number;
156 | TimeStatus: number;
157 | eventId: number;
158 | marketId: string;
159 | marketName: string;
160 | oddData: oddProps;
161 | oddId: string;
162 | oddName: string;
163 | oddType: OddTypes;
164 | odds: number;
165 | sports: SportsListProps;
166 | stake: number;
167 | potential: number;
168 | }
169 |
170 | export interface SportsProps {
171 | betslipData: BetslipProps[];
172 | liveMatches: any[];
173 | recentBets: any[];
174 | betAmount: number;
175 | betslipOpen: boolean;
176 | search: string;
177 | }
178 |
179 | export interface oddProps {
180 | id: string;
181 | marketId: string;
182 | marketName: string;
183 | add_time: string;
184 | ss: string | null;
185 | time_str: string | null;
186 | home_od?: string | undefined;
187 | away_od?: string | undefined;
188 | draw_od?: string | undefined;
189 | over_od?: string | undefined;
190 | under_od?: string | undefined;
191 | handicap?: string | undefined;
192 | }
193 |
194 | export interface SelectOddProps {
195 | event: SportsEventProps;
196 | odd: oddProps;
197 | oddType: OddTypes;
198 | sports: SportsListProps;
199 | }
200 |
--------------------------------------------------------------------------------
/src/ui-component/extended/Snackbar.tsx:
--------------------------------------------------------------------------------
1 | import { SyntheticEvent } from 'react';
2 |
3 | import { Alert, Button, Fade, Grow, IconButton, Slide, SlideProps, Snackbar as MuiSnackbar } from '@mui/material';
4 |
5 | import CloseIcon from '@mui/icons-material/Close';
6 |
7 | import { KeyedObject } from 'types';
8 | import { useDispatch, useSelector } from 'store';
9 | import { closeSnackbar } from 'store/reducers/snackbar';
10 |
11 | function TransitionSlideLeft(props: SlideProps) {
12 | return ;
13 | }
14 |
15 | function TransitionSlideUp(props: SlideProps) {
16 | return ;
17 | }
18 |
19 | function TransitionSlideRight(props: SlideProps) {
20 | return ;
21 | }
22 |
23 | function TransitionSlideDown(props: SlideProps) {
24 | return ;
25 | }
26 |
27 | function GrowTransition(props: SlideProps) {
28 | return ;
29 | }
30 |
31 | const animation: KeyedObject = {
32 | SlideLeft: TransitionSlideLeft,
33 | SlideUp: TransitionSlideUp,
34 | SlideRight: TransitionSlideRight,
35 | SlideDown: TransitionSlideDown,
36 | Grow: GrowTransition,
37 | Fade
38 | };
39 |
40 | const Snackbar = () => {
41 | const dispatch = useDispatch();
42 | const snackbar = useSelector((state) => state.snackbar);
43 | const { actionButton, anchorOrigin, alert, close, message, open, transition, variant } = snackbar;
44 |
45 | const handleClose = (event: SyntheticEvent | Event, reason?: string) => {
46 | if (reason === 'clickaway') {
47 | return;
48 | }
49 | dispatch(closeSnackbar());
50 | };
51 |
52 | return (
53 | <>
54 | {/* default snackbar */}
55 | {variant === 'default' && (
56 |
68 |
71 |
72 |
73 |
74 | >
75 | }
76 | />
77 | )}
78 |
79 | {/* alert snackbar */}
80 | {variant === 'alert' && (
81 |
91 |
96 | {actionButton !== false && (
97 |
100 | )}
101 | {close !== false && (
102 |
103 |
104 |
105 | )}
106 | >
107 | }
108 | sx={{
109 | ...(alert.variant === 'outlined' && {
110 | bgcolor: 'background.paper'
111 | })
112 | }}
113 | >
114 | {message}
115 |
116 |
117 | )}
118 | >
119 | );
120 | };
121 |
122 | export default Snackbar;
123 |
--------------------------------------------------------------------------------
/src/types/default-theme.ts:
--------------------------------------------------------------------------------
1 | import { Color, PaletteMode } from '@mui/material';
2 | import { Property } from 'csstype';
3 |
4 | export interface CustomizationProps {
5 | fontFamily: Property.FontFamily;
6 | borderRadius?: number;
7 | navType: PaletteMode;
8 | presetColor?: string;
9 | rtlLayout?: boolean;
10 | outlinedFilled?: boolean;
11 | }
12 |
13 | export interface CustomShadowProps {
14 | z1: string;
15 | z8: string;
16 | z12: string;
17 | z16: string;
18 | z20: string;
19 | z24: string;
20 | primary: string;
21 | secondary: string;
22 | orange: string;
23 | success: string;
24 | warning: string;
25 | error: string;
26 | }
27 |
28 | export interface CustomTypography {
29 | customInput?: {
30 | marginTop: number;
31 | marginBottom: number;
32 | '& > label': {
33 | top: string;
34 | left: number;
35 | color?: Color | (Color | undefined)[] | Color[];
36 | '&[data-shrink="false"]': {
37 | top: string;
38 | };
39 | };
40 | '& > div > input': {
41 | padding: string;
42 | };
43 | '& legend': {
44 | display: string;
45 | };
46 | '& fieldset': {
47 | top: number;
48 | };
49 | };
50 | mainContent?: {
51 | backgroundColor?: string;
52 | width: string;
53 | minHeight: string;
54 | flexGrow: number;
55 | padding: string;
56 | marginTop: string;
57 | marginRight: string;
58 | borderRadius: string;
59 | };
60 | menuCaption?: {
61 | fontSize: string;
62 | fontWeight: number;
63 | color?: Color | (Color | undefined)[] | Color[];
64 | padding: string;
65 | textTransform: 'uppercase' | 'lowercase' | 'capitalize' | 'inherit';
66 | marginTop: string;
67 | };
68 | subMenuCaption?: {
69 | fontSize: string;
70 | fontWeight: number;
71 | color: Color | (Color | undefined)[] | Color[];
72 | textTransform: 'uppercase' | 'lowercase' | 'capitalize' | 'inherit';
73 | };
74 | commonAvatar?: {
75 | cursor: string;
76 | borderRadius: string;
77 | };
78 | smallAvatar?: {
79 | width: string;
80 | height: string;
81 | fontSize: string;
82 | };
83 | mediumAvatar?: {
84 | width: string;
85 | height: string;
86 | fontSize: string;
87 | };
88 | largeAvatar?: {
89 | width: string;
90 | height: string;
91 | fontSize: string;
92 | };
93 | heading?: string;
94 | textDark?: string;
95 | grey900?: string;
96 | grey800?: string;
97 | grey700?: string;
98 | grey600?: string;
99 | grey500?: string;
100 | grey400?: string;
101 | grey300?: string;
102 | grey200?: string;
103 | grey100?: string;
104 | grey50?: string;
105 | secondaryLight?: string;
106 | secondary200?: string;
107 | secondaryDark?: string;
108 | secondaryMain?: string;
109 | background?: string;
110 | darkPrimaryLight?: string;
111 | darkPrimaryMain?: string;
112 | darkPrimaryDark?: string;
113 | darkSecondaryMain?: string;
114 | darkSecondaryLight?: string;
115 | darkSecondary800?: string;
116 | darkSecondary200?: string;
117 | darkSecondaryDark?: string;
118 | secondary800?: string;
119 | darkPrimary800?: string;
120 | darkPrimary200?: string;
121 | darkLevel2?: string;
122 | darkLevel1?: string;
123 | darkPaper?: string;
124 | darkTextPrimary?: string;
125 | darkTextSecondary?: string;
126 | darkBackground?: string;
127 | primaryDark?: string;
128 | primary800?: string;
129 | primary200?: string;
130 | primaryLight?: string;
131 | primaryMain?: string;
132 | colors?: CustomTypography;
133 | paper?: string;
134 | backgroundDefault?: string;
135 | menuSelected?: string;
136 | menuSelectedBack?: string;
137 | divider?: string;
138 | customization?: CustomizationProps;
139 | z1?: string;
140 | z8?: string;
141 | z12?: string;
142 | z16?: string;
143 | z20?: string;
144 | z24?: string;
145 | primary?: string;
146 | secondary?: string;
147 | orange?: string;
148 | orangeLight?: string;
149 | orangeMain?: string;
150 | orangeDark?: string;
151 | successLight?: string;
152 | success200?: string;
153 | successMain?: string;
154 | successDark?: string;
155 | success?: string;
156 | warning?: string;
157 | error?: string;
158 | errorLight?: string;
159 | errorMain?: string;
160 | errorDark?: string;
161 | warningLight?: string;
162 | warningMain?: string;
163 | warningDark?: string;
164 | }
165 |
--------------------------------------------------------------------------------
/src/layout/UserLayout/NavItem.tsx:
--------------------------------------------------------------------------------
1 | import React, { memo, useEffect, useState } from 'react';
2 | import { useLocation, useNavigate } from 'react-router-dom';
3 |
4 | import { CardContent, Grid, Tab, Tabs, Typography, useTheme } from '@mui/material';
5 | import SettingsIcon from '@mui/icons-material/SettingsTwoTone';
6 | import CreditCardIcon from '@mui/icons-material/CreditCardTwoTone';
7 | import EmojiEventsIcon from '@mui/icons-material/EmojiEventsTwoTone';
8 | import PersonOutlineIcon from '@mui/icons-material/PersonOutlineTwoTone';
9 |
10 | import { FormattedMessage } from 'react-intl';
11 |
12 | import useConfig from 'hooks/useConfig';
13 | import config from 'config';
14 |
15 | function a11yProps(index: number) {
16 | return {
17 | id: `simple-tab-${index}`,
18 | 'aria-controls': `simple-tabpanel-${index}`
19 | };
20 | }
21 |
22 | const tabsOption = [
23 | {
24 | label: ,
25 | link: '/user/wallet',
26 | icon:
27 | },
28 | {
29 | label: ,
30 | link: '/user/account',
31 | icon:
32 | },
33 | {
34 | label: ,
35 | link: '/user/referral',
36 | icon:
37 | },
38 | {
39 | label: ,
40 | link: '/user/preferences',
41 | icon:
42 | }
43 | ];
44 |
45 | const NavItem = () => {
46 | const theme = useTheme();
47 | const { borderRadius } = useConfig();
48 | const [value, setValue] = useState(0);
49 | const navigate = useNavigate();
50 | const { pathname } = useLocation();
51 |
52 | const handleChange = (event: React.SyntheticEvent, newValue: number) => {
53 | navigate(tabsOption[newValue].link);
54 | setValue(newValue);
55 | };
56 | useEffect(() => {
57 | const currentIndex = tabsOption.findIndex((e) => document.location.pathname.toString() === e.link);
58 | if (currentIndex !== -1) {
59 | setValue(currentIndex);
60 | }
61 | }, [pathname]);
62 |
63 | return (
64 |
65 | svg': {
95 | marginBottom: '0px !important',
96 | marginRight: 1.25,
97 | height: 20,
98 | width: 20
99 | },
100 | '& button > div > span': {
101 | display: 'block'
102 | },
103 | '& > div > span': {
104 | display: 'none'
105 | }
106 | }}
107 | >
108 | {tabsOption.map((tab, index) => (
109 |
114 |
115 | {tab.label}
116 |
117 |
118 | }
119 | {...a11yProps(index)}
120 | />
121 | ))}
122 |
123 |
124 | );
125 | };
126 |
127 | export default memo(NavItem);
128 |
--------------------------------------------------------------------------------