update
This commit is contained in:
57
src/components/home/Deal/CounDown/index.tsx
Normal file
57
src/components/home/Deal/CounDown/index.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
'use client';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
const CounDown: React.FC = () => {
|
||||
const [days, setDays] = useState(0);
|
||||
const [hours, setHours] = useState(0);
|
||||
const [minutes, setMinutes] = useState(0);
|
||||
const [seconds, setSeconds] = useState(0);
|
||||
|
||||
const deadline: Date = new globalThis.Date('2025-12-31');
|
||||
|
||||
const getTime = () => {
|
||||
const time = deadline.getTime() - Date.now();
|
||||
|
||||
setDays(Math.floor(time / (1000 * 60 * 60 * 24)));
|
||||
setHours(Math.floor((time / (1000 * 60 * 60)) % 24));
|
||||
setMinutes(Math.floor((time / 1000 / 60) % 60));
|
||||
setSeconds(Math.floor((time / 1000) % 60));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => getTime(), 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex items-center gap-2">
|
||||
<p> {days < 10 ? '0' + days : days} </p> <span>:</span>
|
||||
</div>
|
||||
<span className="blocl mt-1 text-sm">Ngày</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex items-center gap-2">
|
||||
<p>{hours < 10 ? '0' + hours : hours} </p> <span>:</span>
|
||||
</div>
|
||||
<span className="blocl mt-1 text-sm">Giờ</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex items-center gap-2">
|
||||
<p>{minutes < 10 ? '0' + minutes : minutes} </p> <span>:</span>
|
||||
</div>
|
||||
<span className="blocl mt-1 text-sm">Phút</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex items-center gap-2">
|
||||
<p>{seconds < 10 ? '0' + seconds : seconds} </p>
|
||||
</div>
|
||||
<span className="blocl mt-1 text-sm">Giây</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CounDown;
|
||||
83
src/components/home/Deal/ProductItem/index.tsx
Normal file
83
src/components/home/Deal/ProductItem/index.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import Tippy from '@tippyjs/react';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
import { DealType } from '@/types';
|
||||
|
||||
type ProductItemProps = {
|
||||
item: DealType;
|
||||
};
|
||||
|
||||
const formatCurrency = (value: number | string) => {
|
||||
const num = typeof value === 'string' ? parseInt(value) : value;
|
||||
return num.toLocaleString('vi-VN');
|
||||
};
|
||||
|
||||
const ProductItem: React.FC<ProductItemProps> = ({ item }) => {
|
||||
const { product_info } = item;
|
||||
const offers = product_info.specialOffer?.all ?? [];
|
||||
|
||||
return (
|
||||
<div className="product-item">
|
||||
<a href={product_info.productUrl} className="product-image relative">
|
||||
{product_info.productImage.large ? (
|
||||
<img
|
||||
src={product_info.productImage.large}
|
||||
width="164"
|
||||
height="164"
|
||||
alt={product_info.productName}
|
||||
className="lazy"
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
src="/static/assets/nguyencong_2023/images/not-image.png"
|
||||
width="164"
|
||||
height="164"
|
||||
alt={product_info.productName}
|
||||
className="lazy"
|
||||
/>
|
||||
)}
|
||||
<span className="p-type-holder">
|
||||
{product_info.productType.isHot === 1 && <i className="p-icon-type p-icon-hot"></i>}
|
||||
{product_info.productType.isNew === 1 && <i className="p-icon-type p-icon-new"></i>}
|
||||
</span>
|
||||
</a>
|
||||
<div className="product-info">
|
||||
<a href={product_info.productUrl}>
|
||||
<h3 className="product-title line-clamp-3">{product_info.productName}</h3>
|
||||
</a>
|
||||
<div className="product-martket-main flex items-center">
|
||||
{product_info.marketPrice > 0 ? (
|
||||
<p className="product-market-price">{product_info.marketPrice.toLocaleString()} ₫</p>
|
||||
) : (
|
||||
<p className="product-market-price">
|
||||
{product_info.sale_rules.normal_price.toLocaleString()} ₫
|
||||
</p>
|
||||
)}
|
||||
<div className="product-percent-price">-{product_info.price_off || 0}%</div>
|
||||
</div>
|
||||
<div className="product-price-main font-bold">
|
||||
{item.price > '0' ? `${formatCurrency(product_info.price)}đ` : 'Liên hệ'}
|
||||
</div>
|
||||
<div className="p-quantity-sale">
|
||||
<i className="sprite sprite-fire-deal"></i>
|
||||
<div className="bg-gradient"></div>
|
||||
<p className="js-line-deal-left"></p>
|
||||
<span>
|
||||
Còn {Number(item.quantity) - Number(item.sale_quantity)}/{Number(item.quantity)} sản
|
||||
phẩm
|
||||
</span>
|
||||
</div>
|
||||
{offers.length > 0 && (
|
||||
<div
|
||||
className="product-offer line-clamp-2"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: product_info.specialOffer!.all![0].title,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductItem;
|
||||
45
src/components/home/Deal/index.tsx
Normal file
45
src/components/home/Deal/index.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Autoplay, Navigation, Pagination } from 'swiper/modules';
|
||||
import { FaCaretRight } from 'react-icons/fa';
|
||||
import CounDown from './CounDown';
|
||||
import ProductItem from './ProductItem';
|
||||
import { productDealData } from './productDealData';
|
||||
|
||||
const BoxProductDeal: React.FC = () => {
|
||||
return (
|
||||
<div className="box-product-deal boder-radius-10">
|
||||
<div className="box-title-deal flex items-center justify-between">
|
||||
<div className="title-deal flex items-center justify-center gap-10">
|
||||
<i className="sprite sprite-icon-deal-home"></i>
|
||||
<h2 className="title font-bold">Giá tốt mỗi ngày</h2>
|
||||
<span className="text-time-deal-home color-white fz-16 font-bold">Kết thúc sau</span>
|
||||
<div className="global-time-deal flex items-center gap-2">
|
||||
<CounDown />
|
||||
</div>
|
||||
</div>
|
||||
<a href="/deal" className="button-deal color-white mb-10 flex items-center">
|
||||
Xem thêm khuyến mãi <FaCaretRight size={16} />
|
||||
</a>
|
||||
</div>
|
||||
<div className="box-list-item-deal swiper-box-deal">
|
||||
<Swiper
|
||||
modules={[Autoplay, Navigation, Pagination]}
|
||||
spaceBetween={12}
|
||||
slidesPerView={6}
|
||||
loop={true}
|
||||
navigation={true}
|
||||
>
|
||||
{productDealData.map((item, index) => (
|
||||
<SwiperSlide key={index}>
|
||||
<ProductItem item={item} />
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BoxProductDeal;
|
||||
1664
src/components/home/Deal/productDealData.ts
Normal file
1664
src/components/home/Deal/productDealData.ts
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user