responsive base v1

This commit is contained in:
hamid zarghami
2025-09-02 12:42:13 +03:30
parent c6b3aa0682
commit 2fa9ab1bbb
27 changed files with 581 additions and 178 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ const AboutPage: NextPage = () => {
return (
<Layout>
<div className="mt-14 px-4 md:px-8 lg:px-20">
<div className="mt-14 px-4 md:px-8 lg:px-20 max-w-full overflow-x-hidden">
{/* عنوان اصلی */}
<div className="text-center mb-16">
<h1 className="text-3xl font-bold text-gray-800">
+14 -14
View File
@@ -5,20 +5,20 @@ import BlogItem from './components/BlogItem'
import LastPost from './components/LastPost'
const BlogsPage: NextPage = () => {
return (
<div className='flex gap-24 p-10'>
<Categories />
<div className='flex-1 flex flex-col gap-6'>
<BlogItem />
<BlogItem />
<BlogItem />
<BlogItem />
</div>
<div className='max-w-[340px] w-full'>
<LastPost />
</div>
</div>
)
return (
<div className='flex gap-24 p-10'>
<Categories />
<div className='flex-1 flex flex-col gap-6'>
<BlogItem />
<BlogItem />
<BlogItem />
<BlogItem />
</div>
<div className='max-w-[340px] w-full'>
<LastPost />
</div>
</div>
)
}
export default function BlogsPageWithLayout() {
+15 -15
View File
@@ -7,10 +7,10 @@ import { NextPage } from "next"
const Cart: NextPage = () => {
return (
<div className="mt-14 px-20">
<div className="border-b border-border flex justify-between items-center">
<div className="flex items-center gap-3 pb-6 border-b-2 border-primary relative top-[1px]">
<div>
<div className="mt-14 px-4 sm:px-8 md:px-20">
<div className="border-b border-border flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 sm:gap-0">
<div className="flex items-center gap-2 sm:gap-3 pb-4 sm:pb-6 border-b-2 border-primary relative top-[1px]">
<div className="text-sm sm:text-base">
سبد خرید
</div>
<div className="size-8 rounded-lg bg-[#F2F2F2] flex items-center justify-center text-primary">
@@ -19,17 +19,17 @@ const Cart: NextPage = () => {
</div>
<Button
className="bg-white shadow h-10"
className="bg-white shadow h-8 sm:h-10 w-full sm:w-auto"
>
<div className="flex items-center gap-2">
<Trash size={20} color="#AD3434" />
<div className="text-sm text-[#AD3434] font-light">حذف همه از سبد خرید</div>
<Trash size={16} color="#AD3434" className="sm:w-5 sm:h-5" />
<div className="text-xs sm:text-sm text-[#AD3434] font-light">حذف همه از سبد خرید</div>
</div>
</Button>
</div>
<div className="mt-6 flex gap-6">
<div className="flex-1 border border-border p-5 rounded-2xl">
<div className="mt-4 sm:mt-6 flex flex-col lg:flex-row gap-4 sm:gap-6">
<div className="flex-1 border border-border p-3 sm:p-5 rounded-xl sm:rounded-2xl">
<CartItem noBorder />
<CartItem />
</div>
@@ -40,7 +40,7 @@ const Cart: NextPage = () => {
total={80580000}
confirmHref="/cart/shipping"
confirmLabel="ادامه به آدرس و ارسال"
className="w-[360px]"
className="w-full lg:w-[360px]"
/>
</div>
</div>
@@ -48,9 +48,9 @@ const Cart: NextPage = () => {
}
export default function CartWithLayout() {
return (
<Layout>
<Cart />
</Layout>
)
return (
<Layout>
<Cart />
</Layout>
)
}
+24
View File
@@ -1,6 +1,23 @@
@import "tailwindcss";
@import "tw-animate-css";
/* بهبود responsive design برای موبایل */
html {
overflow-x: hidden;
}
body {
overflow-x: hidden;
max-width: 100vw;
}
/* اطمینان از عدم overflow در container ها */
.container,
.max-w-full {
max-width: 100vw;
overflow-x: hidden;
}
@custom-variant dark (&:is(.dark *));
@theme inline {
@@ -131,6 +148,13 @@ body {
font-feature-settings: "lnum"; /* اطمینان از نمایش اعداد انگلیسی */
}
/* Add bottom padding for mobile bottom menu */
@media (max-width: 768px) {
body {
padding-bottom: 80px;
}
}
html,
body {
height: 100%;
+8 -8
View File
@@ -4,31 +4,31 @@ import { FC } from 'react'
const BlogCard: FC = () => {
return (
<div className='bg-white p-3 rounded-2xl shadow w-full '>
<div className='bg-white p-3 rounded-2xl shadow w-full overflow-hidden'>
<Image
src='https://picsum.photos/200/300?grayscale'
width={357}
height={201}
alt=''
className='max-w-full max-h-[181px] object-cover rounded-2xl'
className='w-full h-[120px] sm:h-[181px] object-cover rounded-xl sm:rounded-2xl'
/>
<div className='mt-3'>
<h6 className='text-primary text-sm'>تکنولوژی</h6>
</div>
<h4 className='mt-2'>
<h4 className='mt-2 text-sm sm:text-base'>
نسل جدید پردازنده اینتل
</h4>
<p className='mt-2 text-sm text-[#7F7F7F] font-light leading-6'>
<p className='mt-2 text-xs sm:text-sm text-[#7F7F7F] font-light leading-5 sm:leading-6'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است....
</p>
<div className='mt-6 flex justify-between items-center'>
<div className='text-sm font-light text-[#7F7F7F]'>1401/7/21</div>
<div className='mt-4 sm:mt-6 flex justify-between items-center'>
<div className='text-xs sm:text-sm font-light text-[#7F7F7F]'>1401/7/21</div>
<div className='flex gap-1 items-center text-[#7F7F7F]'>
<div className='text-sm font-light'>ادامه مطلب</div>
<ArrowLeft size={16} color='#7F7F7F' />
<div className='text-xs sm:text-sm font-light'>ادامه مطلب</div>
<ArrowLeft size={14} color='#7F7F7F' className='sm:w-4 sm:h-4' />
</div>
</div>
</div>
+20 -5
View File
@@ -1,5 +1,5 @@
'use client'
import { FC } from 'react'
import { FC, useState, useEffect } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react';
import { Pagination } from 'swiper/modules';
import Image from 'next/image';
@@ -7,10 +7,25 @@ import { useGetLanding } from '../hooks/useHomeData';
const Carousel: FC = () => {
const { data } = useGetLanding()
const [isMobile, setIsMobile] = useState(false)
if (!data?.results?.sliders?.desktop || data.results.sliders.desktop.length === 0) {
useEffect(() => {
const checkIsMobile = () => {
setIsMobile(window.innerWidth < 768) // md breakpoint
}
checkIsMobile()
window.addEventListener('resize', checkIsMobile)
return () => window.removeEventListener('resize', checkIsMobile)
}, [])
// Choose appropriate sliders based on device type
const sliders = isMobile ? data?.results?.sliders?.mobile : data?.results?.sliders?.desktop
if (!sliders || sliders.length === 0) {
return (
<div className='mt-5 h-[400px] bg-gray-200 rounded-lg flex items-center justify-center'>
<div className='mt-5 h-[200px] sm:h-[300px] md:h-[400px] bg-gray-200 rounded-lg flex items-center justify-center'>
<p className="text-gray-500">اسلایدری موجود نیست</p>
</div>
);
@@ -19,9 +34,9 @@ const Carousel: FC = () => {
return (
<div className='mt-5 relative' style={{ zIndex: 0 }}>
<Swiper pagination={true} modules={[Pagination]} className="mySwiper pb-5" style={{ zIndex: 0, position: 'relative' }}>
{data.results.sliders.desktop.map((slider) => (
{sliders.map((slider) => (
<SwiperSlide key={slider._id}>
<div className='h-[400px] relative'>
<div className='h-[200px] sm:h-[300px] md:h-[400px] relative'>
<Image
src={slider.imageUrl}
alt={slider.altText}
+18 -11
View File
@@ -3,6 +3,7 @@ import React from 'react'
import CategoryItem from './CategoryItem'
import { useGetCategories } from '@/share/hooks/useShareData'
import { Category } from '@/share/types/SharedTypes'
import { Swiper, SwiperSlide } from 'swiper/react'
const Categories = () => {
@@ -10,17 +11,23 @@ const Categories = () => {
const parentCategories = data?.results?.data?.filter(cat => !cat.parent) || []
return (
<div className='flex gap-6 justify-center'>
{
parentCategories?.map((item: Category) => {
return (
<CategoryItem key={item._id} image={item.imageUrl} title={item.title_fa} />
)
})
}
<div className='w-full'>
<Swiper
spaceBetween={16}
slidesPerView={'auto'}
className='h-full'
breakpoints={{
640: {
spaceBetween: 24,
},
}}
>
{parentCategories?.map((item: Category) => (
<SwiperSlide key={item._id} className='!w-auto'>
<CategoryItem image={item.imageUrl} title={item.title_fa} />
</SwiperSlide>
))}
</Swiper>
</div>
)
}
+4 -4
View File
@@ -8,11 +8,11 @@ type Props = {
const CategoryItem: FC<Props> = (props) => {
return (
<div className='text-center' >
<div className='size-[113px] rounded-full overflow-hidden'>
<Image src={props.image} alt={props.title} width={113} height={113} />
<div className='text-center'>
<div className='size-[80px] sm:size-[100px] md:size-[113px] rounded-full overflow-hidden'>
<Image src={props.image} alt={props.title} width={113} height={113} className='w-full h-full object-cover' />
</div>
<div className='mt-3 text-sm text-[#191919]'>
<div className='mt-2 sm:mt-3 text-xs sm:text-sm text-[#191919]'>
{props.title}
</div>
</div>
+12 -7
View File
@@ -7,9 +7,9 @@ import { Swiper, SwiperSlide } from 'swiper/react';
const HotOffer: FC = () => {
return (
<div className=' bg-[#F2F2F2] rounded-2xl flex py-6'>
<div className='px-6 min-w-[140px] max-w-[180px] flex flex-col justify-center'>
<div className='text-center text-primary font-extrabold text-sm'>
<div className='bg-[#F2F2F2] rounded-xl sm:rounded-2xl flex flex-col sm:flex-row py-4 sm:py-6'>
<div className='px-4 sm:px-6 w-full sm:min-w-[140px] sm:max-w-[180px] flex flex-col justify-center items-center sm:items-start'>
<div className='text-center text-primary font-extrabold text-xs sm:text-sm'>
پیشنهاد های
<br />
داغ
@@ -17,22 +17,27 @@ const HotOffer: FC = () => {
سندس
کالا
</div>
<div className='mt-6 flex justify-center'>
<div className='mt-4 sm:mt-6 flex justify-center'>
<Image
src={'/images/hot_offer.png'}
alt=''
width={120}
height={150}
className='max-w-full h-auto'
className='max-w-[80px] sm:max-w-full h-auto'
/>
</div>
</div>
<div className='flex-1 overflow-hidden px-4'>
<div className='flex-1 overflow-hidden px-2 sm:px-4 mt-4 sm:mt-0'>
<Swiper
spaceBetween={16}
spaceBetween={8}
slidesPerView={'auto'}
className='h-full'
breakpoints={{
640: {
spaceBetween: 16,
},
}}
>
<SwiperSlide className='!w-auto'>
<ProductCard />
+2 -2
View File
@@ -31,10 +31,10 @@ const NewestProducts: FC = () => {
}}
className="w-full"
>
<CarouselContent className='gap-2 h-[380px]'>
<CarouselContent className='gap-1 sm:gap-2 h-[380px]'>
{
landing?.results?.latestProducts?.map((product) => (
<CarouselItem key={product._id} className="basis-[292px]">
<CarouselItem key={product._id} className="basis-[240px] sm:basis-[292px]">
<ProductCard item={product} />
</CarouselItem>
))
+2 -2
View File
@@ -25,9 +25,9 @@ const PopularProducts: FC = () => {
}}
className="w-full"
>
<CarouselContent className='gap-2'>
<CarouselContent className='gap-1 sm:gap-2'>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index} className="basis-[292px]">
<CarouselItem key={index} className="basis-[240px] sm:basis-[292px]">
<ProductCard />
</CarouselItem>
))}
+5 -1
View File
@@ -4,14 +4,17 @@ import "../../public/css/fontiran.css";
import 'swiper/css';
import QueryProvider from "@/config/QueryProvider";
import ToastContainer from "@/components/Toast";
import MobileBottomMenu from "@/components/MobileBottomMenu";
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { viewport } from './viewport'
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export { viewport };
export default function RootLayout({
children,
}: Readonly<{
@@ -23,6 +26,7 @@ export default function RootLayout({
<QueryProvider>
{children}
<ToastContainer />
<MobileBottomMenu />
<ReactQueryDevtools initialIsOpen={false} />
</QueryProvider>
</body>
+7 -7
View File
@@ -18,27 +18,27 @@ const HomePage: NextPage = () => {
return (
<div>
<Carousel />
<div className='mt-24 px-20'>
<div className='mt-12 sm:mt-16 md:mt-24 px-4 sm:px-8 md:px-20'>
<HotOffer />
<div className='mt-24'>
<div className='mt-12 sm:mt-16 md:mt-24'>
<Categories />
</div>
<div className='mt-24'>
<div className='mt-12 sm:mt-16 md:mt-24'>
<Banners3 />
</div>
</div>
<div className='mt-24 bg-[#FAF8F6] p-20'>
<div className='mt-12 sm:mt-16 md:mt-24 bg-[#FAF8F6] p-4 sm:p-8 md:p-20'>
<NewestProducts />
<div className='mt-24'>
<div className='mt-12 sm:mt-16 md:mt-24'>
<Banners4 />
</div>
<div className='mt-20'>
<div className='mt-12 sm:mt-16 md:mt-20'>
<PopularProducts />
</div>
</div>
<div className='mt-24 px-20'>
<div className='mt-12 sm:mt-16 md:mt-24 px-4 sm:px-8 md:px-20'>
<Blogs />
</div>
</div>
+10 -10
View File
@@ -19,8 +19,8 @@ import Questions from '@/app/product/components/Questions'
const SingleProduct: NextPage = () => {
return (
<div className='mt-14 px-20'>
<div className='flex justify-between'>
<div className='mt-14 px-4 sm:px-8 md:px-20'>
<div className='flex flex-col sm:flex-row justify-between gap-4 sm:gap-0'>
<Breadcrumb aria-label="breadcrumb">
<BreadcrumbList className="text-sm text-muted-foreground">
<BreadcrumbItem>
@@ -37,13 +37,13 @@ const SingleProduct: NextPage = () => {
</BreadcrumbList>
</Breadcrumb>
<div className='text-primary text-sm'>فروشنده شوید</div>
<div className='text-primary text-xs sm:text-sm'>فروشنده شوید</div>
</div>
<div className='flex gap-6 mt-14 flex-row-reverse'>
<div className='flex flex-col lg:flex-row gap-4 sm:gap-6 mt-8 sm:mt-12 md:mt-14'>
<ShopInformation />
<div className='flex-1 flex flex-col gap-6'>
<div className='flex gap-6'>
<div className='flex flex-col lg:flex-row gap-4 sm:gap-6'>
<ProductImage />
<BaseInformation />
</div>
@@ -61,9 +61,9 @@ const SingleProduct: NextPage = () => {
}
export default function SingleProductWithLayout() {
return (
<Layout>
<SingleProduct />
</Layout>
)
return (
<Layout>
<SingleProduct />
</Layout>
)
}
+4 -4
View File
@@ -15,7 +15,7 @@ import ProductCard from '@/components/ProductCard'
const Products: NextPage = () => {
return (
<div className="mt-14 px-20">
<div className="mt-14 px-4 sm:px-8 md:px-20">
<Breadcrumb aria-label="breadcrumb">
<BreadcrumbList className="text-sm text-muted-foreground">
<BreadcrumbItem>
@@ -32,13 +32,13 @@ const Products: NextPage = () => {
</BreadcrumbList>
</Breadcrumb>
<div className='mt-14 flex gap-6'>
<div className='mt-8 sm:mt-12 md:mt-14 flex flex-col lg:flex-row gap-4 sm:gap-6'>
<Filters />
<div className='flex-1'>
<Sorts />
<div className='mt-10'>
<GridWrapper desktop={4} mobile={1}>
<div className='mt-6 sm:mt-8 md:mt-10'>
<GridWrapper desktop={4} mobile={2} gapMobile={3} gapDesktop={6}>
<ProductCard />
<ProductCard />
<ProductCard />
+17 -17
View File
@@ -36,15 +36,15 @@ const ProfilePage = () => {
}
return (
<div className="p-6">
<div className="p-4 sm:p-6">
<Menu pageActive='profile' />
<div className='mt-10'>
<div className="flex gap-6">
<div className='mt-6 sm:mt-8 md:mt-10'>
<div className="flex flex-col xl:flex-row gap-4 sm:gap-6">
{/* Left Content - Form */}
<div className="flex-1 ">
<div className="bg-[#FAFAFA] rounded-lg p-6">
<div className="flex items-center justify-between mb-6">
<h1 className="text-lg font-bold text-gray-900">اطلاعات کاربری</h1>
<div className="bg-[#FAFAFA] rounded-lg p-4 sm:p-6">
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between mb-4 sm:mb-6 gap-3 sm:gap-0">
<h1 className="text-base sm:text-lg font-bold text-gray-900">اطلاعات کاربری</h1>
<Button
onClick={() => setIsEditing(!isEditing)}
variant="outline"
@@ -55,7 +55,7 @@ const ProfilePage = () => {
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
<Input
label="نام و نام خانوادگی"
value={userInfo.name}
@@ -121,7 +121,7 @@ const ProfilePage = () => {
/>
</div>
<div className="mt-4">
<div className="mt-3 sm:mt-4">
<Input
label="آدرس"
value={userInfo.address}
@@ -131,7 +131,7 @@ const ProfilePage = () => {
</div>
{isEditing && (
<div className="mt-6 flex gap-3">
<div className="mt-4 sm:mt-6 flex flex-col sm:flex-row gap-3">
<Button
onClick={handleSubmit}
className="px-8 bg-blue-600 hover:bg-blue-700"
@@ -149,18 +149,18 @@ const ProfilePage = () => {
</div>
</div>
<div className='flex flex-col gap-6'>
<div className='size-[240px] bg-[#FAFAFA] rounded-[10px] flex flex-col gap-6 justify-center items-center h-full'>
<div className='size-20 bg-[#F2F2F2] rounded-full flex justify-center items-center'>
<ShoppingCart size={40} color='#000' />
<div className='flex flex-row xl:flex-col gap-4 sm:gap-6'>
<div className='w-full xl:w-[240px] xl:h-[240px] bg-[#FAFAFA] rounded-[10px] flex flex-col gap-4 sm:gap-6 justify-center items-center h-[120px] sm:h-[160px] xl:h-[240px]'>
<div className='size-12 sm:size-16 xl:size-20 bg-[#F2F2F2] rounded-full flex justify-center items-center'>
<ShoppingCart size={24} color='#000' className='sm:w-8 sm:h-8 xl:w-10 xl:h-10' />
</div>
<div>
سفارشات
</div>
</div>
<div className='size-[240px] bg-[#FAFAFA] rounded-[10px] flex flex-col gap-6 justify-center items-center h-full'>
<div className='size-20 bg-[#F2F2F2] rounded-full flex justify-center items-center'>
<Heart size={40} color='#000' />
<div className='w-full xl:w-[240px] xl:h-[240px] bg-[#FAFAFA] rounded-[10px] flex flex-col gap-4 sm:gap-6 justify-center items-center h-[120px] sm:h-[160px] xl:h-[240px]'>
<div className='size-12 sm:size-16 xl:size-20 bg-[#F2F2F2] rounded-full flex justify-center items-center'>
<Heart size={24} color='#000' className='sm:w-8 sm:h-8 xl:w-10 xl:h-10' />
</div>
<div>
علاقه مندی ها
@@ -168,7 +168,7 @@ const ProfilePage = () => {
</div>
</div>
<div className='w-[300px] min-h-full bg-red-50 rounded-[10px]'>
<div className='w-full xl:w-[300px] min-h-[200px] xl:min-h-full bg-red-50 rounded-[10px] hidden xl:block'>
</div>
</div>
</div>
+8
View File
@@ -0,0 +1,8 @@
import { Viewport } from "next";
export const viewport: Viewport = {
width: "device-width",
initialScale: 1,
maximumScale: 1,
userScalable: false,
};
+216
View File
@@ -0,0 +1,216 @@
'use client'
import { FC, useState } from 'react'
import { ArrowLeft2 } from 'iconsax-react'
import { useRouter } from 'next/navigation'
type Props = {
isOpen: boolean
onClose: () => void
}
const CategoryModal: FC<Props> = ({ isOpen, onClose }) => {
const router = useRouter()
const [selectedMainCategory, setSelectedMainCategory] = useState<number>(0)
const [expandedSubcategory, setExpandedSubcategory] = useState<string | null>(null)
// Main categories for the left column
const mainCategories = [
{ icon: '🏪', title: 'سوپر مارکت ارگانیک' },
{ icon: '🍞', title: 'خانه نان و شیرینی سالم' },
{ icon: '🍎', title: 'بوفه رژیم‌های خاص' },
{ icon: '💪', title: 'بوفه سبک زندگی' },
{ icon: '🌿', title: 'عطاری سلامت' },
{ icon: '🎁', title: 'بوفه هدایا و سوغات' }
]
// Subcategories for each main category
const categorySubcategories = {
'سوپر مارکت ارگانیک': [
{ title: 'ارگانیک گواهی‌دار', hasChildren: false },
{ title: 'روغن های سالم', hasChildren: true },
{ title: 'چاشنی سلامت', hasChildren: true },
{ title: 'صبحانه سالم', hasChildren: false },
{ title: 'نوشیدنی سالم', hasChildren: false },
{ title: 'آرایشی', hasChildren: false },
{ title: 'بهداشتی', hasChildren: false },
{ title: 'تازه خوری', hasChildren: false },
{ title: 'حبوبات و غلات', hasChildren: false },
{ title: 'تنقلات', hasChildren: false },
{ title: 'چای و دمنوش', hasChildren: false },
{ title: 'قهوه', hasChildren: false },
{ title: 'قند و شکر', hasChildren: false }
],
'خانه نان و شیرینی سالم': [
{ title: 'نان سنتی', hasChildren: false },
{ title: 'نان صنعتی', hasChildren: false },
{ title: 'شیرینی', hasChildren: false },
{ title: 'کیک و کلوچه', hasChildren: false }
],
'بوفه رژیم‌های خاص': [
{ title: 'رژیم کتو', hasChildren: false },
{ title: 'رژیم وگان', hasChildren: false },
{ title: 'بدون گلوتن', hasChildren: false }
],
'بوفه سبک زندگی': [
{ title: 'ورزشی', hasChildren: false },
{ title: 'لاغری', hasChildren: false },
{ title: 'سالمندان', hasChildren: false }
],
'عطاری سلامت': [
{ title: 'گیاهان دارویی', hasChildren: false },
{ title: 'عسل طبیعی', hasChildren: false },
{ title: 'دمنوش', hasChildren: false }
],
'بوفه هدایا و سوغات': [
{ title: 'هدایا', hasChildren: false },
{ title: 'سوغات', hasChildren: false },
{ title: 'بسته بندی ویژه', hasChildren: false }
]
}
// Third level subcategories (for items that expand)
const thirdLevelCategories = {
'روغن های سالم': [
{ icon: '🫒', title: 'روغن زیتون پیوست و مو' },
{ icon: '🌻', title: 'روغن ماساژ' },
{ icon: '🥥', title: 'روغن های خوراکی' }
],
'چاشنی سلامت': [
{ icon: '🥒', title: 'ترشی' },
{ icon: '🥫', title: 'رب ها' },
{ icon: '🍯', title: 'سس ها' },
{ icon: '🥬', title: 'سبزیجات خشک' },
{ icon: '🌶️', title: 'ادویه' },
{ icon: '🍎', title: 'سرکه' },
{ icon: '🫒', title: 'زیتون' }
]
}
const handleMainCategoryClick = (index: number) => {
setSelectedMainCategory(index)
setExpandedSubcategory(null)
}
const handleSubcategoryClick = (subcategory: { title: string; hasChildren: boolean }) => {
if (subcategory.hasChildren && thirdLevelCategories[subcategory.title as keyof typeof thirdLevelCategories]) {
setExpandedSubcategory(expandedSubcategory === subcategory.title ? null : subcategory.title)
} else {
router.push(`/products/${subcategory.title}`)
onClose()
}
}
if (!isOpen) return null
const currentMainCategory = mainCategories[selectedMainCategory]
const currentSubcategories = categorySubcategories[currentMainCategory.title as keyof typeof categorySubcategories] || []
return (
<div className="fixed top-[120px] left-0 right-0 bottom-0 bg-white z-40 md:hidden">
<div className="flex h-full overflow-hidden">
{/* Left Column - Main Categories */}
<div className="w-28 bg-gray-100 overflow-y-auto">
<div className="p-2 space-y-2">
{mainCategories.map((category, index) => (
<div key={index}>
<div
className={`flex flex-col items-center text-center p-2 cursor-pointer rounded-lg transition-colors ${index === selectedMainCategory ? 'bg-white shadow-sm' : 'hover:bg-gray-200'
}`}
onClick={() => handleMainCategoryClick(index)}
>
<div className="w-12 h-12 bg-white rounded-full flex items-center justify-center mb-1 shadow-sm">
<span className="text-lg">{category.icon}</span>
</div>
<span className="text-xs text-gray-800 leading-tight text-center">
{category.title}
</span>
</div>
{index < mainCategories.length - 1 && (
<div className="border-b border-gray-200 mx-1" />
)}
</div>
))}
</div>
</div>
{/* Right Column - Subcategories */}
<div className="flex-1 bg-white overflow-y-auto">
<div className="px-4 py-4">
{/* Special Categories */}
<div className="space-y-1 mb-4">
<div
className="py-3 cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => {
router.push('/products')
onClose()
}}
>
<span className="text-primary font-medium text-sm">همه محصولات سوپر مارکت ارگانیک</span>
</div>
<div
className="py-3 cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => {
router.push('/products/organic')
onClose()
}}
>
<span className="text-gray-800 font-medium text-sm">ارگانیک گواهیدار</span>
</div>
</div>
{/* Subcategories List */}
<div>
{currentSubcategories.map((subcategory, index) => (
<div key={index}>
<div
className="flex items-center justify-between py-3 cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => handleSubcategoryClick(subcategory)}
>
<span className="text-gray-800 text-sm">{subcategory.title}</span>
{subcategory.hasChildren && (
<ArrowLeft2 size={16} color="#666" />
)}
</div>
{/* Expanded third level categories */}
{expandedSubcategory === subcategory.title && thirdLevelCategories[subcategory.title as keyof typeof thirdLevelCategories] && (
<div className="mt-2 mb-4 p-4 bg-gray-50 rounded-lg">
<div className="text-sm text-primary mb-3 font-medium">
همه محصولات {subcategory.title}
</div>
<div className="grid grid-cols-2 gap-4">
{thirdLevelCategories[subcategory.title as keyof typeof thirdLevelCategories].map((item, itemIndex) => (
<div
key={itemIndex}
className="flex flex-col items-center p-4 bg-white rounded-lg cursor-pointer hover:bg-gray-100 transition-colors"
onClick={() => {
router.push(`/products/${item.title}`)
onClose()
}}
>
<div className="w-14 h-14 bg-white rounded-full flex items-center justify-center mb-3 border border-gray-200">
<span className="text-xl">{item.icon}</span>
</div>
<span className="text-sm text-gray-800 text-center leading-tight font-medium">
{item.title}
</span>
</div>
))}
</div>
</div>
)}
{index < currentSubcategories.length - 1 && (
<div className="border-b border-gray-100" />
)}
</div>
))}
</div>
</div>
</div>
</div>
</div>
)
}
export default CategoryModal
+2 -2
View File
@@ -33,7 +33,7 @@ const Input: FC<Props> = (props: Props) => {
const [search, setSearch] = useState<string>('')
const inputClass = clx(
'w-full h-10 text-black block px-4 text-xs rounded-xl border border-[#D0D0D0]',
'w-full h-10 sm:h-12 text-black block px-3 sm:px-4 text-xs sm:text-sm rounded-xl border border-[#D0D0D0]',
props.readOnly && 'bg-gray-100 border-0 text-description',
props.variant === 'search' && 'bg-[#EEF0F7] border-0 pr-10',
props.className
@@ -80,7 +80,7 @@ const Input: FC<Props> = (props: Props) => {
return (
<div className='w-full'>
<label className='text-sm text-black'>
<label className='text-xs sm:text-sm text-black'>
{props.label}
</label>
+51
View File
@@ -0,0 +1,51 @@
'use client'
import { FC, useState } from 'react'
import { Profile, MessageText, ShoppingCart, HambergerMenu, Home } from 'iconsax-react'
import CategoryModal from './CategoryModal'
const MobileBottomMenu: FC = () => {
const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false)
const menuItems = [
{ icon: Profile, label: 'پروفایل', active: false },
{ icon: MessageText, label: 'چت', active: false },
{ icon: ShoppingCart, label: 'سبد خرید', active: false },
{ icon: HambergerMenu, label: 'منو', active: false, onClick: () => setIsCategoryModalOpen(!isCategoryModalOpen) },
{ icon: Home, label: 'خانه', active: true },
]
return (
<>
{/* Mobile Bottom Menu */}
<div className="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 z-50 md:hidden">
<div className="flex items-center justify-around py-3 px-2">
{menuItems.map((item, index) => {
const IconComponent = item.icon
return (
<button
key={index}
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'
}`}
>
<IconComponent
size={24}
color={item.active ? '#9333ea' : '#6b7280'}
/>
<span className="text-xs text-center leading-tight">{item.label}</span>
</button>
)
})}
</div>
</div>
{/* Category Modal */}
<CategoryModal
isOpen={isCategoryModalOpen}
onClose={() => setIsCategoryModalOpen(false)}
/>
</>
)
}
export default MobileBottomMenu
+13 -5
View File
@@ -27,8 +27,13 @@ const Modal: FC<Props> = ({ open, close, children, title, isHeader = false, clas
if (!open) return null
const isFullScreen = className?.includes('max-w-full') && className?.includes('h-full')
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className={cn(
"fixed inset-0 z-50",
isFullScreen ? "flex" : "flex items-center justify-center"
)}>
{/* Backdrop */}
<div
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
@@ -37,13 +42,16 @@ const Modal: FC<Props> = ({ open, close, children, title, isHeader = false, clas
{/* Modal */}
<div className={cn(
"relative bg-white rounded-2xl shadow-xl max-w-md w-full mx-4 max-h-[90vh] overflow-y-auto",
"relative bg-white shadow-xl overflow-hidden",
isFullScreen
? "w-full h-full"
: "rounded-xl sm:rounded-2xl max-w-sm sm:max-w-md w-full mx-2 sm:mx-4 max-h-[90vh]",
className
)}>
{/* Header */}
{isHeader && (
<div className="flex items-center justify-between p-6 border-b border-gray-200">
<h2 className="text-lg font-semibold text-gray-900">{title}</h2>
<div className="flex items-center justify-between p-4 sm:p-6 border-b border-gray-200">
<h2 className="text-base sm:text-lg font-semibold text-gray-900">{title}</h2>
<button
onClick={close}
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
@@ -54,7 +62,7 @@ const Modal: FC<Props> = ({ open, close, children, title, isHeader = false, clas
)}
{/* Content */}
<div className="p-6">
<div className="p-4 sm:p-6">
{children}
</div>
</div>
+10 -10
View File
@@ -11,18 +11,18 @@ type Props = {
const ProductCard: FC<Props> = ({ item }) => {
if (item) return (
<div className='bg-white rounded-[40px] p-6 w-full max-w-[280px] mx-auto shadow'>
<div className='bg-white rounded-[20px] sm:rounded-[40px] p-4 sm:p-6 w-full max-w-[240px] sm:max-w-[280px] mx-auto shadow'>
<div className='flex justify-center'>
<Image
src={item.imagesUrl.cover}
width={170}
height={170}
alt=''
className='max-w-[150px] max-h-[150px] object-contain'
className='max-w-[120px] sm:max-w-[150px] max-h-[120px] sm:max-h-[150px] object-contain'
/>
</div>
<h4 className='line-clamp-2 text-[#383E43] mt-6 text-sm text-center leading-5 h-12'>
<h4 className='line-clamp-2 text-[#383E43] mt-4 sm:mt-6 text-xs sm:text-sm text-center leading-4 sm:leading-5 h-10 sm:h-12'>
{item.title_fa}
</h4>
@@ -32,10 +32,10 @@ const ProductCard: FC<Props> = ({ item }) => {
<div className='size-2 rounded-full bg-red-500'></div>
</div>
<div className='mt-5 text-sm'>
<div className='mt-4 sm:mt-5 text-xs sm:text-sm'>
{NumberFormat(item.default_variant.price.selling_price)} تومان
</div>
<div className='mt-1 text-sm text-[#7F7F7F] line-through'>
<div className='mt-1 text-xs sm:text-sm text-[#7F7F7F] line-through'>
{NumberFormat(item.default_variant.price.retailPrice)}
</div>
@@ -45,18 +45,18 @@ const ProductCard: FC<Props> = ({ item }) => {
</div>
)
return (
<div className='bg-white rounded-[40px] p-6 w-full max-w-[280px] mx-auto shadow'>
<div className='bg-white rounded-[20px] sm:rounded-[40px] p-4 sm:p-6 w-full max-w-[240px] sm:max-w-[280px] mx-auto shadow'>
<div className='flex justify-center'>
<Image
src={`https://dkstatics-public.digikala.com/digikala-products/40026b18c2b053ac4a68c3288556dc899a77aecd_1727277566.jpg?x-oss-process=image/resize,m_lfit,h_300,w_300/format,webp/quality,q_80`}
width={170}
height={170}
alt=''
className='max-w-[150px] max-h-[150px] object-contain'
className='max-w-[120px] sm:max-w-[150px] max-h-[120px] sm:max-h-[150px] object-contain'
/>
</div>
<h4 className='line-clamp-2 text-[#383E43] mt-6 text-sm text-center leading-5'>
<h4 className='line-clamp-2 text-[#383E43] mt-4 sm:mt-6 text-xs sm:text-sm text-center leading-4 sm:leading-5'>
شارژر دیواری 65 وات سامسونگ سه پورت Type-C مدل EP-T6530- اورجینال
</h4>
@@ -66,10 +66,10 @@ const ProductCard: FC<Props> = ({ item }) => {
<div className='size-2 rounded-full bg-red-500'></div>
</div>
<div className='mt-5 text-sm'>
<div className='mt-4 sm:mt-5 text-xs sm:text-sm'>
260,000 تومان
</div>
<div className='mt-1 text-sm text-[#7F7F7F] line-through'>
<div className='mt-1 text-xs sm:text-sm text-[#7F7F7F] line-through'>
70,400,000
</div>
+3 -3
View File
@@ -69,7 +69,7 @@ const Select: FC<Props> = ({
<div className="w-full relative" ref={dropdownRef}>
<div
className={cn(
"w-full h-10 px-4 py-2 text-sm border border-[#D0D0D0] rounded-xl bg-white cursor-pointer flex items-center justify-between",
"w-full h-10 sm:h-12 px-3 sm:px-4 py-2 text-xs sm:text-sm border border-[#D0D0D0] rounded-xl bg-white cursor-pointer flex items-center justify-between",
disabled && "bg-gray-100 cursor-not-allowed",
error_text && "border-red-500",
className
@@ -89,11 +89,11 @@ const Select: FC<Props> = ({
</div>
{isOpen && (
<div className="absolute top-full left-0 right-0 mt-1 bg-white border border-[#D0D0D0] rounded-xl shadow-lg z-50 max-h-60 overflow-y-auto">
<div className="absolute top-full left-0 right-0 mt-1 bg-white border border-[#D0D0D0] rounded-xl shadow-lg z-50 max-h-48 sm:max-h-60 overflow-y-auto">
{items.map((item, index) => (
<div
key={index}
className="px-4 py-2 hover:bg-gray-50 cursor-pointer text-sm"
className="px-3 sm:px-4 py-2 hover:bg-gray-50 cursor-pointer text-xs sm:text-sm"
onClick={() => handleSelect(item)}
>
{item.label}
+1 -1
View File
@@ -8,7 +8,7 @@ interface LayoutProps {
const Layout: FC<LayoutProps> = ({ children }) => {
return (
<div className="min-h-screen flex flex-col">
<div className="min-h-screen flex flex-col max-w-full overflow-x-hidden">
<Header />
<main className="flex-1">
{children}
+32 -30
View File
@@ -6,14 +6,14 @@ import { FC } from 'react'
const Footer: FC = () => {
return (
<div className='mt-24 bg-[#F5F5F5] p-20 flex gap-20'>
<div className='bg-[#F2F2F2] max-w-[450px] p-7 rounded-2xl border border-border'>
<div className='mt-12 sm:mt-16 md:mt-24 bg-[#F5F5F5] p-4 sm:p-8 md:p-20 flex flex-col lg:flex-row gap-8 sm:gap-12 md:gap-20'>
<div className='bg-[#F2F2F2] w-full lg:max-w-[450px] p-4 sm:p-6 md:p-7 rounded-2xl border border-border'>
<div>LOGO</div>
<div className='mt-6 text-sm text-[#383E43] '>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده
</div>
<div className='mt-20 text-[#383E43] text-sm'>
<div className='mt-8 sm:mt-12 md:mt-20 text-[#383E43] text-sm'>
<div className='flex gap-3'>
<Call color='#383E43' size={20} />
<div>تلفن: 67341</div>
@@ -33,49 +33,51 @@ const Footer: FC = () => {
</div>
<div className='mt-14 flex justify-end'>
<div className='mt-8 sm:mt-10 md:mt-14 flex justify-end'>
<div className='size-10 bg-amber-200'></div>
</div>
</div>
<div className='flex-1'>
<div className='w-full rounded-xl bg-[#F2F2F2] border border-border h-[72px] flex items-center justify-between px-6'>
<div className='w-full rounded-xl bg-[#F2F2F2] border border-border h-auto sm:h-[72px] flex flex-col sm:flex-row items-start sm:items-center justify-between p-4 sm:px-6 sm:py-0 gap-3 sm:gap-0'>
<div className='text-[#383E43]'>
دانلود اپلیکیشن
</div>
<div className='flex gap-2'>
<div className='flex gap-2 flex-wrap'>
<Image
width={132}
height={48}
alt='download from app store'
src='/images/appstore.png'
className='w-24 sm:w-[132px] h-auto'
/>
<Image
width={142}
height={48}
alt='download from google play'
src='/images/googleplay.png'
className='w-24 sm:w-[142px] h-auto'
/>
</div>
</div>
<div className='w-full rounded-xl bg-[#F2F2F2] border border-border h-[72px] flex items-center justify-between px-6 mt-6'>
<div className='text-[#383E43]'>
<div className='w-full rounded-xl bg-[#F2F2F2] border border-border h-auto sm:h-[72px] flex flex-col sm:flex-row items-start sm:items-center justify-between p-4 sm:px-6 sm:py-0 gap-3 sm:gap-0 mt-4 sm:mt-6'>
<div className='text-[#383E43] text-sm sm:text-base'>
با ثبت ایمیل از آخرین تخفیف ها با خبر شوید
</div>
<div className='flex gap-2'>
<div className='bg-[#E5E5E5] h-12 flex gap-3 items-center px-3 rounded-[8px]'>
<div className='flex gap-2 w-full sm:w-auto'>
<div className='bg-[#E5E5E5] h-12 flex gap-3 items-center px-3 rounded-[8px] flex-1 sm:flex-none'>
<Sms size={20} color='#383E43' />
<Separator className='bg-[#C9C9C9]' style={{ height: 15 }} orientation='vertical' />
<input placeholder='آدرس ایمیل' className='bg-transparent outline-none text-sm' />
<input placeholder='آدرس ایمیل' className='bg-transparent outline-none text-sm w-full' />
</div>
<Button className='h-12 w-[72px]'>
<Button className='h-12 w-[72px] flex-shrink-0'>
ثبت
</Button>
</div>
</div>
<div className='w-full rounded-xl bg-[#F2F2F2] border border-border h-[72px] flex items-center justify-between px-6 mt-6'>
<div className='text-[#383E43]'>
<div className='w-full rounded-xl bg-[#F2F2F2] border border-border h-auto sm:h-[72px] flex flex-col sm:flex-row items-start sm:items-center justify-between p-4 sm:px-6 sm:py-0 gap-3 sm:gap-0 mt-4 sm:mt-6'>
<div className='text-[#383E43] text-sm sm:text-base'>
ما را در شبکه های اجتماعی دنبال کنید
</div>
@@ -92,29 +94,29 @@ const Footer: FC = () => {
</div>
</div>
<div className='mt-20 flex justify-between'>
<div className='mt-8 sm:mt-12 md:mt-20 flex flex-col sm:flex-row justify-between gap-6 sm:gap-0'>
<div>
<div>همراه با سندس کالا</div>
<ul className='flex mt-6 flex-col gap-4 font-light'>
<li className='text-[#878787]'>تماس با ما</li>
<li className='text-[#878787]'>درباره سندس کالا</li>
<li className='text-[#878787]'>فروش در سندس کالا</li>
<div className='text-sm sm:text-base font-medium'>همراه با سندس کالا</div>
<ul className='flex mt-4 sm:mt-6 flex-col gap-3 sm:gap-4 font-light'>
<li className='text-[#878787] text-sm sm:text-base'>تماس با ما</li>
<li className='text-[#878787] text-sm sm:text-base'>درباره سندس کالا</li>
<li className='text-[#878787] text-sm sm:text-base'>فروش در سندس کالا</li>
</ul>
</div>
<div>
<div>راهنمای خرید از سندس کالا</div>
<ul className='flex mt-6 flex-col gap-4 font-light'>
<li className='text-[#878787]'>نحوه ثبت سفارش</li>
<li className='text-[#878787]'>قوانین مرجوعی کالا</li>
<li className='text-[#878787]'>پاسخ به پرسش ها متداول</li>
<div className='text-sm sm:text-base font-medium'>راهنمای خرید از سندس کالا</div>
<ul className='flex mt-4 sm:mt-6 flex-col gap-3 sm:gap-4 font-light'>
<li className='text-[#878787] text-sm sm:text-base'>نحوه ثبت سفارش</li>
<li className='text-[#878787] text-sm sm:text-base'>قوانین مرجوعی کالا</li>
<li className='text-[#878787] text-sm sm:text-base'>پاسخ به پرسش ها متداول</li>
</ul>
</div>
<div>
<div>خدمات مشتریان</div>
<ul className='flex mt-6 flex-col gap-4 font-light'>
<li className='text-[#878787]'>حساب کاربری من</li>
<li className='text-[#878787]'>سبد خرید</li>
<li className='text-[#878787]'>حریم حصوصی</li>
<div className='text-sm sm:text-base font-medium'>خدمات مشتریان</div>
<ul className='flex mt-4 sm:mt-6 flex-col gap-3 sm:gap-4 font-light'>
<li className='text-[#878787] text-sm sm:text-base'>حساب کاربری من</li>
<li className='text-[#878787] text-sm sm:text-base'>سبد خرید</li>
<li className='text-[#878787] text-sm sm:text-base'>حریم حصوصی</li>
</ul>
</div>
</div>
+76 -14
View File
@@ -1,47 +1,109 @@
'use client'
import Input from '@/components/Input'
import { Separator } from '@/components/ui/separator'
import { DocumentText, Home, Profile, ShoppingCart } from 'iconsax-react'
import { FC, Fragment } from 'react'
import { DocumentText, Home, Profile, ShoppingCart, HambergerMenu } from 'iconsax-react'
import { FC, Fragment, useState } from 'react'
import Menu from './components/Menu'
const Header: FC = () => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
return (
<Fragment>
<div className='fixed top-0 bg-white w-full z-[9998] pb-4'>
<div className='flex items-center justify-between px-6 py-[18px]'>
<div className='flex gap-[30px] items-center'>
<div>LOGO</div>
<Input className='w-[500px]' variant='search' placeholder='جستجو' />
<div className='fixed top-0 bg-white w-full z-[9998] border-b border-gray-100 max-w-full overflow-hidden'>
{/* بخش بالایی هدر */}
<div className='flex items-center justify-between px-3 sm:px-4 md:px-6 py-3 sm:py-4'>
{/* منوی همبرگری موبایل */}
<div className='md:hidden'>
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className='p-2 rounded-lg hover:bg-gray-50'
>
<HambergerMenu size={24} color='#333333' />
</button>
</div>
<div className='flex items-center gap-6'>
<div className='h-10 border border-border py-3 px-4 rounded-[12px] flex items-center gap-2.5'>
<div className='flex gap-2 sm:gap-4 md:gap-[30px] items-center flex-1 md:flex-none'>
<div className='text-base sm:text-lg font-bold text-purple-600'>LOGO</div>
<Input
className='hidden md:block w-[300px] lg:w-[500px]'
variant='search'
placeholder='جستجو'
/>
</div>
<div className='flex items-center gap-1 sm:gap-2 md:gap-6'>
<div className='hidden md:flex h-10 border border-border py-3 px-4 rounded-[12px] items-center gap-2.5'>
<Profile size={20} color='#333333' />
<div className='text-sm text-[#333333]'>حساب کاربری</div>
</div>
<Separator style={{ height: 25 }} orientation='vertical' />
<div className='md:hidden'>
<Profile size={24} color='#333333' />
</div>
<Separator className='hidden md:block' style={{ height: 25 }} orientation='vertical' />
<div className='h-10 p-3 rounded-[12px] border border-border flex items-center gap-2.5'>
<ShoppingCart size={20} color='#333333' />
</div>
</div>
</div>
<div className='mt-7 text-sm px-6 flex items-center gap-7'>
{/* نوار جستجو موبایل */}
<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'>
<Menu />
<Separator style={{ height: 20 }} orientation='vertical' />
<div className='flex items-center gap-2.5'>
<div className='flex items-center gap-2.5 cursor-pointer hover:text-purple-600 transition-colors'>
<Home size={20} color='#333333' />
<div className='text-[#333333]'>صفحه نخست</div>
</div>
<div className='flex items-center gap-2.5'>
<div className='flex items-center gap-2.5 cursor-pointer hover:text-purple-600 transition-colors'>
<DocumentText size={20} color='#333333' />
<div className='text-[#333333]'>مجله</div>
</div>
</div>
{/* منوی موبایل */}
{isMobileMenuOpen && (
<div className='md:hidden bg-white border-t border-gray-100'>
<div className='px-4 py-4 space-y-4'>
<div className='flex items-center gap-3 py-3 border-b border-gray-100'>
<Profile size={20} color='#333333' />
<span className='text-sm text-gray-800'>حساب کاربری</span>
</div>
<div className='space-y-3'>
<div className='flex items-center gap-3 py-2 cursor-pointer hover:bg-gray-50 rounded-lg px-2'>
<Home size={20} color='#333333' />
<span className='text-sm text-gray-800'>صفحه نخست</span>
</div>
<div className='flex items-center gap-3 py-2 cursor-pointer hover:bg-gray-50 rounded-lg px-2'>
<DocumentText size={20} color='#333333' />
<span className='text-sm text-gray-800'>مجله</span>
</div>
</div>
<div className='pt-4 border-t border-gray-100'>
<Menu />
</div>
</div>
</div>
)}
</div>
<div className='h-[140px]'></div>
{/* فضای خالی برای جبران ارتفاع fixed header */}
<div className={`${isMobileMenuOpen ? 'h-[280px] sm:h-[260px] md:h-[140px]' : 'h-[100px] sm:h-[120px] md:h-[140px]'}`}></div>
</Fragment>
)
}
+6 -5
View File
@@ -40,7 +40,7 @@ const Menu: FC = () => {
const renderCategoryLevel = (categories: Category[], level: number) => {
return (
<div className='w-64 border-l border-gray-200 last:border-l-0 flex flex-col min-h-0'>
<div className='w-48 md:w-64 border-l border-gray-200 last:border-l-0 flex flex-col min-h-0'>
<div className='p-2 overflow-y-auto max-h-[calc(100vh-200px)]'>
{categories.map((category) => (
<div
@@ -80,12 +80,13 @@ const Menu: FC = () => {
onMouseEnter={() => setIsOpen(true)}
>
<HambergerMenu size={24} color='#333333' />
<div className='text-[#333333]'>دسته بندی کالاها</div>
<div className='text-[#333333] hidden md:block'>دسته بندی کالاها</div>
<div className='text-[#333333] md:hidden text-xs'>دستهها</div>
</div>
{isOpen && (
<div
className='absolute top-full right-0 mt-2 bg-white rounded-xl shadow-lg border border-gray-200 z-[9999] flex max-w-[90vw] max-h-screen overflow-hidden'
className='absolute top-full right-0 mt-2 bg-white rounded-xl shadow-lg border border-gray-200 z-[9999] flex max-w-[90vw] md:max-w-none max-h-screen overflow-hidden'
onMouseLeave={() => {
setIsOpen(false)
setHoveredPath([])
@@ -93,7 +94,7 @@ const Menu: FC = () => {
>
{/* دسته‌های اصلی (سطح اول) */}
{isLoading ? (
<div className='w-64 border-l border-gray-200 flex items-center justify-center h-40'>
<div className='w-48 md:w-64 border-l border-gray-200 flex items-center justify-center h-40'>
<div className='text-gray-500'>در حال بارگذاری...</div>
</div>
) : parentCategories.length > 0 ? (
@@ -113,7 +114,7 @@ const Menu: FC = () => {
})}
</>
) : (
<div className='w-64 border-l border-gray-200 flex items-center justify-center h-40'>
<div className='w-48 md:w-64 border-l border-gray-200 flex items-center justify-center h-40'>
<div className='text-gray-500'>دستهبندیای یافت نشد</div>
</div>
)}