update
This commit is contained in:
37
src/components/product/Category/BannerCategory/index.tsx
Normal file
37
src/components/product/Category/BannerCategory/index.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Autoplay, Navigation, Pagination } from 'swiper/modules';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { bannerData } from '@/data/banner';
|
||||
|
||||
const BannerCategory = () => {
|
||||
const dataSlider = bannerData[0].product_list;
|
||||
|
||||
return (
|
||||
<div className="box-banner-category">
|
||||
<Swiper
|
||||
modules={[Autoplay, Navigation, Pagination]}
|
||||
spaceBetween={12}
|
||||
slidesPerView={1}
|
||||
loop={true}
|
||||
>
|
||||
{dataSlider?.banner_category_2023?.map((banner, index) => (
|
||||
<SwiperSlide key={index}>
|
||||
<Link href={banner.desUrl} className="item-banner boder-radius-10">
|
||||
<Image
|
||||
src={banner.fileUrl}
|
||||
width={1909}
|
||||
height={57}
|
||||
alt={banner.title}
|
||||
priority={true}
|
||||
className="boder-radius-10"
|
||||
/>
|
||||
</Link>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BannerCategory;
|
||||
@@ -0,0 +1,67 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname, useSearchParams } from 'next/navigation';
|
||||
import { PriceFilter, AttributeFilterList, BrandFilter } from '@/types';
|
||||
import { FaXmark } from 'react-icons/fa6';
|
||||
|
||||
interface Filters {
|
||||
price_filter_list?: PriceFilter[];
|
||||
attribute_filter_list?: AttributeFilterList[];
|
||||
brand_filter_list?: BrandFilter[];
|
||||
current_category?: { url: string };
|
||||
}
|
||||
|
||||
const ActiveFilters: React.FC<{ filters: Filters }> = ({ filters }) => {
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const fullUrl = `${pathname}?${searchParams.toString()}`;
|
||||
|
||||
const selectedPrice = filters.price_filter_list?.filter((f) => fullUrl.includes(f.url)) ?? [];
|
||||
const selectedBrand = filters.brand_filter_list?.filter((f) => fullUrl.includes(f.url)) ?? [];
|
||||
const selectedAttr =
|
||||
filters.attribute_filter_list?.flatMap((attr) =>
|
||||
attr.value_list.filter((v) => pathname.includes(v.url)),
|
||||
) ?? [];
|
||||
|
||||
const allSelected = [...selectedPrice, ...selectedBrand, ...selectedAttr];
|
||||
const isFiltered = allSelected.length;
|
||||
|
||||
console.log(isFiltered);
|
||||
|
||||
if (isFiltered === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="info-filter-category flex gap-3">
|
||||
<p className="title">Lọc theo:</p>
|
||||
<div className="list-filter-category list-filter-active list-filter-last flex flex-wrap items-center gap-3">
|
||||
{selectedPrice.map((item) => (
|
||||
<Link key={item.url} href={item.url} className="item flex items-center gap-2 bg-white">
|
||||
{item.name} <FaXmark />
|
||||
</Link>
|
||||
))}
|
||||
{selectedBrand.map((item) => (
|
||||
<Link key={item.url} href={item.url} className="item flex items-center gap-2 bg-white">
|
||||
{item.name} <FaXmark />
|
||||
</Link>
|
||||
))}
|
||||
{selectedAttr.map((val) => (
|
||||
<Link key={val.url} href={val.url} className="item flex items-center gap-2 bg-white">
|
||||
{val.name} <FaXmark />
|
||||
</Link>
|
||||
))}
|
||||
|
||||
{isFiltered >= 1 && (
|
||||
<Link
|
||||
href={filters.current_category?.url ?? '#'}
|
||||
className="item delete-filter-all flex items-center gap-2 bg-white"
|
||||
>
|
||||
Xóa tất cả <FaXmark />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActiveFilters;
|
||||
106
src/components/product/Category/BoxFilter/index.tsx
Normal file
106
src/components/product/Category/BoxFilter/index.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { PriceFilter, AttributeFilterList, BrandFilter } from '@/types';
|
||||
import { FaSortDown } from 'react-icons/fa6';
|
||||
import ActiveFilters from './ActiveFilters';
|
||||
|
||||
interface Filters {
|
||||
price_filter_list?: PriceFilter[];
|
||||
attribute_filter_list?: AttributeFilterList[];
|
||||
brand_filter_list?: BrandFilter[];
|
||||
}
|
||||
|
||||
interface BoxFilterProps {
|
||||
filters: Filters;
|
||||
}
|
||||
|
||||
const BoxFilter: React.FC<BoxFilterProps> = ({ filters }) => {
|
||||
const { price_filter_list, attribute_filter_list, brand_filter_list } = filters;
|
||||
|
||||
return (
|
||||
<div className="box-filter-category boder-radius-10">
|
||||
{/* khoảng giá */}
|
||||
{price_filter_list && (
|
||||
<div className="info-filter-category flex gap-10">
|
||||
<p className="title">Khoảng giá:</p>
|
||||
<div className="list-filter-category flex flex-1 flex-wrap items-center gap-2">
|
||||
{price_filter_list.map((ItemPrice, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`item item-cetner flex gap-4 ${ItemPrice.is_selected == '1' ? 'current' : ''}`}
|
||||
>
|
||||
<Link href={ItemPrice.url}>{ItemPrice.name}</Link>
|
||||
<a href={ItemPrice.url}>
|
||||
(${ItemPrice.is_selected == '1' ? 'Xóa' : ItemPrice.count})
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* chọn thiêu tiêu trí */}
|
||||
{attribute_filter_list && (
|
||||
<div className="info-filter-category flex gap-10">
|
||||
<p className="title">Chọn theo tiêu chí:</p>
|
||||
<div className="list-filter-category flex flex-1 flex-wrap items-center gap-3">
|
||||
{/* thương hiệu */}
|
||||
{brand_filter_list && brand_filter_list.length > 0 && (
|
||||
<div className={`item ${brand_filter_list[0].is_selected === '1' ? 'current' : ''}`}>
|
||||
<div className="flex items-center">
|
||||
{brand_filter_list[0].is_selected === '1' ? (
|
||||
<span>{brand_filter_list[0].name}</span>
|
||||
) : (
|
||||
<span>Thương hiệu</span>
|
||||
)}
|
||||
<FaSortDown size={16} style={{ marginBottom: 8 }} />
|
||||
</div>
|
||||
<ul>
|
||||
{brand_filter_list.map((item, idx) => (
|
||||
<li key={idx} className="flex items-center gap-3">
|
||||
<Link href={item.url}>{item.name}</Link>
|
||||
<Link href={item.url}>({item.is_selected === '1' ? 'Xóa' : item.count})</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Attribute filter */}
|
||||
{attribute_filter_list && attribute_filter_list.length > 0 && (
|
||||
<>
|
||||
{attribute_filter_list.map((attr, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className={`item ${attr.value_list[0]?.is_selected === '1' ? 'current' : ''}`}
|
||||
>
|
||||
<a href="javascript:void(0)" className="flex items-center">
|
||||
{attr.value_list[0]?.is_selected === '1' ? (
|
||||
<span>{attr.value_list[0].name}</span>
|
||||
) : (
|
||||
<span>{attr.name}</span>
|
||||
)}
|
||||
<FaSortDown size={16} style={{ marginBottom: 8 }} />
|
||||
</a>
|
||||
<ul>
|
||||
{attr.value_list.map((val) => (
|
||||
<li key={val.id} className="flex items-center gap-3">
|
||||
<Link href={val.url}>{val.name}</Link>
|
||||
<Link href={val.url}>{val.is_selected === '1' ? 'Xóa' : val.count}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ActiveFilters filters={filters} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default BoxFilter;
|
||||
93
src/components/product/Category/BoxSort/index.tsx
Normal file
93
src/components/product/Category/BoxSort/index.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { FaGrip, FaList } from 'react-icons/fa6';
|
||||
|
||||
interface SortItem {
|
||||
key: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface SortProps {
|
||||
sort_by_collection: SortItem[];
|
||||
product_display_type?: 'grid' | 'list';
|
||||
}
|
||||
|
||||
const BoxSort: React.FC<SortProps> = ({ sort_by_collection, product_display_type }) => {
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<div className="box-sort-category flex items-center justify-between">
|
||||
<div className="sort-option flex items-center gap-3">
|
||||
{sort_by_collection
|
||||
.filter((item) =>
|
||||
['price-desc', 'price-asc', 'comment', 'rating', 'name'].includes(item.key),
|
||||
)
|
||||
.map((item) => {
|
||||
let label: string | null = null;
|
||||
let iconClass: string | null = null;
|
||||
|
||||
switch (item.key) {
|
||||
case 'price-desc':
|
||||
label = 'Giá giảm dần';
|
||||
iconClass = 'sprite-more sprite-gia-giam-category';
|
||||
break;
|
||||
case 'price-asc':
|
||||
label = 'Giá tăng dần';
|
||||
iconClass = 'sprite-more sprite-gia-tang-cateogry';
|
||||
break;
|
||||
case 'comment':
|
||||
label = 'Trao đổi';
|
||||
iconClass = 'sprite-more sprite-trao-doi-category';
|
||||
break;
|
||||
case 'rating':
|
||||
label = 'Đánh giá';
|
||||
iconClass = 'sprite-more sprite-danh-gia-category';
|
||||
break;
|
||||
case 'name':
|
||||
label = 'Tên A->Z';
|
||||
break;
|
||||
}
|
||||
return (
|
||||
<Link
|
||||
key={item.key}
|
||||
href={item.url}
|
||||
className={`item flex items-center ${
|
||||
pathname.includes(item.key) ? 'selected' : ''
|
||||
}`}
|
||||
>
|
||||
{iconClass && <i className={iconClass}></i>}
|
||||
<span>{label}</span>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="sort-bar-select-category flex items-center gap-3">
|
||||
<a
|
||||
href="javascript:;"
|
||||
className={`item-sort-bar d-flex align-items-center ${
|
||||
product_display_type === 'grid' ? 'active' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
window.location.reload();
|
||||
}}
|
||||
>
|
||||
<FaGrip />
|
||||
</a>
|
||||
<a
|
||||
href="javascript:;"
|
||||
className={`item-sort-bar ${product_display_type === 'list' ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
console.log('Set display to list');
|
||||
window.location.reload();
|
||||
}}
|
||||
>
|
||||
<FaList />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BoxSort;
|
||||
30
src/components/product/Category/ItemCategoryChild/index.tsx
Normal file
30
src/components/product/Category/ItemCategoryChild/index.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { ChildCategory } from '@/types';
|
||||
|
||||
interface BoxCategoryChildProps {
|
||||
item: ChildCategory;
|
||||
}
|
||||
|
||||
const ItemCategoryChild: React.FC<BoxCategoryChildProps> = ({ item }) => {
|
||||
const ItemImage = item.big_image
|
||||
? item.big_image
|
||||
: item.thumnail
|
||||
? item.thumnail
|
||||
: 'https://nguyencongpc.vn/static/assets/nguyencong_2023/images/favicon.png';
|
||||
|
||||
return (
|
||||
<li>
|
||||
<Link href={item.url}>
|
||||
<div className="border-img lazy flex items-center justify-center">
|
||||
<Image src={ItemImage} width={60} height={60} alt={item.title} />
|
||||
</div>
|
||||
<p className="txt font-weight-500">{item.title}</p>
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default ItemCategoryChild;
|
||||
124
src/components/product/Category/index.tsx
Normal file
124
src/components/product/Category/index.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import type { CategoryData } from '@/types';
|
||||
import { productCategoryData } from '@/data/product/category';
|
||||
import { findCategoryBySlug } from '@/lib/product/category';
|
||||
|
||||
// box
|
||||
import { Breadcrumb } from '@components/common/Breadcrumb';
|
||||
import BannerCategory from './BannerCategory';
|
||||
import ItemCategoryChild from './ItemCategoryChild';
|
||||
import BoxFilter from './BoxFilter';
|
||||
import BoxSort from './BoxSort';
|
||||
import ItemProduct from '@/components/common/ItemProduct';
|
||||
|
||||
interface CategoryPageProps {
|
||||
slug: string; // khai báo prop slug
|
||||
}
|
||||
|
||||
const CategoryPage: React.FC<CategoryPageProps> = ({ slug }) => {
|
||||
// Ép kiểu dữ liệu từ index.ts về CategoryData[]
|
||||
const categories = productCategoryData as unknown as CategoryData[];
|
||||
const currentCategory = findCategoryBySlug(slug, categories);
|
||||
|
||||
const breadcrumbItems = currentCategory?.current_category?.path?.path?.map((p) => ({
|
||||
name: p.name,
|
||||
url: p.url,
|
||||
})) ?? [
|
||||
{ name: 'Trang chủ', url: '/' },
|
||||
{ name: currentCategory?.current_category.name, url: currentCategory?.current_category.url },
|
||||
];
|
||||
// Trường hợp không tìm thấy danh mục
|
||||
if (!currentCategory) {
|
||||
return (
|
||||
<div className="flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100 py-50">
|
||||
<div className="max-w-md rounded-2xl bg-white p-8 text-center shadow-xl">
|
||||
<div className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-blue-100">
|
||||
<svg
|
||||
className="h-8 w-8 text-blue-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M9.172 9.172a4 4 0 015.656 5.656M6.343 6.343a8 8 0 0111.314 11.314M12 12l.01.01"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h1 className="text-2xl font-bold text-gray-800">Không tìm thấy danh mục</h1>
|
||||
|
||||
<p className="mt-3 text-gray-600">
|
||||
Đường dẫn <code className="rounded bg-gray-100 px-2 py-0.5 text-sm">{slug}</code> không
|
||||
tồn tại hoặc đã bị xoá.
|
||||
</p>
|
||||
|
||||
<Link
|
||||
href="/"
|
||||
className="mt-6 inline-flex items-center justify-center rounded-lg bg-blue-600 px-6 py-2.5 font-medium text-white transition hover:bg-blue-700 focus:ring-2 focus:ring-blue-400 focus:outline-none"
|
||||
>
|
||||
← Về trang chủ
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// lấy sản phẩm
|
||||
const products = Object.values(currentCategory.product_list);
|
||||
|
||||
return (
|
||||
<div className="page-category">
|
||||
<div className="container">
|
||||
<Breadcrumb items={breadcrumbItems} />
|
||||
|
||||
<BannerCategory />
|
||||
|
||||
<h1 className="name-category font-bold">{currentCategory.current_category.name}</h1>
|
||||
<div className="box-content-category">
|
||||
<ul className="category-child boder-radius-10 flex flex-wrap justify-center">
|
||||
{currentCategory.current_category.children?.map((item, index) => (
|
||||
<ItemCategoryChild item={item} key={index} />
|
||||
))}
|
||||
</ul>
|
||||
{/* filter */}
|
||||
<BoxFilter filters={currentCategory} />
|
||||
|
||||
<div className="box-list-product-category boder-radius-10">
|
||||
{/* filter sort */}
|
||||
<BoxSort
|
||||
sort_by_collection={currentCategory.sort_by_collection}
|
||||
product_display_type="grid"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* list product */}
|
||||
|
||||
<div className="list-product-category grid grid-cols-5 gap-3">
|
||||
{products.map((item, index) => (
|
||||
<ItemProduct key={index} item={item} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="paging flex items-center justify-center">
|
||||
{currentCategory.paging_collection.map((item, index) => (
|
||||
<Link
|
||||
key={index}
|
||||
href={item.url}
|
||||
className={`item ${item.is_active === '1' ? 'current' : ''}`}
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CategoryPage;
|
||||
77
src/components/product/ProductDetail/ImageProduct/index.tsx
Normal file
77
src/components/product/ProductDetail/ImageProduct/index.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Autoplay, Navigation, Pagination, Thumbs } from 'swiper/modules';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { ProductImageGallery } from '@/types';
|
||||
import type { Swiper as SwiperType } from 'swiper';
|
||||
import '@fancyapps/ui/dist/fancybox/fancybox.css';
|
||||
import { Fancybox, type FancyboxOptions } from '@fancyapps/ui';
|
||||
|
||||
interface ImageProps {
|
||||
ItemImage: ProductImageGallery[];
|
||||
}
|
||||
|
||||
export const ImageProduct: React.FC<ImageProps> = ({ ItemImage }) => {
|
||||
const [thumbsSwiper, setThumbsSwiper] = useState<SwiperType | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
Fancybox.bind("[data-fancybox='gallery']", {
|
||||
dragToClose: true,
|
||||
Toolbar: {
|
||||
display: {
|
||||
left: [],
|
||||
middle: ['counter'],
|
||||
right: ['zoom', 'close'],
|
||||
},
|
||||
},
|
||||
Thumbs: { autoStart: false },
|
||||
} as any);
|
||||
|
||||
return () => {
|
||||
Fancybox.unbind("[data-fancybox='gallery']");
|
||||
Fancybox.close();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="product-images-show">
|
||||
<div className="gallery-top product-info-image">
|
||||
<Swiper
|
||||
modules={[Autoplay, Navigation, Pagination, Thumbs]}
|
||||
spaceBetween={12}
|
||||
slidesPerView={1}
|
||||
loop={true}
|
||||
thumbs={{ swiper: thumbsSwiper }}
|
||||
>
|
||||
{ItemImage?.map((item, index) => (
|
||||
<SwiperSlide key={index}>
|
||||
<Link href={item.size.original} data-fancybox="gallery" className="bigImage">
|
||||
<Image src={item.size.original} alt={''} width="595" height="595" />
|
||||
</Link>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
<div className="gallery-thumbs product-images-slider mt-2">
|
||||
<Swiper
|
||||
modules={[Autoplay, Navigation, Pagination, Thumbs]}
|
||||
spaceBetween={12}
|
||||
slidesPerView={6}
|
||||
loop={true}
|
||||
onSwiper={setThumbsSwiper}
|
||||
>
|
||||
{ItemImage?.map((item, index) => (
|
||||
<SwiperSlide key={index}>
|
||||
<div className="smallImage">
|
||||
<Image src={item.size.original} alt={''} width="90" height="60" />
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
51
src/components/product/ProductDetail/index.tsx
Normal file
51
src/components/product/ProductDetail/index.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import type { ProductDetailData } from '@/types';
|
||||
import { productDetailData } from '@/data/product/detail';
|
||||
import { findProductDetailBySlug } from '@/lib/product/productdetail';
|
||||
import { ErrorLink } from '@components/common/error';
|
||||
|
||||
import { Breadcrumb } from '@components/common/Breadcrumb';
|
||||
import { ImageProduct } from './ImageProduct';
|
||||
|
||||
interface ProductDetailPageProps {
|
||||
slug: string;
|
||||
}
|
||||
|
||||
const ProductDetailPage: React.FC<ProductDetailPageProps> = ({ slug }) => {
|
||||
const productDetails = productDetailData as unknown as ProductDetailData[];
|
||||
const Products = findProductDetailBySlug(slug, productDetails);
|
||||
|
||||
const breadcrumbItems = Products?.product_info?.productPath?.[0]?.path.map((item) => ({
|
||||
name: item.name,
|
||||
url: item.url,
|
||||
})) ?? [{ name: 'Trang chủ', url: '/' }];
|
||||
|
||||
// Trường hợp không tìm thấy chi tiết sản phẩm
|
||||
// Không tìm thấy chi tiết sản phẩm
|
||||
if (!Products) {
|
||||
return <ErrorLink />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container">
|
||||
<Breadcrumb items={breadcrumbItems} />
|
||||
</div>
|
||||
<section className="page-product-detail mt-2 bg-white">
|
||||
<div className="container">
|
||||
<div className="box-content-product-detail flex justify-between gap-5">
|
||||
<div className="box-left">
|
||||
{/* image product */}
|
||||
<ImageProduct ItemImage={Products.product_info.productImageGallery} />
|
||||
</div>
|
||||
<div className="box-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductDetailPage;
|
||||
Reference in New Issue
Block a user