This commit is contained in:
2025-12-27 12:01:54 +07:00
parent e2063bce4c
commit 7606157d26
19 changed files with 259 additions and 37 deletions

View File

@@ -6,12 +6,12 @@ import { productCategoryData } from '@/data/product/category';
import { findCategoryBySlug } from '@/lib/product/category';
// box
import { Breadcrumb } from '@components/common/Breadcrumb';
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';
import ItemProduct from '@/components/Common/ItemProduct';
interface CategoryPageProps {
slug: string; // khai báo prop slug

View File

@@ -0,0 +1,86 @@
import { FaCheckSquare } from 'react-icons/fa';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Autoplay, Navigation, Pagination, Thumbs } from 'swiper/modules';
export const BoxBought = () => {
return (
<div className="pro-customer-bought">
<svg
className="pcb-icon"
viewBox="0 0 438.533 438.533"
width={16}
height={16}
fill="red"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d="M409.133,109.203c-19.608-33.592-46.205-60.189-79.798-79.796C295.736,9.801,259.058,0,219.273,0
c-39.781,0-76.47,9.801-110.063,29.407c-33.595,19.604-60.192,46.201-79.8,79.796C9.801,142.8,0,179.489,0,219.267
c0,39.78,9.804,76.463,29.407,110.062c19.607,33.592,46.204,60.189,79.799,79.798c33.597,19.605,70.283,29.407,110.063,29.407
s76.47-9.802,110.065-29.407c33.593-19.602,60.189-46.206,79.795-79.798c19.603-33.596,29.403-70.284,29.403-110.062
C438.533,179.485,428.732,142.795,409.133,109.203z M334.332,232.111L204.71,361.736c-3.617,3.613-7.896,5.428-12.847,5.428
c-4.952,0-9.235-1.814-12.85-5.428l-29.121-29.13c-3.617-3.613-5.426-7.898-5.426-12.847c0-4.941,1.809-9.232,5.426-12.847
l87.653-87.646l-87.657-87.65c-3.617-3.612-5.426-7.898-5.426-12.845c0-4.949,1.809-9.231,5.426-12.847l29.121-29.13
c3.619-3.615,7.898-5.424,12.85-5.424c4.95,0,9.233,1.809,12.85,5.424l129.622,129.621c3.613,3.614,5.42,7.898,5.42,12.847
C339.752,224.213,337.945,228.498,334.332,232.111z"
/>
</g>
</svg>
<div className="pcb-slider swiper-customer-bought">
<Swiper
modules={[Autoplay, Navigation, Pagination, Thumbs]}
spaceBetween={12}
slidesPerView={1}
loop={true}
autoplay={{
delay: 3000,
disableOnInteraction: false,
}}
>
<SwiperSlide>
<div>
<p>
<b>Khách hàng Anh Tuấn (036 856 xxxx)</b>
</p>
<p>Đã mua hàng 2 giờ trước</p>
</div>
</SwiperSlide>
<SwiperSlide>
<div>
<p>
<b>Khách hàng Quốc Trung (035 348 xxxx)</b>
</p>
<p>Đã mua hàng 1 giờ trước</p>
</div>
</SwiperSlide>
<SwiperSlide>
<div>
<p>
<b>Khách hàng Quang Ngọc (097 478 xxxx)</b>
</p>
<p>Đã mua hàng 30 phút trước</p>
</div>
</SwiperSlide>
<SwiperSlide>
<div>
<p>
<b>Khách hàng Mạnh Lực (037 204 xxxx)</b>
</p>
<p>Đã mua hàng 25 phút trước</p>
</div>
</SwiperSlide>
<SwiperSlide>
<div>
<p>
<b>Khách hàng Hiếu (096 859 xxxx)</b>
</p>
<p>Đã mua hàng 20 phút trước</p>
</div>
</SwiperSlide>
</Swiper>
</div>
</div>
);
};

View File

@@ -1,4 +1,6 @@
import type { ProductDetailData } from '@/types';
import CounDown from '@/components/Common/CounDown';
import { formatCurrency } from '@/lib/formatPrice';
export const BoxPrice = (item: ProductDetailData) => {
return (
@@ -9,10 +11,70 @@ export const BoxPrice = (item: ProductDetailData) => {
<i className="sprite sprite-flashsale-detail"></i>
<p className="title-deal font-weight-800">flash sale</p>
</div>
<div className="box-middle product-time-holder global-time-deal flex gap-2"></div>
<div className="box-right">
<div className="box-product-deal"></div>
<div className="box-middle product-time-holder global-time-deal flex gap-2">
<CounDown deadline={item.product_info.sale_rules.to_time} />
</div>
<div className="box-right">
<div className="box-product-deal">
<p className="text-deal-detail">
Còn{' '}
{(() => {
const deal = item.product_info.deal_list[0];
return Number(deal.quantity) - deal.sale_order;
})()}
/{item.product_info.deal_list[0].quantity} sản phẩm
</p>
<div className="p-quantity-sale" data-quantity-left="3" data-quantity-sale-total="5">
<i className="sprite sprite-fire-deal"></i>
<div className="bg-gradient"></div>
{(() => {
const deal = item.product_info.deal_list[0];
const percentRemaining =
((Number(deal.quantity) - deal.sale_order) / Number(deal.quantity)) * 100;
return (
<>
<p
className="js-line-deal-left"
style={{ width: `${percentRemaining}%` }}
></p>
</>
);
})()}
</div>
</div>
</div>
</div>
)}
{/* giá */}
{item.product_info.marketPrice > '0' && item.product_info.sale_rules.type == 'deal' && (
<div
className="box-price-detail boder-radius-10 flex flex-wrap items-center"
style={{ rowGap: '8px' }}
>
<p className="price-detail font-bold">
{item.product_info.price !== '0'
? `${formatCurrency(item.product_info.price)}đ`
: 'Liên hệ'}
</p>
{item.product_info.marketPrice > '0' && (
<>
<span className="market-price-detail font-weight-500">
{formatCurrency(item.product_info.marketPrice)}
</span>
<div className="save-price-detail flex items-center gap-1">
<span>Tiết kiệm</span>
{(() => {
return formatCurrency(
Number(item.product_info.marketPrice) - Number(item.product_info.price),
);
})()}
<span>đ</span>
</div>
</>
)}
</div>
)}
</>

View File

@@ -2,11 +2,14 @@ import type { ProductDetailData } from '@/types';
import Link from 'next/link';
import { BoxPrice } from './BoxPrice';
import { BoxBought } from './BoxBought';
export const BoxInfoRight = (item: ProductDetailData) => {
return (
<>
<h1 className="product-name color-black line-clamp-3">{item.product_info.productName}</h1>
<h1 className="product-name color-black line-clamp-3 font-bold">
{item.product_info.productName}
</h1>
<div className="list-basic-product-info flex flex-wrap items-center">
<div className="item-basic">
@@ -125,6 +128,31 @@ export const BoxInfoRight = (item: ProductDetailData) => {
</div>
</>
)}
{/* yên tâm mua hàng */}
<div className="box-product-policy-detal boder-radius-10" style={{ marginTop: '24px' }}>
<h2 className="title font-[600]">Yên tâm mua hàng</h2>
<div className="list-showroom-detail flex flex-wrap justify-between">
<div className="item flex items-center gap-2">
<i className="sprite sprite-camket-detail"></i>
<p>Cam kết giá tốt nhất thị trường.</p>
</div>
<div className="item flex items-center gap-2">
<i className="sprite sprite-sanphammoi-detail"></i>
<p>Sản phẩm mới 100%.</p>
</div>
<div className="item flex items-center gap-2">
<i className="sprite sprite-1doi1-detail"></i>
<p>Lỗi 1 đi 1 ngay lập tức.</p>
</div>
<div className="item flex items-center gap-2">
<i className="sprite sprite-hotrotragop-detail"></i>
<p>Hỗ trợ trả góp - Thủ tục nhanh gọn.</p>
</div>
</div>
</div>
<BoxBought />
</>
);
};

View File

@@ -4,9 +4,9 @@ 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 { ErrorLink } from '@/components/Common/error';
import { Breadcrumb } from '@components/common/Breadcrumb';
import { Breadcrumb } from '@/components/Common/Breadcrumb';
import { ImageProduct } from './ImageProduct';
import { ProductSummary } from './ProductSummary';
import { ComboSetBox } from './ComboSet';