mobile header and footer
This commit is contained in:
@@ -1,17 +1,61 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { Profile, MessageText, ShoppingCart, HambergerMenu, Home } from 'iconsax-react'
|
import { Profile, MessageText, ShoppingCart, HambergerMenu, Home } from 'iconsax-react'
|
||||||
|
import { useRouter, usePathname } from 'next/navigation'
|
||||||
import CategoryModal from './CategoryModal'
|
import CategoryModal from './CategoryModal'
|
||||||
|
import { useSharedStore } from '@/share/store/sharedStore'
|
||||||
|
import { useLocalCart } from '@/app/product/hooks/useLocalCart'
|
||||||
|
import { useGetCart } from '@/app/cart/hooks/useCartData'
|
||||||
|
|
||||||
const MobileBottomMenu: FC = () => {
|
const MobileBottomMenu: FC = () => {
|
||||||
|
const router = useRouter()
|
||||||
|
const pathname = usePathname()
|
||||||
const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false)
|
const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false)
|
||||||
|
const { isLogin } = useSharedStore()
|
||||||
|
|
||||||
|
// Get cart count based on login status
|
||||||
|
const { data: cartData } = useGetCart()
|
||||||
|
const { getLocalCartItemsCount } = useLocalCart()
|
||||||
|
const cartCount = isLogin
|
||||||
|
? (cartData?.results?.cart?.items_count || 0)
|
||||||
|
: getLocalCartItemsCount()
|
||||||
|
|
||||||
|
const handleNavigation = (path: string) => {
|
||||||
|
router.push(path)
|
||||||
|
}
|
||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{ icon: Profile, label: 'پروفایل', active: false },
|
{
|
||||||
{ icon: MessageText, label: 'چت', active: false },
|
icon: Profile,
|
||||||
{ icon: ShoppingCart, label: 'سبد خرید', active: false },
|
label: 'پروفایل',
|
||||||
{ icon: HambergerMenu, label: 'منو', active: false, onClick: () => setIsCategoryModalOpen(!isCategoryModalOpen) },
|
path: '/profile',
|
||||||
{ icon: Home, label: 'خانه', active: true },
|
onClick: () => handleNavigation(isLogin ? '/profile' : '/auth')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: MessageText,
|
||||||
|
label: 'چت',
|
||||||
|
path: '/profile/chat',
|
||||||
|
onClick: () => handleNavigation(isLogin ? '/profile/chat' : '/auth')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: ShoppingCart,
|
||||||
|
label: 'سبد خرید',
|
||||||
|
path: '/cart',
|
||||||
|
badge: cartCount,
|
||||||
|
onClick: () => handleNavigation('/cart')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: HambergerMenu,
|
||||||
|
label: 'منو',
|
||||||
|
path: '',
|
||||||
|
onClick: () => setIsCategoryModalOpen(!isCategoryModalOpen)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Home,
|
||||||
|
label: 'خانه',
|
||||||
|
path: '/',
|
||||||
|
onClick: () => handleNavigation('/')
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -21,17 +65,27 @@ const MobileBottomMenu: FC = () => {
|
|||||||
<div className="flex items-center justify-around py-3 px-2">
|
<div className="flex items-center justify-around py-3 px-2">
|
||||||
{menuItems.map((item, index) => {
|
{menuItems.map((item, index) => {
|
||||||
const IconComponent = item.icon
|
const IconComponent = item.icon
|
||||||
|
const isActive = item.path ? pathname === item.path : false
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
onClick={item.onClick}
|
onClick={item.onClick}
|
||||||
className={`flex flex-col items-center gap-1 p-2 min-w-0 flex-1 ${item.active ? 'text-purple-600' : 'text-gray-600'
|
className={`flex flex-col items-center gap-1 p-2 min-w-0 flex-1 ${isActive ? 'text-purple-600' : 'text-gray-600'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
<div className="relative">
|
||||||
<IconComponent
|
<IconComponent
|
||||||
size={24}
|
size={24}
|
||||||
color={item.active ? '#9333ea' : '#6b7280'}
|
color={isActive ? '#9333ea' : '#6b7280'}
|
||||||
/>
|
/>
|
||||||
|
{/* Badge for cart count */}
|
||||||
|
{item.badge !== undefined && (
|
||||||
|
<div className="absolute -top-1.5 -right-3 bg-primary text-white text-[10px] font-medium rounded-full min-w-[18px] h-[18px] flex items-center justify-center px-1 shadow-sm">
|
||||||
|
{item.badge}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<span className="text-xs text-center leading-tight">{item.label}</span>
|
<span className="text-xs text-center leading-tight">{item.label}</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|||||||
+42
-27
@@ -2,7 +2,7 @@
|
|||||||
import Input from '@/components/Input'
|
import Input from '@/components/Input'
|
||||||
import MenuItem from '@/components/MenuItem'
|
import MenuItem from '@/components/MenuItem'
|
||||||
import { Separator } from '@/components/ui/separator'
|
import { Separator } from '@/components/ui/separator'
|
||||||
import { DocumentText, Home, Profile, HambergerMenu, InfoCircle, Messages1 } from 'iconsax-react'
|
import { DocumentText, Home, InfoCircle, Messages1, SearchNormal1 } from 'iconsax-react'
|
||||||
import { FC, Fragment, useEffect, useState } from 'react'
|
import { FC, Fragment, useEffect, useState } from 'react'
|
||||||
import Menu from './components/Menu'
|
import Menu from './components/Menu'
|
||||||
import { useSharedStore } from './store/sharedStore'
|
import { useSharedStore } from './store/sharedStore'
|
||||||
@@ -14,7 +14,7 @@ import Link from 'next/link'
|
|||||||
|
|
||||||
const Header: FC = () => {
|
const Header: FC = () => {
|
||||||
|
|
||||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
const [isSearchOpen, setIsSearchOpen] = useState(false)
|
||||||
const { setIsLogin } = useSharedStore()
|
const { setIsLogin } = useSharedStore()
|
||||||
|
|
||||||
const handleSetIsLogin = async () => {
|
const handleSetIsLogin = async () => {
|
||||||
@@ -30,19 +30,47 @@ const Header: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className='fixed top-0 bg-white w-full z-[9998] border-b border-gray-100 max-w-full'>
|
<div className='fixed top-0 bg-white w-full z-[9998] border-b border-gray-100 max-w-full'>
|
||||||
{/* بخش بالایی هدر */}
|
{/* موبایل: لوگو و آیکون جستجو */}
|
||||||
<div className='flex items-center justify-between px-3 sm:px-4 md:px-6 py-3 sm:py-4'>
|
|
||||||
{/* منوی همبرگری موبایل */}
|
|
||||||
<div className='md:hidden'>
|
<div className='md:hidden'>
|
||||||
|
{!isSearchOpen ? (
|
||||||
|
<div className='flex items-center justify-between px-4 py-4'>
|
||||||
|
<Link href='/'>
|
||||||
|
<Image
|
||||||
|
src='/images/logo.png'
|
||||||
|
alt='logo'
|
||||||
|
width={120}
|
||||||
|
height={50}
|
||||||
|
className='max-w-[120px] w-[100px] max-h-[50px] object-contain'
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
onClick={() => setIsSearchOpen(true)}
|
||||||
className='p-2 rounded-lg hover:bg-gray-50'
|
className='p-2 rounded-lg hover:bg-gray-50'
|
||||||
>
|
>
|
||||||
<HambergerMenu size={24} color='#333333' />
|
<SearchNormal1 size={24} color='#8C90A3' />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className='flex items-center gap-2 px-4 py-4'>
|
||||||
|
<Input
|
||||||
|
className='w-full'
|
||||||
|
variant='search'
|
||||||
|
placeholder='جستجو'
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsSearchOpen(false)}
|
||||||
|
className='text-sm text-gray-600 whitespace-nowrap px-2'
|
||||||
|
>
|
||||||
|
لغو
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='flex gap-2 sm:gap-4 md:gap-[30px] items-center flex-1 md:flex-none'>
|
{/* دسکتاپ: هدر کامل */}
|
||||||
|
<div className='hidden md:flex items-center justify-between px-6 py-4'>
|
||||||
|
<div className='flex gap-[30px] items-center'>
|
||||||
<Link href='/'>
|
<Link href='/'>
|
||||||
<Image
|
<Image
|
||||||
src='/images/logo.png'
|
src='/images/logo.png'
|
||||||
@@ -53,36 +81,23 @@ const Header: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<Input
|
<Input
|
||||||
className='hidden md:block w-[300px] lg:w-[500px]'
|
className='w-[300px] lg:w-[500px]'
|
||||||
variant='search'
|
variant='search'
|
||||||
placeholder='جستجو'
|
placeholder='جستجو'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex items-center gap-1 sm:gap-2 md:gap-6'>
|
<div className='flex items-center gap-6'>
|
||||||
<div>
|
<div>
|
||||||
<Account />
|
<Account />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='md:hidden'>
|
<Separator style={{ height: 25 }} orientation='vertical' />
|
||||||
<Profile size={24} color='#333333' />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Separator className='hidden md:block' style={{ height: 25 }} orientation='vertical' />
|
|
||||||
|
|
||||||
<Cart />
|
<Cart />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* نوار جستجو موبایل */}
|
|
||||||
<div className='md:hidden px-3 sm:px-4 pb-3 sm:pb-4'>
|
|
||||||
<Input
|
|
||||||
className='w-full'
|
|
||||||
variant='search'
|
|
||||||
placeholder='جستجو'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* بخش پایینی هدر - فقط دسکتاپ */}
|
{/* بخش پایینی هدر - فقط دسکتاپ */}
|
||||||
<div className='hidden md:flex mt-2 text-sm px-6 pb-4 items-center gap-7'>
|
<div className='hidden md:flex mt-2 text-sm px-6 pb-4 items-center gap-7'>
|
||||||
<Menu />
|
<Menu />
|
||||||
@@ -119,7 +134,7 @@ const Header: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* منوی موبایل */}
|
{/* منوی موبایل */}
|
||||||
{isMobileMenuOpen && (
|
{/* {isMobileMenuOpen && (
|
||||||
<div className='md:hidden bg-white border-t border-gray-100'>
|
<div className='md:hidden bg-white border-t border-gray-100'>
|
||||||
<div className='px-4 py-4 space-y-4'>
|
<div className='px-4 py-4 space-y-4'>
|
||||||
<div className='flex items-center gap-3 py-3 border-b border-gray-100'>
|
<div className='flex items-center gap-3 py-3 border-b border-gray-100'>
|
||||||
@@ -154,11 +169,11 @@ const Header: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* فضای خالی برای جبران ارتفاع fixed header */}
|
{/* فضای خالی برای جبران ارتفاع fixed header */}
|
||||||
<div className={`${isMobileMenuOpen ? 'h-[280px] sm:h-[260px] md:h-[120px]' : 'h-[120px] sm:h-[120px] md:h-[120px]'}`}></div>
|
<div className='h-[72px] md:h-[120px]'></div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user