Commit 8515c989 by Arjun Jhukal

initialized the create player layout and game detail page

parent 0af072d4
...@@ -12,10 +12,12 @@ ...@@ -12,10 +12,12 @@
"@emotion/styled": "^11.14.1", "@emotion/styled": "^11.14.1",
"@mui/material": "^7.3.2", "@mui/material": "^7.3.2",
"@reduxjs/toolkit": "^2.9.0", "@reduxjs/toolkit": "^2.9.0",
"@tanstack/react-table": "^8.21.3",
"@wandersonalwes/iconsax-react": "0.0.10", "@wandersonalwes/iconsax-react": "0.0.10",
"formik": "^2.4.6", "formik": "^2.4.6",
"lightgallery": "^2.9.0-beta.1",
"next": "15.5.3", "next": "15.5.3",
"react": "19.1.0", "react": "^19.1.0",
"react-dom": "19.1.0", "react-dom": "19.1.0",
"react-quill-new": "3.4.6", "react-quill-new": "3.4.6",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
...@@ -1793,6 +1795,39 @@ ...@@ -1793,6 +1795,39 @@
"tailwindcss": "4.1.13" "tailwindcss": "4.1.13"
} }
}, },
"node_modules/@tanstack/react-table": {
"version": "8.21.3",
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz",
"integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==",
"license": "MIT",
"dependencies": {
"@tanstack/table-core": "8.21.3"
},
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/@tanstack/table-core": {
"version": "8.21.3",
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz",
"integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tybys/wasm-util": { "node_modules/@tybys/wasm-util": {
"version": "0.10.1", "version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
...@@ -4945,6 +4980,15 @@ ...@@ -4945,6 +4980,15 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/lightgallery": {
"version": "2.9.0-beta.1",
"resolved": "https://registry.npmjs.org/lightgallery/-/lightgallery-2.9.0-beta.1.tgz",
"integrity": "sha512-4Bl1vsYGOsI6RsPyephAUFW8bbZuZlLrpxU59cfKYKPDEX5Mhxfo1DUoUIJ+j5QPNrHEqrd+QeQtnGUCCwqK2g==",
"license": "GPLv3",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/lightningcss": { "node_modules/lightningcss": {
"version": "1.30.1", "version": "1.30.1",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
......
...@@ -13,14 +13,16 @@ ...@@ -13,14 +13,16 @@
"@emotion/styled": "^11.14.1", "@emotion/styled": "^11.14.1",
"@mui/material": "^7.3.2", "@mui/material": "^7.3.2",
"@reduxjs/toolkit": "^2.9.0", "@reduxjs/toolkit": "^2.9.0",
"@tanstack/react-table": "^8.21.3",
"@wandersonalwes/iconsax-react": "0.0.10",
"formik": "^2.4.6", "formik": "^2.4.6",
"lightgallery": "^2.9.0-beta.1",
"next": "15.5.3", "next": "15.5.3",
"react": "19.1.0", "react": "^19.1.0",
"react-dom": "19.1.0", "react-dom": "19.1.0",
"react-quill-new": "3.4.6",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
"yup": "^1.7.0", "yup": "^1.7.0"
"@wandersonalwes/iconsax-react": "0.0.10",
"react-quill-new": "3.4.6"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3", "@eslint/eslintrc": "^3",
......
import GameDetailPage from '@/components/pages/dashboard/adminDashboard/games/GameDetail'
import React from 'react' import React from 'react'
export default function AdminGamePage() { export default function AdminGamePage() {
return ( return (
<div>AdminGamePage</div> <GameDetailPage />
) )
} }
"use client";
import PageHeader from '@/components/molecules/PageHeader' import PageHeader from '@/components/molecules/PageHeader'
import AddGameForm from '@/components/pages/dashboard/adminDashboard/games/AddGameForm' import AddGameForm from '@/components/pages/dashboard/adminDashboard/games/AddGameForm'
import { useParams } from 'next/navigation';
import React from 'react' import React from 'react'
export default function EditGame() { export default function EditGame() {
const params = useParams();
const id = params?.id as string;
return ( return (
<> <>
<PageHeader title="Add Game" /> <PageHeader title="Add Game" />
<AddGameForm /> <AddGameForm id={id} />
</> </>
) )
} }
import PageHeader from '@/components/molecules/PageHeader'
import AddPlayerForm from '@/components/pages/dashboard/adminDashboard/players/addPlayerForm'
import React from 'react'
export default function AddPlayer() {
return (
<>
<PageHeader
title='Add Player'
/>
<AddPlayerForm />
</>
)
}
import PageHeader from '@/components/molecules/PageHeader'
import { PATH } from '@/routes/PATH'
import React from 'react'
export default function Players() {
return (
<>
<PageHeader
title='Players'
cta={{ url: PATH.ADMIN.PLAYERS.ADD_PLAYER.ROOT, label: "Add New Player" }}
/>
</>
)
}
...@@ -150,7 +150,14 @@ ...@@ -150,7 +150,14 @@
@apply !bg-white; @apply !bg-white;
} }
.MuiInputBase-input { /* .MuiInputBase-input {
padding: 0 !important; padding: 0 !important;
} } */
}
.general-content-box p {
font-size: 14px;
font-weight: 400;
line-height: 120%;
color: var(--para-light);
} }
\ No newline at end of file
...@@ -10,7 +10,7 @@ interface Option { ...@@ -10,7 +10,7 @@ interface Option {
interface SelectFieldProps { interface SelectFieldProps {
name: string; name: string;
label: string; label?: string;
value: string; value: string;
onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void; onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
onBlur?: (e: React.FocusEvent<HTMLSelectElement>) => void; onBlur?: (e: React.FocusEvent<HTMLSelectElement>) => void;
......
// import React from 'react'
// export default function Pagination() {
// return (
// .pagi
// )
// }
import { Button } from "@mui/material";
import SelectField from "../atom/SelectField";
interface TableHeaderProps {
search: string;
setSearch: (value: string) => void;
filterMethod: string;
setFilterMethod: (value: string) => void;
onDownloadCSV: () => void;
}
export default function TableHeader({
search,
setSearch,
filterMethod,
setFilterMethod,
onDownloadCSV,
}: TableHeaderProps) {
return (
<div className="table__header p-4 mb-4 flex justify-between">
<div className="inpute__field relative">
<input
type="search"
placeholder="Search keywords..."
name="search"
id="search"
value={search}
onChange={(e) => setSearch(e.target.value)}
className="rounded-[8px] border-solid border-[1px] border-gray pl-7 outline-none focus:outline-primary-light text-[14px] focus:border-primary"
/>
</div>
<div className="header-right flex justify-end items-center gap-2">
<SelectField
name="search"
value={filterMethod}
onChange={(e) => setFilterMethod(e.target.value)}
options={[
{ value: "all", label: "All Method" },
{ value: "crypto", label: "Crypto" },
{ value: "paypal", label: "USD/Paypal" },
]}
/>
<Button onClick={onDownloadCSV}>Download CSV</Button>
</div>
</div>
);
}
...@@ -35,7 +35,7 @@ export default function Toast() { ...@@ -35,7 +35,7 @@ export default function Toast() {
return ( return (
<div <div
className={`fixed top-4 right-4 flex max-w-sm w-full items-start gap-3 rounded-xl border-l-4 px-4 py-3 shadow-lg transition-all duration-300 animate-in slide-in-from-right className={`z-[9999] fixed top-4 right-4 flex max-w-sm w-full items-start gap-3 rounded-xl border-l-4 px-4 py-3 shadow-lg transition-all duration-300 animate-in slide-in-from-right
data-[state=closed]:slide-out-to-right data-[state=closed]:fade-out data-[state=closed]:slide-out-to-right data-[state=closed]:fade-out
${variantStyles[currentVariant]}`} ${variantStyles[currentVariant]}`}
> >
......
...@@ -9,7 +9,7 @@ export default function AdminSearchBar() { ...@@ -9,7 +9,7 @@ export default function AdminSearchBar() {
<Box> <Box>
<div className="inpute__field relative"> <div className="inpute__field relative">
<input type="search" placeholder="Ctrl + K" name="search" id="search" className="rounded-[4px] border-solid border-[1px] border-gray pl-5 outline-none focus:outline-primary-light" /> <input type="search" placeholder="Ctrl + K" name="search" id="search" className="rounded-[4px] border-solid border-[1px] border-gray pl-5 outline-none focus:outline-primary-light" />
<SearchNormal color="#71717A" size={18} className="absolute left-2 top-1/2 transform -translate-y-1/2" /> <SearchNormal color="#71717A" size={16} className="absolute left-2 top-1/2 transform -translate-y-1/2" />
</div> </div>
</Box> </Box>
) )
......
"use client";
import Image from "next/image";
import LightGallery from "lightgallery/react";
import lgZoom from "lightgallery/plugins/zoom";
import lgThumbnail from "lightgallery/plugins/thumbnail";
import "lightgallery/css/lightgallery.css";
import "lightgallery/css/lg-zoom.css";
import "lightgallery/css/lg-thumbnail.css";
interface CustomLightGalleryProps {
images: string[];
aspectRatio?: string;
column?: string | number;
}
export default function CustomLightGallery({
images,
aspectRatio,
column
}: CustomLightGalleryProps) {
const baseGrid = "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2";
const gridClass = column
? `${baseGrid} lg:grid-cols-7`
: `${baseGrid} lg:grid-cols-5`;
return (
<LightGallery
speed={500}
plugins={[lgZoom, lgThumbnail]}
elementClassNames={`${gridClass}`}
>
{images.map((img, index) => (
<a
key={index}
href={img}
className={`relative w-full ${aspectRatio || "aspect-[210/120]"} block`}
>
<Image
src={img}
alt={`Screenshot ${index + 1}`}
fill
className="object-cover rounded-lg"
/>
</a>
))}
</LightGallery>
);
}
import { PATH } from '@/routes/PATH'; import { PATH } from '@/routes/PATH';
import { List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material' import { List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'
import { StatusUp } from '@wandersonalwes/iconsax-react' import { Game, StatusUp, UserSearch } from '@wandersonalwes/iconsax-react'
import { usePathname, useRouter } from 'next/navigation' import { usePathname, useRouter } from 'next/navigation'
import React from 'react' import React from 'react'
...@@ -42,7 +42,7 @@ export default function AdminMenu({ open }: { open: boolean }) { ...@@ -42,7 +42,7 @@ export default function AdminMenu({ open }: { open: boolean }) {
> >
<ListItemIcon className={open ? "expanded" : "collapsed"}> <ListItemIcon className={open ? "expanded" : "collapsed"}>
<StatusUp /> <Game />
</ListItemIcon> </ListItemIcon>
<ListItemText <ListItemText
primary="Games" primary="Games"
...@@ -50,6 +50,28 @@ export default function AdminMenu({ open }: { open: boolean }) { ...@@ -50,6 +50,28 @@ export default function AdminMenu({ open }: { open: boolean }) {
/> />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
<ListItem>
<ListItemButton
className={[
open ? "expanded" : "collapsed",
[
PATH.ADMIN.PLAYERS.ROOT,
PATH.ADMIN.PLAYERS.ADD_PLAYER.ROOT,
"/edit-game"
].some(path => pathname.startsWith(path)) ? "active" : ""
].join(" ")}
onClick={() => { router.push(PATH.ADMIN.PLAYERS.ROOT) }}
>
<ListItemIcon className={open ? "expanded" : "collapsed"}>
<UserSearch />
</ListItemIcon>
<ListItemText
primary="Players"
className={open ? "expanded" : "collapsed"}
/>
</ListItemButton>
</ListItem>
</List> </List>
) )
} }
...@@ -12,7 +12,7 @@ import { useRouter } from "next/navigation"; ...@@ -12,7 +12,7 @@ import { useRouter } from "next/navigation";
import * as Yup from "yup"; import * as Yup from "yup";
interface AddGameFormProps { interface AddGameFormProps {
id?: string | number id?: string
} }
const validationSchema = Yup.object({ const validationSchema = Yup.object({
......
"use client";
import React, { useMemo, useState } from "react";
import {
useReactTable,
getCoreRowModel,
getPaginationRowModel,
ColumnDef,
flexRender,
getSortedRowModel,
} from "@tanstack/react-table";
import { Button, Pagination } from "@mui/material";
import TableHeader from "@/components/molecules/TableHeader";
import { ArrowDown, ArrowUp } from "@wandersonalwes/iconsax-react";
interface PlayerTransaction {
id: number;
playerName: string;
method: string;
type: string;
amount: number;
sweepcoins: string;
date: string;
}
const data: PlayerTransaction[] = [
{ id: 244, playerName: "Harry Michael", method: "Paypal", type: "Deposit", amount: 56.68, sweepcoins: "56,598", date: "July 23, 2025 [15:69]" },
{ id: 243, playerName: "Harry Michael", method: "Crypto", type: "Withdraw", amount: 56.68, sweepcoins: "56,598", date: "July 23, 2025 [15:69]" },
{ id: 242, playerName: "Harry Michael", method: "Paypal", type: "Deposit", amount: 56.68, sweepcoins: "56,598", date: "July 23, 2025 [15:69]" },
{ id: 241, playerName: "Harry Michael", method: "Paypal", type: "Deposit", amount: 56.68, sweepcoins: "56,598", date: "July 23, 2025 [15:69]" },
{ id: 240, playerName: "Harry Michael", method: "Crypto", type: "Deposit", amount: 56.68, sweepcoins: "56,598", date: "July 23, 2025 [15:69]" },
{ id: 239, playerName: "Harry Michael", method: "Paypal", type: "Deposit", amount: 56.68, sweepcoins: "56,598", date: "July 23, 2025 [15:69]" },
{ id: 238, playerName: "Harry Michael", method: "Crypto", type: "Deposit", amount: 56.68, sweepcoins: "56,598", date: "July 23, 2025" },
];
export default function GameTransactionTable() {
const [search, setSearch] = useState("");
const [filterMethod, setFilterMethod] = useState("all");
const [sorting, setSorting] = useState<{ id: string; desc: boolean }[]>([]);
const columns = useMemo<ColumnDef<PlayerTransaction>[]>(
() => [
{
accessorKey: "id",
header: ({ column }) => (
<button
onClick={() => column.toggleSorting()}
className="flex items-center gap-1"
>
#ID
{{
asc: <ArrowUp size={14} />,
desc: <ArrowDown size={14} />,
}[column.getIsSorted() as string] || null}
</button>
),
},
{ accessorKey: "playerName", header: "Player Name" },
{ accessorKey: "method", header: "Method" },
{ accessorKey: "type", header: "Type" },
{ accessorKey: "amount", header: "Amount USD" },
{ accessorKey: "sweepcoins", header: "Sweepcoins" },
{ accessorKey: "date", header: "Transaction Date" },
],
[]
);
const filteredData = useMemo(() => {
return data.filter((row) => {
const searchMatch =
row.playerName.toLowerCase().includes(search.toLowerCase()) ||
row.type.toLowerCase().includes(search.toLowerCase()) ||
row.date.toLowerCase().includes(search.toLowerCase());
const methodMatch = filterMethod === "all" || row.method.toLowerCase() === filterMethod;
return searchMatch && methodMatch;
});
}, [search, filterMethod]);
const table = useReactTable({
data: filteredData,
columns,
state: { sorting },
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
});
const downloadCSV = () => {
};
return (
<section className="transaction__root">
<div className="section-title mb-4">
<h2 className="text-[20px] leading-[140%] font-[600]">
Games Under Diner Frenzy Spins
</h2>
</div>
<div className="border-gray border-solid border-[1px] rounded-[8px] lg:rounded-[16px]">
<TableHeader
search={search}
setSearch={setSearch}
filterMethod={filterMethod}
setFilterMethod={setFilterMethod}
onDownloadCSV={downloadCSV}
/>
<table className="min-w-full border-collapse border border-gray-200 text-left">
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th
key={header.id}
className="text-[12px] font-[600] text-title p-2 py-6 px-6 bg-light-gray"
>
{flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id} className="odd:bg-white even:bg-gray-50">
{row.getVisibleCells().map((cell) => (
<td key={cell.id} className=" p-2 py-6 px-6">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
{/* Pagination */}
<div className="flex justify-between items-center mt-4 px-8 py-6">
<div>
<span>Row per page:</span>
<select
value={table.getState().pagination.pageSize}
onChange={(e) => table.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={10} variant="outlined" shape="rounded" sx={{ gap: "8px" }} />
</div>
</div>
</section>
);
}
import TableHeader from '@/components/molecules/TableHeader';
import CustomLightGallery from '@/components/organism/LightGallery';
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import TransactionBlock from './Transaction';
export default function GameDetailPage() {
const screenshots = Array.from({ length: 12 }).map(
() => "/assets/images/auth-image.png"
);
const relatedGames = Array.from({ length: 8 }).map(
() => "/assets/images/auth-image.png"
);
return (
<>
<section className="game__detail__intro mb-14">
<div className="lg:grid grid-cols-12 gap-8 xl:gap-10">
<div className="lg:col-span-5 xl:col-span-4 game__featured__image relative aspect-[338/338] rounded-[10px] overflow-hidden">
<Image src={"/assets/images/fallback.png"} alt="Game Name" fill className="object-cover" />
</div>
<div className="game__content lg:col-span-7 xl:col-span-8">
<div className="flex items-start justify-between pb-6 mb-6 border-b-[1px] border-solid border-[rgba(0,0,0,0.1)]">
<div className="section__title">
<strong className="text-bold block mb-6 text-[12px]">
Active Players:{" "}
<span className="bg-primary-light rounded-[20px] py-1 px-2">
6985
</span>
</strong>
<h1 className='text-[24px] leading-[133%] mb-4'>Panda Master</h1>
<ul className="flex justify-start items-center gap-12">
<li className='flex gap-2' >
<p className="mb-1 text-[14px] leading-[120%] text-para-light">
Type:
</p>
<strong className="text-[14px] leading-[120%] font-[500] text-title">
Fishing
</strong>
</li>
<li className='flex gap-2' >
<p className="mb-1 text-[14px] leading-[120%] text-para-light">
Provider:
</p>
<strong className="text-[14px] leading-[120%] font-[500] text-title">
PG Soft
</strong>
</li>
</ul>
</div>
<Link href={"/games/1"} className='ss-btn bg-primary-grad max-w-fit text-white'>Edit Game Details</Link>
</div>
<div className="general-content-box content mb-6">
<p>Diner Frenzy Spins is a fast-paced, food-themed slot game where sizzling reels serve up delicious wins. Set in a retro diner, it features wild symbols, bonus rounds, and free spin combos that bring the kitchen chaos to life with every spin. With exciting bonus rounds, wild symbols, and free spin feature.. Read More</p>
</div>
<div className="game__key__highlight flex justify-between lg:flex-row flex-col gap-4 py-5 px-6 bg-[rgba(143,167,226,0.10)] rounded-[8px]">
<div className="highlight">
<p className='text-[12px] leading-[120%] font-[500] text-para-light'>This week total Screentime</p>
<strong className='text-[16px] leading-[120%] font-[600]'>689hr</strong>
</div>
<div className="highlight">
<p className='text-[12px] leading-[120%] font-[500] text-para-light'>Available Credit</p>
<strong className='text-[16px] leading-[120%] font-[600]'>$326,126.05 <span className='text-[12px] leading-[120%] font-[500] text-para-light'>/100,000</span></strong>
</div>
<div className="highlight">
<p className='text-[12px] leading-[120%] font-[500] text-para-light'>Unsettled Credit</p>
<strong className='text-[16px] leading-[120%] font-[600]'>$326,126.05 <span className='text-[12px] leading-[120%] font-[500] text-para-light'>/100,000</span></strong>
</div>
</div>
</div>
</div>
</section>
{screenshots.length ? <section className="game__screenshots mb-14">
<div className="section-title mb-4">
<h2 className="text-[20px] leading-[140%] font-[600]">
Uploaded Game-Screenshots
</h2>
</div>
<CustomLightGallery images={screenshots} />
</section> : null}
{relatedGames.length ? <section className="game__screenshots mb-14">
<div className="section-title mb-4">
<h2 className="text-[20px] leading-[140%] font-[600]">
Games Under Diner Frenzy Spins
</h2>
</div>
<CustomLightGallery images={relatedGames} aspectRatio='aspect-[148/164]' column="7" />
</section> : null}
<TransactionBlock />
</>
)
}
...@@ -102,7 +102,7 @@ export default function AdminGameList() { ...@@ -102,7 +102,7 @@ export default function AdminGameList() {
{/* CTA */} {/* CTA */}
<Link <Link
href={`/game/${game.id}`} href={`/games/${game.id}`}
className="ss-btn bg-primary-grad text-white max-w-fit" className="ss-btn bg-primary-grad text-white max-w-fit"
> >
Game Overview Game Overview
......
import React from 'react'
export default function PlayerListing() {
return (
<div>PlayerListing</div>
)
}
...@@ -3,6 +3,7 @@ import { configureStore } from "@reduxjs/toolkit"; ...@@ -3,6 +3,7 @@ import { configureStore } from "@reduxjs/toolkit";
import auth from "@/slice/authSlice"; import auth from "@/slice/authSlice";
import toastSlice from "@/slice/toastSlice"; import toastSlice from "@/slice/toastSlice";
import { gameApi } from "@/services/gameApi"; import { gameApi } from "@/services/gameApi";
import { playerApi } from "@/services/playerApi";
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
...@@ -10,11 +11,13 @@ export const store = configureStore({ ...@@ -10,11 +11,13 @@ export const store = configureStore({
toastSlice, toastSlice,
[authApi.reducerPath]: authApi.reducer, [authApi.reducerPath]: authApi.reducer,
[gameApi.reducerPath]: gameApi.reducer, [gameApi.reducerPath]: gameApi.reducer,
[playerApi.reducerPath]: playerApi.reducer,
}, },
middleware: (getDefaultMiddleware) => middleware: (getDefaultMiddleware) =>
getDefaultMiddleware() getDefaultMiddleware()
.concat(authApi.middleware) .concat(authApi.middleware)
.concat(gameApi.middleware) .concat(gameApi.middleware)
.concat(playerApi.middleware)
}) })
......
...@@ -23,7 +23,16 @@ export const PATH = { ...@@ -23,7 +23,16 @@ export const PATH = {
ROOT: "/games/add-game" ROOT: "/games/add-game"
}, },
EDIT_GAME: { EDIT_GAME: {
ROOT: "/games/edit-game/:id" ROOT: "/games/edit-game/"
}
},
PLAYERS: {
ROOT: "/players",
ADD_PLAYER: {
ROOT: "/players/add-player"
},
EDIT_PLAYER: {
ROOT: "/players/edit-player/"
} }
} }
}, },
......
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "./baseQuery";
import { PlayerProps, PlayerResponseProps } from "@/types/player";
import { GlobalResponse } from "@/types/config";
export const playerApi = createApi({
reducerPath: "playerApi",
baseQuery: baseQuery,
tagTypes: ["players"],
endpoints: (builder) => ({
createPlayer: builder.mutation<PlayerResponseProps, FormData>({
query: (body) => ({
url: "/api/admin/add-user",
method: "POST",
body: body
}),
invalidatesTags: ["players"]
}),
getAllPlayer: builder.query<PlayerResponseProps[], null>({
query: () => ({
url: "/api/admin/get-users",
method: "GET"
}),
providesTags: ['players']
}),
getPlayerById: builder.query<PlayerResponseProps, { id: number }>({
query: ({ id }) => ({
url: `/api/admin/get-user/${id}`,
method: "GET"
}),
providesTags: ['players']
}),
getPlayerBalanceById: builder.query<PlayerResponseProps, { id: number }>({
query: ({ id }) => ({
url: `/api/admin/get-balance/${id}`,
method: "GET"
}),
providesTags: ['players']
}),
updatePlayerById: builder.mutation<PlayerResponseProps, { id: number, data: FormData }>({
query: ({ id, data }) => ({
url: `/api/admin/update-user/${id}`,
method: "POST",
body: data
}),
invalidatesTags: ["players"]
}),
deletePlayerById: builder.mutation<GlobalResponse, { id: number }>({
query: ({ id }) => ({
url: `/api/admin/update-user/${id}`,
method: "DELETE",
}),
invalidatesTags: ["players"]
}),
})
})
export const {
useCreatePlayerMutation,
useGetAllPlayerQuery,
useGetPlayerByIdQuery,
useGetPlayerBalanceByIdQuery, useUpdatePlayerByIdMutation,
useDeletePlayerByIdMutation
} = playerApi;
\ No newline at end of file
...@@ -49,6 +49,9 @@ export default function Palette(mode: ThemeMode) { ...@@ -49,6 +49,9 @@ export default function Palette(mode: ThemeMode) {
// Final MUI Theme // Final MUI Theme
return createTheme({ return createTheme({
typography: {
fontFamily: "Inter, sans-serif",
},
palette: { palette: {
mode: mode as PaletteMode, mode: mode as PaletteMode,
common: { common: {
...@@ -127,7 +130,7 @@ export default function Palette(mode: ThemeMode) { ...@@ -127,7 +130,7 @@ export default function Palette(mode: ThemeMode) {
}, },
}, },
input: { input: {
p0dding: 0, padding: 0,
"&::placeholder": { "&::placeholder": {
color: "var(--Gray, #999)", color: "var(--Gray, #999)",
fontWeight: 400, fontWeight: 400,
...@@ -263,14 +266,6 @@ export default function Palette(mode: ThemeMode) { ...@@ -263,14 +266,6 @@ export default function Palette(mode: ThemeMode) {
} }
} }
}, },
typography: {
fontFamily: "Inter, sans-serif",
subtitle1: {
fontSize: "14px",
fontWeight: 500,
lineHeight: "120%",
color: "var(--Title, #0E0E11)"
}
}
}); });
} }
\ No newline at end of file
import { ImageProps } from "./config";
export interface PlayerProps {
name: string;
email: string;
first_name: string;
last_name: string;
wallet_address?: string;
address?: string;
city?: string;
phone?: string;
password: string;
password_confirmation: string;
profile_image: File | null;
}
export const initialPlayerValues: PlayerProps = {
name: "",
email: "",
first_name: "",
last_name: "",
wallet_address: "",
address: "",
city: "",
phone: "",
password: "",
password_confirmation: "",
profile_image: null,
};
export interface PlayerItem extends PlayerProps {
id: string | number
}
export interface PlayerResponseProps {
data: {
data: PlayerItem;
message: string;
status: string;
}
}
\ No newline at end of file
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