fix: some duplications and tags
This commit is contained in:
+116
-151
@@ -1,8 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React, { useMemo, useRef, useState } from 'react'
|
||||
import React, { useMemo, useRef, useState } from 'react';
|
||||
import { motion, PanInfo, Variants } from 'framer-motion';
|
||||
import MenuItemType from './SideMenuItem'
|
||||
import SideMenuItem from './SideMenuItem';
|
||||
import NotificationBellIcon from '../icons/NotificationBellIcon';
|
||||
import CupIcon from '../icons/CupIcon';
|
||||
@@ -13,9 +12,9 @@ import GameControllerIcon from '../icons/GameControllerIcon';
|
||||
import ThumbsUpIcon from '../icons/ThumbsUpIcon';
|
||||
import NoteBoardIcon from '../icons/NoteBoardIcon';
|
||||
import DirectboxReceiveIcon from '../icons/DirectboxReceiveIcon';
|
||||
import BlurredOverlayContainer from '../overlays/BlurredOverlayContainer';
|
||||
import SettingIcon from '../icons/SettingsIcon';
|
||||
import ExitIcon from '../icons/ExitIcon';
|
||||
import BlurredOverlayContainer from '../overlays/BlurredOverlayContainer';
|
||||
import NightModeSwitch from '../button/NightModeSwitch';
|
||||
import Button from '../button/PrimaryButton';
|
||||
import { useAuthStore } from '@/zustand/authStore';
|
||||
@@ -27,61 +26,39 @@ type MenuItemType = {
|
||||
title: string;
|
||||
icon: React.ReactElement;
|
||||
auth?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
const menuItems: Array<Array<MenuItemType>> = [
|
||||
[
|
||||
{
|
||||
href: '/', title: 'اعلان ها', icon: <NotificationBellIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: 'my-services', title: 'باشگاه مشتریان', icon: <CupIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: 'services', title: 'کد های تخفیف', icon: <TicketDiscountIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: 'orders', title: 'لیست سفارشات', icon: <CalendarSearchIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: 'transactions', title: 'لیست تراکنش ها', icon: <ReceiptIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: '/', title: 'بازی و سرگرمی ها', icon: <GameControllerIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: 'my-services', title: 'معرفی به دوستان', icon: <ThumbsUpIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: 'services', title: 'گزارش اشکال', icon: <NoteBoardIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
href: 'invoices', title: 'نصب اپلیکیشن', icon: <DirectboxReceiveIcon width={20} height={20} />
|
||||
},
|
||||
{ href: '/', title: 'اعلان ها', icon: <NotificationBellIcon width={20} height={20} /> },
|
||||
{ href: 'my-services', title: 'باشگاه مشتریان', icon: <CupIcon width={20} height={20} /> },
|
||||
{ href: 'services', title: 'کد های تخفیف', icon: <TicketDiscountIcon width={20} height={20} /> },
|
||||
{ href: 'orders', title: 'لیست سفارشات', icon: <CalendarSearchIcon width={20} height={20} /> },
|
||||
{ href: 'transactions', title: 'لیست تراکنش ها', icon: <ReceiptIcon width={20} height={20} /> },
|
||||
{ href: '/', title: 'بازی و سرگرمی ها', icon: <GameControllerIcon width={20} height={20} /> },
|
||||
{ href: 'my-services', title: 'معرفی به دوستان', icon: <ThumbsUpIcon width={20} height={20} /> },
|
||||
{ href: 'services', title: 'گزارش اشکال', icon: <NoteBoardIcon width={20} height={20} /> },
|
||||
{ href: 'invoices', title: 'نصب اپلیکیشن', icon: <DirectboxReceiveIcon width={20} height={20} /> }
|
||||
],
|
||||
[],
|
||||
[
|
||||
{
|
||||
auth: true, href: undefined, title: 'تنظیمات', icon: <SettingIcon width={20} height={20} />
|
||||
},
|
||||
{
|
||||
auth: true, href: '?logout', title: 'خروج', icon: <ExitIcon width={20} height={20} />
|
||||
},
|
||||
{ auth: true, href: undefined, title: 'تنظیمات', icon: <SettingIcon width={20} height={20} /> },
|
||||
{ auth: true, href: '?logout', title: 'خروج', icon: <ExitIcon width={20} height={20} /> }
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
type Props = {
|
||||
menuState: boolean,
|
||||
toggleMenuState: React.MouseEventHandler<HTMLDivElement> | undefined
|
||||
nightModeState: boolean,
|
||||
togglenightModeState: React.MouseEventHandler<HTMLDivElement> | undefined
|
||||
}
|
||||
menuState: boolean;
|
||||
toggleMenuState: React.MouseEventHandler<HTMLDivElement> | undefined;
|
||||
nightModeState: boolean;
|
||||
togglenightModeState: React.MouseEventHandler<HTMLDivElement> | undefined;
|
||||
};
|
||||
|
||||
function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeState }: Props) {
|
||||
const menuStateMemo = useMemo(() => menuState, [menuState]);
|
||||
const [logoutModalVisible, setLogoutModalVisible] = useState(false);
|
||||
const closeRef: React.Ref<HTMLDivElement> | undefined = useRef(null);
|
||||
const userIsAuthenticated = true; //useAuthStore((state) => state.isAuthenticated);
|
||||
const closeRef = useRef<HTMLDivElement>(null);
|
||||
const userIsAuthenticated = true; // useAuthStore((state) => state.isAuthenticated);
|
||||
const authLogout = useAuthStore((state) => state.logout);
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
@@ -89,35 +66,20 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
|
||||
const pathname = usePathname();
|
||||
|
||||
const variants: Variants = {
|
||||
hidden: {
|
||||
x: '100%',
|
||||
transition: {
|
||||
duration: 0.1,
|
||||
ease: 'easeInOut',
|
||||
},
|
||||
},
|
||||
visible: {
|
||||
x: 0,
|
||||
transition: {
|
||||
delay: 0.075,
|
||||
duration: 0.1,
|
||||
ease: 'easeInOut',
|
||||
},
|
||||
},
|
||||
hidden: { x: '100%', transition: { duration: 0.1, ease: 'easeInOut' } },
|
||||
visible: { x: 0, transition: { delay: 0.075, duration: 0.1, ease: 'easeInOut' } }
|
||||
};
|
||||
|
||||
const onDrag = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
|
||||
if (info.offset.x > 20) {
|
||||
if (closeRef.current) {
|
||||
closeRef.current.click();
|
||||
}
|
||||
if (info.offset.x > 20 && closeRef.current) {
|
||||
closeRef.current.click();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const toggleLogoutModalVisiblity = (e: React.MouseEvent<HTMLAnchorElement> | React.MouseEvent<HTMLButtonElement> | React.MouseEvent<HTMLDivElement> | undefined) => {
|
||||
const toggleLogoutModalVisiblity = (e?: React.MouseEvent) => {
|
||||
e?.stopPropagation();
|
||||
setLogoutModalVisible((state) => !state);
|
||||
}
|
||||
};
|
||||
|
||||
const onLogout = (e: React.MouseEvent<HTMLButtonElement> | null) => {
|
||||
if (!e) return;
|
||||
@@ -127,102 +89,105 @@ function SideMenu({ menuState, toggleMenuState, nightModeState, togglenightModeS
|
||||
}
|
||||
};
|
||||
|
||||
const hrefOnClicks: Array<{ href: string, handler: React.MouseEventHandler<HTMLAnchorElement> | undefined }> = [
|
||||
{ href: '?logout', handler: toggleLogoutModalVisiblity }
|
||||
]
|
||||
const hrefOnClicks = [{ href: '?logout', handler: toggleLogoutModalVisiblity }];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='w-full' ref={closeRef} onClick={toggleMenuState} >
|
||||
<div className='w-full' ref={closeRef} onClick={toggleMenuState}>
|
||||
<BlurredOverlayContainer bgOpacity={40} visible={menuStateMemo} outDelay={150} inDuration={200}>
|
||||
<motion.div
|
||||
drag='x'
|
||||
dragConstraints={{ left: 0, right: 20 }}
|
||||
transition={{ type: "spring", stiffness: 200, damping: 20 }}
|
||||
dragTransition={{ bounceDamping: 10, bounceStiffness: 600 }}
|
||||
dragElastic={0.05}
|
||||
onDragEnd={onDrag}
|
||||
initial="hidden"
|
||||
animate={menuState ? 'visible' : 'hidden'}
|
||||
variants={variants}
|
||||
data-visible={menuState}
|
||||
data-isvisible={menuStateMemo}
|
||||
onClick={(e) => { e.stopPropagation(); }}
|
||||
className={`fixed top-0 bottom-0 right-0 ease-in-out not-xl:!rounded-s-none overflow-clip bg-white w-[200px] h-dvh flex flex-col z-40`}>
|
||||
<ul className="overflow-y-scroll noscrollbar pt-20 pb-10 flex flex-col justify-between h-full ">
|
||||
<li>
|
||||
<div className='flex flex-col gap-[60px]'>
|
||||
<div className='flex flex-col gap-[23px]'>
|
||||
<div className='pt-2 text-start text-sm px-12 text-menu-header'>منو</div>
|
||||
{menuItems[0].filter((x) => x.auth ? userIsAuthenticated && x : x).map((v, i) => {
|
||||
const isActive = pathname === `/${name}/${v.href}`
|
||||
return <SideMenuItem
|
||||
className={clsx(
|
||||
isActive && 'text-foreground!'
|
||||
)}
|
||||
key={i}
|
||||
href={(v.href ?? '')}
|
||||
title={v.title}
|
||||
icon={
|
||||
<div className={clsx(
|
||||
isActive ? 'text-foreground!' : 'text-icon-deactive'
|
||||
)}
|
||||
>
|
||||
{v.icon}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li className='flex flex-col gap-6 pt-16'>
|
||||
{menuItems[2].filter((x) => x.auth ? userIsAuthenticated && x : x).map((v, i) => {
|
||||
return <SideMenuItem
|
||||
key={i}
|
||||
href={v.href || ''}
|
||||
onClick={v.href && hrefOnClicks.find((i) => i.href === v.href)?.handler || undefined}
|
||||
title={v.title}
|
||||
icon={<div className='text-icon-deactive'>{v.icon}</div>}
|
||||
/>
|
||||
})}
|
||||
<SideMenuItem href={''} title={''} icon={<></>}><NightModeSwitch checked={nightModeState} onClick={togglenightModeState} /></SideMenuItem>
|
||||
</li>
|
||||
</ul>
|
||||
</motion.div>
|
||||
<aside aria-label="منوی کناری">
|
||||
<motion.nav
|
||||
drag='x'
|
||||
dragConstraints={{ left: 0, right: 20 }}
|
||||
transition={{ type: "spring", stiffness: 200, damping: 20 }}
|
||||
dragTransition={{ bounceDamping: 10, bounceStiffness: 600 }}
|
||||
dragElastic={0.05}
|
||||
onDragEnd={onDrag}
|
||||
initial="hidden"
|
||||
animate={menuState ? 'visible' : 'hidden'}
|
||||
variants={variants}
|
||||
data-visible={menuState}
|
||||
data-isvisible={menuStateMemo}
|
||||
onClick={(e) => { e.stopPropagation(); }}
|
||||
className="fixed top-0 bottom-0 right-0 bg-white w-[200px] h-dvh flex flex-col z-40 overflow-clip not-xl:!rounded-s-none"
|
||||
>
|
||||
<section className="flex-1 overflow-y-scroll noscrollbar pt-20 pb-10 flex flex-col justify-between">
|
||||
<div>
|
||||
<header className="px-12">
|
||||
<h6 className="text-start text-sm text-menu-header mt-2 mb-[23px]">منو</h6>
|
||||
</header>
|
||||
|
||||
<nav aria-label="لینکهای اصلی">
|
||||
<ul>
|
||||
{menuItems[0]
|
||||
.filter(item => !item.auth || (item.auth && userIsAuthenticated))
|
||||
.map((item, index) => {
|
||||
const isActive = pathname === `/${name}/${item.href}`;
|
||||
return (
|
||||
<li key={index} className="mt-[18px]">
|
||||
<SideMenuItem
|
||||
className={clsx(isActive && 'text-foreground!')}
|
||||
href={item.href ?? ''}
|
||||
title={item.title}
|
||||
icon={
|
||||
<span className={clsx(isActive ? 'text-foreground!' : 'text-icon-deactive')}>
|
||||
{item.icon}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<section aria-label="پایین منو">
|
||||
<ul className="flex flex-col gap-6 pt-16">
|
||||
{menuItems[2]
|
||||
.filter(item => !item.auth || (item.auth && userIsAuthenticated))
|
||||
.map((item, index) => (
|
||||
<SideMenuItem
|
||||
key={index}
|
||||
href={item.href ?? ''}
|
||||
onClick={
|
||||
typeof item.href === 'string'
|
||||
? hrefOnClicks.find((i) => i.href === item.href)?.handler
|
||||
: undefined
|
||||
} title={item.title}
|
||||
icon={<span className="text-icon-deactive">{item.icon}</span>}
|
||||
/>
|
||||
))}
|
||||
<SideMenuItem href={''} title={''} icon={<></>}>
|
||||
<NightModeSwitch checked={nightModeState} onClick={togglenightModeState} />
|
||||
</SideMenuItem>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</motion.nav>
|
||||
</aside>
|
||||
</BlurredOverlayContainer>
|
||||
</div>
|
||||
<BlurredOverlayContainer visible={logoutModalVisible} onClick={toggleLogoutModalVisiblity} inDuration={100} outDuration={100} outDelay={75}>
|
||||
<div
|
||||
className='absolute top-1/2 left-0 w-full px-6' onClick={toggleLogoutModalVisiblity}>
|
||||
<motion.div
|
||||
animate={{ y: logoutModalVisible ? [10, 0] : [0, 10], }}
|
||||
transition={{ duration: 0.1, ease: 'easeInOut' }}
|
||||
className='top-1/2 min-w-xs w-full max-w-sm justify-self-center text-center -translate-y-1/2 px-6 pt-8 pb-9 drop-shadow-container bg-white/63 rounded-4xl'
|
||||
>
|
||||
<div className='text-base font-medium'>خروج از سیستم</div>
|
||||
<div className='text-xs font-medium mt-6'>آیا میخواهید از سیستم خارج شوید؟</div>
|
||||
<div className='grid grid-cols-2 gap-5.5 mt-8'>
|
||||
<Button
|
||||
onClick={onLogout}
|
||||
className='text-sm font-normal'
|
||||
>
|
||||
بله خارج میشوم
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
className='bg-disabled! text-disabled2! text-sm font-normal'
|
||||
onClick={toggleLogoutModalVisiblity}
|
||||
>
|
||||
منصرف شدم
|
||||
</Button>
|
||||
{/* Logout Modal */}
|
||||
<BlurredOverlayContainer visible={logoutModalVisible} onClick={toggleLogoutModalVisiblity} inDuration={100} outDuration={100} outDelay={75}>
|
||||
<div className="absolute top-1/2 left-0 w-full px-6" onClick={toggleLogoutModalVisiblity}>
|
||||
<motion.div
|
||||
animate={{ y: logoutModalVisible ? [10, 0] : [0, 10] }}
|
||||
transition={{ duration: 0.1, ease: 'easeInOut' }}
|
||||
className="top-1/2 min-w-xs w-full max-w-sm text-center -translate-y-1/2 px-6 pt-8 pb-9 drop-shadow-container bg-white/63 rounded-4xl"
|
||||
>
|
||||
<h2 className="text-base font-medium">خروج از سیستم</h2>
|
||||
<p className="text-xs font-medium mt-6">آیا میخواهید از سیستم خارج شوید؟</p>
|
||||
<div className="grid grid-cols-2 gap-5.5 mt-8">
|
||||
<Button onClick={onLogout} className="text-sm font-normal">بله خارج میشوم</Button>
|
||||
<Button onClick={toggleLogoutModalVisiblity} className="bg-disabled! text-disabled2! text-sm font-normal">منصرف شدم</Button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</BlurredOverlayContainer>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default SideMenu;
|
||||
export default SideMenu;
|
||||
Reference in New Issue
Block a user