Commit 8d123a5c by Arjun Jhukal

Merge branch 'main' into 'ui/slider'

# Conflicts:
#   src/app/globals.css
parents 417568f9 3868fb5b
import PageHeader from '@/components/molecules/PageHeader' import PageHeader from '@/components/molecules/PageHeader'
import GeneralPageLiting from '@/components/pages/dashboard/adminDashboard/pages'
import React from 'react' import React from 'react'
export default function AllPages() { export default function AllPages() {
return ( return (
<> <>
<PageHeader title='All Pages' cta={{ label: "Add New Page", url: "/pages/add-page" }} /> <PageHeader title='All Pages' cta={{ label: "Add New Page", url: "/pages/add-page" }} />
<GeneralPageLiting />
</> </>
) )
} }
import React from 'react'
import React from "react";
import { Box, Skeleton } from "@mui/material";
export default function Loading() { export default function Loading() {
return ( return (
<div>loading</div> <section className="detail__banner mb-8 animate-pulse">
) <div className="grid grid-cols-12 gap-8 lg:gap-20">
{/* Left Image Skeleton */}
<div className="col-span-12 md:col-span-4">
<Box className="aspect-[420/433] relative rounded-xl overflow-hidden">
<Skeleton variant="rectangular" width="100%" height="100%" sx={{ borderRadius: "12px" }} />
</Box>
</div>
{/* Right Content Skeleton */}
<div className="col-span-12 md:col-span-8 flex flex-col gap-4">
{/* Tags */}
<div className="flex gap-4">
<Skeleton variant="rounded" width={120} height={24} />
<Skeleton variant="rounded" width={80} height={24} />
</div>
{/* Title */}
<Skeleton variant="text" width="60%" height={40} />
{/* Description */}
<Skeleton variant="text" width="100%" height={20} />
<Skeleton variant="text" width="95%" height={20} />
<Skeleton variant="text" width="90%" height={20} />
{/* Action Buttons */}
<div className="flex gap-2 flex-wrap">
<Skeleton variant="rounded" width={160} height={50} />
<Skeleton variant="rounded" width={160} height={50} />
<Skeleton variant="rounded" width={160} height={50} />
</div>
{/* Play Now Button */}
<Skeleton variant="rounded" width={180} height={45} />
{/* Screenshots */}
<div className="grid grid-cols-3 gap-2">
{[1, 2, 3].map((i) => (
<Skeleton key={i} variant="rectangular" height={100} sx={{ borderRadius: "8px" }} />
))}
</div>
</div>
</div>
</section>
);
} }
import { getPageDetail } from '@/serverApi/pages';
import { renderHTML } from '@/utils/RenderHTML';
import { ArrowRight2 } from '@wandersonalwes/iconsax-react';
import { notFound, redirect } from 'next/navigation';
import React from 'react'
export default async function GeneralPage(props: { params: Promise<{ slug: string }> }) {
const { slug } = await props.params;
let pageData = null;
console.log(pageData);
try {
pageData = await getPageDetail(slug);
} catch (err) {
console.log("❌ Failed to fetch games:", err);
return notFound();
}
if (!pageData?.data) {
return notFound();
}
return (
<section className="general__page__root">
<div className="section__title mb-6">
<h1 className='text-[24px] leading-[120%]'>{pageData?.data?.name}</h1>
</div>
<div className="page__content">
<div className="grid grid-cols-12 gap-5">
{/* <div className="col-span-12 md:col-span lg:col-span-3">
{pageData?.data?.content.length ? <div className="rounded-[24px] p-4" style={{
background: "rgba(118, 107, 120, 0.55)"
}}>
<ul>
{pageData.data.content.map((content) => (
<li key={content.heading}>
<a href="#" className='text-[14px] font-[500] leading-[120%] py-2 px-3 flex items-center gap-1'><ArrowRight2 size={14} />{content?.heading}</a>
</li>
))}
</ul>
</div> : ""}
</div> */}
<div className="col-span-12">
<div className="general-content-box">
{pageData.data.content.map((content) => (
renderHTML(content.description)))}
</div>
</div>
</div>
</div>
</section>
)
}
import DepositHistoryPage from '@/components/pages/dashboard/userDashboard/depositHistory'
import React from 'react'
export default function DepositHistory() {
return (
<DepositHistoryPage />
)
}
import AddPlayerPage from '@/components/pages/dashboard/adminDashboard/players/addPlayerForm';
import AddPlayerForm from '@/components/pages/dashboard/adminDashboard/players/addPlayerForm/AddPlayerForm';
import EditUserProfile from '@/components/pages/dashboard/userDashboard/account/profile/editProfile';
import React from 'react'
export default async function UserAccountUpdate(props: { params: Promise<{ id: string }> }) {
const { id } = await props.params;
return (
<EditUserProfile id={id} />
)
}
import EditUserWallet from '@/components/pages/dashboard/userDashboard/account/profile/editUserWallet'
import { Button, InputLabel, OutlinedInput } from '@mui/material'
import { InfoCircle, WalletCheck } from '@wandersonalwes/iconsax-react'
import React from 'react'
export default function UserWallet() {
return (
<EditUserWallet />
)
}
"use client"; // "use client";
import TabController from "@/components/molecules/TabController"; import TabController from "@/components/molecules/TabController";
import UserProfileCard from "@/components/organism/Cards/UserProfileCard"; import UserProfileCard from "@/components/organism/Cards/UserProfileCard";
import Link from "next/link"; import { getUserGameBalance } from "@/serverApi/game";
import { usePathname } from "next/navigation";
export default function ProfileTabs({ section }: { section: React.ReactNode }) {
const pathname = usePathname();
export default async function ProfileTabs({ section }: { section: React.ReactNode }) {
const balance = await getUserGameBalance();
const links = [ const links = [
{ href: "/account/profile/account", label: "Account Details" }, { href: "/account/profile/account", label: "Account Details" },
{ href: "/account/profile/wallet", label: "Wallet Information" }, { href: "/account/profile/wallet", label: "Wallet Information" },
...@@ -19,7 +18,7 @@ export default function ProfileTabs({ section }: { section: React.ReactNode }) { ...@@ -19,7 +18,7 @@ export default function ProfileTabs({ section }: { section: React.ReactNode }) {
<div className='profile__root'> <div className='profile__root'>
<div className="grid lg:grid-cols-12 gap-6"> <div className="grid lg:grid-cols-12 gap-6">
<div className="col-span-12 lg:col-span-5"> <div className="col-span-12 lg:col-span-5">
<UserProfileCard /> <UserProfileCard balance={balance} />
</div> </div>
<div className="col-span-12 lg:col-span-7"> <div className="col-span-12 lg:col-span-7">
<TabController links={links} /> <TabController links={links} />
......
import React from 'react' import { redirect } from 'next/navigation';
export default function ProfilePage() { export default function ProfilePage() {
return ( return redirect("/account/profile/account");
<div>ProfilePage</div>
)
} }
import WithdrawnHistoryPage from '@/components/pages/dashboard/userDashboard/withdrawlHistory'
import React from 'react'
export default function WithdrawlHistory() {
return (
<WithdrawnHistoryPage />
)
}
...@@ -24,7 +24,7 @@ export default function RootLayout({ ...@@ -24,7 +24,7 @@ export default function RootLayout({
return ( return (
<html lang="en"> <html lang="en">
{/* className="dark" */} {/* className="dark" */}
<body className={`${inter.className} scroll-smooth dark`}> <body className={`${inter.className} scroll-smooth dark`} cz-shortcut-listen="true">
<ProviderWrapper> <ProviderWrapper>
{children} {children}
......
"use client"; "use client";
import { useThemeContext } from "@/context/ThemeContext";
import { InputLabel } from "@mui/material"; import { InputLabel } from "@mui/material";
import React from "react"; import React from "react";
...@@ -32,6 +33,8 @@ export default function SelectField({ ...@@ -32,6 +33,8 @@ export default function SelectField({
error, error,
touched, touched,
}: SelectFieldProps) { }: SelectFieldProps) {
const theme = useThemeContext();
console.log("theme", theme);
return ( return (
<div className="input__field"> <div className="input__field">
<InputLabel className="block text-sm font-semibold mb-2"> <InputLabel className="block text-sm font-semibold mb-2">
......
...@@ -5,7 +5,7 @@ import { formatDateTime } from '@/utils/formatDateTime'; ...@@ -5,7 +5,7 @@ import { formatDateTime } from '@/utils/formatDateTime';
import Image from 'next/image' import Image from 'next/image'
import React from 'react' import React from 'react'
export default function UserProfileCard() { export default function UserProfileCard({ balance }: { balance: any }) {
const user = useAppSelector(state => state.auth.user); const user = useAppSelector(state => state.auth.user);
const { date } = formatDateTime(user?.registered_date as string); const { date } = formatDateTime(user?.registered_date as string);
return ( return (
...@@ -26,7 +26,7 @@ export default function UserProfileCard() { ...@@ -26,7 +26,7 @@ export default function UserProfileCard() {
<div className="flex justify-center items-center gap-3"> <div className="flex justify-center items-center gap-3">
<Image src={"/assets/images/current-balance.svg"} alt='' width={48} height={48} /> <Image src={"/assets/images/current-balance.svg"} alt='' width={48} height={48} />
<div className="content mt-3 text-start"> <div className="content mt-3 text-start">
<strong className="text-[12px] leading-[120%] font-[700] text-white block ">$30,000</strong> <strong className="text-[12px] leading-[120%] font-[700] text-white block ">${balance?.data?.current_balance}</strong>
<span className="text-white text-[9px]">Current Balance</span> <span className="text-white text-[9px]">Current Balance</span>
</div> </div>
</div> </div>
...@@ -35,22 +35,22 @@ export default function UserProfileCard() { ...@@ -35,22 +35,22 @@ export default function UserProfileCard() {
<div className="w-full rounded-[14px] p-4 lg:py-6" style={{ background: "rgba(191, 26, 198, 0.10)" }}> <div className="w-full rounded-[14px] p-4 lg:py-6" style={{ background: "rgba(191, 26, 198, 0.10)" }}>
<Image src={"/assets/images/deposit.svg"} alt='' width={48} height={48} className='mx-auto' /> <Image src={"/assets/images/deposit.svg"} alt='' width={48} height={48} className='mx-auto' />
<div className="content mt-3 "> <div className="content mt-3 ">
<strong className="text-[12px] leading-[120%] font-[700] text-white block ">$30,000</strong> <strong className="text-[12px] leading-[120%] font-[700] text-white block ">${balance?.data?.total_deposit}</strong>
<span className="text-white text-[9px]">Current Balance</span> <span className="text-white text-[9px]">Total Deposited</span>
</div> </div>
</div> </div>
<div className="w-full rounded-[14px] p-4 lg:py-6" style={{ background: "rgba(191, 26, 198, 0.10)" }}> <div className="w-full rounded-[14px] p-4 lg:py-6" style={{ background: "rgba(191, 26, 198, 0.10)" }}>
<Image src={"/assets/images/withdrawn.svg"} alt='' width={48} height={48} className='mx-auto' /> <Image src={"/assets/images/withdrawn.svg"} alt='' width={48} height={48} className='mx-auto' />
<div className="content mt-3"> <div className="content mt-3">
<strong className="text-[12px] leading-[120%] font-[700] text-white block ">$30,000</strong> <strong className="text-[12px] leading-[120%] font-[700] text-white block ">$3{balance?.data?.total_withdrawl}</strong>
<span className="text-white text-[9px]">Current Balance</span> <span className="text-white text-[9px]">Total Withdrawl</span>
</div> </div>
</div> </div>
<div className="w-full rounded-[14px] p-4 lg:py-6" style={{ background: "rgba(191, 26, 198, 0.10)" }}> <div className="w-full rounded-[14px] p-4 lg:py-6" style={{ background: "rgba(191, 26, 198, 0.10)" }}>
<Image src={"/assets/images/withdrawn.svg"} alt='' width={48} height={48} className='mx-auto' /> <Image src={"/assets/images/withdrawn.svg"} alt='' width={48} height={48} className='mx-auto' />
<div className="content mt-3"> <div className="content mt-3">
<strong className="text-[12px] leading-[120%] font-[700] text-white block ">$30,000</strong> <strong className="text-[12px] leading-[120%] font-[700] text-white block ">${balance?.data?.total_wining || 0}</strong>
<span className="text-white text-[9px]">Current Balance</span> <span className="text-white text-[9px]">Total Winnings</span>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -3,15 +3,15 @@ import { Transitions } from '@/components/molecules/Transition'; ...@@ -3,15 +3,15 @@ import { Transitions } from '@/components/molecules/Transition';
import { useAppDispatch, useAppSelector } from '@/hooks/hook'; import { useAppDispatch, useAppSelector } from '@/hooks/hook';
import { PATH } from '@/routes/PATH'; import { PATH } from '@/routes/PATH';
import { clearTokens } from '@/slice/authSlice'; import { clearTokens } from '@/slice/authSlice';
import { Box, Button, ButtonBase, ClickAwayListener, Fade, List, ListItem, ListItemText, Paper, Popper, Stack, Typography } from '@mui/material' import { Box, Button, ButtonBase, ClickAwayListener, Fade, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Paper, Popper, Stack, Typography } from '@mui/material'
import { ArrowDown2 } from '@wandersonalwes/iconsax-react';
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import React, { useRef, useState } from 'react' import React, { useRef, useState } from 'react'
import UserProfileMenu from './UserProfileMenu';
const avataur1 = '/assets/images/avatar-6.png'; const avataur1 = '/assets/images/avatar-6.png';
import { ArrowDown2, ArrowUp2, Coin, Logout, MoneySend, Profile, Wallet2 } from "@wandersonalwes/iconsax-react";
export default function Profile() {
export default function ProfileBlock() {
const anchorRef = useRef<any>(null); const anchorRef = useRef<any>(null);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const handleToggle = () => { const handleToggle = () => {
...@@ -27,6 +27,39 @@ export default function Profile() { ...@@ -27,6 +27,39 @@ export default function Profile() {
setOpen(false); setOpen(false);
}; };
const id = open ? 'profile-dropdown' : "" const id = open ? 'profile-dropdown' : ""
const menuItems = [
{
label: "Profile",
href: "/account/profile/account",
icon: <Profile size="20" />,
},
{
label: "Game Credentials",
href: "/credentials",
icon: <Wallet2 size="20" />,
},
{
label: "Deposit History",
href: "/account/deposit-history",
icon: <Coin size="20" />,
},
{
label: "Withdraw History",
href: "/account/withdrawl-history",
icon: <MoneySend size="20" />,
},
{
label: "Logout",
href: "#",
icon: <Logout size="20" />,
onClick: (e: React.MouseEvent) => {
e.preventDefault();
dispatch(clearTokens());
router.replace("/login");
},
},
];
return ( return (
<Box > <Box >
<Button <Button
...@@ -103,7 +136,21 @@ export default function Profile() { ...@@ -103,7 +136,21 @@ export default function Profile() {
</ListItem> </ListItem>
</List> </List>
) : ( ) : (
<UserProfileMenu /> <List>
{menuItems.map((item, idx) => (
<ListItem key={idx} disablePadding>
<ListItemButton
component={item.href ? Link : "button"}
href={item.href || undefined}
onClick={item.onClick}
className={`flex items-center py-3 px-4 hover:bg-[#FBF4FB]`}
>
<ListItemIcon className="min-w-[30px] mr-1">{item.icon}</ListItemIcon>
<ListItemText primary={item.label} />
</ListItemButton>
</ListItem>
))}
</List>
) )
} }
......
import { List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useAppDispatch } from "@/hooks/hook";
import { clearTokens } from "@/slice/authSlice";
import { ArrowDown2, ArrowUp2, Coin, Logout, MoneySend, Profile, Wallet2 } from "@wandersonalwes/iconsax-react";
const UserProfileMenu = () => {
const router = useRouter();
const dispatch = useAppDispatch();
const menuItems = [
{
label: "Profile",
href: "/account/profile/account",
icon: <Profile size="20" />,
},
{
label: "Game Credentials",
href: "/credentials",
icon: <Wallet2 size="20" />,
},
{
label: "Deposit History",
href: "/account/deposit-history",
icon: <Coin size="20" />,
},
{
label: "Withdraw History",
href: "/account/withdrawl-history",
icon: <MoneySend size="20" />,
},
{
label: "Logout",
href: "#",
icon: <Logout size="20" />,
onClick: (e: React.MouseEvent) => {
e.preventDefault();
dispatch(clearTokens());
router.replace("/login");
},
},
];
return (
<List>
{menuItems.map((item, idx) => (
<ListItem key={idx} disablePadding>
<ListItemButton
component={item.href ? Link : "button"}
href={item.href || undefined}
onClick={item.onClick}
className={`flex items-center py-3 px-4 hover:bg-[#FBF4FB]`}
>
<ListItemIcon className="min-w-[30px] mr-1">{item.icon}</ListItemIcon>
<ListItemText primary={item.label} />
</ListItemButton>
</ListItem>
))}
</List>
);
};
export default UserProfileMenu;
...@@ -60,7 +60,7 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -60,7 +60,7 @@ export default function UserMenu({ open }: { open: boolean }) {
/> />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
<ListItem> {/* <ListItem>
<ListItemButton <ListItemButton
className={[ className={[
open ? "expanded" : "collapsed", open ? "expanded" : "collapsed",
...@@ -81,7 +81,7 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -81,7 +81,7 @@ export default function UserMenu({ open }: { open: boolean }) {
className={open ? "expanded" : "collapsed"} className={open ? "expanded" : "collapsed"}
/> />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem> */}
</List> </List>
<List> <List>
<ListItem> <ListItem>
...@@ -89,13 +89,11 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -89,13 +89,11 @@ export default function UserMenu({ open }: { open: boolean }) {
className={[ className={[
open ? "expanded" : "collapsed", open ? "expanded" : "collapsed",
[ [
PATH.ADMIN.GAMES.ROOT, PATH.USER.GENERAL_PAGES.REFUND_POLICY.ROOT
PATH.ADMIN.GAMES.ADD_GAME.ROOT,
"/edit-game"
].some(path => pathname.startsWith(path)) ? "active" : "" ].some(path => pathname.startsWith(path)) ? "active" : ""
].join(" ")} ].join(" ")}
onClick={() => { router.push(PATH.DASHBOARD.ROOT) }} onClick={() => { router.push(PATH.USER.GENERAL_PAGES.REFUND_POLICY.ROOT) }}
> >
<ListItemIcon className={open ? "expanded" : "collapsed"}> <ListItemIcon className={open ? "expanded" : "collapsed"}>
...@@ -112,19 +110,17 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -112,19 +110,17 @@ export default function UserMenu({ open }: { open: boolean }) {
className={[ className={[
open ? "expanded" : "collapsed", open ? "expanded" : "collapsed",
[ [
PATH.ADMIN.GAMES.ROOT, PATH.USER.GENERAL_PAGES.ACCESSIBILITY.ROOT
PATH.ADMIN.GAMES.ADD_GAME.ROOT,
"/edit-game"
].some(path => pathname.startsWith(path)) ? "active" : "" ].some(path => pathname.startsWith(path)) ? "active" : ""
].join(" ")} ].join(" ")}
onClick={() => { router.push(PATH.ADMIN.GAMES.ROOT) }} onClick={() => { router.push(PATH.USER.GENERAL_PAGES.ACCESSIBILITY.ROOT) }}
> >
<ListItemIcon className={open ? "expanded" : "collapsed"}> <ListItemIcon className={open ? "expanded" : "collapsed"}>
<ReceiptEdit size={18} /> <ReceiptEdit size={18} />
</ListItemIcon> </ListItemIcon>
<ListItemText <ListItemText
primary="Accessibility" primary="AML Policy"
className={open ? "expanded" : "collapsed"} className={open ? "expanded" : "collapsed"}
/> />
</ListItemButton> </ListItemButton>
...@@ -134,12 +130,10 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -134,12 +130,10 @@ export default function UserMenu({ open }: { open: boolean }) {
className={[ className={[
open ? "expanded" : "collapsed", open ? "expanded" : "collapsed",
[ [
PATH.ADMIN.GAMES.ROOT, PATH.USER.GENERAL_PAGES.SWEEPSTAKE_POLICY.ROOT
PATH.ADMIN.GAMES.ADD_GAME.ROOT,
"/edit-game"
].some(path => pathname.startsWith(path)) ? "active" : "" ].some(path => pathname.startsWith(path)) ? "active" : ""
].join(" ")} ].join(" ")}
onClick={() => { router.push(PATH.ADMIN.GAMES.ROOT) }} onClick={() => { router.push(PATH.USER.GENERAL_PAGES.SWEEPSTAKE_POLICY.ROOT) }}
> >
<ListItemIcon className={open ? "expanded" : "collapsed"}> <ListItemIcon className={open ? "expanded" : "collapsed"}>
...@@ -156,12 +150,10 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -156,12 +150,10 @@ export default function UserMenu({ open }: { open: boolean }) {
className={[ className={[
open ? "expanded" : "collapsed", open ? "expanded" : "collapsed",
[ [
PATH.ADMIN.GAMES.ROOT, PATH.USER.GENERAL_PAGES.TERMS_AND_CONDITIONS.ROOT
PATH.ADMIN.GAMES.ADD_GAME.ROOT,
"/edit-game"
].some(path => pathname.startsWith(path)) ? "active" : "" ].some(path => pathname.startsWith(path)) ? "active" : ""
].join(" ")} ].join(" ")}
onClick={() => { router.push(PATH.ADMIN.GAMES.ROOT) }} onClick={() => { router.push(PATH.USER.GENERAL_PAGES.TERMS_AND_CONDITIONS.ROOT) }}
> >
<ListItemIcon className={open ? "expanded" : "collapsed"}> <ListItemIcon className={open ? "expanded" : "collapsed"}>
...@@ -178,12 +170,10 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -178,12 +170,10 @@ export default function UserMenu({ open }: { open: boolean }) {
className={[ className={[
open ? "expanded" : "collapsed", open ? "expanded" : "collapsed",
[ [
PATH.ADMIN.GAMES.ROOT, PATH.USER.GENERAL_PAGES.PRIVACY_POLICY.ROOT
PATH.ADMIN.GAMES.ADD_GAME.ROOT,
"/edit-game"
].some(path => pathname.startsWith(path)) ? "active" : "" ].some(path => pathname.startsWith(path)) ? "active" : ""
].join(" ")} ].join(" ")}
onClick={() => { router.push(PATH.ADMIN.GAMES.ROOT) }} onClick={() => { router.push(PATH.USER.GENERAL_PAGES.PRIVACY_POLICY.ROOT) }}
> >
<ListItemIcon className={open ? "expanded" : "collapsed"}> <ListItemIcon className={open ? "expanded" : "collapsed"}>
...@@ -195,14 +185,12 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -195,14 +185,12 @@ export default function UserMenu({ open }: { open: boolean }) {
/> />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
<ListItem> {/* <ListItem>
<ListItemButton <ListItemButton
className={[ className={[
open ? "expanded" : "collapsed", open ? "expanded" : "collapsed",
[ [
PATH.ADMIN.GAMES.ROOT, PATH.USER.GENERAL_PAGES.PRIVACY_POLICY.ROOT
PATH.ADMIN.GAMES.ADD_GAME.ROOT,
"/edit-game"
].some(path => pathname.startsWith(path)) ? "active" : "" ].some(path => pathname.startsWith(path)) ? "active" : ""
].join(" ")} ].join(" ")}
onClick={() => { router.push(PATH.ADMIN.GAMES.ROOT) }} onClick={() => { router.push(PATH.ADMIN.GAMES.ROOT) }}
...@@ -216,10 +204,10 @@ export default function UserMenu({ open }: { open: boolean }) { ...@@ -216,10 +204,10 @@ export default function UserMenu({ open }: { open: boolean }) {
className={open ? "expanded" : "collapsed"} className={open ? "expanded" : "collapsed"}
/> />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem> */}
</List> </List>
</div> </div>
<div className="support"> <div className="support mt-4">
<button type="button" className="ss-btn support__btn flex items-center gap-2 w-full justify-start"> <button type="button" className="ss-btn support__btn flex items-center gap-2 w-full justify-start">
<SupportIcon /> <SupportIcon />
{open ? <strong className='text-[14px] font-semibold opacity-80 !text-white'>Support</strong> : null} {open ? <strong className='text-[14px] font-semibold opacity-80 !text-white'>Support</strong> : null}
......
...@@ -16,10 +16,10 @@ export default function CustomTable<TData>({ table, loading = false, ...@@ -16,10 +16,10 @@ export default function CustomTable<TData>({ table, loading = false,
const rowCount = table.getRowModel().rows.length; const rowCount = table.getRowModel().rows.length;
const columnCount = table.getAllLeafColumns().length; const columnCount = table.getAllLeafColumns().length;
const user = useAppSelector((state) => state.auth.user) const user = useAppSelector((state) => state.auth.user)
if (user?.role && user?.role.toUpperCase() === "USER") { if (user?.role && user?.role.toUpperCase() !== "USER") {
return ( return (
<table className="min-w-full border-collapse border border-gray-200 text-left"> <table className="min]-w-full border-collapse border border-gray-200 text-left">
<thead> <thead>
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}> <tr key={headerGroup.id}>
...@@ -101,8 +101,8 @@ export default function CustomTable<TData>({ table, loading = false, ...@@ -101,8 +101,8 @@ export default function CustomTable<TData>({ table, loading = false,
Array.from({ length: skeletonRows }).map((_, rowIndex) => ( Array.from({ length: skeletonRows }).map((_, rowIndex) => (
<tr key={`skeleton-${rowIndex}`} className="animate-pulse"> <tr key={`skeleton-${rowIndex}`} className="animate-pulse">
{Array.from({ length: columnCount }).map((_, colIndex) => ( {Array.from({ length: columnCount }).map((_, colIndex) => (
<td key={`skeleton-cell-${rowIndex}-${colIndex}`} className="text-[14px] p-2 lg:p-4 "> <td key={`skeleton-cell-${rowIndex}-${colIndex}`} className="text-[14px] p-2 lg:p-4 " >
<div className="h-4 w-full rounded-xl bg-[rgba(255, 255, 255, 0.10)]" /> <div className="h-4 w-full rounded-xl bg-[rgba(255, 255, 255, 0.10)]" style={{ background: "rgba(255, 255, 255, 0.10)" }} />
</td> </td>
))} ))}
</tr> </tr>
......
...@@ -18,8 +18,10 @@ const validationSchema = Yup.object().shape({ ...@@ -18,8 +18,10 @@ const validationSchema = Yup.object().shape({
.max(255) .max(255)
.required('Email is required'), .required('Email is required'),
displayName: Yup.string() displayName: Yup.string()
.required('Display Name is required') .required("Display Name is required")
.max(50, 'Display Name must be less than 50 characters'), .max(14, "Display Name must be less than 14 characters")
.min(6, "Display Name must be at least 6 characters long")
.matches(/^\S+$/, "Display Name cannot contain spaces"),
password: Yup.string() password: Yup.string()
.required('Password is required') .required('Password is required')
.test( .test(
......
"use client";
import ActionGroup from '@/components/molecules/Action';
import TableHeader from '@/components/molecules/TableHeader';
import CustomTable from '@/components/organism/Table';
import { useAppDispatch } from '@/hooks/hook';
import { PATH } from '@/routes/PATH';
import { useDeletePageByIdMutation, useGetAllPageQuery } from '@/services/pageApi';
import { showToast, ToastVariant } from '@/slice/toastSlice';
import { PageRequestProps } from '@/types/page';
import { Checkbox, Pagination } from '@mui/material';
import { ColumnDef, getCoreRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table';
import React, { useMemo, useState } from 'react'
export default function GeneralPageLiting() {
const dispatch = useAppDispatch();
const [search, setSearch] = useState("");
const [sorting, setSorting] = useState<{ id: string; desc: boolean }[]>([]);
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const { data, isLoading: loadingPages } = useGetAllPageQuery({
page,
per_page: pageSize,
search: search || ""
});
const [deletePage, { isLoading: deleting }] = useDeletePageByIdMutation();
const filteredData = useMemo(() => data?.data?.data || [], [data]);
const columns = useMemo<ColumnDef<PageRequestProps>[]>(() => [
{
id: 'select',
header: ({ table }) => (
<Checkbox
indeterminate={
table.getIsSomePageRowsSelected() &&
!table.getIsAllPageRowsSelected()
}
checked={table.getIsAllPageRowsSelected()}
onChange={table.getToggleAllPageRowsSelectedHandler()}
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onChange={row.getToggleSelectedHandler()}
/>
),
size: 50
},
{
accessorKey: 'id',
header: '#ID',
cell: ({ row }) => row.original.id
},
{
accessorKey: "name",
header: "Title",
cell: ({ row }) => (
<strong className="text-primary block text-[12px] leading-[120%] font-[500] capitalize">
{row.original.name}
</strong>
),
},
{
accessorKey: 'description',
header: 'Description',
cell: ({ row }) => (
<span className="text-[12px] font-[500] max-w-[380px]">{row.original.description}</span>
)
},
{
accessorKey: 'registeredDate',
header: 'Registered Date',
// cell:
},
{
id: 'action',
header: 'Action',
cell: ({ row }) => (
<ActionGroup
// onView={`${PATH.ADMIN.PAGES.ROOT}/${row.original.id}`}
onEdit={`${PATH.ADMIN.PAGES.EDIT_PAGE.ROOT}/${row.original.id}`}
onDelete={async () => {
const response = await deletePage({ id: row.original.id || "" }).unwrap();
dispatch(
showToast({
message: response.message,
variant: ToastVariant.SUCCESS
})
)
}}
/>
),
},
], []);
const table = useReactTable({
data: filteredData || [],
columns,
state: { sorting },
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
})
return (
<section className="genral__page__lisiting">
<div className="border-gray border-solid border-[1px] rounded-[8px] lg:rounded-[16px]">
<TableHeader
search={search}
setSearch={setSearch}
onDownloadCSV={() => { }}
/>
<CustomTable
table={table}
loading={loadingPages}
/>
<div className="flex justify-between items-center mt-4 px-8 py-6">
<div>
<span>Row per page:</span>
<select
value={pageSize}
onChange={(e) => setPageSize(Number(e.target.value))}
className="ml-2 border border-gray-300 rounded p-1"
>
{[5, 10, 15, 20].map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
</div>
<Pagination count={data?.data?.pagination.total_pages || 1}
page={page}
onChange={(_, value) => setPage(value)} variant="outlined" shape="rounded" sx={{ gap: "8px" }} />
</div>
</div>
</section>
)
}
"use client"
import SilverCoinIcon from '@/icons/SilverCoinIcon'
import { useGetUserBalanceBySlugQuery } from '@/services/userApi'
import { Box } from '@mui/material'
import React from 'react'
export default function UserCoin({ slug }: { slug: string }) {
const { data } = useGetUserBalanceBySlugQuery({ slug });
return (
<Box sx={{
background: "linear-gradient(0deg, rgba(234, 47, 231, 0.10) 0%, rgba(234, 47, 231, 0.10) 100%)",
borderRadius: "16px"
}} className="flex justify-center items-center gap-2 py-4 px-6 min-w-[30%] ">
<SilverCoinIcon />
<div className="coins">
<strong className="text-[16px] leading-4 font-[600] block mb-1">{data?.balance||0}</strong>
<span className="text-[12px] block">Current Sweep Coins</span>
</div>
</Box>
)
}
...@@ -8,6 +8,7 @@ import SilverCoinIcon from "@/icons/SilverCoinIcon"; ...@@ -8,6 +8,7 @@ import SilverCoinIcon from "@/icons/SilverCoinIcon";
import ScreenShotSlider from "@/components/molecules/Sliders/ScreenShotSlider"; import ScreenShotSlider from "@/components/molecules/Sliders/ScreenShotSlider";
import CustomLightGallery from "@/components/organism/LightGallery"; import CustomLightGallery from "@/components/organism/LightGallery";
import Link from "next/link"; import Link from "next/link";
import UserCoin from "./UserCoin";
export default function ExclusiveGameDetail({ game }: { game: SingleGameResponse }) { export default function ExclusiveGameDetail({ game }: { game: SingleGameResponse }) {
return ( return (
...@@ -31,7 +32,7 @@ export default function ExclusiveGameDetail({ game }: { game: SingleGameResponse ...@@ -31,7 +32,7 @@ export default function ExclusiveGameDetail({ game }: { game: SingleGameResponse
{renderHTML(game?.data?.description)} {renderHTML(game?.data?.description)}
</div> </div>
<div className="action__group flex flex-wrap gap-2"> <div className="action__group flex flex-wrap gap-2">
<Box sx={{ {/* <Box sx={{
background: "linear-gradient(0deg, rgba(234, 47, 231, 0.10) 0%, rgba(234, 47, 231, 0.10) 100%)", background: "linear-gradient(0deg, rgba(234, 47, 231, 0.10) 0%, rgba(234, 47, 231, 0.10) 100%)",
borderRadius: "16px" borderRadius: "16px"
}} className="flex justify-center items-center gap-2 py-4 px-6 min-w-[30%] "> }} className="flex justify-center items-center gap-2 py-4 px-6 min-w-[30%] ">
...@@ -40,7 +41,8 @@ export default function ExclusiveGameDetail({ game }: { game: SingleGameResponse ...@@ -40,7 +41,8 @@ export default function ExclusiveGameDetail({ game }: { game: SingleGameResponse
<strong className="text-[16px] leading-4 font-[600] block mb-1">20,000</strong> <strong className="text-[16px] leading-4 font-[600] block mb-1">20,000</strong>
<span className="text-[12px] block">Current Sweep Coins</span> <span className="text-[12px] block">Current Sweep Coins</span>
</div> </div>
</Box> </Box> */}
<UserCoin slug={game?.data?.provider} />
<Box sx={{ <Box sx={{
borderRadius: "16px" borderRadius: "16px"
......
...@@ -25,7 +25,7 @@ export default async function ExclusiveGamePage() { ...@@ -25,7 +25,7 @@ export default async function ExclusiveGamePage() {
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 gap-4"> <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 gap-4">
{ {
games?.data?.data.map((game) => ( games?.data?.data.map((game) => (
<a href={`exclusive-games/${game.id}`} className="group block overflow-hidden hover:shadow-md transition rounded-2xl aspect-[208/222] relative" key={game.id}> <ProtectedLink href={`exclusive-games/${game.id}`} className="group block overflow-hidden hover:shadow-md transition rounded-2xl aspect-[208/222] relative" key={game.id}>
<Tooltip title={game.name}> <Tooltip title={game.name}>
<Image <Image
src={game.thumbnail || "/assets/images/fallback.png"} src={game.thumbnail || "/assets/images/fallback.png"}
...@@ -34,7 +34,7 @@ export default async function ExclusiveGamePage() { ...@@ -34,7 +34,7 @@ export default async function ExclusiveGamePage() {
className="w-full h-[222px] object-cover group-hover:scale-105 transition-transform duration-300" className="w-full h-[222px] object-cover group-hover:scale-105 transition-transform duration-300"
/> />
</Tooltip> </Tooltip>
</a> </ProtectedLink>
)) ))
} }
</div> </div>
......
...@@ -51,6 +51,8 @@ export default function WithdrawnHistoryPage() { ...@@ -51,6 +51,8 @@ export default function WithdrawnHistoryPage() {
} }
] ]
console.log(data);
const table = useReactTable({ const table = useReactTable({
data: data?.data?.data || [], data: data?.data?.data || [],
// data: dummyDeposits, // data: dummyDeposits,
...@@ -62,9 +64,8 @@ export default function WithdrawnHistoryPage() { ...@@ -62,9 +64,8 @@ export default function WithdrawnHistoryPage() {
return ( return (
<> <>
<CustomTable table={table} loading={isLoading} emptyMessage="You haven't deposite yet!" /> <CustomTable table={table} loading={isLoading} emptyMessage="You haven't deposite yet!" />
<div className="flex justify-between items-center mt-4 px-8 py-6"> {data && data?.data?.data.length > 5 ? <div className="flex justify-between items-center mt-4 px-8 py-6">
<Pagination count={data?.data?.pagination?.total_pages || 1}
<Pagination count={data?.data?.pagination.total_pages || 1}
page={page} page={page}
onChange={(_, value) => setPage(value)} variant="outlined" shape="rounded" sx={{ gap: "8px" }} /> onChange={(_, value) => setPage(value)} variant="outlined" shape="rounded" sx={{ gap: "8px" }} />
<div> <div>
...@@ -81,7 +82,7 @@ export default function WithdrawnHistoryPage() { ...@@ -81,7 +82,7 @@ export default function WithdrawnHistoryPage() {
))} ))}
</select> </select>
</div> </div>
</div> </div> : ""}
</> </>
) )
} }
...@@ -42,6 +42,9 @@ export const PATH = { ...@@ -42,6 +42,9 @@ export const PATH = {
ROOT: "/pages", ROOT: "/pages",
ADD_PAGE: { ADD_PAGE: {
ROOT: "/pages/add-page" ROOT: "/pages/add-page"
},
EDIT_PAGE: {
ROOT: "/pages/edit-page"
} }
}, },
NOTIFICATIONS: { NOTIFICATIONS: {
...@@ -66,6 +69,23 @@ export const PATH = { ...@@ -66,6 +69,23 @@ export const PATH = {
PASSWORD: { PASSWORD: {
ROOT: "/profile/password" ROOT: "/profile/password"
} }
},
GENERAL_PAGES: {
PRIVACY_POLICY: {
ROOT: "/general/privacy-policy"
},
REFUND_POLICY: {
ROOT: "/general/refund-policy"
},
SWEEPSTAKE_POLICY: {
ROOT: "/general/sweepstake-policy"
},
ACCESSIBILITY: {
ROOT: "/general/aml-policy"
},
TERMS_AND_CONDITIONS: {
ROOT: "/general/terms-and-conditions"
}
} }
} }
} }
\ No newline at end of file
import { PageRequestProps, PageResponseProps } from "@/types/page";
import { cookies } from "next/headers";
import { serverBaseQuery } from "./serverBaseQuery";
export async function getPageDetail(slug: string): Promise<PageResponseProps | undefined> {
return serverBaseQuery(`/api/general/page/${slug}`);
}
import { createApi } from "@reduxjs/toolkit/query/react"; import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "./baseQuery"; import { baseQuery } from "./baseQuery";
import { GlobalResponse, QueryParams } from "@/types/config"; import { GlobalResponse, QueryParams } from "@/types/config";
import { PageListResponse, PageResponseProps } from "@/types/page";
export const pageApi = createApi({ export const pageApi = createApi({
reducerPath: "pageApi", reducerPath: "pageApi",
...@@ -14,7 +15,7 @@ export const pageApi = createApi({ ...@@ -14,7 +15,7 @@ export const pageApi = createApi({
body: body body: body
}) })
}), }),
getAllPage: builder.mutation<GlobalResponse, QueryParams>({ getAllPage: builder.query<PageListResponse, QueryParams>({
query: (body) => ({ query: (body) => ({
url: "/api/admin/page/list", url: "/api/admin/page/list",
method: "GET", method: "GET",
...@@ -38,7 +39,7 @@ export const pageApi = createApi({ ...@@ -38,7 +39,7 @@ export const pageApi = createApi({
export const { export const {
useCreatePageMutation, useCreatePageMutation,
useGetAllPageMutation, useGetAllPageQuery,
useUpdatePageByIdMutation, useUpdatePageByIdMutation,
useDeletePageByIdMutation useDeletePageByIdMutation
} = pageApi; } = pageApi;
\ No newline at end of file
...@@ -28,10 +28,18 @@ export const userApi = createApi({ ...@@ -28,10 +28,18 @@ export const userApi = createApi({
query: () => ({ query: () => ({
url: "/api/get-balance", url: "/api/get-balance",
method: "GET" method: "GET"
}) }),
providesTags: ['user']
}),
getUserBalanceBySlug: builder.query<{ provider: string; balance: number, flag: string }, { slug: string }>({
query: ({ slug }) => ({
url: `/api/balance/${slug}`,
method: "GET"
}),
providesTags: ['user']
}) })
}) })
}) })
export const { useAddUserWalletMutation, useUpdateUserProfileMutation, useGetUserBalanceQuery } = userApi; export const { useAddUserWalletMutation, useUpdateUserProfileMutation, useGetUserBalanceQuery, useGetUserBalanceBySlugQuery } = userApi;
\ No newline at end of file \ No newline at end of file
export interface pageRequestProps { import { Pagination } from "./game";
export interface PageRequestProps {
id?: string;
name: string; name: string;
slug: string; slug: string;
description: string; description: string;
...@@ -8,6 +11,21 @@ export interface pageRequestProps { ...@@ -8,6 +11,21 @@ export interface pageRequestProps {
}[] }[]
} }
export interface PageResponseProps {
success: boolean,
data: PageRequestProps;
message: string;
}
export interface PageListResponse {
success: boolean,
data: {
data: PageRequestProps[];
pagination: Pagination;
};
message: string;
}
export const pageInitialData = { export const pageInitialData = {
name: "", name: "",
slug: "", slug: "",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment