diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index 44a9da9..cc92274 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -27,7 +27,7 @@ const AboutPage: NextPage = () => { return ( -
+
{/* عنوان اصلی */}

diff --git a/src/app/blogs/page.tsx b/src/app/blogs/page.tsx index 780e82d..cd3a800 100644 --- a/src/app/blogs/page.tsx +++ b/src/app/blogs/page.tsx @@ -5,20 +5,20 @@ import BlogItem from './components/BlogItem' import LastPost from './components/LastPost' const BlogsPage: NextPage = () => { - return ( -
- -
- - - - -
-
- -
-
- ) + return ( +
+ +
+ + + + +
+
+ +
+
+ ) } export default function BlogsPageWithLayout() { diff --git a/src/app/cart/page.tsx b/src/app/cart/page.tsx index 07d7c40..5fe80fa 100644 --- a/src/app/cart/page.tsx +++ b/src/app/cart/page.tsx @@ -7,10 +7,10 @@ import { NextPage } from "next" const Cart: NextPage = () => { return ( -
-
-
-
+
+
+
+
سبد خرید
@@ -19,17 +19,17 @@ const Cart: NextPage = () => {
-
-
+
+
@@ -40,7 +40,7 @@ const Cart: NextPage = () => { total={80580000} confirmHref="/cart/shipping" confirmLabel="ادامه به آدرس و ارسال" - className="w-[360px]" + className="w-full lg:w-[360px]" />
@@ -48,9 +48,9 @@ const Cart: NextPage = () => { } export default function CartWithLayout() { - return ( - - - - ) + return ( + + + + ) } \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index eb491af..ba5da47 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -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%; diff --git a/src/app/home/components/BlogCard.tsx b/src/app/home/components/BlogCard.tsx index 45e7b1b..4169f2f 100644 --- a/src/app/home/components/BlogCard.tsx +++ b/src/app/home/components/BlogCard.tsx @@ -4,31 +4,31 @@ import { FC } from 'react' const BlogCard: FC = () => { return ( -
+
تکنولوژی
-

+

نسل جدید پردازنده اینتل

-

+

لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است....

-
-
1401/7/21
+
+
1401/7/21
-
ادامه مطلب
- +
ادامه مطلب
+
diff --git a/src/app/home/components/Carousel.tsx b/src/app/home/components/Carousel.tsx index 788aaf0..66f7628 100644 --- a/src/app/home/components/Carousel.tsx +++ b/src/app/home/components/Carousel.tsx @@ -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 ( -
+

اسلایدری موجود نیست

); @@ -19,9 +34,9 @@ const Carousel: FC = () => { return (
- {data.results.sliders.desktop.map((slider) => ( + {sliders.map((slider) => ( -
+
{slider.altText} { @@ -10,17 +11,23 @@ const Categories = () => { const parentCategories = data?.results?.data?.filter(cat => !cat.parent) || [] return ( -
- { - parentCategories?.map((item: Category) => { - return ( - - - ) - }) - } - - +
+ + {parentCategories?.map((item: Category) => ( + + + + ))} +
) } diff --git a/src/app/home/components/CategoryItem.tsx b/src/app/home/components/CategoryItem.tsx index 9e6ae9b..2d8ee08 100644 --- a/src/app/home/components/CategoryItem.tsx +++ b/src/app/home/components/CategoryItem.tsx @@ -8,11 +8,11 @@ type Props = { const CategoryItem: FC = (props) => { return ( -
-
- {props.title} +
+
+ {props.title}
-
+
{props.title}
diff --git a/src/app/home/components/HotOffer.tsx b/src/app/home/components/HotOffer.tsx index 7c32120..4b77a4a 100644 --- a/src/app/home/components/HotOffer.tsx +++ b/src/app/home/components/HotOffer.tsx @@ -7,9 +7,9 @@ import { Swiper, SwiperSlide } from 'swiper/react'; const HotOffer: FC = () => { return ( -
-
-
+
+
+
پیشنهاد های
داغ @@ -17,22 +17,27 @@ const HotOffer: FC = () => { سندس کالا
-
+
-
+
diff --git a/src/app/home/components/LatestProducts.tsx b/src/app/home/components/LatestProducts.tsx index 303c1ab..dfe6f7c 100644 --- a/src/app/home/components/LatestProducts.tsx +++ b/src/app/home/components/LatestProducts.tsx @@ -31,10 +31,10 @@ const NewestProducts: FC = () => { }} className="w-full" > - + { landing?.results?.latestProducts?.map((product) => ( - + )) diff --git a/src/app/home/components/PopularProducts.tsx b/src/app/home/components/PopularProducts.tsx index 05a472f..5894707 100644 --- a/src/app/home/components/PopularProducts.tsx +++ b/src/app/home/components/PopularProducts.tsx @@ -25,9 +25,9 @@ const PopularProducts: FC = () => { }} className="w-full" > - + {Array.from({ length: 5 }).map((_, index) => ( - + ))} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index d676530..5a7ff96 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -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({ {children} + diff --git a/src/app/page.tsx b/src/app/page.tsx index dccffe6..f1e5eaa 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -18,27 +18,27 @@ const HomePage: NextPage = () => { return (
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/src/app/product/[id]/page.tsx b/src/app/product/[id]/page.tsx index 08c0c55..f1000b1 100644 --- a/src/app/product/[id]/page.tsx +++ b/src/app/product/[id]/page.tsx @@ -19,8 +19,8 @@ import Questions from '@/app/product/components/Questions' const SingleProduct: NextPage = () => { return ( -
-
+
+
@@ -37,13 +37,13 @@ const SingleProduct: NextPage = () => { -
فروشنده شوید
+
فروشنده شوید
-
+
-
+
@@ -61,9 +61,9 @@ const SingleProduct: NextPage = () => { } export default function SingleProductWithLayout() { - return ( - - - - ) + return ( + + + + ) } \ No newline at end of file diff --git a/src/app/products/[id]/page.tsx b/src/app/products/[id]/page.tsx index aa85e0e..8348519 100644 --- a/src/app/products/[id]/page.tsx +++ b/src/app/products/[id]/page.tsx @@ -15,7 +15,7 @@ import ProductCard from '@/components/ProductCard' const Products: NextPage = () => { return ( -
+
@@ -32,13 +32,13 @@ const Products: NextPage = () => { -
+
-
- +
+ diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index 27ab28f..88dd467 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -36,15 +36,15 @@ const ProfilePage = () => { } return ( -
+
-
-
+
+
{/* Left Content - Form */}
-
-
-

اطلاعات کاربری

+
+
+

اطلاعات کاربری

-
+
{ />
-
+
{
{isEditing && ( -
+
-
-
-
- +
+
+
+
سفارشات
-
-
- +
+
+
علاقه مندی ها @@ -168,7 +168,7 @@ const ProfilePage = () => {
-
+
diff --git a/src/app/viewport.ts b/src/app/viewport.ts new file mode 100644 index 0000000..0992cba --- /dev/null +++ b/src/app/viewport.ts @@ -0,0 +1,8 @@ +import { Viewport } from "next"; + +export const viewport: Viewport = { + width: "device-width", + initialScale: 1, + maximumScale: 1, + userScalable: false, +}; diff --git a/src/components/CategoryModal.tsx b/src/components/CategoryModal.tsx new file mode 100644 index 0000000..81feaea --- /dev/null +++ b/src/components/CategoryModal.tsx @@ -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 = ({ isOpen, onClose }) => { + const router = useRouter() + const [selectedMainCategory, setSelectedMainCategory] = useState(0) + const [expandedSubcategory, setExpandedSubcategory] = useState(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 ( +
+
+ {/* Left Column - Main Categories */} +
+
+ {mainCategories.map((category, index) => ( +
+
handleMainCategoryClick(index)} + > +
+ {category.icon} +
+ + {category.title} + +
+ {index < mainCategories.length - 1 && ( +
+ )} +
+ ))} +
+
+ + {/* Right Column - Subcategories */} +
+
+ {/* Special Categories */} +
+
{ + router.push('/products') + onClose() + }} + > + همه محصولات سوپر مارکت ارگانیک +
+
{ + router.push('/products/organic') + onClose() + }} + > + ارگانیک گواهی‌دار +
+
+ + {/* Subcategories List */} +
+ {currentSubcategories.map((subcategory, index) => ( +
+
handleSubcategoryClick(subcategory)} + > + {subcategory.title} + {subcategory.hasChildren && ( + + )} +
+ + {/* Expanded third level categories */} + {expandedSubcategory === subcategory.title && thirdLevelCategories[subcategory.title as keyof typeof thirdLevelCategories] && ( +
+
+ همه محصولات {subcategory.title} +
+
+ {thirdLevelCategories[subcategory.title as keyof typeof thirdLevelCategories].map((item, itemIndex) => ( +
{ + router.push(`/products/${item.title}`) + onClose() + }} + > +
+ {item.icon} +
+ + {item.title} + +
+ ))} +
+
+ )} + + {index < currentSubcategories.length - 1 && ( +
+ )} +
+ ))} +
+
+
+
+
+ ) +} + +export default CategoryModal \ No newline at end of file diff --git a/src/components/Input.tsx b/src/components/Input.tsx index 294321d..c4f48b9 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -33,7 +33,7 @@ const Input: FC = (props: Props) => { const [search, setSearch] = useState('') 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) => { return (
-