increable offers + fix bugs
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import { FC } from 'react'
|
||||
import { useGetLanding } from '../hooks/useHomeData'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
|
||||
const Banners3: FC = () => {
|
||||
|
||||
@@ -10,15 +11,21 @@ const Banners3: FC = () => {
|
||||
return (
|
||||
<div className='flex gap-4'>
|
||||
<div className='flex flex-col gap-2 h-full flex-1'>
|
||||
<div className='flex-1 h-full cursor-pointer' onClick={() => data?.results?.banners?.[1]?.linkUrl && window.open(data.results.banners[1].linkUrl, '_blank')}>
|
||||
<Image src={data?.results?.banners?.[1]?.imageUrl as string} height={500} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[1]?.altText as string} />
|
||||
<div className='flex-1 h-full'>
|
||||
<Link href={data?.results?.banners?.[1]?.linkUrl || '#'}>
|
||||
<Image src={data?.results?.banners?.[1]?.imageUrl as string} height={500} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className='flex-1 h-full cursor-pointer' onClick={() => data?.results?.banners?.[2]?.linkUrl && window.open(data.results.banners[2].linkUrl, '_blank')}>
|
||||
<Image src={data?.results?.banners?.[2]?.imageUrl as string} height={500} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[2]?.altText as string} />
|
||||
<div className='flex-1 h-full'>
|
||||
<Link href={data?.results?.banners?.[2]?.linkUrl || '#'}>
|
||||
<Image src={data?.results?.banners?.[2]?.imageUrl as string} height={500} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[2]?.altText as string} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-1 h-full cursor-pointer' onClick={() => data?.results?.banners?.[0]?.linkUrl && window.open(data.results.banners[0].linkUrl, '_blank')}>
|
||||
<Image src={data?.results?.banners?.[0]?.imageUrl as string} height={1000} width={1000} className='flex-1 rounded-lg h-full object-cover' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
<div className='flex-1 h-full'>
|
||||
<Link href={data?.results?.banners?.[0]?.linkUrl || '#'}>
|
||||
<Image src={data?.results?.banners?.[0]?.imageUrl as string} height={1000} width={1000} className='flex-1 rounded-lg h-full object-cover' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { FC } from 'react'
|
||||
import { useGetLanding } from '../hooks/useHomeData'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
|
||||
const Banners4: FC = () => {
|
||||
const { data } = useGetLanding()
|
||||
@@ -9,20 +10,28 @@ const Banners4: FC = () => {
|
||||
return (
|
||||
<div className='flex gap-6 h-[340px]'>
|
||||
<div className='flex-1 bg-primary/10 h-full rounded-[10px]'>
|
||||
<Image src={data?.results?.banners?.[3]?.imageUrl as string} height={340} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
<Link href={data?.results?.banners?.[3]?.linkUrl || '#'}>
|
||||
<Image src={data?.results?.banners?.[3]?.imageUrl as string} height={340} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className='w-[158px] flex flex-col gap-6'>
|
||||
<div className='w-[158px] h-[158px] rounded-[10px] bg-slate-100'>
|
||||
<Image src={data?.results?.banners?.[4]?.imageUrl as string} height={158} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
<Link href={data?.results?.banners?.[4]?.linkUrl || '#'}>
|
||||
<Image src={data?.results?.banners?.[4]?.imageUrl as string} height={158} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className='w-[158px] h-[158px] rounded-[10px] bg-slate-200'>
|
||||
<Image src={data?.results?.banners?.[5]?.imageUrl as string} height={158} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
<Link href={data?.results?.banners?.[5]?.linkUrl || '#'}>
|
||||
<Image src={data?.results?.banners?.[5]?.imageUrl as string} height={158} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='w-[400px] bg-amber-50'>
|
||||
<Image src={data?.results?.banners?.[6]?.imageUrl as string} height={400} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
<Link href={data?.results?.banners?.[6]?.linkUrl || '#'}>
|
||||
<Image src={data?.results?.banners?.[6]?.imageUrl as string} height={400} width={1000} className='flex-1 rounded-lg' alt={data?.results?.banners?.[0]?.altText as string} />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { FC, useState, useEffect } from 'react'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Pagination } from 'swiper/modules';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { useGetLanding } from '../hooks/useHomeData';
|
||||
|
||||
const Carousel: FC = () => {
|
||||
@@ -32,17 +33,25 @@ const Carousel: FC = () => {
|
||||
<Swiper pagination={true} modules={[Pagination]} className="mySwiper pb-5" style={{ zIndex: 0, position: 'relative' }}>
|
||||
{sliders.map((slider) => (
|
||||
<SwiperSlide key={slider._id}>
|
||||
<div
|
||||
className='h-[200px] sm:h-[300px] md:h-[400px] relative cursor-pointer'
|
||||
onClick={() => slider.linkUrl && window.open(slider.linkUrl, '_blank')}
|
||||
>
|
||||
<Image
|
||||
src={slider.imageUrl}
|
||||
alt={slider.altText}
|
||||
fill
|
||||
className="object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
{slider.linkUrl ? (
|
||||
<Link href={slider.linkUrl} className='block h-[200px] sm:h-[300px] md:h-[400px] relative'>
|
||||
<Image
|
||||
src={slider.imageUrl}
|
||||
alt={slider.altText}
|
||||
fill
|
||||
className="object-cover rounded-lg"
|
||||
/>
|
||||
</Link>
|
||||
) : (
|
||||
<div className='h-[200px] sm:h-[300px] md:h-[400px] relative'>
|
||||
<Image
|
||||
src={slider.imageUrl}
|
||||
alt={slider.altText}
|
||||
fill
|
||||
className="object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
|
||||
@@ -4,9 +4,19 @@ import ProductCard from '@/components/ProductCard'
|
||||
import Image from 'next/image'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
import { useGetLanding } from '../hooks/useHomeData'
|
||||
|
||||
|
||||
const HotOffer: FC = () => {
|
||||
|
||||
const { data } = useGetLanding()
|
||||
|
||||
const incredibleOffers = data?.results?.incredibleOffers || []
|
||||
|
||||
if (!incredibleOffers.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<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'>
|
||||
@@ -41,18 +51,11 @@ const HotOffer: FC = () => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SwiperSlide className='!w-auto'>
|
||||
<ProductCard />
|
||||
</SwiperSlide>
|
||||
<SwiperSlide className='!w-auto'>
|
||||
<ProductCard />
|
||||
</SwiperSlide>
|
||||
<SwiperSlide className='!w-auto'>
|
||||
<ProductCard />
|
||||
</SwiperSlide>
|
||||
<SwiperSlide className='!w-auto'>
|
||||
<ProductCard />
|
||||
</SwiperSlide>
|
||||
{incredibleOffers.map((product) => (
|
||||
<SwiperSlide key={product._id} className='!w-auto'>
|
||||
<ProductCard item={product} />
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import axios from "@/config/axios";
|
||||
import { SiteSettingResponse } from "@/app/privacy/types/Types";
|
||||
|
||||
export const getSiteSetting = async (name: string) => {
|
||||
const { data } = await axios.get(`/site-setting?name=${name}`);
|
||||
export const getSiteSetting = async (
|
||||
name: string
|
||||
): Promise<SiteSettingResponse> => {
|
||||
const params = new URLSearchParams();
|
||||
if (name !== "all") {
|
||||
params.append("name", name);
|
||||
}
|
||||
const { data } = await axios.get<SiteSettingResponse>(
|
||||
`/site-setting${params.toString() ? `?${params.toString()}` : ""}`
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
export interface DownloadAppDetail {
|
||||
pic: string;
|
||||
url: string;
|
||||
_id: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface SocialMediaLink {
|
||||
icon: string;
|
||||
url: string;
|
||||
_id: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface SiteSetting {
|
||||
_id: string;
|
||||
siteLogo: string;
|
||||
footerDescription: string;
|
||||
footerAddress: string;
|
||||
footerEmail: string;
|
||||
footerPhone: string;
|
||||
downloadAppDetails: DownloadAppDetail[];
|
||||
socialMediaLinks: SocialMediaLink[];
|
||||
shipmentContent: string;
|
||||
faqContent: string;
|
||||
policyContent: string;
|
||||
returnRulesContent: string;
|
||||
jobsContent: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SiteSettingResponse {
|
||||
status: number;
|
||||
success: boolean;
|
||||
results: {
|
||||
siteSetting: SiteSetting;
|
||||
};
|
||||
}
|
||||
@@ -1,21 +1,34 @@
|
||||
'use client'
|
||||
import { Star1 } from 'iconsax-react'
|
||||
import { FC, useEffect } from 'react'
|
||||
import { Product } from '@/types/product.types'
|
||||
import { FC, useEffect, useMemo } from 'react'
|
||||
import { Product, Review } from '@/types/product.types'
|
||||
import Image from 'next/image'
|
||||
import { clx } from '@/helpers/utils'
|
||||
import { useProductStore } from '../store/Store'
|
||||
|
||||
interface BaseInformationProps {
|
||||
product: Product
|
||||
reviews?: Review[]
|
||||
}
|
||||
|
||||
const BaseInformation: FC<BaseInformationProps> = ({ product }) => {
|
||||
const BaseInformation: FC<BaseInformationProps> = ({ product, reviews = [] }) => {
|
||||
|
||||
const { setVariantId, variantId } = useProductStore()
|
||||
|
||||
const brand = product.brand
|
||||
|
||||
// محاسبه میانگین امتیاز و تعداد دیدگاهها
|
||||
const { averageRating, reviewsCount } = useMemo(() => {
|
||||
if (!reviews.length) {
|
||||
return { averageRating: 0, reviewsCount: 0 }
|
||||
}
|
||||
const totalRating = reviews.reduce((sum, review) => sum + review.rating, 0)
|
||||
return {
|
||||
averageRating: Number((totalRating / reviews.length).toFixed(1)),
|
||||
reviewsCount: reviews.length
|
||||
}
|
||||
}, [reviews])
|
||||
|
||||
// تابع برای انتخاب variant
|
||||
const handleVariantSelect = (variantId: string) => {
|
||||
setVariantId(variantId)
|
||||
@@ -43,14 +56,28 @@ const BaseInformation: FC<BaseInformationProps> = ({ product }) => {
|
||||
{brand.title_fa}
|
||||
</h3>
|
||||
<div className='size-1.5 rounded-full bg-[#E5E5E5]'></div>
|
||||
<div className='flex items-center gap-1'>
|
||||
<button
|
||||
onClick={() => {
|
||||
const reviewsSection = document.getElementById('reviews-section')
|
||||
reviewsSection?.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
}}
|
||||
className='flex items-center gap-1 hover:opacity-80 transition-opacity cursor-pointer'
|
||||
>
|
||||
<Star1 size={16} color='#FFC107' variant='Bold' className='sm:w-5 sm:h-5' />
|
||||
<span className='text-xs sm:text-sm'>3.5</span>
|
||||
</div>
|
||||
<span className='text-xs sm:text-sm'>
|
||||
{reviewsCount > 0 ? `${averageRating} امتیاز` : '۰ امتیاز'}
|
||||
</span>
|
||||
</button>
|
||||
<div className='size-1.5 rounded-full bg-[#E5E5E5]'></div>
|
||||
<div className='text-primary text-xs sm:text-sm'>
|
||||
8 دیدگاه
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
const reviewsSection = document.getElementById('reviews-section')
|
||||
reviewsSection?.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
}}
|
||||
className='text-primary text-xs sm:text-sm hover:underline'
|
||||
>
|
||||
{reviewsCount} دیدگاه
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* نمایش variant ها */}
|
||||
|
||||
@@ -33,7 +33,7 @@ const Reviews: FC<ReviewsProps> = ({ reviews = [] }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-12 sm:mt-16 w-full">
|
||||
<div id="reviews-section" className="mt-12 sm:mt-16 w-full scroll-mt-20">
|
||||
<div className="flex items-center justify-end gap-3 flex-row-reverse">
|
||||
<h2 className="text-primary text-base sm:text-lg">نظرات خریداران</h2>
|
||||
<div className="w-1 h-6 bg-primary rounded"></div>
|
||||
|
||||
@@ -18,6 +18,7 @@ import Questions from '@/app/product/components/Questions'
|
||||
import { useGetDetailProduct } from '@/app/product/hooks/useProductData'
|
||||
import PageLoading from '@/components/PageLoading'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
|
||||
interface SingleProductProps {
|
||||
id: string
|
||||
@@ -42,7 +43,7 @@ const SingleProduct = ({ id }: SingleProductProps) => {
|
||||
<Breadcrumb aria-label="breadcrumb">
|
||||
<BreadcrumbList className="text-sm text-muted-foreground">
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">فروشگاه آناهیتا</BreadcrumbLink>
|
||||
<BreadcrumbLink href="/">{SHOP_CONFIG.fullName}</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
{categoryPath.map((category, index) => (
|
||||
<div key={category.id} className="flex items-center">
|
||||
@@ -51,7 +52,7 @@ const SingleProduct = ({ id }: SingleProductProps) => {
|
||||
{index === categoryPath.length - 1 ? (
|
||||
<BreadcrumbPage className="text-foreground">{category.title_fa}</BreadcrumbPage>
|
||||
) : (
|
||||
<BreadcrumbLink href={`/products?category=${category.id}`}>
|
||||
<BreadcrumbLink href={`/products/${category.title_en}`}>
|
||||
{category.title_fa}
|
||||
</BreadcrumbLink>
|
||||
)}
|
||||
@@ -68,7 +69,7 @@ const SingleProduct = ({ id }: SingleProductProps) => {
|
||||
<div className='flex-1 flex flex-col gap-6'>
|
||||
<div className='flex flex-col lg:flex-row gap-4 sm:gap-6'>
|
||||
<ProductImage product={product} />
|
||||
<BaseInformation product={product} />
|
||||
<BaseInformation product={product} reviews={reviews} />
|
||||
</div>
|
||||
<div>
|
||||
<Specifications product={product} />
|
||||
|
||||
@@ -21,6 +21,7 @@ import { useInfiniteCategoryProductsData } from '../hooks/useInfiniteProductsDat
|
||||
import { IProduct } from '@/types/landing.types'
|
||||
import { Product } from '@/types/products.types'
|
||||
import { useSearchParams, useParams } from 'next/navigation'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
|
||||
const Products: NextPage = () => {
|
||||
const [showMobileFilters, setShowMobileFilters] = useState(false)
|
||||
@@ -109,8 +110,19 @@ const Products: NextPage = () => {
|
||||
market_status: defaultVariant?.market_status || 'active',
|
||||
price: price,
|
||||
stock: defaultVariant?.stock || 0,
|
||||
postingTime: defaultVariant?.postingTime || 0,
|
||||
isFreeShip: defaultVariant?.isFreeShip || false,
|
||||
isWholeSale: defaultVariant?.isWholeSale || false
|
||||
isWholeSale: defaultVariant?.isWholeSale || false,
|
||||
shop: defaultVariant?.shop || { _id: '', shopName: '', shopDescription: '', logo: '' },
|
||||
shipmentMethod: defaultVariant?.shipmentMethod?.map(method => ({
|
||||
_id: method._id,
|
||||
name: method.name,
|
||||
description: method.description,
|
||||
deliveryTime: method.deliveryTime,
|
||||
deliveryType: method.deliveryType as "Standard" | "SameDay" | "Express"
|
||||
})) || [],
|
||||
warranty: defaultVariant?.warranty || { _id: 0, duration: '', logoUrl: '', name: '' },
|
||||
meterage: []
|
||||
},
|
||||
variants: (product.variants || []).map(variant => ({
|
||||
...variant,
|
||||
@@ -128,7 +140,7 @@ const Products: NextPage = () => {
|
||||
<Breadcrumb aria-label="breadcrumb">
|
||||
<BreadcrumbList className="text-sm text-muted-foreground">
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">فروشگاه آناهیتا</BreadcrumbLink>
|
||||
<BreadcrumbLink href="/">{SHOP_CONFIG.fullName}</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
{data?.pages?.[0]?.results.breadcrumb?.map((item, index) => (
|
||||
<div key={item._id} className="flex items-center">
|
||||
|
||||
@@ -30,10 +30,10 @@ const ProductCard: FC<Props> = ({ item }) => {
|
||||
if (!item?._id || !item?.variants[0]?._id) return
|
||||
|
||||
if (isWished) {
|
||||
removeWishlist({ productId: item._id.toString(), variantId: item.variants[0]._id })
|
||||
removeWishlist({ productId: String(item._id), variantId: item.variants[0]._id })
|
||||
setIsWished(false)
|
||||
} else {
|
||||
addWishlist({ productId: item._id.toString(), variantId: item.variants[0]._id })
|
||||
addWishlist({ productId: String(item._id), variantId: item.variants[0]._id })
|
||||
setIsWished(true)
|
||||
}
|
||||
}
|
||||
@@ -53,54 +53,24 @@ const ProductCard: FC<Props> = ({ item }) => {
|
||||
<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>
|
||||
{/* <div className='flex flex-wrap justify-end items-center gap-1.5 mt-4'>
|
||||
|
||||
{
|
||||
item.variants.map((variant) => {
|
||||
if (variant.meterage) {
|
||||
return <div className='text-[10px] px-4 border border-border rounded-lg whitespace-nowrap' key={variant._id}>{variant?.meterage?.value}</div>
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className='flex flex-wrap justify-end items-center gap-1.5 mt-4'>
|
||||
{
|
||||
item.variants.map((variant) => {
|
||||
if (variant.color) {
|
||||
return <div className='text-[10px] px-4 border border-border rounded-lg whitespace-nowrap' key={variant._id}>
|
||||
<div className='size-2 rounded-full' style={{ backgroundColor: variant?.color?.value }}></div>
|
||||
</div>
|
||||
}
|
||||
})
|
||||
}
|
||||
{
|
||||
item.variants.map((variant) => {
|
||||
if (variant.size) {
|
||||
return <div className='text-[10px] px-4 border border-border rounded-lg whitespace-nowrap' key={variant._id}>{variant?.size?.value}</div>
|
||||
}
|
||||
})
|
||||
}
|
||||
</div> */}
|
||||
|
||||
<div className='flex items-center justify-between mt-4 sm:mt-5'>
|
||||
<div className='flex flex-col gap-1'>
|
||||
<div className='text-xs sm:text-sm font-bold'>
|
||||
{item.default_variant.price.selling_price && item.default_variant.price.selling_price > 0
|
||||
{item?.default_variant?.price?.selling_price && item.default_variant.price.selling_price > 0
|
||||
? `${NumberFormat(item.default_variant.price.selling_price)} تومان`
|
||||
: 'بدون قیمت'
|
||||
}
|
||||
</div>
|
||||
{((item.default_variant.price.discount_percent > 0 && item.default_variant.price.selling_price > 0) ||
|
||||
(item.default_variant.price.is_specialSale && item.default_variant.price.selling_price > 0)) && (
|
||||
{((item?.default_variant?.price?.discount_percent > 0 && item.default_variant.price.selling_price > 0) ||
|
||||
(item?.default_variant?.price?.is_specialSale && item.default_variant.price.selling_price > 0)) && (
|
||||
<div className='text-xs sm:text-sm text-[#7F7F7F] line-through'>
|
||||
{NumberFormat(item.default_variant.price.retailPrice)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{((item.default_variant.price.discount_percent > 0 && item.default_variant.price.selling_price > 0) ||
|
||||
(item.default_variant.price.is_specialSale && item.default_variant.price.selling_price > 0)) && (
|
||||
{((item?.default_variant?.price?.discount_percent > 0 && item.default_variant.price.selling_price > 0) ||
|
||||
(item?.default_variant?.price?.is_specialSale && item.default_variant.price.selling_price > 0)) && (
|
||||
<div className='bg-red-500 text-white text-xs px-2 py-1 rounded-full'>
|
||||
{item.default_variant.price.discount_percent > 0
|
||||
? `${item.default_variant.price.discount_percent}%`
|
||||
|
||||
+69
-64
@@ -1,12 +1,17 @@
|
||||
'use client'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { Call, Instagram, Location, Sms, Youtube, Whatsapp } from 'iconsax-react'
|
||||
import { Call, Location, Sms } from 'iconsax-react'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { FC } from 'react'
|
||||
import { SHOP_CONFIG } from '@/config/const'
|
||||
import { useGetSiteSetting } from '@/app/privacy/hooks/usePrivacyData'
|
||||
|
||||
const Footer: FC = () => {
|
||||
|
||||
const { data: siteSetting } = useGetSiteSetting('all')
|
||||
|
||||
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'>
|
||||
@@ -15,31 +20,36 @@ const Footer: FC = () => {
|
||||
width={100}
|
||||
height={100}
|
||||
alt='logo'
|
||||
src='/images/logo.png'
|
||||
src={siteSetting?.results?.siteSetting?.siteLogo || '/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 dangerouslySetInnerHTML={{ __html: siteSetting?.results?.siteSetting?.footerDescription || '' }} className='mt-6 text-sm text-[#383E43] leading-6'>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div className='flex gap-3 mt-4'>
|
||||
<Sms color='#383E43' size={20} />
|
||||
<div>کدپستی: 1136834843</div>
|
||||
</div>
|
||||
<div className='flex gap-3 mt-4'>
|
||||
<Location color='#383E43' size={20} className='min-w-5' />
|
||||
<div className='leading-5'>
|
||||
تهران، میدان امام خمینی، خیابان فردوسی، خیابان سرهنگ سخائی
|
||||
نبش کوچه بهنیا، پلاک40، طبقه چهارم، واحد12
|
||||
{siteSetting?.results?.siteSetting?.footerPhone && (
|
||||
<div className='flex gap-3'>
|
||||
<Call color='#383E43' size={20} />
|
||||
<div>تلفن: {siteSetting.results.siteSetting.footerPhone}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{siteSetting?.results?.siteSetting?.footerEmail && (
|
||||
<div className='flex gap-3 mt-4'>
|
||||
<Sms color='#383E43' size={20} />
|
||||
<div>ایمیل: {siteSetting.results.siteSetting.footerEmail}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{siteSetting?.results?.siteSetting?.footerAddress && (
|
||||
<div className='flex gap-3 mt-4'>
|
||||
<Location color='#383E43' size={20} className='min-w-5' />
|
||||
<div className='leading-5'>
|
||||
{siteSetting.results.siteSetting.footerAddress}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -48,31 +58,26 @@ const Footer: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-1'>
|
||||
<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] text-sm sm:text-base font-light'>
|
||||
دانلود اپلیکیشن
|
||||
{siteSetting?.results?.siteSetting?.downloadAppDetails && siteSetting.results.siteSetting.downloadAppDetails.length > 0 && (
|
||||
<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] text-sm sm:text-base font-light'>
|
||||
دانلود اپلیکیشن
|
||||
</div>
|
||||
<div className='flex gap-2 flex-wrap'>
|
||||
{siteSetting.results.siteSetting.downloadAppDetails.map((app) => (
|
||||
<Link key={app.id} href={app.url} target="_blank" rel="noopener noreferrer">
|
||||
<Image
|
||||
width={132}
|
||||
height={48}
|
||||
alt='download app'
|
||||
src={app.pic}
|
||||
className='size-10 object-contain'
|
||||
/>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex gap-2 flex-wrap'>
|
||||
<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>
|
||||
)}
|
||||
|
||||
<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 font-light'>
|
||||
@@ -90,29 +95,29 @@ const Footer: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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 font-light'>
|
||||
ما را در شبکه های اجتماعی دنبال کنید
|
||||
</div>
|
||||
{siteSetting?.results?.siteSetting?.socialMediaLinks && siteSetting.results.siteSetting.socialMediaLinks.length > 0 && (
|
||||
<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 font-light'>
|
||||
ما را در شبکه های اجتماعی دنبال کنید
|
||||
</div>
|
||||
|
||||
<div className='flex gap-1.5'>
|
||||
<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 className='flex gap-1.5'>
|
||||
{siteSetting.results.siteSetting.socialMediaLinks.map((social) => (
|
||||
<Link key={social.id} href={social.url} target="_blank" rel="noopener noreferrer">
|
||||
<div className='size-10 bg-[#878787] hover:bg-primary rounded-full flex justify-center items-center transition-colors'>
|
||||
<Image
|
||||
src={social.icon}
|
||||
alt='social media'
|
||||
width={20}
|
||||
height={20}
|
||||
className='w-5 h-5 object-contain brightness-0 invert'
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</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>
|
||||
|
||||
+49
-12
@@ -1,8 +1,27 @@
|
||||
export interface IShop {
|
||||
_id: string;
|
||||
shopName: string;
|
||||
shopDescription: string;
|
||||
logo: string;
|
||||
shopName?: string;
|
||||
shopDescription?: string;
|
||||
logo?: string;
|
||||
}
|
||||
|
||||
export interface IBrand {
|
||||
_id: string;
|
||||
status: string;
|
||||
title_en: string;
|
||||
title_fa: string;
|
||||
images: string[];
|
||||
logoUrl: string;
|
||||
}
|
||||
|
||||
export interface ISize {
|
||||
_id: number;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface ISpecification {
|
||||
title: string;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
export interface IPrice {
|
||||
@@ -21,8 +40,14 @@ export interface IDefaultVariant {
|
||||
market_status: string;
|
||||
price: IPrice;
|
||||
stock: number;
|
||||
postingTime: number;
|
||||
isFreeShip: boolean;
|
||||
isWholeSale: boolean;
|
||||
shop: IShop;
|
||||
shipmentMethod: IShipmentMethod[];
|
||||
warranty: IWarranty;
|
||||
size?: ISize;
|
||||
meterage: IMeterage[];
|
||||
}
|
||||
|
||||
export interface IShipmentMethod {
|
||||
@@ -70,18 +95,27 @@ export interface IProduct {
|
||||
_id: number;
|
||||
title_fa: string;
|
||||
title_en: string;
|
||||
seoTitle: string | null;
|
||||
seoDescription: string | null;
|
||||
model: string;
|
||||
source?: string;
|
||||
seoTitle?: string | null;
|
||||
seoDescription?: string | null;
|
||||
metaDescription?: string;
|
||||
model?: string;
|
||||
description: string;
|
||||
tags: string[];
|
||||
shop: IShop;
|
||||
status: string;
|
||||
advantages?: string[];
|
||||
disAdvantages?: string[];
|
||||
shop?: IShop;
|
||||
status?: string;
|
||||
imagesUrl: IImagesUrl;
|
||||
url: string;
|
||||
url?: string;
|
||||
isFake?: string;
|
||||
voice?: string | null;
|
||||
specifications?: ISpecification[];
|
||||
brand?: IBrand;
|
||||
category?: ICategory;
|
||||
default_variant: IDefaultVariant;
|
||||
variants: IVariant[];
|
||||
isWishlist: boolean;
|
||||
variants: (IVariant | { _id: string })[];
|
||||
isWishlist?: boolean;
|
||||
}
|
||||
|
||||
export interface ICategory {
|
||||
@@ -91,7 +125,10 @@ export interface ICategory {
|
||||
icon: string;
|
||||
imageUrl: string;
|
||||
description: string;
|
||||
url: string;
|
||||
theme?: string;
|
||||
leaf?: boolean;
|
||||
parent?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface ISlider {
|
||||
|
||||
Reference in New Issue
Block a user