add: profile dropdown

This commit is contained in:
Mahyar Khanbolooki
2025-08-10 16:30:37 +03:30
parent 29363c1a15
commit ac30ac1ecf
4 changed files with 154 additions and 24 deletions
+73 -23
View File
@@ -1,14 +1,14 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
'use client'
import React from 'react'
import NightModeSwitch from '../button/NightModeSwitch'
import BurgerMenuIcon from '../icons/BurgerMenuIcon'
import NotificationBellIcon from '../icons/NotificationBellIcon'
import WalletIcon from '../icons/WalletIcon'
import GridIcon from '../icons/GridIcon'
import Image from 'next/image'
import { ArrowDown2 } from 'iconsax-react'
import { ArrowDown2, LogoutCurve, ProfileCircle, Setting2 } from 'iconsax-react'
import Dropdown from '../utils/Dropdown'
import Seperator from '../utils/Seperator'
import Link from 'next/link'
import { useParams } from 'next/navigation'
type Props = {
profileDropState: boolean,
@@ -21,7 +21,10 @@ type Props = {
toggleNightModeState: React.MouseEventHandler<HTMLDivElement> | undefined
}
function TopBar({ profileDropState, toggleProfileDropState, menuState, toggleMenuState, searchModalState, toggleSearchModalState, nightModeState, toggleNightModeState }: Props) {
function TopBar({ profileDropState, toggleProfileDropState, toggleMenuState }: Props) {
const params = useParams();
const { name } = params;
return (
<div className="w-full">
<div className='grid grid-cols-3 overflow-hidden rounded-2xl w-full h-12 lg:h-24 px-2 xl:gap-8 items-center'>
@@ -44,26 +47,32 @@ function TopBar({ profileDropState, toggleProfileDropState, menuState, toggleMen
</div> */}
</div>
<div className='flex justify-center'>
<Image
width={73}
height={25}
alt='Profile avatar'
className='rounded-full'
<Image
width={73}
height={25}
alt='Profile avatar'
className='rounded-full'
src={'/assets/images/danak-logo.png'} />
</div>
<div className='flex items-center justify-end gap-3'>
<div className='flex items-center justify-end gap-3 xl:gap-6'>
{/* <NightModeSwitch checked={nightMode} onClick={toggleNightMode} /> */}
{/* <img className='hidden sm:block' src={rectangles} /> */}
<GridIcon className='size-4.5 text-icon-active' />
<WalletIcon className='size-4.5 text-icon-active' />
<NotificationBellIcon className='size-4.5 text-icon-active' />
<button className='flex items-center justify-between' onClick={toggleProfileDropState}>
<Image
width={24}
height={24}
alt='Profile avatar'
className='rounded-full'
src={'/assets/images/user-avatar.png'} />
<span className='relative'>
<NotificationBellIcon className='size-4.5 text-icon-active' />
<span className='absolute -right-1 -top-1 bg-red-500 size-3 rounded-full text-[8px] text-white'>
<div className='mt-0.25 place-self-center'>2</div>
</span>
</span>
<button
id='profile-drop-toggle'
className='flex items-center justify-between'
onClick={toggleProfileDropState}>
<Image
width={24}
height={24}
alt='Profile avatar'
className='rounded-full'
src={'/assets/images/user-avatar.png'} />
<div className='pe-0 hidden xl:inline-flex items-end' >
<div className='ps-2 pe-1 text-xs text-nowrap'>مهرداد مظفری</div>
<ArrowDown2 className='stroke-disabled-text' size={14} />
@@ -71,7 +80,48 @@ function TopBar({ profileDropState, toggleProfileDropState, menuState, toggleMen
</div>
</button>
</div>
{/* <Dropdown state={profileDrop} toggle={setProfileDrop} /> */}
<Dropdown
active={profileDropState}
toggle={toggleProfileDropState}
>
<div className='place-items-center pt-8'>
<Image
src={'/assets/images/user-avatar.png'}
width={56}
height={56}
className='rounded-full'
unoptimized
alt={'user avatar'}
/>
<p className='text-xs mt-2'>mail@danakcorp.com</p>
</div>
<Seperator className='my-6' />
<div className='flex flex-col gap-3'>
<Link
href={`/${name}/profile`}
className='flex items-center gap-3 px-6'>
<ProfileCircle size={20} className='stroke-foreground' />
<div className='text-xs'>پروفایل</div>
</Link>
<Link
href={`/${name}/profile/settings`}
className='flex items-center gap-3 px-6'>
<Setting2 size={20} className='stroke-foreground' />
<div className='text-xs'>تنظیمات</div>
</Link>
</div>
<Seperator className='my-6' />
<button
onClick={() => { }}
className='flex items-center gap-3 px-6'>
<LogoutCurve size={20} className='stroke-foreground' />
<div className='text-xs'>خروج</div>
</button>
</Dropdown>
</div>
</div>
)
+62
View File
@@ -0,0 +1,62 @@
'use client';
import clsx from 'clsx'
import { HTMLMotionProps, motion } from 'framer-motion';
import { CloseCircle } from 'iconsax-react'
import React, { useEffect, useRef } from 'react'
interface DropdownProps extends Omit<HTMLMotionProps<"div">, "ref"> {
active?: boolean,
toggle?: React.MouseEventHandler<HTMLButtonElement> | undefined,
children?: React.ReactNode
};
function Dropdown({ active, toggle, children, ...rest }: DropdownProps) {
const boxRef = useRef<HTMLDivElement>(null);
const closeButtonRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (boxRef.current && !boxRef.current.contains(event.target as Node)) {
closeButtonRef.current?.click();
}
};
if (active) {
document.addEventListener('click', handleClickOutside);
}
return () => {
document.removeEventListener('click', handleClickOutside);
};
}, [active]);
return (
<motion.div
ref={boxRef}
initial={{ y: active ? 0 : '-10%', scale: active ? 1 : 0.95, opacity: active ? 1 : 0 }}
animate={{ y: active ? 0 : '-10%', scale: active ? 1 : 0.95, opacity: active ? 1 : 0 }}
transition={{ duration: 0.1 }}
className={clsx(
'box-shadow-normal',
'fixed inset-0 bg-container rounded-normal z-50',
'xl:absolute xl:top-18 xl:left-3 xl:right-auto xl:h-screen xl:w-[300px]',
active === false && 'pointer-events-none'
)}
{...rest}
>
<div className='relative w-full h-full'>
<button
ref={closeButtonRef}
className='xl:hidden'
onClick={toggle} >
<CloseCircle size={20} className='cursor-pointer stroke-foreground absolute left-6 top-6' />
</button>
{children}
</div>
</motion.div>
)
}
export default Dropdown
+18
View File
@@ -0,0 +1,18 @@
'use client';
import clsx from 'clsx'
import React from 'react'
function Seperator({ className, ...rest }: React.HTMLAttributes<HTMLHRElement>) {
return (
<hr
className={clsx(
'border-border',
className
)}
{...rest}
/>
)
}
export default Seperator
@@ -52,7 +52,7 @@ function ClientMenuRouteWrapper({ children }: Props) {
</div>
<div className="fixed bottom-0 left-0 right-0 z-50 px-4">
<div className="fixed bottom-0 left-0 right-0 z-45 px-4">
<BottomNavBar />
</div>