privacy + return policy
This commit is contained in:
@@ -3,13 +3,14 @@ import { Calendar, Eye, User } from 'iconsax-react'
|
||||
import LastPost from '../components/LastPost'
|
||||
import { NextPage } from 'next'
|
||||
import Layout from '@/hoc/Layout'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
|
||||
const BlogDetail: NextPage = () => {
|
||||
return (
|
||||
<div className="max-w-7xl mx-auto px-4 py-8">
|
||||
{/* Breadcrumb */}
|
||||
<div className="text-sm text-gray-500 mb-6">
|
||||
فروشگاه سندس طلا / راهنما ها / تست اقلام و قطعات / گلکسی بوک
|
||||
فروشگاه {SHOP_CONFIG.name} / راهنما ها / تست اقلام و قطعات / گلکسی بوک
|
||||
</div>
|
||||
|
||||
<div className="flex gap-8">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { NextPage } from 'next'
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
|
||||
import Layout from '@/hoc/Layout'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
|
||||
const FaqPage: NextPage = () => {
|
||||
const faqData = [
|
||||
@@ -15,8 +16,8 @@ const FaqPage: NextPage = () => {
|
||||
answer: "این خطا معمولاً زمانی رخ میدهد که شماره ملی قبلاً در سیستم ثبت شده است. در صورت اطمینان از صحت اطلاعات، با پشتیبانی تماس بگیرید."
|
||||
},
|
||||
{
|
||||
question: "برای ثبت نام در سندس کالا به چه مدارکی نیاز است؟",
|
||||
answer: "برای ثبت نام در سندس کالا نیاز به مدارک شناسایی، مجوزهای کسب و کار و اطلاعات بانکی معتبر دارید."
|
||||
question: `برای ثبت نام در ${SHOP_CONFIG.fullName} به چه مدارکی نیاز است؟`,
|
||||
answer: `برای ثبت نام در ${SHOP_CONFIG.fullName} نیاز به مدارک شناسایی، مجوزهای کسب و کار و اطلاعات بانکی معتبر دارید.`
|
||||
},
|
||||
{
|
||||
question: "نام تجاری به چه معناست ؟",
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import { FC } from 'react'
|
||||
import ProductCard from '@/components/ProductCard'
|
||||
import Image from 'next/image'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
|
||||
|
||||
const HotOffer: FC = () => {
|
||||
@@ -14,7 +15,8 @@ const HotOffer: FC = () => {
|
||||
<br />
|
||||
داغ
|
||||
<br />
|
||||
سندس
|
||||
{SHOP_CONFIG.name}
|
||||
<br />
|
||||
کالا
|
||||
</div>
|
||||
<div className='mt-4 sm:mt-6 flex justify-center'>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import * as api from "../service/Service";
|
||||
|
||||
export const useGetSiteSetting = (name: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["site-setting", name],
|
||||
queryFn: () => api.getSiteSetting(name),
|
||||
enabled: !!name,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,110 @@
|
||||
'use client'
|
||||
|
||||
import Layout from '@/hoc/Layout'
|
||||
import { NextPage } from 'next'
|
||||
import { useGetSiteSetting } from './hooks/usePrivacyData'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator
|
||||
} from '@/components/ui/breadcrumb'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { ShieldTick } from 'iconsax-react'
|
||||
import Link from 'next/link'
|
||||
|
||||
const PrivacyPage: NextPage = () => {
|
||||
|
||||
const { data } = useGetSiteSetting('policyContent')
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="mt-14 px-4 sm:px-6 md:px-8 lg:px-12 xl:px-20 max-w-full overflow-x-hidden">
|
||||
{/* Breadcrumb */}
|
||||
<div className="mb-6 sm:mb-8">
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="/" className="text-gray-600 hover:text-gray-800">
|
||||
خانه
|
||||
</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className='rotate-180' />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage className="text-gray-800 font-medium">
|
||||
حریم خصوصی
|
||||
</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
|
||||
{/* عنوان اصلی */}
|
||||
<div className="text-center mb-8 sm:mb-12">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 bg-primary/10 rounded-full mb-4 sm:mb-6">
|
||||
<ShieldTick
|
||||
color='#DA2129'
|
||||
size={32}
|
||||
className="sm:w-10 sm:h-10 text-primary"
|
||||
/>
|
||||
</div>
|
||||
<h1 className="text-xl sm:text-2xl lg:text-3xl font-bold text-gray-800 mb-3 sm:mb-4">
|
||||
سیاستهای حفظ حریم خصوصی
|
||||
</h1>
|
||||
<p className="text-gray-600 text-sm sm:text-base max-w-2xl mx-auto leading-relaxed">
|
||||
اطلاعاتی درباره نحوه جمعآوری، استفاده و حفاظت از دادههای شخصی شما در پلتفرم ما
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator className="mb-8 sm:mb-12" />
|
||||
|
||||
{/* محتوای اصلی */}
|
||||
{data?.results ? (
|
||||
<div className="bg-white rounded-lg border border-gray-100 shadow-sm p-4 sm:p-6 lg:p-8">
|
||||
<div
|
||||
className="prose prose-sm sm:prose-base lg:prose-lg prose-gray max-w-none
|
||||
prose-headings:text-gray-800 prose-headings:font-bold
|
||||
prose-p:text-gray-700 prose-p:leading-relaxed prose-p:mb-4
|
||||
prose-li:text-gray-700 prose-li:leading-relaxed
|
||||
prose-strong:text-gray-800 prose-strong:font-semibold
|
||||
prose-ul:space-y-2 prose-ol:space-y-2"
|
||||
dangerouslySetInnerHTML={{ __html: data.results.siteSetting.policyContent }}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white rounded-lg border border-gray-100 shadow-sm p-8 text-center">
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 bg-gray-100 rounded-full mb-4">
|
||||
<ShieldTick size={20} className="text-gray-400" />
|
||||
</div>
|
||||
<p className="text-gray-500 text-sm sm:text-base">
|
||||
در حال بارگذاری اطلاعات...
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* بخش تماس برای سوالات بیشتر */}
|
||||
<div className="mt-8 sm:mt-12 bg-gradient-to-r from-primary/5 to-primary/10 rounded-lg p-4 sm:p-6 lg:p-8 text-center">
|
||||
<h3 className="text-lg sm:text-xl font-semibold text-gray-800 mb-3 sm:mb-4">
|
||||
سوالی دارید؟
|
||||
</h3>
|
||||
<p className="text-gray-600 text-sm sm:text-base mb-4 sm:mb-6 leading-relaxed max-w-2xl mx-auto">
|
||||
اگر در مورد سیاستهای حفظ حریم خصوصی سوال یا نگرانی دارید،
|
||||
میتوانید با تیم پشتیبانی ما تماس بگیرید.
|
||||
</p>
|
||||
<Link
|
||||
href="/contact"
|
||||
className="inline-flex items-center gap-2 bg-primary text-white px-4 py-2 sm:px-6 sm:py-3 rounded-lg hover:bg-primary/90 transition-colors text-sm sm:text-base font-medium"
|
||||
>
|
||||
تماس با ما
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export default PrivacyPage
|
||||
@@ -0,0 +1,6 @@
|
||||
import axios from "@/config/axios";
|
||||
|
||||
export const getSiteSetting = async (name: string) => {
|
||||
const { data } = await axios.get(`/site-setting?name=${name}`);
|
||||
return data;
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
'use client'
|
||||
|
||||
import Layout from '@/hoc/Layout'
|
||||
import { NextPage } from 'next'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator
|
||||
} from '@/components/ui/breadcrumb'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { ArrowRotateLeft } from 'iconsax-react'
|
||||
import Link from 'next/link'
|
||||
import { useGetSiteSetting } from '../privacy/hooks/usePrivacyData'
|
||||
|
||||
const ReturnPolicyPage: NextPage = () => {
|
||||
|
||||
const { data } = useGetSiteSetting('returnRulesContent')
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="mt-14 px-4 sm:px-6 md:px-8 lg:px-12 xl:px-20 max-w-full overflow-x-hidden">
|
||||
{/* Breadcrumb */}
|
||||
<div className="mb-6 sm:mb-8">
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link href="/" className="text-gray-600 hover:text-gray-800">
|
||||
خانه
|
||||
</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className='rotate-180' />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage className="text-gray-800 font-medium">
|
||||
قوانین مرجوعی کالا
|
||||
</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
|
||||
{/* عنوان اصلی */}
|
||||
<div className="text-center mb-8 sm:mb-12">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 sm:w-20 sm:h-20 bg-primary/10 rounded-full mb-4 sm:mb-6">
|
||||
<ArrowRotateLeft
|
||||
size={32}
|
||||
color='#000000'
|
||||
className="sm:w-10 sm:h-10 text-primary"
|
||||
/>
|
||||
</div>
|
||||
<h1 className="text-xl sm:text-2xl lg:text-3xl font-bold text-gray-800 mb-3 sm:mb-4">
|
||||
قوانین مرجوعی کالا
|
||||
</h1>
|
||||
<p className="text-gray-600 text-sm sm:text-base max-w-2xl mx-auto leading-relaxed">
|
||||
سیاستهای بازگشت کالا و شرایط مرجوعی در فروشگاه ما را مطالعه کنید
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator className="mb-8 sm:mb-12" />
|
||||
|
||||
{/* محتوای اصلی */}
|
||||
{data?.results ? (
|
||||
<div className="bg-white rounded-lg border border-gray-100 shadow-sm p-4 sm:p-6 lg:p-8">
|
||||
<div
|
||||
className="prose prose-sm sm:prose-base lg:prose-lg prose-gray max-w-none
|
||||
prose-headings:text-gray-800 prose-headings:font-bold
|
||||
prose-p:text-gray-700 prose-p:leading-relaxed prose-p:mb-4
|
||||
prose-li:text-gray-700 prose-li:leading-relaxed
|
||||
prose-strong:text-gray-800 prose-strong:font-semibold
|
||||
prose-ul:space-y-2 prose-ol:space-y-2"
|
||||
dangerouslySetInnerHTML={{ __html: data.results.siteSetting.returnRulesContent }}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white rounded-lg border border-gray-100 shadow-sm p-8 text-center">
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 bg-gray-100 rounded-full mb-4">
|
||||
<ArrowRotateLeft size={20} className="text-gray-400" />
|
||||
</div>
|
||||
<p className="text-gray-500 text-sm sm:text-base">
|
||||
در حال بارگذاری اطلاعات...
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export default ReturnPolicyPage
|
||||
@@ -0,0 +1,61 @@
|
||||
'use client'
|
||||
import { FC, ReactNode } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { useSharedStore } from '@/share/store/sharedStore'
|
||||
|
||||
interface MenuItemProps {
|
||||
icon: ReactNode
|
||||
title: string
|
||||
href: string
|
||||
requiresLogin?: boolean
|
||||
className?: string
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
const MenuItem: FC<MenuItemProps> = ({
|
||||
icon,
|
||||
title,
|
||||
href,
|
||||
requiresLogin = false,
|
||||
className = '',
|
||||
onClick
|
||||
}) => {
|
||||
const { isLogin } = useSharedStore()
|
||||
|
||||
const handleClick = () => {
|
||||
if (onClick) {
|
||||
onClick()
|
||||
}
|
||||
}
|
||||
|
||||
const content = (
|
||||
<div
|
||||
className={`flex items-center gap-2.5 cursor-pointer transition-colors hover:text-blue-600 ${className}`}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<div className="text-[#333333] group-hover:text-blue-600 transition-colors">
|
||||
{icon}
|
||||
</div>
|
||||
<div className="text-[#333333] group-hover:text-blue-600 transition-colors">
|
||||
{title}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
// اگر نیاز به لاگین دارد و کاربر لاگین نیست، لینک را غیرفعال میکنیم
|
||||
if (requiresLogin && !isLogin) {
|
||||
return (
|
||||
<div className="opacity-50 cursor-not-allowed">
|
||||
{content}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Link href={href} className="group">
|
||||
{content}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default MenuItem
|
||||
@@ -4,3 +4,9 @@ export const BASE_URL = "https://shop-api.dev.danakcorp.com";
|
||||
// export const BASE_URL = "http://192.168.1.111:4000";
|
||||
|
||||
export const PRIMARY_COLOR = "#DA2129";
|
||||
|
||||
// تنظیمات فروشگاه
|
||||
export const SHOP_CONFIG = {
|
||||
name: "فجر مرکزی", // نام فروشگاه - میتوان آن را تغییر داد
|
||||
fullName: "تابلو فجر مرکزی", // نام کامل فروشگاه
|
||||
};
|
||||
|
||||
+92
-36
@@ -1,14 +1,24 @@
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { Call, Instagram, Location, Sms } from 'iconsax-react'
|
||||
import { Call, Instagram, Location, Sms, Youtube, Whatsapp } from 'iconsax-react'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { FC } from 'react'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
|
||||
const Footer: FC = () => {
|
||||
return (
|
||||
<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='flex justify-center'>
|
||||
<Image
|
||||
width={100}
|
||||
height={100}
|
||||
alt='logo'
|
||||
src='/images/logo.png'
|
||||
className='w-full h-auto max-h-20 max-w-20 object-contain'
|
||||
/>
|
||||
</div>
|
||||
<div className='mt-6 text-sm text-[#383E43] '>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده
|
||||
</div>
|
||||
@@ -43,20 +53,24 @@ const Footer: FC = () => {
|
||||
دانلود اپلیکیشن
|
||||
</div>
|
||||
<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'
|
||||
/>
|
||||
<Link href="https://apps.apple.com/app/id123456789" target="_blank" rel="noopener noreferrer">
|
||||
<Image
|
||||
width={132}
|
||||
height={48}
|
||||
alt='download from app store'
|
||||
src='/images/appstore.png'
|
||||
className='w-24 sm:w-[132px] h-auto hover:opacity-80 transition-opacity'
|
||||
/>
|
||||
</Link>
|
||||
<Link href="https://play.google.com/store/apps/details?id=com.danak.shop" target="_blank" rel="noopener noreferrer">
|
||||
<Image
|
||||
width={142}
|
||||
height={48}
|
||||
alt='download from google play'
|
||||
src='/images/googleplay.png'
|
||||
className='w-24 sm:w-[142px] h-auto hover:opacity-80 transition-opacity'
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -82,41 +96,83 @@ const Footer: FC = () => {
|
||||
</div>
|
||||
|
||||
<div className='flex gap-1.5'>
|
||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center'>
|
||||
<Instagram size={20} color='#fff' />
|
||||
</div>
|
||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center'>
|
||||
<Instagram size={20} color='#fff' />
|
||||
</div>
|
||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center'>
|
||||
<Instagram size={20} color='#fff' />
|
||||
</div>
|
||||
<Link href="https://instagram.com/danakshop" target="_blank" rel="noopener noreferrer">
|
||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center transition-colors'>
|
||||
<Instagram size={20} color='#fff' />
|
||||
</div>
|
||||
</Link>
|
||||
<Link href="https://wa.me/989123456789" target="_blank" rel="noopener noreferrer">
|
||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center transition-colors'>
|
||||
<Whatsapp size={20} color='#fff' />
|
||||
</div>
|
||||
</Link>
|
||||
<Link href="https://youtube.com/@danakshop" target="_blank" rel="noopener noreferrer">
|
||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center transition-colors'>
|
||||
<Youtube size={20} color='#fff' />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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 className='text-sm sm:text-base font-medium'>همراه با سندس کالا</div>
|
||||
<div className='text-sm sm:text-base font-medium'>همراه با {SHOP_CONFIG.fullName}</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>
|
||||
<li>
|
||||
<Link href="/contact" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
تماس با ما
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/about" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
درباره {SHOP_CONFIG.fullName}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
فروش در {SHOP_CONFIG.fullName}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<div className='text-sm sm:text-base font-medium'>راهنمای خرید از سندس کالا</div>
|
||||
<div className='text-sm sm:text-base font-medium'>راهنمای خرید از {SHOP_CONFIG.fullName}</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>
|
||||
<li>
|
||||
<Link href="/faq" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
نحوه ثبت سفارش
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/return-policy" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
قوانین مرجوعی کالا
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/faq" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
پاسخ به پرسش ها متداول
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<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>
|
||||
<li>
|
||||
<Link href="/profile" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
حساب کاربری من
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/cart" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
سبد خرید
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/privacy" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||
حریم خصوصی
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+49
-17
@@ -1,7 +1,8 @@
|
||||
'use client'
|
||||
import Input from '@/components/Input'
|
||||
import MenuItem from '@/components/MenuItem'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { DocumentText, Home, Profile, HambergerMenu } from 'iconsax-react'
|
||||
import { DocumentText, Home, Profile, HambergerMenu, InfoCircle, Messages1 } from 'iconsax-react'
|
||||
import { FC, Fragment, useEffect, useState } from 'react'
|
||||
import Menu from './components/Menu'
|
||||
import { useSharedStore } from './store/sharedStore'
|
||||
@@ -86,14 +87,34 @@ const Header: FC = () => {
|
||||
<Menu />
|
||||
<Separator style={{ height: 20 }} orientation='vertical' />
|
||||
|
||||
<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 cursor-pointer hover:text-purple-600 transition-colors'>
|
||||
<DocumentText size={20} color='#333333' />
|
||||
<div className='text-[#333333]'>مجله</div>
|
||||
</div>
|
||||
<MenuItem
|
||||
icon={<Home size={20} color='#333333' />}
|
||||
title="صفحه نخست"
|
||||
href="/"
|
||||
/>
|
||||
<MenuItem
|
||||
icon={<DocumentText size={20} color='#333333' />}
|
||||
title="مجله"
|
||||
href="/blogs"
|
||||
/>
|
||||
<MenuItem
|
||||
icon={<DocumentText size={20} color='#333333' />}
|
||||
title="پیگیری سفارشات"
|
||||
href="/profile/orders"
|
||||
requiresLogin={true}
|
||||
/>
|
||||
|
||||
<MenuItem
|
||||
icon={<InfoCircle size={18} color='#333333' />}
|
||||
title="درباره ما"
|
||||
href="/about"
|
||||
/>
|
||||
|
||||
<MenuItem
|
||||
icon={<Messages1 size={18} color='#333333' />}
|
||||
title="تماس با ما"
|
||||
href="/contact"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* منوی موبایل */}
|
||||
@@ -106,14 +127,25 @@ const Header: FC = () => {
|
||||
</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>
|
||||
<MenuItem
|
||||
icon={<Home size={20} />}
|
||||
title="صفحه نخست"
|
||||
href="/"
|
||||
className="py-2 hover:bg-gray-50 rounded-lg px-2"
|
||||
/>
|
||||
<MenuItem
|
||||
icon={<DocumentText size={20} />}
|
||||
title="مجله"
|
||||
href="/blogs"
|
||||
className="py-2 hover:bg-gray-50 rounded-lg px-2"
|
||||
/>
|
||||
<MenuItem
|
||||
icon={<DocumentText size={20} />}
|
||||
title="پیگیری سفارشات"
|
||||
href="/profile/orders"
|
||||
requiresLogin={true}
|
||||
className="py-2 hover:bg-gray-50 rounded-lg px-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='pt-4 border-t border-gray-100'>
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover"
|
||||
import { useGetCart } from '@/app/cart/hooks/useCartData'
|
||||
import { useGetCart, useUpdateCart } from '@/app/cart/hooks/useCartData'
|
||||
import { useRemoveFromCart } from '@/app/cart/hooks/useCartData'
|
||||
import { CartItemType } from '@/app/cart/types/Types'
|
||||
import { LocalCartItem } from '@/app/product/store/LocalCartStore'
|
||||
@@ -18,35 +18,64 @@ import { Button } from '@/components/ui/button'
|
||||
import { useSharedStore } from '@/share/store/sharedStore'
|
||||
import { useLocalCart } from '@/app/product/hooks/useLocalCart'
|
||||
import { useOfflineCartProducts, EnrichedOfflineCartItem } from '@/share/hooks/useOfflineCartProducts'
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
const Cart = () => {
|
||||
const { isLogin } = useSharedStore()
|
||||
const { data: cartData, isLoading } = useGetCart()
|
||||
const removeFromCartMutation = useRemoveFromCart()
|
||||
const updateCartMutation = useUpdateCart()
|
||||
|
||||
// Local cart hooks for offline users
|
||||
const {
|
||||
localCartItems,
|
||||
removeFromLocalCart,
|
||||
getLocalCartItemsCount
|
||||
getLocalCartItemsCount,
|
||||
clearLocalCart
|
||||
} = useLocalCart()
|
||||
|
||||
// Track previous login state to detect login events
|
||||
const prevIsLoginRef = useRef(isLogin)
|
||||
|
||||
// Get enriched product data for offline cart items
|
||||
const {
|
||||
enrichedCartItems,
|
||||
isLoading: isLoadingOfflineProducts
|
||||
} = useOfflineCartProducts(localCartItems)
|
||||
|
||||
// Sync local cart to server when user logs in
|
||||
useEffect(() => {
|
||||
const prevIsLogin = prevIsLoginRef.current
|
||||
prevIsLoginRef.current = isLogin
|
||||
|
||||
// Check if user just logged in and has local cart items
|
||||
if (!prevIsLogin && isLogin && localCartItems.length > 0) {
|
||||
// Add each local cart item to server cart
|
||||
const syncPromises = localCartItems.map(async (item) => {
|
||||
try {
|
||||
await updateCartMutation.mutateAsync({
|
||||
productId: item.productId,
|
||||
variantId: item.variantId,
|
||||
quantity: item.quantity
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Failed to sync cart item:', item, error)
|
||||
}
|
||||
})
|
||||
|
||||
// Clear local cart after sync attempt
|
||||
Promise.all(syncPromises).finally(() => {
|
||||
clearLocalCart()
|
||||
})
|
||||
}
|
||||
}, [isLogin, localCartItems, updateCartMutation, clearLocalCart])
|
||||
|
||||
const handleRemoveItem = async (productId: number, variantId: string) => {
|
||||
if (isLogin) {
|
||||
try {
|
||||
await removeFromCartMutation.mutateAsync({
|
||||
productId,
|
||||
variantId
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error removing item from cart:', error)
|
||||
}
|
||||
await removeFromCartMutation.mutateAsync({
|
||||
productId,
|
||||
variantId
|
||||
})
|
||||
} else {
|
||||
removeFromLocalCart(productId, variantId)
|
||||
}
|
||||
@@ -102,7 +131,16 @@ const Cart = () => {
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<div className='text-center py-4 text-gray-500'>سبد خرید شما خالی است</div>
|
||||
<div className='text-center py-4'>
|
||||
<div className='text-gray-500 mb-2'>
|
||||
{!isLogin ? 'سبد خرید شما خالی است' : 'سبد خرید شما خالی است'}
|
||||
</div>
|
||||
{!isLogin && (
|
||||
<div className='text-xs text-gray-400'>
|
||||
آیتمهای اضافه شده به سبد خرید در مرورگر شما ذخیره میشوند
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -114,6 +152,20 @@ const Cart = () => {
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{/* Login encouragement message for offline users */}
|
||||
{!isLogin && (
|
||||
<div className='mt-4 p-3 bg-blue-50 border border-blue-200 rounded-lg text-center'>
|
||||
<div className='text-xs text-blue-700 mb-2'>
|
||||
برای ذخیره سبد خرید و همگامسازی در همه دستگاهها، وارد حساب کاربری شوید
|
||||
</div>
|
||||
<Link href="/auth" className='inline-block'>
|
||||
<Button size="sm" variant="outline" className='text-blue-600 border-blue-300 hover:bg-blue-100'>
|
||||
ورود به حساب
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
@@ -133,7 +185,7 @@ const CartItemCard = ({
|
||||
// Handle both online and offline items with enriched data
|
||||
const productTitle = isOnline
|
||||
? (item as CartItemType).product.title_fa
|
||||
: (item as EnrichedOfflineCartItem).product?.title_fa || 'در حال بارگذاری...'
|
||||
: (item as EnrichedOfflineCartItem).product?.title_fa || 'در حال بارگذاری محصول...'
|
||||
|
||||
const productImage = isOnline
|
||||
? (item as CartItemType).product.imagesUrl.cover
|
||||
@@ -153,6 +205,7 @@ const CartItemCard = ({
|
||||
|
||||
// Check if product data is still loading for offline items
|
||||
const isProductLoading = !isOnline && !(item as EnrichedOfflineCartItem).product
|
||||
const hasError = !isOnline && !isProductLoading && !(item as EnrichedOfflineCartItem).variant
|
||||
|
||||
return (
|
||||
<div className='bg-white rounded-lg p-3 flex gap-3 shadow-sm border border-gray-100'>
|
||||
@@ -173,12 +226,14 @@ const CartItemCard = ({
|
||||
{productCategory}
|
||||
</div>
|
||||
<div className='text-sm text-gray-800 mb-2 line-clamp-2'>
|
||||
{isProductLoading ? 'در حال بارگذاری...' : productTitle}
|
||||
{hasError ? 'خطا در بارگذاری محصول' : isProductLoading ? 'در حال بارگذاری محصول...' : productTitle}
|
||||
</div>
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='text-sm font-semibold text-gray-900'>
|
||||
{isProductLoading ? (
|
||||
{hasError ? (
|
||||
`${quantity} عدد`
|
||||
) : isProductLoading ? (
|
||||
'در حال بارگذاری...'
|
||||
) : (
|
||||
`${NumberFormat(productPrice)} تومان`
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user