Commit 91cc1cd6 by Arjun Jhukal

updated the sidebar appbar and basic games page layut

parent 60f68308
import PageHeader from '@/components/molecules/PageHeader'
import { PATH } from '@/routes/PATH'
import React from 'react'
export default function AdminGames() {
return (
<div>AdminGames</div>
<div className="admin__game__root">
<PageHeader title="Games" cta={{ label: "Add New Game", url: PATH.ADMIN.GAMES.ADD_GAME.ROOT }} />
</div>
)
}
......@@ -45,6 +45,7 @@
--color-white: var(--white);
--color-black: var(--black);
--color-gray: var(--gray);
--color-title: var(--title);
--color-light-gray: var(--light-gray);
--color-primary-light: var(--primary-light);
--color-primary: var(--primary);
......
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { Geist, Geist_Mono, Inter } from "next/font/google";
import "./globals.css";
import ProviderWrapper from "./ProviderWrapper";
......@@ -8,6 +8,13 @@ export const metadata: Metadata = {
description: "Generated by create next app",
};
const inter = Inter({
subsets: ['latin'],
fallback: ['sans-serif'],
weight: ['300', '400', '500', '700'],
adjustFontFallback: false
});
export default function RootLayout({
children,
}: Readonly<{
......@@ -16,7 +23,7 @@ export default function RootLayout({
return (
<html lang="en">
{/* className="dark" */}
<body >
<body className="scroll-smooth" style={{ fontFamily: inter.style.fontFamily }}>
<ProviderWrapper>
{children}
</ProviderWrapper>
......
import { styled, Theme } from '@mui/material/styles';
import MuiAvatar, { AvatarProps as MuiAvatarProps } from '@mui/material/Avatar';
import React from 'react';
interface Props extends MuiAvatarProps {
color?: 'primary' | 'secondary' | string;
type?: 'filled' | 'outlined' | 'combined';
size?: 'sm' | 'md' | 'lg' | 'badge';
}
const AvatarStyle = styled(MuiAvatar, {
shouldForwardProp: (prop) => !['color', 'type', 'size'].includes(prop as string),
})<Props>(({ theme, color, type, size }: { theme: Theme } & Props) => ({
width: 40,
height: 40,
borderRadius: 8,
// Optional styles based on type/color
backgroundColor: type === 'filled' ? theme.palette.primary.main : 'transparent',
border: type === 'outlined' ? `2px solid ${theme.palette.primary.main}` : undefined,
color: type === 'filled' ? theme.palette.common.white : theme.palette.primary.main,
}));
export default function Avatar({ children, color = 'primary', type = 'filled', size = 'md', ...others }: Props) {
return (
<AvatarStyle color={color} type={type} size={size} {...others}>
{children}
</AvatarStyle>
);
}
......@@ -4,6 +4,9 @@ import { Box } from '@mui/material'
import React from 'react'
import Sidebar from '../organism/Sidebar'
import Header from '../organism/Header'
import { styled } from '@mui/material/styles';
import { usePathname } from 'next/navigation';
import Breadcrumb from '../molecules/Breadcrumb';
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
const [open, setOpen] = React.useState(false);
......@@ -15,13 +18,27 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
const handleDrawerClose = () => {
setOpen(false);
};
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
...theme.mixins.toolbar,
}));
const pathname = usePathname();
return (
<Box sx={{ display: 'flex' }}>
<Header open={open} handleDrawerOpen={handleDrawerOpen} />
<Sidebar open={open} handleDrawerOpen={handleDrawerOpen} />
{/* <div className="root_container">
<div className="content_box p-4 lg:pl-11 lg:pr-12 lg:py-8">{children}</div>
</div> */}
<div className="root_container w-full">
<DrawerHeader />
<div className="content_box p-4 lg:pl-11 lg:pr-12 lg:py-8">
{/* {pathname !== '/' && <Breadcrumb />} */}
{children}</div>
</div>
</Box>
)
}
'use client';
import React from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Box, Typography, Stack } from '@mui/material';
import { ArrowRight2 } from '@wandersonalwes/iconsax-react';
export default function Breadcrumb() {
const pathname = usePathname();
const pathSegments = pathname?.split('/').filter(Boolean) || [];
const breadcrumbs = pathSegments.map((segment, index) => {
const label = segment.replace(/-/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
const href = '/' + pathSegments.slice(0, index + 1).join('/');
return { label, href };
});
return (
<Stack direction="row" spacing={1} alignItems="center" className='mb-2'>
<Link href="/" className='text-title font-[500] text-[10px] lg:text-[12px] leading-[120%]'>
Home
</Link>
{breadcrumbs.map((crumb, idx) => (
<React.Fragment key={crumb.href}>
<ArrowRight2 size={10} />
{idx === breadcrumbs.length - 1 ? (
<strong className='text-title !font-[500] text-[10px] lg:text-[12px] leading-[120%]' >
{crumb.label}
</strong>
) : (
<Link href={crumb.href} className='text-title font-[500] text-[10px] lg:text-[12px] leading-[120%]'>
{crumb.label}
</Link>
)}
</React.Fragment>
))}
</Stack>
);
}
import { Box } from '@mui/material'
import React from 'react'
import Breadcrumb from './Breadcrumb'
import Link from 'next/link'
export default function PageHeader({ title, cta }: { title?: string, cta?: { label: string, url: string } }) {
return (
<Box className='flex flex-col md:flex-row md:items-center md:justify-between gap-2 mb-6'>
<div className="header__left">
<Breadcrumb />
{title && <h1 className="text-[24px] leading-[133%] font-bold text-title">{title}</h1>}
</div>
{cta && (
<div className="header__right">
<Link href={cta.url} className="ss-btn bg-primary-grad text-white hover:opacity-90">
{cta.label}
</Link>
</div>
)}
</Box>
)
}
import React from "react";
export type TransitionPosition =
| 'top-right'
| 'top'
| 'top-left'
| 'bottom-right'
| 'bottom'
| 'bottom-left';
export interface TransitionsProps extends React.HTMLAttributes<HTMLDivElement> {
children?: React.ReactNode;
type?: string; // kept for API compatibility
position?: TransitionPosition;
in?: boolean; // controls show/hide
}
export const Transitions = React.forwardRef<HTMLDivElement, TransitionsProps>(({
children,
type = 'grow',
position = 'top',
in: inProp = false,
...other
}, ref) => {
const [isMounted, setIsMounted] = React.useState(false);
const [isVisible, setIsVisible] = React.useState(false);
React.useEffect(() => {
if (inProp) {
setIsMounted(true);
setTimeout(() => setIsVisible(true), 10);
} else {
setIsVisible(false);
setTimeout(() => setIsMounted(false), 300);
}
}, [inProp]);
const getTransform = () => {
switch (position) {
case 'top-right': return isVisible ? 'translate(0,0)' : 'translate(20px,-20px)';
case 'top': return isVisible ? 'translate(0,0)' : 'translate(0,-20px)';
case 'top-left': return isVisible ? 'translate(0,0)' : 'translate(-20px,-20px)';
case 'bottom-right': return isVisible ? 'translate(0,0)' : 'translate(20px,20px)';
case 'bottom': return isVisible ? 'translate(0,0)' : 'translate(0,20px)';
case 'bottom-left': return isVisible ? 'translate(0,0)' : 'translate(-20px,20px)';
default: return isVisible ? 'translate(0,0)' : 'translate(0,20px)';
}
};
const getOpacity = () => (isVisible ? 1 : 0);
if (!isMounted) return null;
return (
<div
ref={ref}
style={{
opacity: getOpacity(),
transform: getTransform(),
transition: 'opacity 0.3s ease, transform 0.3s ease',
...other.style
}}
{...other}
>
{children}
</div>
);
});
Transitions.displayName = 'Transitions';
// "use client";
import { Box } from "@mui/material";
import OutlinedInput from "@mui/material/OutlinedInput";
import React from 'react'
export default function AdminSearchBar() {
return (
<Box>
<OutlinedInput
name='search'
id='search'
placeholder='Ctrl + K'
/>
</Box>
)
}
import { Box, IconButton } from '@mui/material'
import React from 'react'
// import AdminSearchBar from './AdminSearchBar'
import dynamic from "next/dynamic";
import { Add } from '@wandersonalwes/iconsax-react';
import NotificationPage from '../Notification';
import Profile from '../Profile';
const AdminSearchBar = dynamic(() => import("./AdminSearchBar"), { ssr: false });
export default function AdminHeader() {
return (
<div>AdminHeader</div>
<Box className='flex items-center gap-4 jutify-content-between w-full'>
{/* <AdminSearchBar /> */}
<input type="text" />
<div className="right flex items-center gap-4">
<IconButton
color="inherit"
sx={[
{
maxWidth: "fit-content"
},
]}
className='!bg-light-gray'
>
<Add className='!text-primary-light' />
</IconButton>
<NotificationPage />
<Profile />
</div>
</Box>
)
}
"use client";
import React, { useRef, useState } from 'react';
import { Badge, Box, IconButton, Popper, useMediaQuery, Paper, ClickAwayListener, CardContent, Typography, Stack } from '@mui/material';
import { Notification } from '@wandersonalwes/iconsax-react';
import Grow from '@mui/material/Grow';
import { Transitions } from '@/components/molecules/Transition';
import Link from 'next/link';
export default function NotificationPage({ badgeCount = 0, width = 300, children }: { badgeCount?: number, width?: number, children?: React.ReactNode }) {
const downMD = useMediaQuery((theme: any) => theme.breakpoints.down('md'));
const anchorRef = useRef<HTMLButtonElement | null>(null);
const [open, setOpen] = useState(false);
const handleToggle = () => setOpen(prev => !prev);
const handleClose = (event: MouseEvent | TouchEvent) => {
if (anchorRef.current && anchorRef.current.contains(event.target as Node)) return;
setOpen(false);
};
return (
<Box>
<IconButton ref={anchorRef} onClick={handleToggle} className='!bg-light-gray'>
<Badge badgeContent={badgeCount} color="success" sx={{ '& .MuiBadge-badge': { top: 2, right: 4 } }}>
<Notification variant="Bold" className="!text-primary-light" />
</Badge>
</IconButton>
<Popper
placement={downMD ? 'bottom' : 'bottom-end'}
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
popperOptions={{ modifiers: [{ name: 'offset', options: { offset: [downMD ? -5 : 0, 9] } }] }}
className='top-[100%]'
>
{({ TransitionProps }) => (
<Transitions type="grow" position={downMD ? 'top' : 'top-right'} in={open} {...TransitionProps}>
<Paper sx={(theme) => ({ borderRadius: 1.5, width: { xs: 320, sm: 420 } })}>
<ClickAwayListener onClickAway={handleClose}>
<CardContent>
<Stack direction="row" sx={{ alignItems: 'center', justifyContent: 'space-between' }}>
<Typography variant="h5">Notifications</Typography>
<Link href="#" color="title">
Mark all read
</Link>
</Stack>
<Stack direction="row" sx={{ justifyContent: 'center', mt: 1.5 }}>
<Link href="#" color="title">
View all
</Link>
</Stack>
</CardContent>
</ClickAwayListener>
</Paper>
</Transitions>
)}
</Popper>
</Box>
);
}
import Avatar from '@/components/atom/Avatar';
import { Transitions } from '@/components/molecules/Transition';
import { Box, Button, ButtonBase, ClickAwayListener, List, ListItem, Paper, Popper, Stack, Typography } from '@mui/material'
import Link from 'next/link';
import React, { useRef, useState } from 'react'
const avataur1 = '/assets/images/avatar-6.png';
export default function Profile() {
const anchorRef = useRef<any>(null);
const [open, setOpen] = useState(false);
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event: MouseEvent | TouchEvent) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
const handleLogout = () => {
}
return (
<Box >
<Button
sx={(theme) => ({
p: 0.25,
borderRadius: 1,
'&:hover': { bgcolor: 'secondary.lighter', ...theme.applyStyles('dark', { bgcolor: 'secondary.light' }) },
'&:focus-visible': {
outline: `2px solid ${theme.palette.secondary.dark}`,
outlineOffset: 2
}
})}
aria-label="open profile"
ref={anchorRef}
aria-controls={open ? 'profile-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
{/* <Avatar alt="profile user" src={avataur1} /> */}
<Stack direction="row" sx={{ gap: 1.25, alignItems: 'center' }}>
<Avatar alt="profile user" src={avataur1} />
<Stack>
<strong className='text-[14px] leading-[120%] font-bold text-text-title block mb-1 text-nowrap'>{"Arjun Jhukal"}</strong>
<p className='text-[12px] text-left leading-[120%] font-bold text-primary-light text-nowrap'>
UI/UX Designer
</p>
</Stack>
</Stack>
</Button>
<Popper
placement="bottom-end"
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
modifiers={[
{
name: 'offset',
options: {
offset: [0, 8], // spacing from anchor
},
},
]}
>
{({ TransitionProps }) => (
<Transitions type="grow" position="top-right" in={open} {...TransitionProps}>
<Paper
sx={{
backgroundColor: 'transparent',
boxShadow: 'none',
borderRadius: 0,
width: '100%', // take full width
maxWidth: 'unset', // remove MUI’s maxWidth restriction
}}
elevation={0}
>
<ClickAwayListener onClickAway={handleClose}>
<List>
<ListItem>
<Link href="#">Visit Sweepstake Website</Link>
</ListItem>
<ListItem
onClick={handleLogout}
className="text-red-600 cursor-pointer"
>
Logout
</ListItem>
</List>
</ClickAwayListener>
</Paper>
</Transitions>
)}
</Popper>
</Box>
)
}
"use client";
import { DRAWER_WIDTH } from '@/config';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar';
import { styled, useTheme, Theme, CSSObject } from '@mui/material/styles';
import { styled } from '@mui/material/styles';
import React from 'react'
import { HambergerMenu } from '@wandersonalwes/iconsax-react';
import AdminHeader from './AdminHeader';
import UserHeader from './UserHeader';
import { OutlinedInput } from '@mui/material';
interface AppBarProps extends MuiAppBarProps {
open?: boolean;
......@@ -18,6 +22,8 @@ const AppBar = styled(MuiAppBar, {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
backgroundColor: theme.palette.common.white,
boxShadow: "none",
variants: [
{
props: ({ open }) => open,
......@@ -28,6 +34,7 @@ const AppBar = styled(MuiAppBar, {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
},
],
......@@ -36,9 +43,12 @@ export default function Header({ open, handleDrawerOpen }: {
open: boolean,
handleDrawerOpen: () => void;
}) {
const user = { role: "ADMIN" }
return (
<AppBar position="fixed" open={open}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
......@@ -49,15 +59,18 @@ export default function Header({ open, handleDrawerOpen }: {
marginRight: 5,
maxWidth: "fit-content"
},
// open && { display: 'none' },
]}
className='!bg-light-gray'
>
{/* <MenuIcon /> */}
<HambergerMenu />
<HambergerMenu className='!text-primary-light' />
</IconButton>
<Typography variant="h6" noWrap component="div">
Mini variant drawer
</Typography>
{
user?.role.toUpperCase() === 'ADMIN' ? (
<AdminHeader />
) : (
<UserHeader />
)
}
</Toolbar>
</AppBar>
)
......
"use client";
import * as React from 'react';
import { styled, useTheme, Theme, CSSObject } from '@mui/material/styles';
import { styled, Theme, CSSObject } from '@mui/material/styles';
import Box from '@mui/material/Box';
import MuiDrawer from '@mui/material/Drawer';
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import List from '@mui/material/List';
import CssBaseline from '@mui/material/CssBaseline';
import Typography from '@mui/material/Typography';
import Divider from '@mui/material/Divider';
import IconButton from '@mui/material/IconButton';
import { HambergerMenu } from "@wandersonalwes/iconsax-react";
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import { DRAWER_WIDTH } from '@/config';
import Image from 'next/image';
import { useAppSelector } from '@/hooks/hook';
import AdminMenu from './AdminSidebar';
import UserMenu from './UserSidebar';
import { useAppSelector } from '@/hooks/hook';
const drawerWidth = DRAWER_WIDTH;
......@@ -50,7 +38,7 @@ const DrawerHeader = styled('div')(({ theme }) => ({
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
}));
......@@ -85,8 +73,8 @@ export default function Sidebar({ open, handleDrawerOpen }: {
handleDrawerOpen: () => void;
}) {
// const user = useAppSelector((state) => state.auth.user);
const user = { role: "USER" }
const user = useAppSelector((state) => state.auth.user);
// const user = { role: "USER" }
return (
<Drawer variant="permanent" open={open}>
<DrawerHeader sx={{ justifyContent: "center" }}>
......
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