update
This commit is contained in:
@@ -703,7 +703,7 @@ export const menuData: MenuTypes = [
|
||||
"big_image": "https://nguyencongpc.vn\/media\/category\/cat_big_3638_1696996039.png",
|
||||
"isParent": "0",
|
||||
"url": "\/rtx-4070",
|
||||
"is_featured": "1",
|
||||
"is_featured": "0",
|
||||
"summary": "<p> <\/p>\r\n<div id=\"eJOY__extension_root\" class=\"eJOY__extension_root_class\" style=\"all: unset;\"> <\/div>",
|
||||
"children": []
|
||||
},
|
||||
|
||||
0
src/components/layout/home/BoxArticle/index.tsx
Normal file
0
src/components/layout/home/BoxArticle/index.tsx
Normal file
83
src/components/layout/home/BoxCategory/ItemProduct.tsx
Normal file
83
src/components/layout/home/BoxCategory/ItemProduct.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import Tippy from '@tippyjs/react';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
import { Product } from '@/types/TypeListProduct';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
|
||||
type ProductItemProps = {
|
||||
item: Product;
|
||||
};
|
||||
|
||||
const formatCurrency = (value: number | string) => {
|
||||
const num = typeof value === 'string' ? parseInt(value) : value;
|
||||
return num.toLocaleString('vi-VN');
|
||||
};
|
||||
|
||||
const ItemProduct: React.FC<ProductItemProps> = ({ item }) => {
|
||||
const offers = item.specialOffer?.all ?? [];
|
||||
|
||||
return (
|
||||
<div className="product-item js-p-item">
|
||||
<a href={item.productUrl} className="product-image relative">
|
||||
{item.productImage.large ? (
|
||||
<Image src={item.productImage.large} width="203" height="203" alt={item.productName} />
|
||||
) : (
|
||||
<Image src="https://nguyencongpc.vn/static/assets/nguyencong_2023/images/not-image.png" alt={item.productName} />
|
||||
)}
|
||||
|
||||
<span className="p-type-holder">
|
||||
{item.productType.isHot === 1 && (
|
||||
<i className="p-icon-type p-icon-hot"></i>
|
||||
)}
|
||||
{item.productType.isNew === 1 && (
|
||||
<i className="p-icon-type p-icon-new"></i>
|
||||
)}
|
||||
</span>
|
||||
|
||||
<span className="p-type-holder p-type-holder-2">
|
||||
{item.productType.isBestSale === 1 && (
|
||||
<i className="p-icon-type p-icon-best-sale"></i>
|
||||
)}
|
||||
</span>
|
||||
</a>
|
||||
<div className="product-info">
|
||||
<Link href={item.productUrl}>
|
||||
<h3 className="product-title line-clamp-3">{item.productName}</h3>
|
||||
</Link>
|
||||
{item.marketPrice > 0 ? (
|
||||
<div className="product-martket-main flex items-center">
|
||||
<p className="product-market-price">
|
||||
{item.marketPrice.toLocaleString()}<u>đ</u>
|
||||
</p>
|
||||
<div className="product-percent-price">-{Math.round(item.price_off)} %</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="product-martket-main flex items-center">
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="product-price-main font-[600]">
|
||||
{item.price > '0'
|
||||
? `${formatCurrency(item.price)}đ`
|
||||
: 'Liên hệ'}
|
||||
</div>
|
||||
{item.specialOffer?.all?.length ? (
|
||||
<div className="product-offer line-clamp-2"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: item.specialOffer!.all![0].title,
|
||||
}} />
|
||||
) : (
|
||||
<div className="product-offer line-clamp-2"></div>
|
||||
)}
|
||||
|
||||
{item.extend?.buy_count ? (
|
||||
<div style={{ height: 18 }}> <b>Đã bán: </b> <span>{item.extend.buy_count}</span> </div>
|
||||
) : (
|
||||
<div style={{ height: 18, display: 'block' }}> </div> )}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ItemProduct;
|
||||
56
src/components/layout/home/BoxCategory/index.tsx
Normal file
56
src/components/layout/home/BoxCategory/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { FaCaretDown } from 'react-icons/fa';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Autoplay, Navigation, Pagination } from 'swiper/modules';
|
||||
import ItemProduct from './ItemProduct'
|
||||
|
||||
import { Category } from '../../../../types/Menu';
|
||||
|
||||
|
||||
import { menuData } from '../../Header/menuData';
|
||||
import {productData} from './productData'
|
||||
|
||||
const BoxListCategory: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
{menuData[0].product.all_category.map((item,index) => (
|
||||
<div className="box-product-category boder-radius-10" key={index}>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="title">
|
||||
<h2 className="title-box font-[600]">{item.title}</h2>
|
||||
</div>
|
||||
<div className="list-category-child flex items-center justify-end flex-1">
|
||||
|
||||
{item.children.slice(0, 4).map((item2,index2) => (
|
||||
<Link key={index2} href={item2.url} className="title-category">{item2.title}</Link>
|
||||
))}
|
||||
|
||||
<Link href={item.url} className="title-all-category flex items-center gap-2">
|
||||
<span>Xem tất cả </span>
|
||||
<FaCaretDown size={16} /></Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="box-list-item-category swiper-product-category">
|
||||
<Swiper
|
||||
modules={[Autoplay, Navigation, Pagination]}
|
||||
spaceBetween={12}
|
||||
slidesPerView={5}
|
||||
loop={true}
|
||||
navigation={true}
|
||||
>
|
||||
{productData.map((item,index) => (
|
||||
<SwiperSlide key={index}>
|
||||
<ItemProduct item={item} />
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default BoxListCategory
|
||||
2161
src/components/layout/home/BoxCategory/productData.ts
Normal file
2161
src/components/layout/home/BoxCategory/productData.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +1,101 @@
|
||||
const ProductItem = ({ item }: { item: Product }) => {};
|
||||
import React from 'react';
|
||||
import Tippy from '@tippyjs/react';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
import { DealType } from '@/types/TypeListProductDeal';
|
||||
|
||||
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;
|
||||
|
||||
@@ -4,6 +4,8 @@ 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 (
|
||||
@@ -28,7 +30,13 @@ const BoxProductDeal: React.FC = () => {
|
||||
slidesPerView={6}
|
||||
loop={true}
|
||||
navigation={true}
|
||||
></Swiper>
|
||||
>
|
||||
{productDealData.map((item,index) => (
|
||||
<SwiperSlide key={index}>
|
||||
<ProductItem item={item} />
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ export const productDealData: TypeListProductDeal = [
|
||||
"priceUnit": "chiếc",
|
||||
"marketPrice": 0,
|
||||
"price": "11690000",
|
||||
"price_off": "",
|
||||
"price_off": 2,
|
||||
"currency": "vnd",
|
||||
"sale_rules": {
|
||||
"price": "11690000",
|
||||
@@ -1422,7 +1422,7 @@ export const productDealData: TypeListProductDeal = [
|
||||
},
|
||||
"comment": {
|
||||
"rate": 5,
|
||||
"total": 3
|
||||
"total": 3,
|
||||
},
|
||||
"quantity": 1,
|
||||
"productSKU": "",
|
||||
|
||||
29
src/components/layout/home/CategoryFeature/index.tsx
Normal file
29
src/components/layout/home/CategoryFeature/index.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import { menuData } from '../../Header/menuData';
|
||||
import ItemCategory from './itemCategory';
|
||||
import { Category } from '../../../../types/Menu';
|
||||
|
||||
const renderFeaturedCategories = (categories: Category[]) => {
|
||||
return categories.map((cat, idx) => (
|
||||
<React.Fragment key={idx}>
|
||||
{cat.is_featured == '1' && <ItemCategory item={cat} />}
|
||||
{cat.children && renderFeaturedCategories(cat.children)}
|
||||
</React.Fragment>
|
||||
));
|
||||
};
|
||||
|
||||
const CategoryFeature = () => {
|
||||
return (
|
||||
<div className="box-category-outstanding boder-radius-10">
|
||||
<div className="title-box">
|
||||
<h2 className="title title-box font-[600]">Danh mục nổi bật</h2>
|
||||
</div>
|
||||
<div className="list-category-outstanding grid grid-cols-10 gap-3">
|
||||
{renderFeaturedCategories(menuData[0].product.all_category)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CategoryFeature;
|
||||
34
src/components/layout/home/CategoryFeature/itemCategory.tsx
Normal file
34
src/components/layout/home/CategoryFeature/itemCategory.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { Category } from '@types/Menu';
|
||||
|
||||
const ItemCategory: React.FC<{ item: Category }> = ({ item }) => {
|
||||
return (
|
||||
<Link href={item.url} className="item-category flex flex-col items-center">
|
||||
<p className="item-category-img">
|
||||
{item.thumnail ? (
|
||||
<Image
|
||||
src={item.thumnail}
|
||||
width={50}
|
||||
height={50}
|
||||
alt={item.title}
|
||||
className="swiper-lazy lazy"
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
src="https://nguyencongpc.vn/static/assets/nguyencong_2023/images/not-image.png"
|
||||
width={50}
|
||||
height={50}
|
||||
alt={item.title}
|
||||
className="border-radius-10"
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
<p className="title line-clamp-2">{item.title}</p>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default ItemCategory;
|
||||
@@ -1,6 +1,9 @@
|
||||
import React from 'react';
|
||||
import SliderHome from './SliderHome';
|
||||
import BoxProductDeal from './BoxDeal';
|
||||
import CategoryFeature from './CategoryFeature';
|
||||
import BoxListCategory from './BoxCategory';
|
||||
|
||||
const Home = () => {
|
||||
return (
|
||||
<div className="page-hompage mt-4">
|
||||
@@ -9,6 +12,11 @@ const Home = () => {
|
||||
<SliderHome />
|
||||
{/* deal */}
|
||||
<BoxProductDeal />
|
||||
{/* box danh mục nổi bật */}
|
||||
<CategoryFeature />
|
||||
|
||||
{/* DANH SÁCH DANH MỤC */}
|
||||
<BoxListCategory />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user