Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sweepstake
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Arjun Jhukal
sweepstake
Commits
0f9f3779
Commit
0f9f3779
authored
Oct 07, 2025
by
Arjun Jhukal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updated the notification listing at admin side
parent
4d2d7d0f
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
428 additions
and
186 deletions
+428
-186
DashboardProvider.tsx
...pp/(dashboard)/(user)/(outsideAuth)/DashboardProvider.tsx
+1
-1
page.tsx
.../(dashboard)/(user)/(outsideAuth)/general/[slug]/page.tsx
+0
-1
page.tsx
src/app/(dashboard)/(user)/(outsideAuth)/page.tsx
+136
-90
globals.css
src/app/globals.css
+5
-0
SelectField.tsx
src/components/atom/SelectField.tsx
+0
-1
index.tsx
src/components/organism/Header/AdminHeader/index.tsx
+10
-5
Notification.tsx
src/components/organism/Header/Notification.tsx
+12
-14
BannerSlider.tsx
.../pages/dashboard/adminDashboard/settings/BannerSlider.tsx
+97
-34
index.tsx
src/components/pages/dashboard/index.tsx
+67
-33
UserCoin.tsx
...ard/games/exclusiveGames/exclusiveGameDetail/UserCoin.tsx
+0
-1
index.tsx
.../pages/dashboard/userDashboard/withdrawlHistory/index.tsx
+0
-1
store.ts
src/hooks/store.ts
+3
-0
pages.ts
src/serverApi/pages.ts
+9
-0
notificationApi.tsx
src/services/notificationApi.tsx
+35
-0
settingApi.ts
src/services/settingApi.ts
+21
-5
notification.ts
src/types/notification.ts
+17
-0
setting.ts
src/types/setting.ts
+15
-0
No files found.
src/app/(dashboard)/(user)/(outsideAuth)/DashboardProvider.tsx
View file @
0f9f3779
...
...
@@ -5,7 +5,7 @@ import React from 'react'
export
default
function
DashboardProvider
({
children
}:
{
children
:
React
.
ReactNode
})
{
const
[
search
,
setSearch
]
=
React
.
useState
(
""
);
const
user
=
useAppSelector
(
state
=>
state
.
auth
.
user
);
const
user
=
useAppSelector
(
state
=>
state
?
.
auth
.
user
);
if
(
user
?.
role
&&
user
.
role
.
toUpperCase
()
===
"ADMIN"
)
{
return
<>
<
h1
className=
"text-[24px] leading-[120%] mb-6"
>
Dashboard
</
h1
>
...
...
src/app/(dashboard)/(user)/(outsideAuth)/general/[slug]/page.tsx
View file @
0f9f3779
...
...
@@ -7,7 +7,6 @@ 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
);
...
...
src/app/(dashboard)/(user)/(outsideAuth)/page.tsx
View file @
0f9f3779
...
...
@@ -5,12 +5,15 @@ import { getAllGames, getSubGames, getUsp } from "@/serverApi/game";
import
{
Tooltip
}
from
"@mui/material"
;
import
Image
from
"next/image"
;
import
DashboardProvider
from
"./DashboardProvider"
;
import
{
getBanners
,
getSubBanners
}
from
"@/serverApi/pages"
;
import
Link
from
"next/link"
;
export
default
async
function
Home
()
{
let
games
=
null
;
let
usps
=
null
;
let
subGames
=
null
;
let
banners
=
null
;
let
subBanners
=
null
;
try
{
games
=
await
getAllGames
();
}
catch
(
err
)
{
...
...
@@ -35,15 +38,25 @@ export default async function Home() {
console
.
log
(
"❌ Failed to fetch games:"
,
err
);
return
<
p
className=
"text-red-500"
>
Failed to load games.
</
p
>;
}
console
.
log
({
subGames
:
subGames
.
data
,
usps
})
try
{
banners
=
await
getBanners
();
}
catch
(
err
)
{
console
.
log
(
"❌ Failed to fetch banner:"
,
err
);
return
<
p
className=
"text-red-500"
>
Failed to load banner.
</
p
>;
}
try
{
subBanners
=
await
getSubBanners
();
}
catch
(
err
)
{
console
.
log
(
"❌ Failed to fetch sub banner:"
,
err
);
return
<
p
className=
"text-red-500"
>
Failed to load sub banner.
</
p
>;
}
// console.log({ subGames: subGames.data, usps })
return
(
<
DashboardProvider
>
<>
<
Dashboard
/>
<>
{
banners
?.
data
.
length
?
<
Dashboard
slides=
{
banners
.
data
}
/>
:
""
}
<
div
className=
"grid gap-4 md:grid-cols-2 lg:grid-cols-4 2xl:grid-cols-5 mb-8"
>
{
games
?.
data
?.
data
.
map
((
game
)
=>
(
...
...
@@ -88,90 +101,123 @@ export default async function Home() {
))
}
</
div
>
</
section
>
<
div
className=
"dashboard-card-wrapper grid grid-cols-2 gap-5 justify-center"
>
<
div
className=
"dashboard-card1 flex px-10 gap-2 rounded-[24px]"
style=
{
{
background
:
"rgba(255, 255, 255, 0.20)"
,
}
}
>
<
div
className=
"py-7 gap-6"
>
<
h1
className=
"text-[40px] mb-[8px]"
style=
{
{
color
:
"#FBD230"
,
lineHeight
:
"96%"
,
letterSpacing
:
"-0.682px"
,
}
}
>
Welcome BONUS!!
</
h1
>
<
p
className=
"text-[13px] mb-[12px]"
style=
{
{
lineHeight
:
"120%"
,
color
:
"#FBD230"
}
}
>
10$ on first play.
</
p
>
<
a
href=
"#"
className=
"px-[18px] py-[11px] rounded-[28px]"
style=
{
{
background
:
"linear-gradient(270deg, #F9B901 0.09%, #D09F12 95.19%)"
,
}
}
>
Play Now
</
a
>
</
div
>
<
div
className=
"dashboard-card-img aspect-[245/245]"
>
<
img
src=
"/assets/images/card1.png"
alt=
""
// className="w-[245px] h-[245px]"
className=
"h-auto max-w-full "
style=
{
{
width
:
"245px"
,
height
:
"245px"
}
}
/>
</
div
>
</
div
>
<
div
className=
"dashboard-card2 flex px-[45px] gap-2 rounded-[24px]"
style=
{
{
background
:
"rgba(255, 255, 255, 0.10)"
,
}
}
>
<
div
className=
"py-[45px] gap-6"
>
<
h1
className=
"text-[40px] mb-[10px]"
style=
{
{
color
:
"#1AF7FE"
,
letterSpacing
:
"-0.682px"
,
lineHeight
:
"96%"
,
}
}
>
Easy.Set.Play
</
h1
>
<
p
className=
"text-[13px] mb-[12px]"
style=
{
{
color
:
"#E7BCFE"
,
lineHeight
:
"120%"
}
}
>
Join the Fun today.
</
p
>
<
a
href=
"#"
className=
"px-[18px] py-[11px] rounded-[28px]"
style=
{
{
background
:
"linear-gradient(270deg, #D620D9 0.09%, #B40EF0 95.19%)"
,
}
}
>
Play Now
</
a
>
</
div
>
<
div
className=
"dashboard-card-img "
>
<
img
src=
"/assets/images/card2.png"
alt=
""
// className="w-[245px] h-[245px]"
className=
"h-auto max-w-full "
style=
{
{
width
:
"245px"
,
height
:
"245px"
}
}
/>
</
div
>
</
div
>
</
div
>
{
subBanners
?.
data
.
length
?
<
div
className=
"dashboard-card-wrapper grid grid-cols-2 gap-5 justify-center"
>
{
subBanners
?.
data
?.
length
>
0
&&
subBanners
.
data
.
map
((
subBanner
,
index
)
=>
(
<
div
key=
{
subBanner
.
name
||
index
}
className=
"dashboard-card1 flex justify-between px-10 gap-2 rounded-[24px]"
style=
{
{
background
:
index
%
2
===
0
?
"rgba(255, 255, 255, 0.10)"
:
"rgba(255, 255, 255, 0.20)"
,
}
}
>
<
div
className=
"py-7 gap-6"
>
{
/* ✅ Render title if available */
}
{
subBanner
?.
name
&&
(
<
h1
className=
"text-[40px] mb-[8px]"
style=
{
{
color
:
"#FBD230"
,
lineHeight
:
"96%"
,
letterSpacing
:
"-0.682px"
,
}
}
>
{
subBanner
.
name
}
</
h1
>
)
}
{
/* ✅ Render description if available */
}
{
subBanner
?.
description
&&
(
<
p
className=
"text-[13px] mb-[12px]"
style=
{
{
lineHeight
:
"120%"
,
color
:
"#FBD230"
}
}
>
{
subBanner
.
description
}
</
p
>
)
}
{
/* ✅ Render CTA button if link exists */
}
{
subBanner
?.
cta_link
&&
(
<
Link
href=
{
subBanner
.
cta_link
}
className=
"px-[18px] py-[11px] rounded-[28px] inline-block"
style=
{
{
background
:
index
%
2
===
0
?
"linear-gradient(270deg, #D620D9 0.09%, #B40EF0 95.19%)"
:
"linear-gradient(270deg, #F9B901 0.09%, #D09F12 95.19%)"
,
}
}
target=
"_blank"
>
Play Now
</
Link
>
)
}
</
div
>
{
/* ✅ Render image only if available */
}
{
subBanner
?.
image_url
&&
(
<
div
className=
"dashboard-card-img aspect-[245/245]"
>
<
Image
src=
{
subBanner
.
image_url
}
alt=
{
subBanner
.
name
||
"Sub Banner"
}
className=
"h-auto max-w-full"
width=
{
245
}
height=
{
245
}
/>
</
div
>
)
}
</
div
>
))
}
{
/* <div
className="dashboard-card2 flex px-[45px] gap-2 rounded-[24px]"
style={{
background: "rgba(255, 255, 255, 0.10)",
}}>
<div className="py-[45px] gap-6">
<h1
className="text-[40px] mb-[10px]"
style={{
color: "#1AF7FE",
letterSpacing: "-0.682px",
lineHeight: "96%",
}}>
Easy.Set.Play
</h1>
<p
className="text-[13px] mb-[12px]"
style={{ color: "#E7BCFE", lineHeight: "120%" }}>
Join the Fun today.
</p>
<a
href="#"
className="px-[18px] py-[11px] rounded-[28px] inline-block"
style={{
background:
"linear-gradient(270deg, #D620D9 0.09%, #B40EF0 95.19%)",
}}>
Play Now
</a>
</div>
<div className="dashboard-card-img ">
<img
src="/assets/images/card2.png"
alt=""
// className="w-[245px] h-[245px]"
className="h-auto max-w-full "
style={{ width: "245px", height: "245px" }}
/>
</div>
</div> */
}
</
div
>
:
null
}
<
UspSlider
uspData=
{
usps
.
data
||
[]
}
/>
</>
</>
</
DashboardProvider
>
);
}
src/app/globals.css
View file @
0f9f3779
...
...
@@ -209,4 +209,8 @@
.lg-backdrop
,
.lg-outer
{
z-index
:
9999
;
}
.banner-desc
span
{
@apply
text-[47px]
leading-[50%]
text-secondary
font-[700];
}
\ No newline at end of file
src/components/atom/SelectField.tsx
View file @
0f9f3779
...
...
@@ -34,7 +34,6 @@ export default function SelectField({
touched
,
}:
SelectFieldProps
)
{
const
theme
=
useThemeContext
();
console
.
log
(
"theme"
,
theme
);
return
(
<
div
className=
"input__field"
>
<
InputLabel
className=
"block text-sm font-semibold mb-2"
>
...
...
src/components/organism/Header/AdminHeader/index.tsx
View file @
0f9f3779
...
...
@@ -7,20 +7,25 @@ import NotificationPage from '../Notification';
import
Profile
from
'../Profile'
;
import
AdminSearchBar
from
'./AdminSearchBar'
;
import
CreatNewRecord
from
'../CreatNewRecord'
;
import
{
useGetAllNotificationQuery
}
from
'@/services/notificationApi'
;
export
default
function
AdminHeader
()
{
const
[
mounted
,
setMounted
]
=
React
.
useState
(
false
);
//
const [mounted, setMounted] = React.useState(false);
React
.
useEffect
(()
=>
{
setMounted
(
true
);
},
[]);
// React.useEffect(() => {
// setMounted(true);
// }, []);
const
[
page
,
setPage
]
=
React
.
useState
(
1
);
const
[
pageSize
,
setPageSize
]
=
React
.
useState
(
10
);
const
{
data
}
=
useGetAllNotificationQuery
({
page
:
page
,
per_page
:
pageSize
});
console
.
log
(
data
);
return
(
<
Box
className=
'flex items-center gap-4 justify-between w-full'
>
<
AdminSearchBar
/>
<
div
className=
"right flex items-center gap-4"
>
<
CreatNewRecord
/>
<
NotificationPage
notifications=
{
[]
}
/>
<
NotificationPage
notifications=
{
data
?.
data
?.
data
||
[]
}
pagination=
{
data
?.
data
?.
pagination
}
/>
<
Profile
/>
</
div
>
</
Box
>
...
...
src/components/organism/Header/Notification.tsx
View file @
0f9f3779
...
...
@@ -15,16 +15,16 @@ import {
import
Fade
from
'@mui/material/Fade'
;
// ✅ Import Fade
import
{
Notification
}
from
'@wandersonalwes/iconsax-react'
;
import
Link
from
'next/link'
;
import
{
NotificationProps
}
from
'@/types/notification'
;
import
{
Pagination
}
from
'@/types/game'
;
type
Notification
=
{
label
:
string
;
description
:
string
;
link
?:
string
;
}
export
default
function
NotificationPage
({
notifications
notifications
,
pagination
}:
{
notifications
:
Notification
[]
notifications
:
NotificationProps
[]
pagination
:
Pagination
|
undefined
})
{
const
anchorRef
=
useRef
<
HTMLButtonElement
|
null
>
(
null
);
const
[
open
,
setOpen
]
=
useState
(
false
);
...
...
@@ -38,6 +38,7 @@ export default function NotificationPage({
const
id
=
open
?
'popper'
:
undefined
;
// const [readNotification,{isLoading}]
return
(
<
Box
>
<
IconButton
...
...
@@ -79,18 +80,15 @@ export default function NotificationPage({
<
Typography
variant=
"h3"
>
Notifications
</
Typography
>
<
Link
href=
{
"#"
}
className=
'text-[12px] leading-[120%] hover:text-primary-dark font-medium'
>
View All
</
Link
>
{
pagination
&&
pagination
?.
count
>
2
?
<
Link
href=
{
"#"
}
className=
'text-[12px] leading-[120%] hover:text-primary-dark font-medium'
>
View All
</
Link
>
:
""
}
</
div
>
{
notifications
.
length
?
(
<
List
className=
'max-h-[320px] overflow-auto px-1'
>
{
notifications
.
map
((
notification
)
=>
(
<
ListItem
className=
'border-b-solid border-b-gray border-b-[1px] !pb-2 mb-2'
key=
{
notification
.
label
}
>
<
Link
href=
{
""
}
>
<
strong
className=
"text-[12px] leading-[120%] font-[500] block mb-1"
>
New User admin404 registerd
</
strong
>
<
p
className=
'text-[10px] leading-[120%] text-para-light'
>
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Nihil, porro!
</
p
>
</
Link
>
notifications
.
map
((
notification
,
index
)
=>
(
<
ListItem
className=
{
`border-b-solid border-b-gray-100 border-b-[1px] rounded-sm !p-2 cursor-pointer ${notification.has_read ? "" : "bg-gray-100"} ${index > 0 ? "mb-2 " : ""}`
}
key=
{
notification
.
id
}
>
<
p
className=
'text-[12px] lg:text-[14px] leading-[120%] text-title'
>
{
notification
.
message
}
</
p
>
</
ListItem
>
))
}
...
...
src/components/pages/dashboard/adminDashboard/settings/BannerSlider.tsx
View file @
0f9f3779
...
...
@@ -3,53 +3,100 @@
import
React
from
"react"
;
import
{
useFormik
}
from
"formik"
;
import
*
as
Yup
from
"yup"
;
import
{
Button
,
InputLabel
,
OutlinedInput
,
IconButton
}
from
"@mui/material"
;
import
{
Button
,
InputLabel
,
OutlinedInput
,
IconButton
,
FormControlLabel
,
Typography
,
Switch
,
}
from
"@mui/material"
;
import
InputFile
from
"@/components/atom/InputFile"
;
import
{
CloseCircle
}
from
"@wandersonalwes/iconsax-react"
;
import
{
useAppDispatch
}
from
"@/hooks/hook"
;
import
{
showToast
,
ToastVariant
}
from
"@/slice/toastSlice"
;
import
{
useGetAllBannerQuery
,
useUpdateBannerMutation
}
from
"@/services/settingApi"
;
const
validationSchema
=
Yup
.
object
({
banners
:
Yup
.
array
().
of
(
Yup
.
object
({
name
:
Yup
.
string
().
required
(
"Banner title is required"
),
description
:
Yup
.
string
().
required
(
"Banner description is required"
),
cta_link
:
Yup
.
string
().
required
(
"CTA link is required"
),
// image: Yup.mixed().required("Banner image is required"),
type
:
Yup
.
boolean
(),
})
),
});
export
default
function
BannerSlider
()
{
const
dispatch
=
useAppDispatch
();
const
{
data
,
isLoading
}
=
useGetAllBannerQuery
();
const
[
updateBanner
,
{
isLoading
:
updating
}]
=
useUpdateBannerMutation
();
console
.
log
(
"banner data"
,
data
);
const
formik
=
useFormik
({
initialValues
:
{
banners
:
[
{
title
:
""
,
description
:
""
,
cta_link
:
""
,
banners
:
data
?.
data
?.
length
?
data
.
data
.
map
((
item
:
any
)
=>
(
{
name
:
item
.
name
||
""
,
description
:
item
.
description
||
""
,
cta_link
:
item
.
cta_link
||
""
,
image
:
null
as
File
|
null
,
},
],
type
:
item
.
type
||
false
,
image_url
:
item
.
image_url
||
""
,
}))
:
[
{
name
:
""
,
description
:
""
,
cta_link
:
""
,
image
:
null
as
File
|
null
,
type
:
false
,
image_url
:
""
,
},
],
},
validationSchema
:
Yup
.
object
({
banners
:
Yup
.
array
().
of
(
Yup
.
object
({
title
:
Yup
.
string
().
required
(
"Banner title is required"
),
description
:
Yup
.
string
().
required
(
"Banner description is required"
),
cta_link
:
Yup
.
string
().
required
(
"CTA link is required"
),
image
:
Yup
.
mixed
().
required
(
"Banner image is required"
),
})
),
}),
onSubmit
:
(
values
)
=>
{
validationSchema
,
enableReinitialize
:
true
,
onSubmit
:
async
(
values
)
=>
{
const
formData
=
new
FormData
();
try
{
values
.
banners
.
forEach
((
banner
,
index
)
=>
{
formData
.
append
(
`banners[
${
index
}
][name]`
,
banner
.
name
);
formData
.
append
(
`banners[
${
index
}
][description]`
,
banner
.
description
);
formData
.
append
(
`banners[
${
index
}
][cta_link]`
,
banner
.
cta_link
);
formData
.
append
(
`banners[
${
index
}
][type]`
,
banner
.
type
?
"true"
:
"false"
);
if
(
banner
.
image
)
{
formData
.
append
(
`banners[
${
index
}
][image]`
,
banner
.
image
);
}
else
if
(
banner
.
image_url
)
{
formData
.
append
(
`banners[
${
index
}
][image_url]`
,
banner
.
image_url
);
}
});
const
response
=
await
updateBanner
(
formData
).
unwrap
();
dispatch
(
showToast
({
message
:
"Banner created successfully"
,
variant
:
ToastVariant
.
ERROR
message
:
response
?.
message
||
"Banner created successfully"
,
variant
:
ToastVariant
.
SUCCESS
,
})
)
}
catch
(
e
:
any
)
{
);
}
catch
(
e
:
any
)
{
console
.
log
(
e
);
dispatch
(
showToast
({
message
:
e
.
message
||
"Something went wrong"
,
variant
:
ToastVariant
.
ERROR
variant
:
ToastVariant
.
ERROR
,
})
)
)
;
}
},
});
...
...
@@ -62,6 +109,7 @@ export default function BannerSlider() {
description
:
""
,
cta_link
:
""
,
image
:
null
,
isSubBanner
:
false
,
},
]);
};
...
...
@@ -75,9 +123,9 @@ export default function BannerSlider() {
return
(
<
form
onSubmit=
{
formik
.
handleSubmit
}
className=
"form__field__wrapper border
-solid border-[1px]
border-gray rounded-[16px] mb-6"
className=
"form__field__wrapper border border-gray rounded-[16px] mb-6"
>
<
div
className=
"form__title py-6 px-10 border-b
-solid border-b-[1px]
border-gray"
>
<
div
className=
"form__title py-6 px-10 border-b border-gray"
>
<
h2
className=
"text-[20px] leading-[140%] font-bold"
>
Banner Slider
</
h2
>
</
div
>
...
...
@@ -90,7 +138,7 @@ export default function BannerSlider() {
{
formik
.
values
.
banners
.
length
>
1
&&
(
<
IconButton
onClick=
{
()
=>
handleRemoveBanner
(
index
)
}
className=
"!absolute !top-2 !right-2 !text-red-500 !
justify-end !
z-[9] max-w-fit"
className=
"!absolute !top-2 !right-2 !text-red-500 !z-[9] max-w-fit"
>
<
CloseCircle
size=
{
18
}
/>
</
IconButton
>
...
...
@@ -103,16 +151,16 @@ export default function BannerSlider() {
</
InputLabel
>
<
OutlinedInput
fullWidth
name=
{
`banners[${index}].
titl
e`
}
name=
{
`banners[${index}].
nam
e`
}
placeholder=
"Enter Banner Title"
value=
{
banner
.
titl
e
}
value=
{
banner
.
nam
e
}
onChange=
{
formik
.
handleChange
}
onBlur=
{
formik
.
handleBlur
}
/>
<
span
className=
"error"
>
{
formik
.
touched
.
banners
?.[
index
]?.
titl
e
&&
(
formik
.
errors
.
banners
?.[
index
]
as
any
)?.
titl
e
?
(
formik
.
errors
.
banners
?.[
index
]
as
any
).
titl
e
{
formik
.
touched
.
banners
?.[
index
]?.
nam
e
&&
(
formik
.
errors
.
banners
?.[
index
]
as
any
)?.
nam
e
?
(
formik
.
errors
.
banners
?.[
index
]
as
any
).
nam
e
:
""
}
</
span
>
</
div
>
...
...
@@ -171,6 +219,7 @@ export default function BannerSlider() {
onBlur=
{
()
=>
formik
.
setFieldTouched
(
`banners[${index}].image`
,
true
)
}
serverFile=
{
data
?.
data
[
index
]?.
image_url
}
/>
<
span
className=
"error"
>
{
formik
.
touched
.
banners
?.[
index
]?.
image
&&
...
...
@@ -179,6 +228,20 @@ export default function BannerSlider() {
:
""
}
</
span
>
</
div
>
{
/* ✅ Banner / Sub Banner Switch */
}
<
div
className=
"input__field"
>
<
FormControlLabel
control=
{
<
Switch
defaultChecked
color=
"primary"
checked=
{
banner
.
type
}
onChange=
{
(
e
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
formik
.
setFieldValue
(
`banners[${index}].type`
,
e
.
target
.
checked
)
}
name=
{
`banners[${index}].type`
}
/>
}
label=
"Mark Sub Banner"
sx=
{
{
color
:
"#000"
,
fontSize
:
"12px"
}
}
/>
</
div
>
</
div
>
))
}
...
...
src/components/pages/dashboard/index.tsx
View file @
0f9f3779
...
...
@@ -3,53 +3,87 @@
import
Image
from
"next/image"
;
import
{
motion
,
AnimatePresence
}
from
"framer-motion"
;
import
{
useState
}
from
"react"
;
import
{
BannerProps
}
from
"@/types/setting"
;
import
{
Button
}
from
"@mui/material"
;
import
{
renderHTML
}
from
"@/utils/RenderHTML"
;
const
slides
=
[
{
id
:
1
,
image
:
"/assets/images/slider1.png"
,
},
// {
// id: 2,
// image: "/assets/images/slider2.jpg",
// },
// {
// id: 3,
// image: "/assets/images/slider1.png",
// },
];
export
default
function
Dashboard
()
{
export
default
function
Dashboard
({
slides
}:
{
slides
:
BannerProps
[]
})
{
const
[
current
,
setCurrent
]
=
useState
(
0
);
const
handleDragEnd
=
(
_
:
any
,
info
:
any
)
=>
{
const
swipeThreshold
=
100
;
// min distance to trigger slide change
if
(
info
.
offset
.
x
<
-
swipeThreshold
&&
current
<
slides
.
length
-
1
)
{
setCurrent
((
prev
)
=>
prev
+
1
);
}
else
if
(
info
.
offset
.
x
>
swipeThreshold
&&
current
>
0
)
{
setCurrent
((
prev
)
=>
prev
-
1
);
}
};
return
(
<
div
className=
"dashboard__root relative w-full mx-auto rounded-2xl mb-8"
>
<
div
className=
"relative h-[240px] w-full overflow-hidden rounded-[50px]"
>
<
AnimatePresence
mode=
"wait"
>
<
motion
.
img
key=
{
slides
[
current
].
id
}
src=
{
slides
[
current
].
image
}
alt=
{
`slide-${slides[current].id}`
}
initial=
{
{
opacity
:
0
,
x
:
100
}
}
animate=
{
{
opacity
:
1
,
x
:
0
}
}
exit=
{
{
opacity
:
0
,
x
:
-
100
}
}
transition=
{
{
duration
:
0.6
}
}
className=
"absolute inset-0 w-full h-full object-cover rounded-2xl"
<
div
className=
"dashboard__root relative w-full mx-auto rounded-2xl mb-8"
>
<
AnimatePresence
mode=
"wait"
>
<
motion
.
div
key=
{
slides
[
current
]?.
name
||
current
}
className=
"relative aspect-[1105/240] rounded-3xl overflow-hidden flex justify-center items-center text-center cursor-grab active:cursor-grabbing"
initial=
{
{
opacity
:
0
,
x
:
100
}
}
animate=
{
{
opacity
:
1
,
x
:
0
}
}
exit=
{
{
opacity
:
0
,
x
:
-
100
}
}
transition=
{
{
duration
:
0.6
}
}
drag=
"x"
dragConstraints=
{
{
left
:
0
,
right
:
0
}
}
onDragEnd=
{
handleDragEnd
}
>
<
Image
src=
{
slides
[
current
].
image_url
||
""
}
alt=
{
slides
[
current
].
name
}
fill
className=
"object-cover z-[-1]"
/>
</
AnimatePresence
>
</
div
>
<
div
className=
"content relative z-10 px-6"
>
<
div
className=
"content relative z-10 px-6 text-center"
>
{
slides
[
current
]?.
name
&&
(
<
h1
className=
"text-[48px] leading-[50%] text-[#3A013F] mb-8"
>
{
slides
[
current
].
name
}
</
h1
>
)
}
{
slides
[
current
]?.
description
&&
(
<
p
className=
"text-[#600167] text-[13px] leading-[120%] font-[700] mb-5 banner-desc"
>
{
renderHTML
(
slides
[
current
].
description
)
}
</
p
>
)
}
{
slides
[
current
]?.
cta_link
&&
(
<
Button
variant=
"contained"
sx=
{
{
borderRadius
:
27
,
background
:
"linear-gradient(270deg, #F9B901 0.09%, #D09F12 95.19%)"
,
}
}
onClick=
{
()
=>
window
.
open
(
slides
[
current
].
cta_link
,
"_blank"
)
}
>
Play Now
</
Button
>
)
}
</
div
>
</
div
>
</
motion
.
div
>
</
AnimatePresence
>
{
/* Dots */
}
<
div
className=
"
absolute bottom-[-24px] left-1/2 -translate-x-1/2 flex gap-2
"
>
<
div
className=
"
justify-center flex gap-2 mt-4
"
>
{
slides
.
map
((
_
,
i
)
=>
(
<
button
key=
{
i
}
onClick=
{
()
=>
setCurrent
(
i
)
}
className=
{
`h-[8px] p-0 ${i === current ? "bg-white w-[24px]" : "bg-gray-400 w-[8px]"
className=
{
`h-[8px] p-0
cursor-pointer
${i === current ? "bg-white w-[24px]" : "bg-gray-400 w-[8px]"
}`
}
/>
))
}
</
div
>
</
div
>
)
)
;
}
src/components/pages/dashboard/userDashboard/games/exclusiveGames/exclusiveGameDetail/UserCoin.tsx
View file @
0f9f3779
...
...
@@ -7,7 +7,6 @@ import React from 'react'
export
default
function
UserCoin
({
slug
}:
{
slug
:
string
})
{
const
{
data
}
=
useGetUserBalanceBySlugQuery
({
slug
});
console
.
log
(
data
);
return
(
<
Box
sx=
{
{
background
:
"linear-gradient(0deg, rgba(234, 47, 231, 0.10) 0%, rgba(234, 47, 231, 0.10) 100%)"
,
...
...
src/components/pages/dashboard/userDashboard/withdrawlHistory/index.tsx
View file @
0f9f3779
...
...
@@ -51,7 +51,6 @@ export default function WithdrawnHistoryPage() {
}
]
console
.
log
(
data
);
const
table
=
useReactTable
({
data
:
data
?.
data
?.
data
||
[],
...
...
src/hooks/store.ts
View file @
0f9f3779
...
...
@@ -10,6 +10,7 @@ import { transactionApi } from "@/services/transaction";
import
{
userApi
}
from
"@/services/userApi"
;
import
{
settingApi
}
from
"@/services/settingApi"
;
import
{
pageApi
}
from
"@/services/pageApi"
;
import
{
notificationApi
}
from
"@/services/notificationApi"
;
export
const
store
=
configureStore
({
reducer
:
{
...
...
@@ -24,6 +25,7 @@ export const store = configureStore({
[
userApi
.
reducerPath
]:
userApi
.
reducer
,
[
settingApi
.
reducerPath
]:
settingApi
.
reducer
,
[
pageApi
.
reducerPath
]:
pageApi
.
reducer
,
[
notificationApi
.
reducerPath
]:
notificationApi
.
reducer
,
},
middleware
:
(
getDefaultMiddleware
)
=>
getDefaultMiddleware
()
...
...
@@ -35,6 +37,7 @@ export const store = configureStore({
.
concat
(
userApi
.
middleware
)
.
concat
(
settingApi
.
middleware
)
.
concat
(
pageApi
.
middleware
)
.
concat
(
notificationApi
.
middleware
)
})
...
...
src/serverApi/pages.ts
View file @
0f9f3779
import
{
PageRequestProps
,
PageResponseProps
}
from
"@/types/page"
;
import
{
cookies
}
from
"next/headers"
;
import
{
serverBaseQuery
}
from
"./serverBaseQuery"
;
import
{
BannerResponseProps
}
from
"@/types/setting"
;
export
async
function
getPageDetail
(
slug
:
string
):
Promise
<
PageResponseProps
|
undefined
>
{
return
serverBaseQuery
(
`/api/general/page/
${
slug
}
`
);
}
export
async
function
getBanners
():
Promise
<
BannerResponseProps
>
{
return
serverBaseQuery
(
`/api/general/home/banner`
)
}
export
async
function
getSubBanners
():
Promise
<
BannerResponseProps
>
{
return
serverBaseQuery
(
`/api/general/home/banner?type=true`
)
}
\ No newline at end of file
src/services/notificationApi.tsx
0 → 100644
View file @
0f9f3779
import
{
createApi
}
from
"@reduxjs/toolkit/query/react"
;
import
{
baseQuery
}
from
"./baseQuery"
;
import
{
NotificationResponse
}
from
"@/types/notification"
;
import
{
GlobalResponse
,
QueryParams
}
from
"@/types/config"
;
export
const
notificationApi
=
createApi
({
reducerPath
:
"notificationApi"
,
baseQuery
:
baseQuery
,
tagTypes
:
[
'Notification'
],
endpoints
:
(
builder
)
=>
({
getAllNotification
:
builder
.
query
<
NotificationResponse
,
QueryParams
>
({
query
:
({
search
,
page
,
per_page
})
=>
{
const
params
=
new
URLSearchParams
();
if
(
search
)
params
.
append
(
'search'
,
search
);
if
(
page
)
params
.
append
(
'page'
,
page
.
toString
());
if
(
per_page
)
params
.
append
(
'page_size'
,
per_page
.
toString
());
const
queryString
=
params
.
toString
();
return
{
url
:
`/api/admin/notifications
${
queryString
?
`?
${
queryString
}
`
:
''
}
`
,
method
:
"GET"
}
},
providesTags
:
[
"Notification"
]
}),
readNotification
:
builder
.
mutation
<
GlobalResponse
,
{
id
:
string
}
>
({
query
:
({
id
})
=>
({
url
:
`/api/admin/notification/
${
id
}
`
,
method
:
"POST"
,
})
})
})
})
export
const
{
useGetAllNotificationQuery
}
=
notificationApi
\ No newline at end of file
src/services/settingApi.ts
View file @
0f9f3779
import
{
createApi
}
from
"@reduxjs/toolkit/query/react"
;
import
{
baseQuery
}
from
"./baseQuery"
;
import
{
GlobalResponse
}
from
"@/types/config"
;
import
{
SiteSettingResponseProps
}
from
"@/types/setting"
;
import
{
BannerResponseProps
,
SiteSettingResponseProps
}
from
"@/types/setting"
;
export
const
settingApi
=
createApi
({
reducerPath
:
"settingApi"
,
baseQuery
:
baseQuery
,
tagTypes
:
[
'settings'
],
tagTypes
:
[
'settings'
,
'banners'
],
endpoints
:
(
builder
)
=>
({
updateSetting
:
builder
.
mutation
<
GlobalResponse
,
FormData
>
({
query
:
(
body
)
=>
({
...
...
@@ -22,8 +22,24 @@ export const settingApi = createApi({
method
:
"GET"
,
}),
providesTags
:
[
'settings'
]
})
}),
updateBanner
:
builder
.
mutation
<
GlobalResponse
,
FormData
>
({
query
:
(
body
)
=>
({
url
:
"/api/admin/setting/banner"
,
method
:
"POST"
,
body
:
body
,
}),
invalidatesTags
:
[
'banners'
]
}),
getAllBanner
:
builder
.
query
<
BannerResponseProps
,
void
>
({
query
:
()
=>
({
url
:
"/api/admin/setting/banner"
,
method
:
"GET"
,
}),
providesTags
:
[
'banners'
]
}),
})
})
export
const
{
useUpdateSettingMutation
,
useGetSettingsQuery
}
=
settingApi
;
\ No newline at end of file
export
const
{
useUpdateSettingMutation
,
useGetSettingsQuery
,
useUpdateBannerMutation
,
useGetAllBannerQuery
}
=
settingApi
;
\ No newline at end of file
src/types/notification.ts
0 → 100644
View file @
0f9f3779
import
{
Pagination
}
from
"./game"
;
export
interface
NotificationProps
{
id
:
string
;
message
:
string
,
has_read
:
boolean
}
export
interface
NotificationResponse
{
success
:
boolean
;
message
:
string
;
data
:
{
data
:
NotificationProps
[]
pagination
:
Pagination
}
}
\ No newline at end of file
src/types/setting.ts
x
→
src/types/setting.ts
View file @
0f9f3779
...
...
@@ -43,3 +43,17 @@ export interface UspProps {
icon_url
?:
string
;
}
export
interface
BannerProps
{
name
:
string
;
description
:
string
;
cta_link
:
string
;
image
?:
File
|
null
;
image_url
?:
string
|
null
;
type
:
boolean
/** TYPE TRUE REPRESENT SUB BANNER */
}
export
interface
BannerResponseProps
{
message
:
string
;
success
:
boolean
;
data
:
BannerProps
[];
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment