update 03/02

This commit is contained in:
2026-02-03 17:20:38 +07:00
parent 6318621cc0
commit 332cb5da14
19 changed files with 1092 additions and 1023 deletions

View File

@@ -0,0 +1,19 @@
import Link from "next/link";
export default function EmptyCart() {
return (
<div className="text-center px-3">
<div className="mb-4">
<img src="images/cart-empty.png" className="block m-auto" />
</div>
<p className="mt-10 mb-6 text-20 font-600">
Không sản phẩm nào trong giỏ hàng của bạn !
</p>
<Link href="/"
className="inline-flex items-center bg-btn text-white leading-[52px] font-500 text-18 rounded-[50px] px-6"
>
VỀ TRANG CHỦ <i className="bx bx-arrow-up-right-stroke text-30" />
</Link>
</div>
)
}

View File

@@ -1,210 +1,64 @@
import { CartData } from "@/data/cart"
import EmptyCart from "./EmptyCart";
import Form from "../form";
import CartItem from "@/components/shared/CartItem"
import { formatPrice } from "@/lib/utils";
export default function Home() { export default function Home() {
console.log(CartData);
const hasCart = CartData.data.length;
if (hasCart == 0 ) {
return <EmptyCart />
}
return ( return (
<div className="cart-page container"> <div className="cart-page container">
<div className="text-center px-3"> <h1 className="text-[#004BA4] leading-10 text-[32px] font-600 mb-6"> Giỏ hàng của tôi </h1>
<div className="mb-4">
<img src="images/cart-empty.png" className="block m-auto" />
</div>
<p className="mt-10 mb-6 text-20 font-600">
{" "}
Không sản phẩm nào trong giỏ hàng của bạn !
</p>
<a
href="/"
className="inline-flex items-center bg-btn text-white leading-[52px] font-500 text-18 rounded-[50px] px-6"
>
{" "}
VỀ TRANG CHỦ <i className="bx bx-arrow-up-right-stroke text-30" />{" "}
</a>
</div>
<h1 className="text-[#004BA4] leading-10 text-[32px] font-600 mb-6">
{" "}
Giỏ hàng của tôi{" "}
</h1>
<div className="lg:flex flex-wrap items-start justify-between gap-6"> <div className="lg:flex flex-wrap items-start justify-between gap-6">
<div className="col-left w-[calc(100%-464px)]"> <div className="col-left w-[calc(100%-464px)]">
<div className="hidden lg:flex flex-wrap items-center justify-between gap-4 bg-white rounded-[12px] mb-3 py-3 px-4 lg:text-[16px] font-500 leading-10"> <div className="hidden lg:flex flex-wrap items-center justify-between gap-4 bg-white rounded-[12px] mb-3 py-3 px-4 lg:text-[16px] font-500 leading-10">
<p className="m-0 text-16 lg:text-[18px]"> 5 sản phẩm </p> <p className="m-0 text-16 lg:text-[18px]"> {hasCart} sản phẩm </p>
<button
type="button" <button type="button" aria-label="Xóa sản phẩm"
className="h-10 border border-[#0678DB] bg-white rounded-[40px] text-[#0678DB] px-6 transition-all duration-100 hover:bg-[#0678DB] hover:text-white" className="h-10 border border-[#0678DB] bg-white rounded-[40px] text-[#0678DB] px-6 transition-all duration-100 hover:bg-[#0678DB] hover:text-white"
aria-label="Xóa sản phẩm" > LÀM TRỐNG GIỎ HÀNG </button>
>
{" "}
LÀM TRỐNG GIỎ HÀNG{" "}
</button>
</div> </div>
<div className="bg-white rounded-[16px] lg:rounded-[12px] mb-3 p-4"> <div className="bg-white rounded-[16px] lg:rounded-[12px] mb-3 p-4">
<div className="cart-item mb-5 last:mb-0"> { CartData.data.map((item:any) =>
<a href="" className="item-img"> <CartItem item={item} key={item.item_id} />
{" "} )}
<img src="images/product-5.jpg" />{" "}
</a>
<div className="item-text">
<div className="item-name">
<a
href=""
className="table uppercase font-500 lg:text-[16px] text-12"
>
HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX 3060 12GB
</a>
<div className="group mt-2 table">
<p className="m-0 text-[#0678DB] font-500 cursor-pointer">
<span> Chi tiết khuyến mại </span>
<i className="bx bx-chevron-down text-[#A0A5AC] text-16 align-middle transition-all group-hover:rotate-[-180deg]" />
</p>
<div className="item-offer group-hover:opacity-100 group-hover:z-[5] group-hover:visible">
<div className="item">
<p>
<span style={{ fontSize: "12pt", color: "#ff0000" }}>
<strong> Tặng Balo Laptop Hoàng PC</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ fontSize: "12pt", color: "#ff0000" }}>
<strong> Tặng Chuột không dây</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ fontSize: "12pt", color: "#ff0000" }}>
<strong> Tặng Bàn di chuột</strong>
</span>
</p>
</div>
</div>
</div>
</div>
<div className="item-quantiy">
<button
type="button"
className="js-quantity-change bx bx-minus"
/>
<input
type="number"
defaultValue={1}
min={1}
data-stock={998}
pattern="[0-9]*"
inputMode="numeric"
className="js-buy-quantity js-quantity-change text-center"
/>
<button type="button" className="js-quantity-change bx bx-plus" />
</div>
<div className="item-price text-right lg:text-left">
<p className="text-[#FF4E2A] font-bold mb-0 lg:mb-1 lg:text-[16px] lg:leading-5 text-13 leading-4">
{" "}
42.000.000 đ{" "}
</p>
<del className="block text-[#A0A5AC] lg:text-[13px] lg:leading-4 text-10 leading-3">
{" "}
52.000.000 đ{" "}
</del>
</div>
<button
type="button"
className="item-delete bx bx-trash w-8 h-8 lg:w-10 lg:h-10 rounded-full border border-[#E7D9D9] bg-[#F8F3F3] text-[#BE1F2D] text-16 lg:text-[20px] hover:text-white hover:bg-[#BE1F2D] hover:border-transparent"
/>
</div>
</div>
</div> </div>
<div className="bg-white p-4 lg:pt-5 rounded-[16px] lg:rounded-[12px]"> <div className="bg-white p-4 lg:pt-5 rounded-[16px] lg:rounded-[12px]">
<p className="font-600 text-16 lg:text-[18px] mb-2 lg:mb-4 leading-5 lg:leading-6"> <p className="font-600 text-16 lg:text-[18px] mb-2 lg:mb-4 leading-5 lg:leading-6">
{" "} Thông tin đơn hàng
Thông tin đơn hàng{" "}
</p> </p>
<div className="flex items-center justify-between gap-3 border-b border-[#D2DAE3] border-dashed pb-4 mb-3 lg:mb-5 leading-5 lg:leading-6 lg:text-[16px]"> <div className="flex items-center justify-between gap-3 border-b border-[#D2DAE3] border-dashed pb-4 mb-3 lg:mb-5 leading-5 lg:leading-6 lg:text-[16px]">
<p className="m-0"> Tổng tiền </p> <p className="m-0"> Tổng tiền </p>
<p className="m-0 font-500 text-15 lg:text-[18px]"> 50.000.000 đ </p> <p className="m-0 font-500 text-15 lg:text-[18px]">
{formatPrice(CartData.cart_summary.total_value)} đ
</p>
</div> </div>
<div className="flex items-center justify-between gap-3 leading-5 lg:leading-6"> <div className="flex items-center justify-between gap-3 leading-5 lg:leading-6">
<p className="m-0 flex items-center gap-2"> <p className="m-0 flex items-center gap-2">
<i className="bx bxs-credit-card-alt text-20 text-[#B5BAC1]" /> <i className="bx bxs-credit-card-alt text-20 text-[#B5BAC1]" />
<span> Tổng thanh toán </span> <span> Tổng thanh toán </span>
</p> </p>
<p className="m-0 text-16 text-[#FF4E2A] font-bold lg:text-[20px]"> <p className="m-0 text-16 text-[#FF4E2A] font-bold lg:text-[20px]">
{" "} {formatPrice(CartData.cart_summary.total_value)} <u>đ</u>
41.450.000 <u>đ</u>{" "}
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<form className="col-right w-[440px] bg-white rounded-[16px] px-5 py-6 sticky top-[90px] z-[1] shadow-[0px_4px_20px_0px_#0615070D] lg:shadow-[none]">
<p className="font-600 text-18 text-[#004BA4] leading-6 mb-1">
{" "}
Thông tin nhận hàng{" "}
</p>
<div className="leading-[18px] text-[#474747] mb-4">
Đ tiếp tục đt hàng, quý khách xin vui lòng
<button
type="button"
aria-label="Đăng nhập"
className="font-500 text-[#0678DB]"
>
{" "}
đăng nhập{" "}
</button>
hoặc nhập thông tin bên dưới. vấn viên sẽ liên hệ theo thông tin bạn
cung cấp đ xác nhận, không mua không sao
</div>
<div>
<input
type="text"
id=""
className="block w-full h-[50px] mb-4 border border-transparent rounded-[12px] bg-[#F3F3F3] px-4"
placeholder="Họ và tên"
/>
<input
type="tel"
id=""
className="block w-full h-[50px] mb-4 border border-transparent rounded-[12px] bg-[#F3F3F3] px-4"
inputMode="numeric"
pattern="[0-9]{10,11}"
maxLength={11}
placeholder="Số điện thoại"
/>
<input
type="email"
id=""
className="block w-full h-[50px] mb-4 border border-transparent rounded-[12px] bg-[#F3F3F3] px-4"
maxLength={254}
placeholder="Nhập email"
/>
<input
type="text"
id=""
className="block w-full h-[50px] mb-2 border border-transparent rounded-[12px] bg-[#F3F3F3] px-4"
placeholder="Địa chỉ nhận hàng"
/>
<p className="text-[#757575] mb-4">
{" "}
<i className="bx bx-info-circle text-16 text-[#0678DB] mr-1 align-text-top" />{" "}
<span> Nhập Số nhà, Đưng, Phường/, Quận, Tỉnh </span>{" "}
</p>
<textarea
id=""
className="block w-full h-[112px] mb-4 border border-transparent rounded-[12px] bg-[#F3F3F3] px-4 pt-[12px] resize-none outline-none"
placeholder="Ghi chú"
defaultValue={""}
/>
</div>
<div className="red font-600 my-4"> </div>
<div className="mt-5">
<button
type="submit"
className="block w-full bg-btn text-white h-[52px] rounded-[50px] font-500 text-18"
>
{" "}
ĐT HÀNG{" "}
</button>
</div>
</form>
</div>
</div>
<Form />
</div>
</div>
) )
} }

View File

@@ -1,5 +1,7 @@
import Link from "next/link";
export default function SendCart() { export default function SendCart() {
return( return (
<div className="max-w-[656px] m-auto my-10"> <div className="max-w-[656px] m-auto my-10">
<div> <div>
<img <img
@@ -10,14 +12,13 @@ export default function SendCart() {
className="block m-auto w-auto h-auto" className="block m-auto w-auto h-auto"
/> />
<h1 className="mt-10 mb-5 font-600 text-center text-[40px] text-[#004BA4] leading-12"> <h1 className="mt-10 mb-5 font-600 text-center text-[40px] text-[#004BA4] leading-12">
{" "} Bạn đã đt hàng thành công
Bạn đã đt hàng thành công{" "}
</h1> </h1>
<div className="text-justify lg:text-[18px] lg:leading-6"> <div className="text-justify lg:text-[18px] lg:leading-6">
<p className="mb-4"> <p className="mb-4">
Chúng tôi vừa nhận được đơn đặt hàng của quý khách trên website Chúng tôi vừa nhận được đơn đặt hàng của quý khách trên website
HOANGHAPC <br /> HOANGHAPC <br />
Đơn hàng này đang đưc xử . Trong vòng{" "} Đơn hàng này đang đưc xử . Trong vòng
<b className="font-600"> 30 phút (giờ làm việc) </b>, bộ phận bán hàng <b className="font-600"> 30 phút (giờ làm việc) </b>, bộ phận bán hàng
trực tuyến sẽ liên hệ lại Quý khách đ xác nhận thời gian đa điểm trực tuyến sẽ liên hệ lại Quý khách đ xác nhận thời gian đa điểm
giao hàng. giao hàng.
@@ -28,13 +29,13 @@ export default function SendCart() {
vời. vời.
</p> </p>
<div className="text-center"> <div className="text-center">
<a <Link
href="/" href="/"
className="inline-flex items-center bg-btn text-white leading-[52px] font-500 text-18 rounded-[50px] px-6" className="inline-flex items-center bg-btn text-white leading-[52px] font-500 text-18 rounded-[50px] px-6"
> >
{" "}
VỀ TRANG CHỦ <i className="bx bx-arrow-up-right-stroke text-30" />{" "} VỀ TRANG CHỦ <i className="bx bx-arrow-up-right-stroke text-30" />
</a> </Link>
</div> </div>
</div> </div>
</div> </div>
@@ -42,9 +43,9 @@ export default function SendCart() {
<i className="bx bx-x-circle text-[red] text-[110px]" /> <i className="bx bx-x-circle text-[red] text-[110px]" />
<p className="font-bold text-20 mt-5"> lỗi xảy ra khi gửi đơn hàng </p> <p className="font-bold text-20 mt-5"> lỗi xảy ra khi gửi đơn hàng </p>
<p className="mb-4"> <p className="mb-4">
{" "}
Đơn hàng của quý khách chưa đưc gửi. Vui lòng quay lại giỏ hàng đ thử Đơn hàng của quý khách chưa đưc gửi. Vui lòng quay lại giỏ hàng đ thử
gửi lại hoặc liên hệ với chúng tôi đ đưc trợ giúp.{" "} gửi lại hoặc liên hệ với chúng tôi đ đưc trợ giúp.
</p> </p>
<p className="mb-4"> Cảm ơn quý khách !</p> <p className="mb-4"> Cảm ơn quý khách !</p>
</div> </div>

View File

@@ -0,0 +1,206 @@
'use client';
import { useState } from "react";
import { useRouter } from 'next/navigation';
import Link from "next/link";
type FormType = {
name: string;
phone: string;
email: string;
address: string;
note: string;
};
type ErrorType = {
name?: string;
phone?: string;
email?: string;
address?: string;
};
export default function Form() {
const router = useRouter();
const [form, setForm] = useState<FormType>({
name: "",
phone: "",
email: "",
address: "",
note: ""
});
const [ errors, setErrors ] = useState<ErrorType>({});
const [ submit, setSubmit ] = useState(false);
// =========================
// Handle change
// =========================
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const { name, value } = e.target;
setForm(prev => ({ ...prev, [name]: value }));
// clear error khi user sửa lại field đó
if (errors[name as keyof ErrorType]) {
setErrors(prev => ({ ...prev, [name]: undefined }));
}
};
// =========================
// Validate
// =========================
const checkField = () => {
const newErrors: ErrorType = {};
if (!form.name.trim()) {
newErrors.name = "Vui lòng nhập họ và tên";
}
if (!form.phone.trim()) {
newErrors.phone = "Vui lòng nhập số điện thoại";
} else if (!/^[0-9]{10,11}$/.test(form.phone)) {
newErrors.phone = "Số điện thoại không hợp lệ";
}
if (!form.email.trim()) {
newErrors.email = "Vui lòng nhập email";
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) {
newErrors.email = "Email không hợp lệ";
}
if (!form.address.trim()) {
newErrors.address = "Vui lòng nhập địa chỉ nhận hàng";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
// =========================
// Submit
// =========================
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setSubmit(false)
if (!checkField()) return;
console.log("Form hợp lệ:", form);
// call API đặt hàng ở đây
setSubmit(true)
router.push('/send-cart');
};
return (
<form
onSubmit={handleSubmit}
className="col-right w-[440px] bg-white rounded-[16px] px-5 py-6 sticky top-[90px] z-[1] shadow-[0px_4px_20px_0px_#0615070D] lg:shadow-none"
>
<p className="font-600 text-18 text-[#004BA4] mb-1">
Thông tin nhận hàng
</p>
<div className="leading-[18px] text-[#474747] mb-4">
Đ tiếp tục đt hàng, quý khách xin vui lòng
<Link href="/dang-nhap" className="font-500 text-[#0678DB]" > Đăng nhập </Link>
hoặc nhập thông tin bên dưới. vấn viên sẽ liên hệ theo thông tin bạn
cung cấp đ xác nhận, không mua không sao
</div>
{/* Họ tên */}
<input
name="name"
value={form.name}
onChange={handleChange}
className={`block w-full h-[50px] mb-4 rounded-[12px] bg-[#F3F3F3] px-4
${errors.name ? "border border-[#FA354A]" : "border border-transparent"}
`}
placeholder="Họ và tên"
/>
{errors.name && (
<p className="text-red-500 text-sm mb-3 mt-1">
{errors.name}
</p>
)}
{/* Số điện thoại */}
<input
name="phone"
value={form.phone}
onChange={handleChange}
type="tel"
maxLength={11}
className={`block w-full h-[50px] mb-4 rounded-[12px] bg-[#F3F3F3] px-4
${errors.phone ? "border border-[#FA354A]" : "border border-transparent"}
`}
placeholder="Số điện thoại"
/>
{errors.phone && (
<p className="text-red-500 text-sm mb-3 mt-1">
{errors.phone}
</p>
)}
{/* Email */}
<input
name="email"
value={form.email}
onChange={handleChange}
type="email"
className={`block w-full h-[50px] mb-4 rounded-[12px] bg-[#F3F3F3] px-4
${errors.email ? "border border-[#FA354A]" : "border border-transparent"}
`}
placeholder="Nhập email"
/>
{errors.email && (
<p className="text-red-500 text-sm mb-3 mt-1">
{errors.email}
</p>
)}
{/* Địa chỉ */}
<input
name="address"
value={form.address}
onChange={handleChange}
className={`block w-full h-[50px] mb-4 rounded-[12px] bg-[#F3F3F3] px-4
${errors.address ? "border border-[#FA354A]" : "border border-transparent"}
`}
placeholder="Địa chỉ nhận hàng"
/>
{errors.address && (
<p className="text-red-500 text-sm mb-3 mt-1">
{errors.address}
</p>
)}
<p className="text-[#757575] mb-4 text-sm">
<i className="bx bx-info-circle text-[#0678DB] mr-1" />
Nhập Số nhà, Đưng, Phường/, Quận, Tỉnh
</p>
{/* Ghi chú */}
<textarea
name="note"
value={form.note}
onChange={handleChange}
className="block w-full h-[112px] mb-5 rounded-[12px] bg-[#F3F3F3] px-4 pt-2 resize-none"
placeholder="Ghi chú"
/>
<button type="submit"
className={`block w-full text-white h-[52px] rounded-[50px] font-500 text-18
${submit ? 'bg-[#A0A5AC] pointer-events-none' : 'bg-btn'}
`}
>
{submit ? 'ĐANG XỬ LÝ' : 'ĐẶT HÀNG'}
</button>
</form>
);
}

View File

@@ -0,0 +1,27 @@
'use client';
export default function ScrollToReviewButton({
avgRate,
total
}) {
const HEADER_HEIGHT = 120;
const goToReview = () => {
const el = document.querySelector('.pd-comment-container');
if (!el) return;
const top =
el.getBoundingClientRect().top + window.scrollY - HEADER_HEIGHT;
window.scrollTo({ top, behavior: 'smooth' });
};
return (
<button type="button" className="m-0 flex items-center gap-1"
onClick={goToReview}
>
<i className={`star star-${avgRate}`} />
<span className="font-500"> ({total}) </span>
</button>
)
}

View File

@@ -1,35 +1,22 @@
'use client';
import { useState } from "react";
import CommentItem from "@/components/shared/CommentItem"
const COMMENT_PER_PAGE = 5; 'use client';
import { useShowMore } from "@/hooks/useShowMore"
import CommentItem from "@/components/shared/CommentItem"
import ShowMoreButton from "@/components/shared/ButtonShowMore"
export default function CommentList( {item}:any ) { export default function CommentList( {item}:any ) {
const total = item?.length; const { displayData, hasMore, loadMore } = useShowMore(item, 5);
const [page, setPage] = useState(1);
const displayCount = page * COMMENT_PER_PAGE;
const hasMore = displayCount < total;
const commentData = item.slice(0, displayCount);
return ( return (
<> <>
<div> <div>
{ {displayData.map((comment: any) => (
commentData.map( (comment:any) => <CommentItem item={comment} key={comment.id} />) <CommentItem item={comment} key={comment.id} />
} ))}
</div> </div>
{hasMore && {hasMore &&
<div className="text-center mt-4"> <ShowMoreButton onClick={loadMore}/>
<button type="button" aria-label="Xem thêm"
className="border border-[#0678DB] text-[#0678DB] rounded-[30px] h-10 px-6 hover:bg-[#0678DB] hover:text-white"
onClick={()=> setPage(prev => prev+1) }
>
XEM THÊM
<i className="bx bx-chevron-down text-20 align-middle mt-[-3px]" />
</button>
</div>
} }
</> </>
) )

View File

@@ -1,8 +1,17 @@
'use client';
import { useState, useMemo } from "react";
import { CommentData } from "@/data/comments"; import { CommentData } from "@/data/comments";
import Form from "./Form"; import Form from "./Form";
import CommentList from "./CommentList"; import CommentList from "./CommentList";
export default function Comment() { export default function Comment() {
const [star, setStar] = useState<number | null>(null);
const filteredComments = useMemo(() => {
if (star === null) return CommentData.list;
return CommentData.list.filter(item => Number(item.rate) === star);
}, [star]);
return ( return (
<div> <div>
@@ -10,31 +19,35 @@ export default function Comment() {
<p className="m-0 text-18 font-500"> {CommentData.list.length} Bình luận </p> <p className="m-0 text-18 font-500"> {CommentData.list.length} Bình luận </p>
<div className="flex flex-wrap gap-2 text-14 font-500 pd-comment-btn"> <div className="flex flex-wrap gap-2 text-14 font-500 pd-comment-btn">
<button type="button" aria-label="Đánh giá" <button type="button"
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-8 hover:border-[#0678DB] hover:text-[#0678DB] current" className={`h-8 border rounded-[40px] px-8
> Tất cả </button> ${star === null ? 'border-[#0678DB] text-[#0678DB]' : 'border-[#D1D5DB]'}`}
onClick={() => setStar(null)}
>
Tất cả
</button>
{buildButtonFilter()} {[5,4,3,2,1].map(s => (
<button type="button"
key={s}
className={`h-8 border rounded-[40px] px-4 flex items-center gap-[3px]
${star === s ? 'border-[#0678DB] text-[#0678DB]' : 'border-[#D1D5DB]'}`}
onClick={() => setStar(s)}
>
{s} <i className="bxr bx-star" />
</button>
))}
</div> </div>
</div> </div>
<div className="border border-[#DDDDDD] rounded-[12px] overflow-hidden js-comment-form"> <div className="border border-[#DDDDDD] rounded-[12px] overflow-hidden js-comment-form">
<Form /> <Form />
</div> </div>
{CommentData.list.length > 0 && {filteredComments.length > 0 && (
<CommentList item={CommentData.list}/> <CommentList item={filteredComments} />
} )}
</div> </div>
) )
} }
function buildButtonFilter(){
const star = [5,4,3,2,1]
return star.map(item => (
<button type="button" aria-label="Đánh giá" key={item}
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-4 hover:border-[#0678DB] hover:text-[#0678DB]"
> {item} <i className="bxr bx-star" /> </button>
))
}

View File

@@ -1,3 +1,4 @@
import parse from 'html-react-parser';
import { formatPrice } from "@/lib/utils"; import { formatPrice } from "@/lib/utils";
import ProductImage from "./images"; import ProductImage from "./images";
import Static from "./static"; import Static from "./static";
@@ -10,6 +11,8 @@ import ProductPrice from "./price";
import ProductOffer from "./offer"; import ProductOffer from "./offer";
import Buttons from "./buttons"; import Buttons from "./buttons";
import ProductSummary from "./summary"; import ProductSummary from "./summary";
import ScrollToReviewButton from "./buttons/ScrollToReviewButton";
import ProductTab from "./products";
import { ReviewData } from "@/data/reviews"; import { ReviewData } from "@/data/reviews";
@@ -31,8 +34,6 @@ export default async function ProductDetail({ slug }: any) {
quantity : slug.quantity quantity : slug.quantity
} }
console.log(slug)
return ( return (
<> <>
<div className="product-detail-page container"> <div className="product-detail-page container">
@@ -49,29 +50,26 @@ export default async function ProductDetail({ slug }: any) {
<div className="col-middle-group w-[464px]"> <div className="col-middle-group w-[464px]">
<div className="pb-3 mb-3 border-b border-[#DEE4EC] flex flex-wrap items-center gap-2"> <div className="pb-3 mb-3 border-b border-[#DEE4EC] flex flex-wrap items-center gap-2">
<button type="button" className="m-0 flex items-center gap-1"> <ScrollToReviewButton
<i className={`star star-${ReviewData.summary.avgRate}`} /> avgRate={ReviewData.summary.avgRate}
<span className="font-500"> ({ReviewData.summary.total}) </span> total={ReviewData.summary.total}
</button> />
<i className="w-[1px] h-4 bg-[#DEE4EC]" /> <i className="w-[1px] h-4 bg-[#DEE4EC]" />
<p className="m-0"> <p className="m-0">
Lượt xem: Lượt xem:
<span className="text-[#004BA4] font-500">{formatPrice(slug.visit)}</span> <span className="text-[#004BA4] font-500">{formatPrice(slug.visit) }</span>
</p> </p>
<i className="w-[1px] h-4 bg-[#DEE4EC]" /> <i className="w-[1px] h-4 bg-[#DEE4EC]" />
<p className="m-0"> <p className="m-0">
Tình trạng: Tình trạng:
<span { slug.quantity > 0
dangerouslySetInnerHTML={{ ? parse('<span class="font-500 text-[#00AD4F]">Còn hàng</span>')
__html: slug.quantity > 0 : parse('<span class="font-500 red">Liên hệ</span>')
? '<span class="font-500 text-[#00AD4F]">Còn hàng</span>' }
: '<span class="font-500 red">Liên hệ</span>'
}}
/>
</p> </p>
</div> </div>
@@ -106,7 +104,7 @@ export default async function ProductDetail({ slug }: any) {
/> />
} }
<div className="pd-comment-container bg-white mb-6 p-8 pt-6 rounded-[24px] text-16 leading-[22px]"> <div className="pd-comment-container bg-white mb-6 p-8 pt-6 rounded-[24px] text-16 leading-[22px]" id="js-comment-container">
<p className="leading-[31px] font-600 text-24 mb-4 pb-4"> <p className="leading-[31px] font-600 text-24 mb-4 pb-4">
Đánh giá bình luận Đánh giá bình luận
</p> </p>
@@ -129,727 +127,7 @@ export default async function ProductDetail({ slug }: any) {
</div> </div>
{/* Sản phẩm tương tự + Sản phẩm đã xem */} {/* Sản phẩm tương tự + Sản phẩm đã xem */}
<div className="pd-product-container bg-white px-6 py-8 rounded-[24px]"> <ProductTab item={slug.related} />
<div className="pd-tab-group relative flex mb-8 border-b border-[#DEE4EC] font-600 text-24 gap-10 leading-[31px] pb-5">
<button type="button" aria-label="tab" className="js-pd-tab">
Sản phẩm tương tự
</button>
<button type="button" aria-label="tab" className="js-pd-tab">
Sản phẩm đã xem
</button>
</div>
<div className="relative z-[1] bg-white relative min-h-[300px] js-product-holder">
<div className="swiper overflow-hidden">
<div className="swiper-wrapper">
<div className="swiper-slide">
<div className="p-item">
<a href="" className="p-img">
<img
src="images/product-1.jpg"
alt=""
width={250}
height={250}
/>
</a>
<div className="p-text">
<div className="p-price-group">
<del>52.000.000 đ</del>
<span className="p-discount">-10%</span>
<p className="p-price">22.000.000 đ</p>
</div>
<a href="" className="p-name">
<h3>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Suscipit quos obcaecati totam, atque vel
</h3>
</a>
<div className="p-btn-group flex items-center justify-between text-16 font-500 leading-[23px]">
<div>
<p className="m-0 text-[#00AD4F] flex items-center gap-1">
<i className="bx bx-check-circle text-18 w-[18px]" />
<span>Sẵn hàng</span>
</p>
<p className="m-0 text-[#E16B10] flex items-center gap-1">
<i className="bx bx-gift text-18 w-[18px]" />
<span>Quà tặng</span>
</p>
</div>
<button
type="button"
className="p-btn bx bx-plus bg-btn text-white rounded-full w-9 h-9 text-20"
aria-label="Mua"
/>
</div>
</div>
<div className="p-tooltip hidden">
<div className="bg-white rounded-[20px] overflow-hidden border-2 border-[#EAECF0] shadow-[0px_6px_8px_-2px_#10182814]">
<p className="tooltip-name px-5 py-4 text-white font-600 text-16 leading-[21px] bg-[linear-gradient(180.3deg,#259AFF_-18.56%,_#114CDD_100.92%)] m-0">
[Tặng bàn phím] HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX
3060 12GB
</p>
<div className="p-4 tooltip-content">
<div className="last:border-0 last:p-0 last:m-0 text-16 border-b border-[#DEE4EC] mb-4 pb-4">
<p className="m-0 flex items-center flex-wrap gap-1">
<b className="font-600">Giá bán:</b>
<b className="font-600 text-[#FF4E2A] text-18">
48.990.000 đ
</b>
<del className="text-[#A0A5AC] font-300">
52.000.000 đ
</del>
<span className="bg-[#FA354A] text-white text-11 px-[6px] leading-[18px] rounded-[20px]">
-6%
</span>
</p>
<p className="m-0">
<b className="font-600">Bảo hành:</b>
<span>Theo từng linh kiện</span>
</p>
</div>
<div className="last:mb-0 mb-6 px-1">
<p className="text-16 font-600 flex items-center leading-6 mb-2">
<i className="icons icon-screen" />
<span>Thông số sản phẩm</span>
</p>
<div className="tooltip-spec">
<div className="item">
CPU: INTEL CORE i5 13400F up 4.6GHz | 10 CORE | 16
THREAD
</div>
<div className="item">
RAM: DDR4 16GB&nbsp;(1x16G) 3200 MHz
</div>
<div className="item">
VGA: NVIDIA RTX&nbsp;3060 12GB&nbsp;GDDR6
</div>
</div>
</div>
<div className="rounded-[12px] bg-[linear-gradient(182.15deg,#FFA480_-18.44%,#EB0C23_60.76%)] p-1 pt-2">
<p className="px-2 text-16 font-600 flex items-center leading-5 mb-2 text-white">
<i className="icons icon-gift" />
<span>Khuyến mại hấp dẫn</span>
</p>
<div className="tooltip-offer rounded-[8px] bg-[#FEF2F2] px-2 py-4">
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Tại Nơi Sử Dụng (Áp Dụng Nội Thành
Nội Hồ Chí Minh)
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Siêu Tốc 1 Đi 1 Trong 24h
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Miễn Phí 100% Vận Chuyển Toàn Quốc
</strong>
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="swiper-slide">
<div className="p-item">
<a href="" className="p-img">
<img
src="images/product-2.jpg"
alt=""
width={250}
height={250}
/>
</a>
<div className="p-text">
<div className="p-price-group">
<p className="p-price">22.000.000 đ</p>
</div>
<a href="" className="p-name">
<h3>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Suscipit quos obcaecati totam, atque vel
</h3>
</a>
<div className="p-btn-group flex items-center justify-between text-16 font-500 leading-[23px]">
<div>
<p className="m-0 red flex items-center gap-1">
<i className="bx bxs-phone text-18 w-[18px]" />
<span>Liên hệ</span>
</p>
</div>
<button
type="button"
className="p-btn bx bx-plus bg-btn text-white rounded-full w-9 h-9 text-20"
aria-label="Mua"
/>
</div>
</div>
<div className="p-tooltip hidden">
<div className="bg-white rounded-[20px] overflow-hidden border-2 border-[#EAECF0] shadow-[0px_6px_8px_-2px_#10182814]">
<p className="tooltip-name px-5 py-4 text-white font-600 text-16 leading-[21px] bg-[linear-gradient(180.3deg,#259AFF_-18.56%,_#114CDD_100.92%)] m-0">
[Tặng bàn phím] HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX
3060 12GB
</p>
<div className="p-4 tooltip-content">
<div className="last:border-0 last:p-0 last:m-0 text-16 border-b border-[#DEE4EC] mb-4 pb-4">
<p className="m-0 flex items-center flex-wrap gap-1">
<b className="font-600">Giá bán:</b>
<b className="font-600 text-[#FF4E2A] text-18">
48.990.000 đ
</b>
<del className="text-[#A0A5AC] font-300">
52.000.000 đ
</del>
<span className="bg-[#FA354A] text-white text-11 px-[6px] leading-[18px] rounded-[20px]">
-6%
</span>
</p>
<p className="m-0">
<b className="font-600">Bảo hành:</b>
<span>Theo từng linh kiện</span>
</p>
</div>
<div className="last:mb-0 mb-6 px-1">
<p className="text-16 font-600 flex items-center leading-6 mb-2">
<i className="icons icon-screen" />
<span>Thông số sản phẩm</span>
</p>
<div className="tooltip-spec">
<div className="item">
CPU: INTEL CORE i5 13400F up 4.6GHz | 10 CORE | 16
THREAD
</div>
<div className="item">
RAM: DDR4 16GB&nbsp;(1x16G) 3200 MHz
</div>
<div className="item">
VGA: NVIDIA RTX&nbsp;3060 12GB&nbsp;GDDR6
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="swiper-slide">
<div className="p-item">
<a href="" className="p-img">
<img
src="images/product-3.jpg"
alt=""
width={250}
height={250}
/>
</a>
<div className="p-text">
<div className="p-price-group">
<del>52.000.000 đ</del>
<span className="p-discount">-10%</span>
<p className="p-price">22.000.000 đ</p>
</div>
<a href="" className="p-name">
<h3>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Suscipit quos obcaecati totam, atque vel
</h3>
</a>
<div className="p-btn-group flex items-center justify-between text-16 font-500 leading-[23px]">
<div>
<p className="m-0 red flex items-center gap-1">
<i className="bx bxs-phone text-18 w-[18px]" />
<span>Liên hệ</span>
</p>
<p className="m-0 text-[#E16B10] flex items-center gap-1">
<i className="bx bx-gift text-18 w-[18px]" />
<span>Quà tặng</span>
</p>
</div>
<button
type="button"
className="p-btn bx bx-plus bg-btn text-white rounded-full w-9 h-9 text-20"
aria-label="Mua"
/>
</div>
</div>
<div className="p-tooltip hidden">
<div className="bg-white rounded-[20px] overflow-hidden border-2 border-[#EAECF0] shadow-[0px_6px_8px_-2px_#10182814]">
<p className="tooltip-name px-5 py-4 text-white font-600 text-16 leading-[21px] bg-[linear-gradient(180.3deg,#259AFF_-18.56%,_#114CDD_100.92%)] m-0">
[Tặng bàn phím] HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX
3060 12GB
</p>
<div className="p-4 tooltip-content">
<div className="last:border-0 last:p-0 last:m-0 text-16 border-b border-[#DEE4EC] mb-4 pb-4">
<p className="m-0 flex items-center flex-wrap gap-1">
<b className="font-600">Giá bán:</b>
<b className="font-600 text-[#FF4E2A] text-18">
48.990.000 đ
</b>
<del className="text-[#A0A5AC] font-300">
52.000.000 đ
</del>
<span className="bg-[#FA354A] text-white text-11 px-[6px] leading-[18px] rounded-[20px]">
-6%
</span>
</p>
<p className="m-0">
<b className="font-600">Bảo hành:</b>
<span>Theo từng linh kiện</span>
</p>
</div>
<div className="last:mb-0 mb-6 px-1">
<p className="text-16 font-600 flex items-center leading-6 mb-2">
<i className="icons icon-screen" />
<span>Thông số sản phẩm</span>
</p>
<div className="tooltip-spec">
<div className="item">
CPU: INTEL CORE i5 13400F up 4.6GHz | 10 CORE | 16
THREAD
</div>
<div className="item">
RAM: DDR4 16GB&nbsp;(1x16G) 3200 MHz
</div>
<div className="item">
VGA: NVIDIA RTX&nbsp;3060 12GB&nbsp;GDDR6
</div>
</div>
</div>
<div className="rounded-[12px] bg-[linear-gradient(182.15deg,#FFA480_-18.44%,#EB0C23_60.76%)] p-1 pt-2">
<p className="px-2 text-16 font-600 flex items-center leading-5 mb-2 text-white">
<i className="icons icon-gift" />
<span>Khuyến mại hấp dẫn</span>
</p>
<div className="tooltip-offer rounded-[8px] bg-[#FEF2F2] px-2 py-4">
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Tại Nơi Sử Dụng (Áp Dụng Nội Thành
Nội Hồ Chí Minh)
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Siêu Tốc 1 Đi 1 Trong 24h
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Miễn Phí 100% Vận Chuyển Toàn Quốc
</strong>
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="swiper-slide">
<div className="p-item">
<a href="" className="p-img">
<img
src="images/product-4.jpg"
alt=""
width={250}
height={250}
/>
</a>
<div className="p-text">
<div className="p-price-group">
<del>52.000.000 đ</del>
<span className="p-discount">-10%</span>
<p className="p-price">22.000.000 đ</p>
</div>
<a href="" className="p-name">
<h3>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Suscipit quos obcaecati totam, atque vel
</h3>
</a>
<div className="p-btn-group flex items-center justify-between text-16 font-500 leading-[23px]">
<div>
<p className="m-0 text-[#00AD4F] flex items-center gap-1">
<i className="bx bx-check-circle text-18 w-[18px]" />
<span>Sẵn hàng</span>
</p>
</div>
<button
type="button"
className="p-btn bx bx-plus bg-btn text-white rounded-full w-9 h-9 text-20"
aria-label="Mua"
/>
</div>
</div>
<div className="p-tooltip hidden">
<div className="bg-white rounded-[20px] overflow-hidden border-2 border-[#EAECF0] shadow-[0px_6px_8px_-2px_#10182814]">
<p className="tooltip-name px-5 py-4 text-white font-600 text-16 leading-[21px] bg-[linear-gradient(180.3deg,#259AFF_-18.56%,_#114CDD_100.92%)] m-0">
[Tặng bàn phím] HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX
3060 12GB
</p>
<div className="p-4 tooltip-content">
<div className="last:border-0 last:p-0 last:m-0 text-16 border-b border-[#DEE4EC] mb-4 pb-4">
<p className="m-0 flex items-center flex-wrap gap-1">
<b className="font-600">Giá bán:</b>
<b className="font-600 text-[#FF4E2A] text-18">
48.990.000 đ
</b>
<del className="text-[#A0A5AC] font-300">
52.000.000 đ
</del>
<span className="bg-[#FA354A] text-white text-11 px-[6px] leading-[18px] rounded-[20px]">
-6%
</span>
</p>
<p className="m-0">
<b className="font-600">Bảo hành:</b>
<span>Theo từng linh kiện</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="swiper-slide">
<div className="p-item">
<a href="" className="p-img">
<img
src="images/product-5.jpg"
alt=""
width={250}
height={250}
/>
</a>
<div className="p-text">
<div className="p-price-group">
<p className="p-price">22.000.000 đ</p>
</div>
<a href="" className="p-name">
<h3>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Suscipit quos obcaecati totam, atque vel
</h3>
</a>
<div className="p-btn-group flex items-center justify-between text-16 font-500 leading-[23px]">
<div>
<p className="m-0 text-[#00AD4F] flex items-center gap-1">
<i className="bx bx-check-circle text-18 w-[18px]" />
<span>Sẵn hàng</span>
</p>
<p />
</div>
<button
type="button"
className="p-btn bx bx-plus bg-btn text-white rounded-full w-9 h-9 text-20"
aria-label="Mua"
/>
</div>
</div>
<div className="p-tooltip hidden">
<div className="bg-white rounded-[20px] overflow-hidden border-2 border-[#EAECF0] shadow-[0px_6px_8px_-2px_#10182814]">
<p className="tooltip-name px-5 py-4 text-white font-600 text-16 leading-[21px] bg-[linear-gradient(180.3deg,#259AFF_-18.56%,_#114CDD_100.92%)] m-0">
[Tặng bàn phím] HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX
3060 12GB
</p>
<div className="p-4 tooltip-content">
<div className="last:border-0 last:p-0 last:m-0 text-16 border-b border-[#DEE4EC] mb-4 pb-4">
<p className="m-0 flex items-center flex-wrap gap-1">
<b className="font-600">Giá bán:</b>
<b className="font-600 text-[#FF4E2A] text-18">
48.990.000 đ
</b>
</p>
<p className="m-0">
<b className="font-600">Bảo hành:</b>
<span>Theo từng linh kiện</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="swiper-slide">
<div className="p-item">
<a href="" className="p-img">
<img
src="images/product-7.jpg"
alt=""
width={250}
height={250}
/>
</a>
<div className="p-text">
<div className="p-price-group">
<del>52.000.000 đ</del>
<span className="p-discount">-10%</span>
<p className="p-price">22.000.000 đ</p>
</div>
<a href="" className="p-name">
<h3>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Suscipit quos obcaecati totam, atque vel
</h3>
</a>
<div className="p-btn-group flex items-center justify-between text-16 font-500 leading-[23px]">
<div>
<p className="m-0 red flex items-center gap-1">
<i className="bx bxs-phone text-18 w-[18px]" />
<span>Liên hệ</span>
</p>
<p className="m-0 text-[#E16B10] flex items-center gap-1">
<i className="bx bx-gift text-18 w-[18px]" />
<span>Quà tặng</span>
</p>
</div>
<button
type="button"
className="p-btn bx bx-plus bg-btn text-white rounded-full w-9 h-9 text-20"
aria-label="Mua"
/>
</div>
</div>
<div className="p-tooltip hidden">
<div className="bg-white rounded-[20px] overflow-hidden border-2 border-[#EAECF0] shadow-[0px_6px_8px_-2px_#10182814]">
<p className="tooltip-name px-5 py-4 text-white font-600 text-16 leading-[21px] bg-[linear-gradient(180.3deg,#259AFF_-18.56%,_#114CDD_100.92%)] m-0">
[Tặng bàn phím] HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX
3060 12GB
</p>
<div className="p-4 tooltip-content">
<div className="last:border-0 last:p-0 last:m-0 text-16 border-b border-[#DEE4EC] mb-4 pb-4">
<p className="m-0 flex items-center flex-wrap gap-1">
<b className="font-600">Giá bán:</b>
<b className="font-600 text-[#FF4E2A] text-18">
48.990.000 đ
</b>
<del className="text-[#A0A5AC] font-300">
52.000.000 đ
</del>
<span className="bg-[#FA354A] text-white text-11 px-[6px] leading-[18px] rounded-[20px]">
-6%
</span>
</p>
<p className="m-0">
<b className="font-600">Bảo hành:</b>
<span>Theo từng linh kiện</span>
</p>
</div>
<div className="last:mb-0 mb-6 px-1">
<p className="text-16 font-600 flex items-center leading-6 mb-2">
<i className="icons icon-screen" />
<span>Thông số sản phẩm</span>
</p>
<div className="tooltip-spec">
<div className="item">
CPU: INTEL CORE i5 13400F up 4.6GHz | 10 CORE | 16
THREAD
</div>
<div className="item">
RAM: DDR4 16GB&nbsp;(1x16G) 3200 MHz
</div>
<div className="item">
VGA: NVIDIA RTX&nbsp;3060 12GB&nbsp;GDDR6
</div>
</div>
</div>
<div className="rounded-[12px] bg-[linear-gradient(182.15deg,#FFA480_-18.44%,#EB0C23_60.76%)] p-1 pt-2">
<p className="px-2 text-16 font-600 flex items-center leading-5 mb-2 text-white">
<i className="icons icon-gift" />
<span>Khuyến mại hấp dẫn</span>
</p>
<div className="tooltip-offer rounded-[8px] bg-[#FEF2F2] px-2 py-4">
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Tại Nơi Sử Dụng (Áp Dụng Nội Thành
Nội Hồ Chí Minh)
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Siêu Tốc 1 Đi 1 Trong 24h
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Miễn Phí 100% Vận Chuyển Toàn Quốc
</strong>
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="swiper-slide">
<div className="p-item">
<a href="" className="p-img">
<img
src="images/product-6.jpg"
alt=""
width={250}
height={250}
/>
</a>
<div className="p-text">
<div className="p-price-group">
<del>52.000.000 đ</del>
<span className="p-discount">-10%</span>
<p className="p-price">22.000.000 đ</p>
</div>
<a href="" className="p-name">
<h3>
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Suscipit quos obcaecati totam, atque vel
</h3>
</a>
<div className="p-btn-group flex items-center justify-between text-16 font-500 leading-[23px]">
<div>
<p className="m-0 text-[#00AD4F] flex items-center gap-1">
<i className="bx bx-check-circle text-18 w-[18px]" />
<span>Sẵn hàng</span>
</p>
<p className="m-0 text-[#E16B10] flex items-center gap-1">
<i className="bx bx-gift text-18 w-[18px]" />
<span>Quà tặng</span>
</p>
</div>
<button
type="button"
className="p-btn bx bx-plus bg-btn text-white rounded-full w-9 h-9 text-20"
aria-label="Mua"
/>
</div>
</div>
<div className="p-tooltip hidden">
<div className="bg-white rounded-[20px] overflow-hidden border-2 border-[#EAECF0] shadow-[0px_6px_8px_-2px_#10182814]">
<p className="tooltip-name px-5 py-4 text-white font-600 text-16 leading-[21px] bg-[linear-gradient(180.3deg,#259AFF_-18.56%,_#114CDD_100.92%)] m-0">
[Tặng bàn phím] HHPC ULTRA 7 265K | 32GB DDR5 | NVIDIA RTX
3060 12GB
</p>
<div className="p-4 tooltip-content">
<div className="last:border-0 last:p-0 last:m-0 text-16 border-b border-[#DEE4EC] mb-4 pb-4">
<p className="m-0 flex items-center flex-wrap gap-1">
<b className="font-600">Giá bán:</b>
<b className="font-600 text-[#FF4E2A] text-18">
48.990.000 đ
</b>
<del className="text-[#A0A5AC] font-300">
52.000.000 đ
</del>
<span className="bg-[#FA354A] text-white text-11 px-[6px] leading-[18px] rounded-[20px]">
-6%
</span>
</p>
<p className="m-0">
<b className="font-600">Bảo hành:</b>
<span>Theo từng linh kiện</span>
</p>
</div>
<div className="last:mb-0 mb-6 px-1">
<p className="text-16 font-600 flex items-center leading-6 mb-2">
<i className="icons icon-screen" />
<span>Thông số sản phẩm</span>
</p>
<div className="tooltip-spec">
<div className="item">
CPU: INTEL CORE i5 13400F up 4.6GHz | 10 CORE | 16
THREAD
</div>
<div className="item">
RAM: DDR4 16GB&nbsp;(1x16G) 3200 MHz
</div>
<div className="item">
VGA: NVIDIA RTX&nbsp;3060 12GB&nbsp;GDDR6
</div>
</div>
</div>
<div className="rounded-[12px] bg-[linear-gradient(182.15deg,#FFA480_-18.44%,#EB0C23_60.76%)] p-1 pt-2">
<p className="px-2 text-16 font-600 flex items-center leading-5 mb-2 text-white">
<i className="icons icon-gift" />
<span>Khuyến mại hấp dẫn</span>
</p>
<div className="tooltip-offer rounded-[8px] bg-[#FEF2F2] px-2 py-4">
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Tại Nơi Sử Dụng (Áp Dụng Nội Thành
Nội Hồ Chí Minh)
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Bảo Hành Siêu Tốc 1 Đi 1 Trong 24h
</strong>
</span>
</p>
</div>
<div className="item">
<p>
<span style={{ color: "red", fontSize: "12pt" }}>
<strong>
Miễn Phí 100% Vận Chuyển Toàn Quốc
</strong>
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</> </>

View File

@@ -4,7 +4,7 @@ import parse from 'html-react-parser';
export default function ProductOffer({ item }: any) { export default function ProductOffer({ item }: any) {
return ( return (
<> <>
{item.all.length > 0 && {item.specialOffer.all.length > 0 &&
<div className="pd-offer-group mb-4 bg-[linear-gradient(182.15deg,#FFA480_-18.44%,#EB0C23_60.76%)] p-1 pt-2 rounded-[8px]"> <div className="pd-offer-group mb-4 bg-[linear-gradient(182.15deg,#FFA480_-18.44%,#EB0C23_60.76%)] p-1 pt-2 rounded-[8px]">
<div className="group-title font-600 text-white flex items-center leading-[22px] mb-2 px-2 text-16"> <div className="group-title font-600 text-white flex items-center leading-[22px] mb-2 px-2 text-16">
<i className="icons icon-gift mr-2 animation-tada -mt-1" /> <i className="icons icon-gift mr-2 animation-tada -mt-1" />
@@ -12,7 +12,7 @@ export default function ProductOffer({ item }: any) {
</div> </div>
<div className="rounded-[8px] bg-[#FEF2F2] px-2 py-4"> <div className="rounded-[8px] bg-[#FEF2F2] px-2 py-4">
{parse(formatTextList(item.all[0].title))} {parse(formatTextList(item.specialOffer.all[0].title))}
</div> </div>
</div> </div>
} }

View File

@@ -0,0 +1,79 @@
'use client';
import { useEffect, useState, useMemo } from "react";
import { Swiper, SwiperSlide } from 'swiper/react';
import { Navigation, Pagination, Autoplay } from 'swiper/modules';
import { ProductHistory } from "@/data/productHistory";
import ProductItem from "@/components/shared/ProductItem"
export default function ProductTab({ item }: any) {
const RelatedData = item.product || [];
const HistoryData = ProductHistory.list || [];
const [active, setActive] = useState<number>(1);
useEffect(() => {
if (RelatedData.length > 0) {
setActive(1);
} else if (HistoryData.length > 0) {
setActive(2);
} else {
setActive(0);
}
}, [RelatedData, HistoryData]);
const products = useMemo(() => {
if (active === 1) return RelatedData;
if (active === 2) return HistoryData;
return [];
}, [active, RelatedData, HistoryData]);
if (active > 0) {
return (
<div className="pd-product-container bg-white px-6 py-8 rounded-[24px]">
<div className="pd-tab-group relative flex mb-8 border-b border-[#DEE4EC] font-600 text-24 gap-10 leading-[31px] pb-5">
{RelatedData.length > 0 &&
<button type="button" aria-label="tab"
className={active === 1 ? 'current' : ''}
onClick={() => setActive(1)}
> Sản phẩm tương tự </button>
}
{HistoryData.length > 0 &&
<button type="button" aria-label="tab"
className={active === 2 ? 'current' : ''}
onClick={() => setActive(2)}
> Sản phẩm đã xem </button>
}
</div>
<div className="relative z-[1] bg-white relative min-h-[300px] js-product-holder">
<Swiper
key={active}
modules={[Navigation, Pagination, Autoplay]}
spaceBetween={24}
slidesPerView={5}
loop={products.length > 5 ? true : false}
autoplay={{
delay: 3000,
disableOnInteraction: false,
}}
navigation={{
prevEl: '.custom-nav .swiper-button-prev',
nextEl: '.custom-nav .swiper-button-next',
}}
breakpoints={{
1600: {
slidesPerView: 6,
},
}}
>
{products.map((item: any) =>
<SwiperSlide key={item.id}>
<ProductItem item={item} />
</SwiperSlide>
)}
</Swiper>
</div>
</div>
)
}
}

View File

@@ -1,37 +1,20 @@
'use client'; 'use client';
import { useState } from "react"; import { useShowMore } from "@/hooks/useShowMore"
import ReviewItem from "@/components/shared/ReviewItem"; import ReviewItem from "@/components/shared/ReviewItem";
import ShowMoreButton from "@/components/shared/ButtonShowMore"
const REVIEW_PER_PAGE = 5;
export default function ReviewList({ item }: any) { export default function ReviewList({ item }: any) {
const total = item?.length;
const [page, setPage] = useState(1); const { displayData, hasMore, loadMore } = useShowMore(item, 5);
const displayCount = page * REVIEW_PER_PAGE;
const hasMore = displayCount < total;
const reviewData = item.slice(0, displayCount);
return ( return (
<> <>
{reviewData && { displayData.map((item:any) =>
reviewData.map((item:any) =>
<ReviewItem key={item.id} item={item} /> <ReviewItem key={item.id} item={item} />
) )}
}
{ hasMore && { hasMore &&
<div className="text-center mt-4"> <ShowMoreButton onClick={loadMore} />
<button
type="button"
className="border border-[#0678DB] text-[#0678DB] rounded-[30px] h-10 px-6 hover:bg-[#0678DB] hover:text-white"
aria-label="Xem thêm"
onClick={() => setPage(prev => prev + 1)}
>
XEM THÊM
<i className="bx bx-chevron-down text-20 align-middle mt-[-3px]" />
</button>
</div>
} }
</> </>
) )

View File

@@ -0,0 +1,19 @@
export default function ButtonShowMore({
onClick,
label = "XEM THÊM",
loading = false
}) {
return (
<div className="text-center mt-4">
<button
type="button"
disabled={loading}
className="border border-[#0678DB] text-[#0678DB] rounded-[30px] h-10 px-6 hover:bg-[#0678DB] hover:text-white disabled:opacity-50"
onClick={onClick}
>
{loading ? "ĐANG TẢI..." : label}
<i className="bx bx-chevron-down text-20 align-middle mt-[-3px]" />
</button>
</div>
);
}

View File

@@ -0,0 +1,75 @@
import Link from "next/link";
import { formatTextList } from "@/lib/utils"
import parse from 'html-react-parser';
import { formatPrice } from "@/lib/utils"
export default function CartItem({ item }: any) {
const {
item_info,
in_cart
} = item;
return (
<div className="cart-item mb-5 last:mb-0">
<Link href={item_info.productUrl} className="item-img">
<img src={item_info.productImage.large} />
</Link>
<div className="item-text">
<div className="item-name">
<Link href={item_info.productUrl}
className="table uppercase font-500 lg:text-[16px] text-12"
>
{item_info.productName}
</Link>
{item_info.specialOffer.all.length > 0 &&
<div className="group mt-2 table">
<p className="m-0 text-[#0678DB] font-500 cursor-pointer">
<span> Chi tiết khuyến mại </span>
<i className="bx bx-chevron-down text-[#A0A5AC] text-16 align-middle transition-all group-hover:rotate-[-180deg]" />
</p>
<div className="item-offer group-hover:opacity-100 group-hover:z-[5] group-hover:visible">
{parse(formatTextList(item_info.specialOffer.all[0].title))}
</div>
</div>
}
</div>
<div className="item-quantiy">
<button type="button" className="js-quantity-change bx bx-minus" />
<input
type="number"
defaultValue={in_cart.quantity}
min={1}
pattern="[0-9]*"
inputMode="numeric"
className="js-buy-quantity js-quantity-change text-center"
/>
<button type="button" className="js-quantity-change bx bx-plus" />
</div>
<div className="item-price text-right lg:text-left">
<p className="text-[#FF4E2A] font-bold mb-0 lg:mb-1 lg:text-[16px] lg:leading-5 text-13 leading-4">
{ formatPrice(item_info.price) } đ
</p>
{item_info.marketPrice > 0 &&
<del className="block text-[#A0A5AC] lg:text-[13px] lg:leading-4 text-10 leading-3">
{ formatPrice(item_info.marketPrice) } đ
</del>
}
</div>
<button
type="button"
className="item-delete bx bx-trash w-8 h-8 lg:w-10 lg:h-10 rounded-full border border-[#E7D9D9] bg-[#F8F3F3] text-[#BE1F2D] text-16 lg:text-[20px] hover:text-white hover:bg-[#BE1F2D] hover:border-transparent"
/>
</div>
</div>
)
}

View File

@@ -14,8 +14,6 @@ export default function CommentItem({ item }: any) {
); );
}; };
console.log('aaaaaaaaaa', item)
return ( return (
<> <>
{ item.is_user_admin == 1 || item.approved == 1 && { item.is_user_admin == 1 || item.approved == 1 &&

501
src/data/cart/index.tsx Normal file
View File

@@ -0,0 +1,501 @@
export const CartData = {
"keywords" : "giỏ hàng",
"description" : "Xem các sản phẩm đã thêm vào trong giỏ hàng",
"title" : "Thông tin giỏ hàng",
"data": [
{
"_id": "product-6667-0",
"item_type": "product",
"item_id": "6667-0",
"item_info": {
"id": 6667,
"priceUnit": "chi\u1ebfc",
"marketPrice": 0,
"hasVAT": 0,
"weight": 0,
"price": 43350000,
"currency": "vnd",
"bulk_price": [],
"configurable": 0,
"productName": "HHPC CORE i7 14700KF | 64GB | NVIDIA RTX 5060 Ti 16G",
"productSummary": "<p>CPU : INTEL CORE i7 14700KF\u00a0UP 5.6GHz |\u00a020 CORES | 28 THREADS<\/p>\r\n<p>RAM : DDR4 64GB\u00a0(2x32G) 3200 MHz<\/p>\r\n<p>VGA:\u00a0NVIDIA RTX\u00a05060 Ti 16G GDDR7 - 2 FAN<\/p>",
"productImage": {
"small": "https:\/\/hoanghapccdn.com\/media\/product\/75_6667_pc_anubis_5060ti_sale.jpg",
"large": "https:\/\/hoanghapccdn.com\/media\/product\/250_6667_pc_anubis_5060ti_sale.jpg",
"original": ""
},
"productUrl": "\/hhpc-core-i7-14700kf-64gb-rtx-5060-ti-16g",
"brand": {
"id": 0,
"name": "",
"image": "",
"url": ""
},
"productSKU": "0",
"quantity": 1,
"addon": [],
"warranty": "theo t\u1eebng linh ki\u1ec7n",
"variants": [],
"variant_option": [],
"extend": [],
"categories": [
{
"id": 170,
"catPath": ":170:1",
"name": "PC 3D Design, Animation",
"url": "\/hhpc-3d"
},
{
"id": 162,
"catPath": ":162:1",
"name": "Photo Editing",
"url": "\/pc-photo-editing"
}
],
"specialOffer": {
"other": [
{
"id": 0,
"title": "<p>\u2b50\u00a0<span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">Gi\u00e1 khuy\u1ebfn m\u00e3i CPU Ryzen 7 9800X3D ch\u1ec9 c\u00f2n<\/span><\/strong><\/span><span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">\u00a0<\/span><span style=\"color: #008000; font-size: x-large;\">10.990.000\u0111<\/span>\u00a0<span style=\"color: #ff0000;\">\u00e1p d\u1ee5ng khi build PC t\u1ea1i Ho\u00e0ng H\u00e0 PC<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1\u00a0CPU Ryzen 7 9800X3D khi mua k\u00e8m main\u00a0B650 tr\u1edf l\u00ean l\u00e0:\u00a0<span style=\"font-size: 18pt;\"><strong>12.290.000\u0111<\/strong><\/span><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1 b\u00e1n l\u1ebb\u00a0CPU Ryzen 7 9800X3D l\u00e0:\u00a0<strong><span style=\"font-size: 18pt;\">13.290.000\u0111<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 L\u01afU \u00dd: Ch\u01b0\u01a1ng tr\u00ecnh kh\u00f4ng \u00e1p d\u1ee5ng c\u1ed9ng d\u1ed3n v\u1edbi c\u00e1c ch\u01b0\u01a1ng tr\u00ecnh kh\u00e1c<\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Ch\u01b0\u01a1ng tr\u00ecnh \u00e1p d\u1ee5ng v\u1edbi kh\u00e1ch h\u00e0ng Build PC c\u00f3 \u0111\u1ee7 th\u00eam 7 linh ki\u1ec7n sau:\u00a0<span style=\"font-size: 12pt;\">VGA,T\u1ea2N NHI\u1ec6T, MAIN, RAM, SSD, NGU\u1ed2N , V\u1ece CASE<\/span><\/span><\/p>",
"type": "",
"thumbnail": "",
"cash_value": 0,
"quantity": 1,
"from_time": "",
"to_time": "",
"url": "",
"description": "",
"status": 1
}
],
"all": [
{
"id": 0,
"title": "<p>\u2b50\u00a0<span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">Gi\u00e1 khuy\u1ebfn m\u00e3i CPU Ryzen 7 9800X3D ch\u1ec9 c\u00f2n<\/span><\/strong><\/span><span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">\u00a0<\/span><span style=\"color: #008000; font-size: x-large;\">10.990.000\u0111<\/span>\u00a0<span style=\"color: #ff0000;\">\u00e1p d\u1ee5ng khi build PC t\u1ea1i Ho\u00e0ng H\u00e0 PC<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1\u00a0CPU Ryzen 7 9800X3D khi mua k\u00e8m main\u00a0B650 tr\u1edf l\u00ean l\u00e0:\u00a0<span style=\"font-size: 18pt;\"><strong>12.290.000\u0111<\/strong><\/span><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1 b\u00e1n l\u1ebb\u00a0CPU Ryzen 7 9800X3D l\u00e0:\u00a0<strong><span style=\"font-size: 18pt;\">13.290.000\u0111<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 L\u01afU \u00dd: Ch\u01b0\u01a1ng tr\u00ecnh kh\u00f4ng \u00e1p d\u1ee5ng c\u1ed9ng d\u1ed3n v\u1edbi c\u00e1c ch\u01b0\u01a1ng tr\u00ecnh kh\u00e1c<\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Ch\u01b0\u01a1ng tr\u00ecnh \u00e1p d\u1ee5ng v\u1edbi kh\u00e1ch h\u00e0ng Build PC c\u00f3 \u0111\u1ee7 th\u00eam 7 linh ki\u1ec7n sau:\u00a0<span style=\"font-size: 12pt;\">VGA,T\u1ea2N NHI\u1ec6T, MAIN, RAM, SSD, NGU\u1ed2N , V\u1ece CASE<\/span><\/span><\/p>",
"type": "",
"thumbnail": "",
"cash_value": 0,
"quantity": 1,
"from_time": "",
"to_time": "",
"url": "",
"description": "",
"status": 1
}
]
},
"specialOfferGroup": [],
"sale_rules": {
"price": 43350000,
"normal_price": 44190000,
"min_purchase": 1,
"max_purchase": 10,
"remain_quantity": 1,
"from_time": 1767574800,
"to_time": 1772415000,
"type": "deal",
"type_id": 340
},
"variant_info": null
},
"in_cart": {
"quantity": 3,
"buyer_note": "",
"price": 43350000,
"total_price": 130050000,
"weight": 0,
"total_weight": 0
}
},
{
"_id": "product-6725-0",
"item_type": "product",
"item_id": "6725-0",
"item_info": {
"id": 6725,
"priceUnit": "chi\u1ebfc",
"marketPrice": 0,
"hasVAT": 0,
"weight": 0,
"price": 28990000,
"currency": "vnd",
"bulk_price": [],
"configurable": 0,
"productName": "HHPC RYZEN 7 9700X | 16G DDR5 | NVIDIA RTX 5060 8G",
"productSummary": "<p>CPU : AMD RYZEN\u00a07 9700X\u00a0UP 5.5GHz |\u00a08 CORES |\u00a016 THREADS<\/p>\r\n<p>RAM : DDR5 32GB 6000Mhz (2x16GB)<\/p>\r\n<p>VGA:\u00a0NVIDIA RTX 5060\u00a08G GDDR7<\/p>",
"productImage": {
"small": "https:\/\/hoanghapccdn.com\/media\/product\/75_6725_pc_gaming_x_ii_a620_sale_2.jpg",
"large": "https:\/\/hoanghapccdn.com\/media\/product\/250_6725_pc_gaming_x_ii_a620_sale_2.jpg",
"original": ""
},
"productUrl": "\/pc-ryzen-7-9700x-16g-d5-rtx-5060-8g",
"brand": {
"id": 0,
"name": "",
"image": "",
"url": ""
},
"productSKU": "0",
"quantity": 1,
"addon": [],
"warranty": "theo t\u1eebng linh ki\u1ec7n",
"variants": [],
"variant_option": [],
"extend": [],
"categories": [
{
"id": 284,
"catPath": ":284",
"name": "PC Gi\u00e1 R\u1ebb",
"url": "\/pc-gia-re"
}
],
"specialOffer": {
"other": [
{
"id": 0,
"title": "<p>\u2b50\u00a0<span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">Gi\u00e1 khuy\u1ebfn m\u00e3i CPU Ryzen 7 9800X3D ch\u1ec9 c\u00f2n<\/span><\/strong><\/span><span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">\u00a0<\/span><span style=\"color: #008000; font-size: x-large;\">10.990.000\u0111<\/span>\u00a0<span style=\"color: #ff0000;\">\u00e1p d\u1ee5ng khi build PC t\u1ea1i Ho\u00e0ng H\u00e0 PC<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1\u00a0CPU Ryzen 7 9800X3D khi mua k\u00e8m main\u00a0B650 tr\u1edf l\u00ean l\u00e0:\u00a0<span style=\"font-size: 18pt;\"><strong>12.290.000\u0111<\/strong><\/span><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1 b\u00e1n l\u1ebb\u00a0CPU Ryzen 7 9800X3D l\u00e0:\u00a0<strong><span style=\"font-size: 18pt;\">13.290.000\u0111<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 L\u01afU \u00dd: Ch\u01b0\u01a1ng tr\u00ecnh kh\u00f4ng \u00e1p d\u1ee5ng c\u1ed9ng d\u1ed3n v\u1edbi c\u00e1c ch\u01b0\u01a1ng tr\u00ecnh kh\u00e1c<\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Ch\u01b0\u01a1ng tr\u00ecnh \u00e1p d\u1ee5ng v\u1edbi kh\u00e1ch h\u00e0ng Build PC c\u00f3 \u0111\u1ee7 th\u00eam 7 linh ki\u1ec7n sau:\u00a0<span style=\"font-size: 12pt;\">VGA,T\u1ea2N NHI\u1ec6T, MAIN, RAM, SSD, NGU\u1ed2N , V\u1ece CASE<\/span><\/span><\/p>",
"type": "",
"thumbnail": "",
"cash_value": 0,
"quantity": 1,
"from_time": "",
"to_time": "",
"url": "",
"description": "",
"status": 1
}
],
"all": [
{
"id": 0,
"title": "<p>\u2b50\u00a0<span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">Gi\u00e1 khuy\u1ebfn m\u00e3i CPU Ryzen 7 9800X3D ch\u1ec9 c\u00f2n<\/span><\/strong><\/span><span style=\"font-size: medium;\"><strong><span style=\"color: #ff0000;\">\u00a0<\/span><span style=\"color: #008000; font-size: x-large;\">10.990.000\u0111<\/span>\u00a0<span style=\"color: #ff0000;\">\u00e1p d\u1ee5ng khi build PC t\u1ea1i Ho\u00e0ng H\u00e0 PC<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1\u00a0CPU Ryzen 7 9800X3D khi mua k\u00e8m main\u00a0B650 tr\u1edf l\u00ean l\u00e0:\u00a0<span style=\"font-size: 18pt;\"><strong>12.290.000\u0111<\/strong><\/span><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Gi\u00e1 b\u00e1n l\u1ebb\u00a0CPU Ryzen 7 9800X3D l\u00e0:\u00a0<strong><span style=\"font-size: 18pt;\">13.290.000\u0111<\/span><\/strong><\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 L\u01afU \u00dd: Ch\u01b0\u01a1ng tr\u00ecnh kh\u00f4ng \u00e1p d\u1ee5ng c\u1ed9ng d\u1ed3n v\u1edbi c\u00e1c ch\u01b0\u01a1ng tr\u00ecnh kh\u00e1c<\/span><\/p>\r\n<p><span style=\"font-size: 12pt;\">\u2b50 Ch\u01b0\u01a1ng tr\u00ecnh \u00e1p d\u1ee5ng v\u1edbi kh\u00e1ch h\u00e0ng Build PC c\u00f3 \u0111\u1ee7 th\u00eam 7 linh ki\u1ec7n sau:\u00a0<span style=\"font-size: 12pt;\">VGA,T\u1ea2N NHI\u1ec6T, MAIN, RAM, SSD, NGU\u1ed2N , V\u1ece CASE<\/span><\/span><\/p>",
"type": "",
"thumbnail": "",
"cash_value": 0,
"quantity": 1,
"from_time": "",
"to_time": "",
"url": "",
"description": "",
"status": 1
}
]
},
"specialOfferGroup": [],
"sale_rules": {
"price": 28990000,
"normal_price": 30190000,
"min_purchase": 1,
"max_purchase": 10,
"remain_quantity": 1,
"from_time": 1769043600,
"to_time": 1772415000,
"type": "deal",
"type_id": 368
},
"variant_info": null
},
"in_cart": {
"quantity": 1,
"buyer_note": "",
"price": 28990000,
"total_price": 28990000,
"weight": 0,
"total_weight": 0
}
},
{
"_id": "product-6669-0",
"item_type": "product",
"item_id": "6669-0",
"item_info": {
"id": 6669,
"priceUnit": "chi\u1ebfc",
"marketPrice": 0,
"hasVAT": 0,
"weight": 0,
"price": 55950000,
"currency": "vnd",
"bulk_price": [],
"configurable": 0,
"productName": "HHPC CORE i7 14700KF | 64GB | NVIDIA RTX 5070 Ti 16G",
"productSummary": "<p>CPU : INTEL CORE i7 14700KF\u00a0UP 5.6GHz |\u00a020 CORES | 28 THREADS<\/p>\r\n<p>RAM : DDR4 64GB\u00a0(2x32G) 3200 MHz<\/p>\r\n<p>VGA:\u00a0NVIDIA RTX\u00a05070 Ti 16G GDDR7<\/p>",
"productImage": {
"small": "https:\/\/hoanghapccdn.com\/media\/product\/75_6669_pc_anubis_14700kf_sale_4.jpg",
"large": "https:\/\/hoanghapccdn.com\/media\/product\/250_6669_pc_anubis_14700kf_sale_4.jpg",
"original": ""
},
"productUrl": "\/hhpc-core-i7-14700kf-64gb-rtx-5070-ti-16g",
"brand": {
"id": 0,
"name": "",
"image": "",
"url": ""
},
"productSKU": "0",
"quantity": 1,
"addon": [],
"warranty": "theo t\u1eebng linh ki\u1ec7n",
"variants": [],
"variant_option": [],
"extend": [],
"categories": [
{
"id": 170,
"catPath": ":170:1",
"name": "PC 3D Design, Animation",
"url": "\/hhpc-3d"
},
{
"id": 162,
"catPath": ":162:1",
"name": "Photo Editing",
"url": "\/pc-photo-editing"
}
],
"specialOffer": {
"all": []
},
"specialOfferGroup": [],
"sale_rules": {
"price": 55950000,
"normal_price": 57090000,
"min_purchase": 1,
"max_purchase": 10,
"remain_quantity": 1,
"from_time": 1767574800,
"to_time": 1772415000,
"type": "deal",
"type_id": 342
},
"variant_info": null
},
"in_cart": {
"quantity": 1,
"buyer_note": "",
"price": 55950000,
"total_price": 55950000,
"weight": 0,
"total_weight": 0
}
},
{
"_id": "product-6668-0",
"item_type": "product",
"item_id": "6668-0",
"item_info": {
"id": 6668,
"priceUnit": "chi\u1ebfc",
"marketPrice": 0,
"hasVAT": 0,
"weight": 0,
"price": 48250000,
"currency": "vnd",
"bulk_price": [],
"configurable": 0,
"productName": "HHPC CORE i7 14700KF | 64GB | NVIDIA RTX 5070 12G",
"productSummary": "<p>CPU : INTEL CORE i7 14700KF\u00a0UP 5.6GHz |\u00a020 CORES | 28 THREADS<\/p>\r\n<p>RAM : DDR4 64GB\u00a0(2x32G) 3200 MHz<\/p>\r\n<p>VGA:\u00a0NVIDIA RTX 5070 12G GDDR7<\/p>",
"productImage": {
"small": "https:\/\/hoanghapccdn.com\/media\/product\/75_6668_pc_anubis_14700kf_sale_3.jpg",
"large": "https:\/\/hoanghapccdn.com\/media\/product\/250_6668_pc_anubis_14700kf_sale_3.jpg",
"original": ""
},
"productUrl": "\/hhpc-core-i7-14700kf-64gb-rtx-5070-12g",
"brand": {
"id": 0,
"name": "",
"image": "",
"url": ""
},
"productSKU": "0",
"quantity": 1,
"addon": [],
"warranty": "theo t\u1eebng linh ki\u1ec7n",
"variants": [],
"variant_option": [],
"extend": [],
"categories": [
{
"id": 170,
"catPath": ":170:1",
"name": "PC 3D Design, Animation",
"url": "\/hhpc-3d"
},
{
"id": 162,
"catPath": ":162:1",
"name": "Photo Editing",
"url": "\/pc-photo-editing"
}
],
"specialOffer": {
"all": []
},
"specialOfferGroup": [],
"sale_rules": {
"price": 48250000,
"normal_price": 49190000,
"min_purchase": 1,
"max_purchase": 10,
"remain_quantity": 1,
"from_time": 1767574800,
"to_time": 1772415000,
"type": "deal",
"type_id": 341
},
"variant_info": null
},
"in_cart": {
"quantity": 1,
"buyer_note": "",
"price": 48250000,
"total_price": 48250000,
"weight": 0,
"total_weight": 0
}
},
{
"_id": "product-5818-0",
"item_type": "product",
"item_id": "5818-0",
"item_info": {
"id": 5818,
"priceUnit": "chi\u1ebfc",
"marketPrice": 0,
"hasVAT": 0,
"weight": 0,
"price": 0,
"currency": "vnd",
"bulk_price": [],
"configurable": 0,
"productName": "HH AI PC RYZEN THREADRIPPER 7970X | 256G DDR5 | NVIDIA RTX 5090 32G",
"productSummary": "<p>CPU: AMD RYZEN THREADRIPPER 7970X UP TO 5.3 GHz | 32 CORE | 64 THREAD<\/p>\r\n<p>MAINBOARD: ASUS PRO WS TRX50-SAGE WIFI<\/p>\r\n<p>T\u1ea2N NHI\u1ec6T: CUSTOM CHO CPU 7970X<\/p>\r\n<p>RAM: DDR5 SAMSUNG ECC 256GB 4800MHz (64Gx4)<\/p>\r\n<p>SSD: SAMSUNG 990 PRO 1TB + 2TB NVME M.2 PCIE GEN 4x4<\/p>\r\n<p>VGA: GIGABYTE RTX 5090 WINDFORCE OC 32GB GDDR7<\/p>\r\n<p>PSU: ASUS TUF GAMING 1200W 80 PLUS GOLD PCIE 5.0<\/p>\r\n<p>CASE: LIAN LI LANCOOL O11 DYNAMIC EVO RGB BLACK<\/p>",
"productImage": {
"small": "https:\/\/hoanghapccdn.com\/media\/product\/75_5818_pc_d___p_o11_dynamic_evo_ha1s.jpg",
"large": "https:\/\/hoanghapccdn.com\/media\/product\/250_5818_pc_d___p_o11_dynamic_evo_ha1s.jpg",
"original": ""
},
"productUrl": "\/hhpc-dep-ryzen-threadripper-7970x-256g-ddr5-nvidia-rtx-5090-32g",
"brand": {
"id": 0,
"name": "",
"image": "",
"url": ""
},
"productSKU": "0",
"quantity": 1,
"addon": [],
"warranty": "theo t\u1eebng linh ki\u1ec7n",
"variants": [],
"variant_option": [],
"extend": [],
"categories": [
{
"id": 92,
"catPath": ":92:1",
"name": "PC Machine Learning \/ AI",
"url": "\/pc-ai-tri-tue-nhan-tao"
}
],
"specialOffer": {
"all": []
},
"specialOfferGroup": [],
"sale_rules": {
"price": 0,
"normal_price": 0,
"min_purchase": 1,
"max_purchase": 1,
"remain_quantity": 1,
"from_time": 0,
"to_time": 0,
"type": ""
},
"variant_info": null
},
"in_cart": {
"quantity": 1,
"buyer_note": "",
"price": 0,
"total_price": 0,
"weight": 0,
"total_weight": 0
}
},
{
"_id": "product-5791-0",
"item_type": "product",
"item_id": "5791-0",
"item_info": {
"id": 5791,
"priceUnit": "chi\u1ebfc",
"marketPrice": 0,
"hasVAT": 0,
"weight": 0,
"price": 454000000,
"currency": "vnd",
"bulk_price": [],
"configurable": 0,
"productName": "HH AI PC DUAL NVIDIA RTX 5090 32G | THREADRIPPER 9960X | 256GB",
"productSummary": "<p>CPU:\u00a0THREADRIPPER\u00a09960X UP 5.4 |\u00a024 CORE | 48 THREAD<\/p>\r\n<p>RAM : 256GB ECC REGISTERED T\u1ef0 S\u1eecA L\u1ed6I (4x64G)<\/p>\r\n<p>VGA : 2x NVIDIA RTX 5090 32GB GDDR7<\/p>",
"productImage": {
"small": "https:\/\/hoanghapccdn.com\/media\/product\/75_5791_pc_aorus_c500_glass_hot.jpg",
"large": "https:\/\/hoanghapccdn.com\/media\/product\/250_5791_pc_aorus_c500_glass_hot.jpg",
"original": ""
},
"productUrl": "\/pcai-threadripper-9960x-256gb-dual-rtx-5090-32g",
"brand": {
"id": 0,
"name": "",
"image": "",
"url": ""
},
"productSKU": "0",
"quantity": 1,
"addon": [],
"warranty": "theo t\u1eebng linh ki\u1ec7n",
"variants": [],
"variant_option": [],
"extend": [],
"categories": [
{
"id": 92,
"catPath": ":92:1",
"name": "PC Machine Learning \/ AI",
"url": "\/pc-ai-tri-tue-nhan-tao"
}
],
"specialOffer": {
"all": []
},
"specialOfferGroup": [],
"sale_rules": {
"price": 454000000,
"normal_price": 454000000,
"min_purchase": 1,
"max_purchase": 1,
"remain_quantity": 1,
"from_time": 0,
"to_time": 0,
"type": "component"
},
"variant_info": null
},
"in_cart": {
"quantity": 1,
"buyer_note": "",
"price": 454000000,
"total_price": 454000000,
"weight": 0,
"total_weight": 0
}
}
],
"cart_summary" : {
"total_value": 28990000,
"total_quantity": 4,
"total_item": 6,
"total_weight": 0,
}
}

File diff suppressed because one or more lines are too long

21
src/hooks/useShowMore.ts Normal file
View File

@@ -0,0 +1,21 @@
'use client';
import { useState, useMemo } from "react";
export function useShowMore<T>(data: T[], perPage = 5) {
const [page, setPage] = useState(1);
const displayData = useMemo(() => {
return data.slice(0, page * perPage);
}, [data, page, perPage]);
const hasMore = displayData.length < data.length;
const loadMore = () => setPage(prev => prev + 1);
return {
displayData,
hasMore,
loadMore,
page
};
}

View File

@@ -50,7 +50,11 @@ export function addProductToCart(productId: number, quantity: number = 1): { suc
items.push({ id: productId, cartQuantity: quantity }); items.push({ id: productId, cartQuantity: quantity });
localStorage.setItem(CART_KEY, JSON.stringify(items)); localStorage.setItem(CART_KEY, JSON.stringify(items));
notifyCartChange(); // Notify change notifyCartChange(); // Notify change
return { success: true, message: 'Đã thêm sản phẩm vào giỏ hàng', isNew: true }; return {
success: true,
message: 'Đã thêm sản phẩm vào giỏ hàng',
isNew: true
};
} }
// 3. Tăng số lượng sản phẩm // 3. Tăng số lượng sản phẩm

View File

@@ -263,10 +263,10 @@ body{min-width:1248px;background:#E8ECF6}
.pd-article-holder .art-item .art-img{width:38%;margin:0;padding-bottom:25.5%} .pd-article-holder .art-item .art-img{width:38%;margin:0;padding-bottom:25.5%}
.pd-article-holder .art-item .art-text{width:calc(62% - 12px)} .pd-article-holder .art-item .art-text{width:calc(62% - 12px)}
.pd-article-holder .art-item .art-title{font-size:14px;line-height:18px;min-height:unset} .pd-article-holder .art-item .art-title{font-size:14px;line-height:18px;min-height:unset}
.pd-tab-group a{position:relative} .pd-tab-group button{position:relative}
.pd-tab-group a::after{content:"";height:3px;background:#0678DB;position:absolute;left:0;right:0;bottom:-20px;transition:.3s all;width:0} .pd-tab-group button::after{content:"";height:3px;background:#0678DB;position:absolute;left:0;right:0;bottom:-20px;transition:.3s all;width:0}
.pd-tab-group a:hover,.pd-tab-group a.current{color:#0678DB} .pd-tab-group button:hover,.pd-tab-group button.current{color:#0678DB}
.pd-tab-group a:hover::after,.pd-tab-group a.current::after{width:100%} .pd-tab-group button:hover::after,.pd-tab-group button.current::after{width:100%}
.item-circle{position:relative;padding-left:18px;margin:0 0 8px} .item-circle{position:relative;padding-left:18px;margin:0 0 8px}
.item-circle:last-child{margin:0} .item-circle:last-child{margin:0}
.item-circle::before{content:"";position:absolute;top:4px;left:4px;border-radius:50%;background:linear-gradient(173.39deg,#81D2FF 7.77%,#4593FF 94.81%);width:8px;height:8px} .item-circle::before{content:"";position:absolute;top:4px;left:4px;border-radius:50%;background:linear-gradient(173.39deg,#81D2FF 7.77%,#4593FF 94.81%);width:8px;height:8px}