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 LastPost from '../components/LastPost'
|
||||||
import { NextPage } from 'next'
|
import { NextPage } from 'next'
|
||||||
import Layout from '@/hoc/Layout'
|
import Layout from '@/hoc/Layout'
|
||||||
|
import { SHOP_CONFIG } from '@/config/const'
|
||||||
|
|
||||||
const BlogDetail: NextPage = () => {
|
const BlogDetail: NextPage = () => {
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto px-4 py-8">
|
<div className="max-w-7xl mx-auto px-4 py-8">
|
||||||
{/* Breadcrumb */}
|
{/* Breadcrumb */}
|
||||||
<div className="text-sm text-gray-500 mb-6">
|
<div className="text-sm text-gray-500 mb-6">
|
||||||
فروشگاه سندس طلا / راهنما ها / تست اقلام و قطعات / گلکسی بوک
|
فروشگاه {SHOP_CONFIG.name} / راهنما ها / تست اقلام و قطعات / گلکسی بوک
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-8">
|
<div className="flex gap-8">
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { NextPage } from 'next'
|
import { NextPage } from 'next'
|
||||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
|
||||||
import Layout from '@/hoc/Layout'
|
import Layout from '@/hoc/Layout'
|
||||||
|
import { SHOP_CONFIG } from '@/config/const'
|
||||||
|
|
||||||
const FaqPage: NextPage = () => {
|
const FaqPage: NextPage = () => {
|
||||||
const faqData = [
|
const faqData = [
|
||||||
@@ -15,8 +16,8 @@ const FaqPage: NextPage = () => {
|
|||||||
answer: "این خطا معمولاً زمانی رخ میدهد که شماره ملی قبلاً در سیستم ثبت شده است. در صورت اطمینان از صحت اطلاعات، با پشتیبانی تماس بگیرید."
|
answer: "این خطا معمولاً زمانی رخ میدهد که شماره ملی قبلاً در سیستم ثبت شده است. در صورت اطمینان از صحت اطلاعات، با پشتیبانی تماس بگیرید."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "برای ثبت نام در سندس کالا به چه مدارکی نیاز است؟",
|
question: `برای ثبت نام در ${SHOP_CONFIG.fullName} به چه مدارکی نیاز است؟`,
|
||||||
answer: "برای ثبت نام در سندس کالا نیاز به مدارک شناسایی، مجوزهای کسب و کار و اطلاعات بانکی معتبر دارید."
|
answer: `برای ثبت نام در ${SHOP_CONFIG.fullName} نیاز به مدارک شناسایی، مجوزهای کسب و کار و اطلاعات بانکی معتبر دارید.`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "نام تجاری به چه معناست ؟",
|
question: "نام تجاری به چه معناست ؟",
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import ProductCard from '@/components/ProductCard'
|
import ProductCard from '@/components/ProductCard'
|
||||||
import Image from 'next/image'
|
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 = () => {
|
const HotOffer: FC = () => {
|
||||||
@@ -14,7 +15,8 @@ const HotOffer: FC = () => {
|
|||||||
<br />
|
<br />
|
||||||
داغ
|
داغ
|
||||||
<br />
|
<br />
|
||||||
سندس
|
{SHOP_CONFIG.name}
|
||||||
|
<br />
|
||||||
کالا
|
کالا
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-4 sm:mt-6 flex justify-center'>
|
<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 BASE_URL = "http://192.168.1.111:4000";
|
||||||
|
|
||||||
export const PRIMARY_COLOR = "#DA2129";
|
export const PRIMARY_COLOR = "#DA2129";
|
||||||
|
|
||||||
|
// تنظیمات فروشگاه
|
||||||
|
export const SHOP_CONFIG = {
|
||||||
|
name: "فجر مرکزی", // نام فروشگاه - میتوان آن را تغییر داد
|
||||||
|
fullName: "تابلو فجر مرکزی", // نام کامل فروشگاه
|
||||||
|
};
|
||||||
|
|||||||
+92
-36
@@ -1,14 +1,24 @@
|
|||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Separator } from '@/components/ui/separator'
|
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 Image from 'next/image'
|
||||||
|
import Link from 'next/link'
|
||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
|
import { SHOP_CONFIG } from '@/config/const'
|
||||||
|
|
||||||
const Footer: FC = () => {
|
const Footer: FC = () => {
|
||||||
return (
|
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='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 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 className='mt-6 text-sm text-[#383E43] '>
|
||||||
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده
|
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده
|
||||||
</div>
|
</div>
|
||||||
@@ -43,20 +53,24 @@ const Footer: FC = () => {
|
|||||||
دانلود اپلیکیشن
|
دانلود اپلیکیشن
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap-2 flex-wrap'>
|
<div className='flex gap-2 flex-wrap'>
|
||||||
<Image
|
<Link href="https://apps.apple.com/app/id123456789" target="_blank" rel="noopener noreferrer">
|
||||||
width={132}
|
<Image
|
||||||
height={48}
|
width={132}
|
||||||
alt='download from app store'
|
height={48}
|
||||||
src='/images/appstore.png'
|
alt='download from app store'
|
||||||
className='w-24 sm:w-[132px] h-auto'
|
src='/images/appstore.png'
|
||||||
/>
|
className='w-24 sm:w-[132px] h-auto hover:opacity-80 transition-opacity'
|
||||||
<Image
|
/>
|
||||||
width={142}
|
</Link>
|
||||||
height={48}
|
<Link href="https://play.google.com/store/apps/details?id=com.danak.shop" target="_blank" rel="noopener noreferrer">
|
||||||
alt='download from google play'
|
<Image
|
||||||
src='/images/googleplay.png'
|
width={142}
|
||||||
className='w-24 sm:w-[142px] h-auto'
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -82,41 +96,83 @@ const Footer: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex gap-1.5'>
|
<div className='flex gap-1.5'>
|
||||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center'>
|
<Link href="https://instagram.com/danakshop" target="_blank" rel="noopener noreferrer">
|
||||||
<Instagram size={20} color='#fff' />
|
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center transition-colors'>
|
||||||
</div>
|
<Instagram size={20} color='#fff' />
|
||||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center'>
|
</div>
|
||||||
<Instagram size={20} color='#fff' />
|
</Link>
|
||||||
</div>
|
<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'>
|
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center transition-colors'>
|
||||||
<Instagram size={20} color='#fff' />
|
<Whatsapp size={20} color='#fff' />
|
||||||
</div>
|
</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>
|
</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 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 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'>
|
<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>
|
||||||
<li className='text-[#878787] text-sm sm:text-base'>درباره سندس کالا</li>
|
<Link href="/contact" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||||
<li className='text-[#878787] text-sm sm:text-base'>فروش در سندس کالا</li>
|
تماس با ما
|
||||||
|
</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<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'>
|
<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>
|
||||||
<li className='text-[#878787] text-sm sm:text-base'>قوانین مرجوعی کالا</li>
|
<Link href="/faq" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||||
<li className='text-[#878787] text-sm sm:text-base'>پاسخ به پرسش ها متداول</li>
|
نحوه ثبت سفارش
|
||||||
|
</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className='text-sm sm:text-base font-medium'>خدمات مشتریان</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'>
|
<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>
|
||||||
<li className='text-[#878787] text-sm sm:text-base'>سبد خرید</li>
|
<Link href="/profile" className='text-[#878787] hover:text-primary transition-colors text-sm sm:text-base'>
|
||||||
<li className='text-[#878787] text-sm sm:text-base'>حریم حصوصی</li>
|
حساب کاربری من
|
||||||
|
</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+49
-17
@@ -1,7 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import Input from '@/components/Input'
|
import Input from '@/components/Input'
|
||||||
|
import MenuItem from '@/components/MenuItem'
|
||||||
import { Separator } from '@/components/ui/separator'
|
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 { 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'
|
||||||
@@ -86,14 +87,34 @@ const Header: FC = () => {
|
|||||||
<Menu />
|
<Menu />
|
||||||
<Separator style={{ height: 20 }} orientation='vertical' />
|
<Separator style={{ height: 20 }} orientation='vertical' />
|
||||||
|
|
||||||
<div className='flex items-center gap-2.5 cursor-pointer hover:text-purple-600 transition-colors'>
|
<MenuItem
|
||||||
<Home size={20} color='#333333' />
|
icon={<Home size={20} color='#333333' />}
|
||||||
<div className='text-[#333333]'>صفحه نخست</div>
|
title="صفحه نخست"
|
||||||
</div>
|
href="/"
|
||||||
<div className='flex items-center gap-2.5 cursor-pointer hover:text-purple-600 transition-colors'>
|
/>
|
||||||
<DocumentText size={20} color='#333333' />
|
<MenuItem
|
||||||
<div className='text-[#333333]'>مجله</div>
|
icon={<DocumentText size={20} color='#333333' />}
|
||||||
</div>
|
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>
|
</div>
|
||||||
|
|
||||||
{/* منوی موبایل */}
|
{/* منوی موبایل */}
|
||||||
@@ -106,14 +127,25 @@ const Header: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='space-y-3'>
|
<div className='space-y-3'>
|
||||||
<div className='flex items-center gap-3 py-2 cursor-pointer hover:bg-gray-50 rounded-lg px-2'>
|
<MenuItem
|
||||||
<Home size={20} color='#333333' />
|
icon={<Home size={20} />}
|
||||||
<span className='text-sm text-gray-800'>صفحه نخست</span>
|
title="صفحه نخست"
|
||||||
</div>
|
href="/"
|
||||||
<div className='flex items-center gap-3 py-2 cursor-pointer hover:bg-gray-50 rounded-lg px-2'>
|
className="py-2 hover:bg-gray-50 rounded-lg px-2"
|
||||||
<DocumentText size={20} color='#333333' />
|
/>
|
||||||
<span className='text-sm text-gray-800'>مجله</span>
|
<MenuItem
|
||||||
</div>
|
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>
|
||||||
|
|
||||||
<div className='pt-4 border-t border-gray-100'>
|
<div className='pt-4 border-t border-gray-100'>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover"
|
} 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 { useRemoveFromCart } from '@/app/cart/hooks/useCartData'
|
||||||
import { CartItemType } from '@/app/cart/types/Types'
|
import { CartItemType } from '@/app/cart/types/Types'
|
||||||
import { LocalCartItem } from '@/app/product/store/LocalCartStore'
|
import { LocalCartItem } from '@/app/product/store/LocalCartStore'
|
||||||
@@ -18,35 +18,64 @@ import { Button } from '@/components/ui/button'
|
|||||||
import { useSharedStore } from '@/share/store/sharedStore'
|
import { useSharedStore } from '@/share/store/sharedStore'
|
||||||
import { useLocalCart } from '@/app/product/hooks/useLocalCart'
|
import { useLocalCart } from '@/app/product/hooks/useLocalCart'
|
||||||
import { useOfflineCartProducts, EnrichedOfflineCartItem } from '@/share/hooks/useOfflineCartProducts'
|
import { useOfflineCartProducts, EnrichedOfflineCartItem } from '@/share/hooks/useOfflineCartProducts'
|
||||||
|
import { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
const Cart = () => {
|
const Cart = () => {
|
||||||
const { isLogin } = useSharedStore()
|
const { isLogin } = useSharedStore()
|
||||||
const { data: cartData, isLoading } = useGetCart()
|
const { data: cartData, isLoading } = useGetCart()
|
||||||
const removeFromCartMutation = useRemoveFromCart()
|
const removeFromCartMutation = useRemoveFromCart()
|
||||||
|
const updateCartMutation = useUpdateCart()
|
||||||
|
|
||||||
// Local cart hooks for offline users
|
// Local cart hooks for offline users
|
||||||
const {
|
const {
|
||||||
localCartItems,
|
localCartItems,
|
||||||
removeFromLocalCart,
|
removeFromLocalCart,
|
||||||
getLocalCartItemsCount
|
getLocalCartItemsCount,
|
||||||
|
clearLocalCart
|
||||||
} = useLocalCart()
|
} = useLocalCart()
|
||||||
|
|
||||||
|
// Track previous login state to detect login events
|
||||||
|
const prevIsLoginRef = useRef(isLogin)
|
||||||
|
|
||||||
// Get enriched product data for offline cart items
|
// Get enriched product data for offline cart items
|
||||||
const {
|
const {
|
||||||
enrichedCartItems,
|
enrichedCartItems,
|
||||||
isLoading: isLoadingOfflineProducts
|
isLoading: isLoadingOfflineProducts
|
||||||
} = useOfflineCartProducts(localCartItems)
|
} = 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) => {
|
const handleRemoveItem = async (productId: number, variantId: string) => {
|
||||||
if (isLogin) {
|
if (isLogin) {
|
||||||
try {
|
await removeFromCartMutation.mutateAsync({
|
||||||
await removeFromCartMutation.mutateAsync({
|
productId,
|
||||||
productId,
|
variantId
|
||||||
variantId
|
})
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error removing item from cart:', error)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
removeFromLocalCart(productId, variantId)
|
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>
|
</div>
|
||||||
|
|
||||||
@@ -114,6 +152,20 @@ const Cart = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</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>
|
</div>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
@@ -133,7 +185,7 @@ const CartItemCard = ({
|
|||||||
// Handle both online and offline items with enriched data
|
// Handle both online and offline items with enriched data
|
||||||
const productTitle = isOnline
|
const productTitle = isOnline
|
||||||
? (item as CartItemType).product.title_fa
|
? (item as CartItemType).product.title_fa
|
||||||
: (item as EnrichedOfflineCartItem).product?.title_fa || 'در حال بارگذاری...'
|
: (item as EnrichedOfflineCartItem).product?.title_fa || 'در حال بارگذاری محصول...'
|
||||||
|
|
||||||
const productImage = isOnline
|
const productImage = isOnline
|
||||||
? (item as CartItemType).product.imagesUrl.cover
|
? (item as CartItemType).product.imagesUrl.cover
|
||||||
@@ -153,6 +205,7 @@ const CartItemCard = ({
|
|||||||
|
|
||||||
// Check if product data is still loading for offline items
|
// Check if product data is still loading for offline items
|
||||||
const isProductLoading = !isOnline && !(item as EnrichedOfflineCartItem).product
|
const isProductLoading = !isOnline && !(item as EnrichedOfflineCartItem).product
|
||||||
|
const hasError = !isOnline && !isProductLoading && !(item as EnrichedOfflineCartItem).variant
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='bg-white rounded-lg p-3 flex gap-3 shadow-sm border border-gray-100'>
|
<div className='bg-white rounded-lg p-3 flex gap-3 shadow-sm border border-gray-100'>
|
||||||
@@ -173,12 +226,14 @@ const CartItemCard = ({
|
|||||||
{productCategory}
|
{productCategory}
|
||||||
</div>
|
</div>
|
||||||
<div className='text-sm text-gray-800 mb-2 line-clamp-2'>
|
<div className='text-sm text-gray-800 mb-2 line-clamp-2'>
|
||||||
{isProductLoading ? 'در حال بارگذاری...' : productTitle}
|
{hasError ? 'خطا در بارگذاری محصول' : isProductLoading ? 'در حال بارگذاری محصول...' : productTitle}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<div className='text-sm font-semibold text-gray-900'>
|
<div className='text-sm font-semibold text-gray-900'>
|
||||||
{isProductLoading ? (
|
{hasError ? (
|
||||||
`${quantity} عدد`
|
`${quantity} عدد`
|
||||||
|
) : isProductLoading ? (
|
||||||
|
'در حال بارگذاری...'
|
||||||
) : (
|
) : (
|
||||||
`${NumberFormat(productPrice)} تومان`
|
`${NumberFormat(productPrice)} تومان`
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user