update 2/2/2026

This commit is contained in:
2026-02-02 16:42:40 +07:00
parent 12509e3a7b
commit 6318621cc0
25 changed files with 1568 additions and 570 deletions

View File

@@ -1,138 +0,0 @@
export default function Article() {
return (
<div className="pd-box-group bg-white mb-6 px-4 py-6 rounded-[24px]">
<p className="text-20 font-600 mb-4"> Tin tức mới nhất </p>
{/* limit: 5 */}
<div className="pd-article-holder flex flex-col gap-4">
<div className="art-item">
<a href="" className="art-img">
<img
src="https://hoanghapccdn.com/media/news/14_100__c___u_h__nh_m__y_t__nh_______h___a_theo_ng__n_s__ch.jpg"
alt=""
width={1}
height={1}
/>
</a>
<div className="art-text">
<a href="" className="art-title">
<h3>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Eum
quidem asperiores provident dicta veniam deleniti eaque
repudiandae cum esse, ducimus officiis quibusdam pariatur
neque voluptates voluptas. Quisquam qui minus dolorum?
</h3>
</a>
<div className="art-summary">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit,
obcaecati ducimus veritatis aliquid sunt accusamus unde nisi
nostrum fugit facere illo quos. Ad error suscipit, quidem optio
aut laudantium at!
</div>
<div className="art-time">
<i className="bx bx-calendar-alt" />
<time>23/4/2024</time>
<i className="w-[1.5px] h-[12px] bg-[#A0A5AC] mx-1" />
<span>Mai Văn Học</span>
</div>
</div>
</div>
<div className="art-item">
<a href="" className="art-img">
<img
src="https://hoanghapccdn.com/media/news/14_100__c___u_h__nh_m__y_t__nh_______h___a_theo_ng__n_s__ch.jpg"
alt=""
width={1}
height={1}
/>
</a>
<div className="art-text">
<a href="" className="art-title">
<h3>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Eum
quidem asperiores provident dicta veniam deleniti eaque
repudiandae cum esse, ducimus officiis quibusdam pariatur
neque voluptates voluptas. Quisquam qui minus dolorum?
</h3>
</a>
<div className="art-summary">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit,
obcaecati ducimus veritatis aliquid sunt accusamus unde nisi
nostrum fugit facere illo quos. Ad error suscipit, quidem optio
aut laudantium at!
</div>
<div className="art-time">
<i className="bx bx-calendar-alt text-16 text-[#A0A5AC]" />
<time>23/4/2024</time>
<i className="w-[1.5px] h-[12px] bg-[#A0A5AC]" />
<span>Mai Văn Học</span>
</div>
</div>
</div>
<div className="art-item">
<a href="" className="art-img">
<img
src="https://hoanghapccdn.com/media/news/14_100__c___u_h__nh_m__y_t__nh_______h___a_theo_ng__n_s__ch.jpg"
alt=""
width={1}
height={1}
/>
</a>
<div className="art-text">
<a href="" className="art-title">
<h3>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Eum
quidem asperiores provident dicta veniam deleniti eaque
repudiandae cum esse, ducimus officiis quibusdam pariatur
neque voluptates voluptas. Quisquam qui minus dolorum?
</h3>
</a>
<div className="art-summary">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit,
obcaecati ducimus veritatis aliquid sunt accusamus unde nisi
nostrum fugit facere illo quos. Ad error suscipit, quidem optio
aut laudantium at!
</div>
<div className="art-time">
<i className="bx bx-calendar-alt text-16 text-[#A0A5AC]" />
<time>23/4/2024</time>
<i className="w-[1.5px] h-[12px] bg-[#A0A5AC]" />
<span>Mai Văn Học</span>
</div>
</div>
</div>
<div className="art-item">
<a href="" className="art-img">
<img
src="https://hoanghapccdn.com/media/news/14_100__c___u_h__nh_m__y_t__nh_______h___a_theo_ng__n_s__ch.jpg"
alt=""
width={1}
height={1}
/>
</a>
<div className="art-text">
<a href="" className="art-title">
<h3>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Eum
quidem asperiores provident dicta veniam deleniti eaque
repudiandae cum esse, ducimus officiis quibusdam pariatur
neque voluptates voluptas. Quisquam qui minus dolorum?
</h3>
</a>
<div className="art-summary">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit,
obcaecati ducimus veritatis aliquid sunt accusamus unde nisi
nostrum fugit facere illo quos. Ad error suscipit, quidem optio
aut laudantium at!
</div>
<div className="art-time">
<i className="bx bx-calendar-alt text-16 text-[#A0A5AC]" />
<time>23/4/2024</time>
<i className="w-[1.5px] h-[12px] bg-[#A0A5AC]" />
<span>Mai Văn Học</span>
</div>
</div>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,17 @@
import ArticleItem from "@/components/shared/ArticleItem"
export default function Article( {item} : any ) {
return (
<div className="pd-box-group bg-white mb-6 px-4 py-6 rounded-[24px]">
<p className="text-20 font-600 mb-4"> Tin tức mới nhất </p>
<div className="pd-article-holder flex flex-col gap-4">
{
item.slice(0,5).map((item:any) =>
<ArticleItem key={item.id} item={item} />
)
}
</div>
</div>
)
}

View File

@@ -1,161 +0,0 @@
export default function Comment() {
return (
<div>
<div className="flex items-center justify-between leading-8 gap-2 mb-4">
<p className="m-0 text-18 font-500"> 0 Bình luận </p>
<div className="flex flex-wrap gap-2 text-14 font-500 pd-comment-btn">
<button
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-8 hover:border-[#0678DB] hover:text-[#0678DB] current"
type="button"
aria-label="Đánh giá"
>
{" "}
Tất cả{" "}
</button>
<button
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-4 hover:border-[#0678DB] hover:text-[#0678DB]"
type="button"
aria-label="Đánh giá"
>
{" "}
5 <i className="bxr bx-star" />{" "}
</button>
<button
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-4 hover:border-[#0678DB] hover:text-[#0678DB]"
type="button"
aria-label="Đánh giá"
>
{" "}
4 <i className="bxr bx-star" />{" "}
</button>
<button
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-4 hover:border-[#0678DB] hover:text-[#0678DB]"
type="button"
aria-label="Đánh giá"
>
{" "}
3 <i className="bxr bx-star" />{" "}
</button>
<button
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-4 hover:border-[#0678DB] hover:text-[#0678DB]"
type="button"
aria-label="Đánh giá"
>
{" "}
2 <i className="bxr bx-star" />{" "}
</button>
<button
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-4 hover:border-[#0678DB] hover:text-[#0678DB]"
type="button"
aria-label="Đánh giá"
>
{" "}
1 <i className="bxr bx-star" />{" "}
</button>
</div>
</div>
<div className="border border-[#DDDDDD] rounded-[12px] overflow-hidden ">
<textarea
className="p-3 w-full resize-none h-[96px] outline-none border-none"
defaultValue={""}
/>
<div className="border-t border-[#DDDDDD] bg-[#F5F6F7] p-[10px_12px] text-right">
<button
className="bg-btn text-white h-10 px-9 text-18 font-500 rounded-[30px]"
type="button"
aria-label="submit"
>
{" "}
GỬI{" "}
</button>
</div>
</div>
<div id="">
<div className="first:border-t first:mt-4 first:pt-4 border-[#D1D5DB] mb-5 flex gap-3 text-14 leading-[18px]">
<div className="w-10 h-10 rounded-full bg-[#9CA3AF] leading-10 text-center uppercase text-white font-600 overflow-hidden">
<span>p</span>
{/* <img src="images/avatar-admin.png" class="block w-full h-full"/> */}
</div>
<div className="w-[calc(100%_-_52px)]">
<div className="flex items-center gap-2 mb-1">
<b className="capitalize"> tên khách hàng </b>
<i className="bxr bxs-radio-circle text-[7px] text-[#6B7280]" />
<span className="text-[#6B7280]"> 11-11-2025, 11:11 </span>
</div>
<i className="star star-2" />
<div className="my-2">
Lorem ipsum dolor, sit amet consectetur adipisicing elit.
Fugiat magnam ipsam pariatur mollitia ratione distinctio magni
corrupti ad expedita. Natus, ullam inventore. Amet
consequuntur aspernatur deserunt accusantium, tempore
blanditiis magni!
</div>
<div className="flex gap-2 leading-[30px]">
<button
className="group flex items-center gap-[6px] border border-[#D1D5DB] px-3 rounded-[20px] hover:border-[#0678DB] hover:text-[#0678DB]"
type="button"
aria-label="actions"
>
{" "}
<i className="group-hover:text-[#0678DB] text-[#928FA8] bxr bx-heart" />{" "}
0{" "}
</button>
<button
className="group flex items-center gap-[6px] border border-[#D1D5DB] px-3 rounded-[20px] hover:border-[#0678DB] hover:text-[#0678DB]"
type="button"
aria-label="actions"
>
{" "}
<i className="group-hover:text-[#0678DB] text-[#928FA8] bxr bx-reply-stroke" />{" "}
Trả lời{" "}
</button>
</div>
<div className="bg-[#F3F4F6] rounded-[12px] overflow-hidden mt-3">
<div className="first:border-0 flex items-start gap-3 p-3 border-t border-[#D1D5DB]">
<div className="w-10 h-10 rounded-full bg-[#9CA3AF] leading-10 text-center uppercase text-white font-600 overflow-hidden">
{/* <span>p</span> */}
<img
src="images/avatar-admin.png"
className="block w-full h-full"
/>
</div>
<div className="w-[calc(100%_-_52px)]">
<div className="flex items-center gap-2 mb-1">
<b className="capitalize"> tên khách hàng </b>
<span className="bg-[linear-gradient(70.1deg,#75798B_62.94%,#ADB5CD_100%)] text-white px-[6px] leading-[18px] rounded-[20px] font-500 text-10">
{" "}
Quản trị viên{" "}
</span>
<i className="bxr bxs-radio-circle text-[7px] text-[#6B7280]" />
<span className="text-[#6B7280]">
{" "}
11-11-2025, 11:11{" "}
</span>
</div>
<div className="my-2" style={{ whiteSpace: "pre-line" }}>
Lorem ipsum dolor, sit amet consectetur adipisicing
elit. Fugiat magnam ipsam pariatur mollitia ratione
distinctio magni corrupti ad expedita. Natus, ullam
inventore. Amet consequuntur aspernatur deserunt
accusantium, tempore blanditiis magni!{" "}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* xem thêm */}
<div className="text-center mt-4">
<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"
>
XEM THÊM{" "}
<i className="bx bx-chevron-down text-20 align-middle mt-[-3px]" />
</button>
</div>
</div>
)
}

View File

@@ -0,0 +1,36 @@
'use client';
import { useState } from "react";
import CommentItem from "@/components/shared/CommentItem"
const COMMENT_PER_PAGE = 5;
export default function CommentList( {item}:any ) {
const total = item?.length;
const [page, setPage] = useState(1);
const displayCount = page * COMMENT_PER_PAGE;
const hasMore = displayCount < total;
const commentData = item.slice(0, displayCount);
return (
<>
<div>
{
commentData.map( (comment:any) => <CommentItem item={comment} key={comment.id} />)
}
</div>
{hasMore &&
<div className="text-center mt-4">
<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

@@ -0,0 +1,16 @@
export default function Form() {
return (
<>
<textarea
className="p-3 w-full resize-none h-[96px] outline-none border-none"
defaultValue={""}
/>
<div className="border-t border-[#DDDDDD] bg-[#F5F6F7] p-[10px_12px] text-right">
<button type="button" aria-label="submit"
className="bg-btn text-white h-10 px-9 text-18 font-500 rounded-[30px]"
> GỬI </button>
</div>
</>
)
}

View File

@@ -0,0 +1,40 @@
import { CommentData } from "@/data/comments";
import Form from "./Form";
import CommentList from "./CommentList";
export default function Comment() {
return (
<div>
<div className="flex items-center justify-between leading-8 gap-2 mb-4">
<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">
<button type="button" aria-label="Đánh giá"
className="h-8 border border-[#D1D5DB] rounded-[40px] flex items-center gap-[3px] px-8 hover:border-[#0678DB] hover:text-[#0678DB] current"
> Tất cả </button>
{buildButtonFilter()}
</div>
</div>
<div className="border border-[#DDDDDD] rounded-[12px] overflow-hidden js-comment-form">
<Form />
</div>
{CommentData.list.length > 0 &&
<CommentList item={CommentData.list}/>
}
</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,38 +1,34 @@
import { formatPrice } from "@/lib/utils";
import ProductImage from "./image";
import ProductImage from "./images";
import Static from "./static";
import ProductDescription from "./description"
import Comment from "./comment";
import Review from "./review";
import Comment from "./comments";
import Review from "./reviews";
import ProductSpec from "./specifications";
import Article from "./article";
import Article from "./articles";
import ProductPrice from "./price";
import ProductOffer from "./offer";
import Buttons from "./button";
import Buttons from "./buttons";
import ProductSummary from "./summary";
export default async function ProductDetail({ slug }: any) {
const {
productName,
productId,
review,
visit,
quantity,
productSummary,
productImage, imageCollection,
price, marketPrice, deal_list, price_off, sale_rules,
hasVAT, warranty,
specialOffer,
productDescription,
productSpec
} = slug
import { ReviewData } from "@/data/reviews";
const image = {
productImage, imageCollection
export default async function ProductDetail({ slug }: any) {
const imageList = {
productImage : slug.productImage,
imageCollection : slug.imageCollection
}
const priceData = {
price, marketPrice, deal_list, price_off, sale_rules, hasVAT, warranty, quantity
price : slug.price,
marketPrice : slug.marketPrice,
deal_list : slug.deal_list,
price_off : slug.price_off,
sale_rules : slug.sale_rules,
hasVAT : slug.hasVAT,
warranty : slug.warranty,
quantity : slug.quantity
}
console.log(slug)
@@ -42,27 +38,27 @@ export default async function ProductDetail({ slug }: any) {
<div className="product-detail-page container">
<div className="pd-info-container static bg-white rounded-[24px] p-6 mb-6">
<h1 className="leading-8 text-[#004BA4] text-24 mb-6 font-600">
{productName}
{slug.productName}
</h1>
<div className="gap-6 flex flex-wrap items-start leading-[18px]">
<div className="col-left-group w-[424px] sticky top-[90px]">
<ProductImage data={image} />
<ProductImage data={imageList} />
</div>
<div className="col-middle-group w-[464px]">
<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">
<i className={`star star-${review.rate}`} />
<span className="font-500"> ({review.total}) </span>
<i className={`star star-${ReviewData.summary.avgRate}`} />
<span className="font-500"> ({ReviewData.summary.total}) </span>
</button>
<i className="w-[1px] h-4 bg-[#DEE4EC]" />
<p className="m-0">
Lượt xem:
<span className="text-[#004BA4] font-500">{formatPrice(visit)}</span>
<span className="text-[#004BA4] font-500">{formatPrice(slug.visit)}</span>
</p>
<i className="w-[1px] h-4 bg-[#DEE4EC]" />
@@ -71,7 +67,7 @@ export default async function ProductDetail({ slug }: any) {
Tình trạng:
<span
dangerouslySetInnerHTML={{
__html: quantity > 0
__html: slug.quantity > 0
? '<span class="font-500 text-[#00AD4F]">Còn hàng</span>'
: '<span class="font-500 red">Liên hệ</span>'
}}
@@ -79,15 +75,15 @@ export default async function ProductDetail({ slug }: any) {
</p>
</div>
{ productSummary &&
<ProductSummary item={productSummary} />
{ slug.productSummary &&
<ProductSummary item={slug.productSummary} />
}
<ProductPrice item={priceData} />
<ProductOffer item={specialOffer}/>
<ProductOffer item={slug.specialOffer}/>
<Buttons item={productId} />
<Buttons item={slug.productId} />
<p className="m-0 flex items-center gap-3 text-16 leading-[22px]">
<i className="icons icon-truck-2 !w-6" />
@@ -103,23 +99,32 @@ export default async function ProductDetail({ slug }: any) {
<div className="pd-content-container flex flex-wrap items-baseline gap-6">
<div className="col-left w-[784px]">
{ productDescription &&
<ProductDescription name={productName} description={productDescription} />
}
{ slug.productDescription &&
<ProductDescription
name={slug.productName}
description={slug.productDescription}
/>
}
<div className="pd-comment-container bg-white mb-6 p-8 pt-6 rounded-[24px] text-16 leading-[22px]">
<Review />
<p className="leading-[31px] font-600 text-24 mb-4 pb-4">
Đánh giá bình luận
</p>
<Review item={ReviewData}/>
<Comment />
</div>
</div>
<div className="col-right w-[440px]">
{productSpec &&
<ProductSpec item={productSpec} />
{slug.productSpec &&
<ProductSpec item={slug.productSpec} />
}
<Article />
{ slug.related['article-article'].length > 0 &&
<Article item={ slug.related['article-article'] } />
}
</div>
</div>

View File

@@ -1,227 +0,0 @@
export default function Review() {
return (
<>
<p className="leading-[31px] font-600 text-24 mb-4 pb-4">
{" "}
Đánh giá bình luận{" "}
</p>
{/* Rating */}
<div className="pd-rating-conatiner mb-9" id="js-pd-rating">
<div className="flex flex-wrap justify-between gap-6">
<div className="w-[200px] text-center">
<p className="font-600 text-[40px] leading-[48px] mb-2"> 0 </p>
<p className="my-2 text-[#6B7280]"> 0 lượt đánh giá </p>
<i className="star star-3" />
<button
className="rating-btn block h-10 w-full text-white text-14 font-500 rounded-[30px] bg-btn uppercase mt-3"
type="button"
aria-label="đánh giá"
/>
</div>
<div className="w-[calc(100%_-_224px)] text-14 font-500 leading-[18px] flex flex-col gap-4">
<div className="flex items-center justify-between gap-2 flex-wrap">
<p className="m-0 flex gap-[3px] w-[30px]">
{" "}
<span>5</span>{" "}
<i className="bx bxs-star text-[#FBBF24] text-16" />{" "}
</p>
<div className="relative bg-[#E8ECF6] overflow-hidden rounded-[30px] h-3 w-[calc(100%_-_71px)]">
<i
className="max-w-[100%] bg-[#0678DB] absolute inset-0"
style={{ width: "0%" }}
/>
</div>
<p className="m-0 text-[#6B7280] w-[25px] text-right"> 0 </p>
</div>
<div className="flex items-center justify-between gap-2 flex-wrap">
<p className="m-0 flex gap-[3px] w-[30px]">
<span>4</span>{" "}
<i className="bx bxs-star text-[#FBBF24] text-16" />
</p>
<div className="relative bg-[#E8ECF6] overflow-hidden rounded-[30px] h-3 w-[calc(100%_-_71px)]">
<i
className="max-w-[100%] bg-[#0678DB] absolute inset-0"
style={{ width: "0%" }}
/>
</div>
<p className="m-0 text-[#6B7280] w-[25px] text-right"> 0 </p>
</div>
<div className="flex items-center justify-between gap-2 flex-wrap">
<p className="m-0 flex gap-[3px] w-[30px]">
<span>3</span>{" "}
<i className="bx bxs-star text-[#FBBF24] text-16" />
</p>
<div className="relative bg-[#E8ECF6] overflow-hidden rounded-[30px] h-3 w-[calc(100%_-_71px)]">
<i
className="max-w-[100%] bg-[#0678DB] absolute inset-0"
style={{ width: "0%" }}
/>
</div>
<p className="m-0 text-[#6B7280] w-[25px] text-right"> 0 </p>
</div>
<div className="flex items-center justify-between gap-2 flex-wrap">
<p className="m-0 flex gap-[3px] w-[30px]">
<span>2</span>{" "}
<i className="bx bxs-star text-[#FBBF24] text-16" />
</p>
<div className="relative bg-[#E8ECF6] overflow-hidden rounded-[30px] h-3 w-[calc(100%_-_71px)]">
<i
className="max-w-[100%] bg-[#0678DB] absolute inset-0"
style={{ width: "0%" }}
/>
</div>
<p className="m-0 text-[#6B7280] w-[25px] text-right"> 0 </p>
</div>
<div className="flex items-center justify-between gap-2 flex-wrap">
<p className="m-0 flex gap-[3px] w-[30px]">
<span>1</span>{" "}
<i className="bx bxs-star text-[#FBBF24] text-16" />
</p>
<div className="relative bg-[#E8ECF6] overflow-hidden rounded-[30px] h-3 w-[calc(100%_-_71px)]">
<i
className="max-w-[100%] bg-[#0678DB] absolute inset-0"
style={{ width: "0%" }}
/>
</div>
<p className="m-0 text-[#6B7280] w-[25px] text-right"> 0 </p>
</div>
</div>
</div>
<div className="pd-rating-form mt-8 hidden">
<div className="flex items-center mb-4 gap-4">
<p className="m-0"> Chọn đánh giá của bạn </p>
<div className="rating-comment clearfix">
<input
type="radio"
className="rating-input"
id="rating-input-review-0-5"
defaultValue={5}
data-title="Quá tuyệt vời"
name="user_post[rate]"
defaultChecked={true}
/>
<label
htmlFor="rating-input-review-0-5"
className="rating-star js-rating-star"
data-title="Quá tuyệt vời"
/>
<input
type="radio"
className="rating-input"
id="rating-input-review-0-4"
defaultValue={4}
data-title="Rất tốt"
name="user_post[rate]"
/>
<label
htmlFor="rating-input-review-0-4"
className="rating-star js-rating-star"
data-title="Rất tốt"
/>
<input
type="radio"
className="rating-input"
id="rating-input-review-0-3"
defaultValue={3}
data-title="Bình thường"
name="user_post[rate]"
/>
<label
htmlFor="rating-input-review-0-3"
className="rating-star js-rating-star"
data-title="Bình thường"
/>
<input
type="radio"
className="rating-input"
id="rating-input-review-0-2"
defaultValue={2}
data-title="Tạm được"
name="user_post[rate]"
/>
<label
htmlFor="rating-input-review-0-2"
className="rating-star js-rating-star"
data-title="Tạm được"
/>
<input
type="radio"
className="rating-input"
id="rating-input-review-0-1"
defaultValue={1}
data-title="Không thích"
name="user_post[rate]"
/>
<label
htmlFor="rating-input-review-0-1"
className="rating-star js-rating-star"
data-title="Không thích"
/>
</div>
<span
id="js-star-tip"
className="star-tip bg-[#2b8ae0] text-white rounded-[3px] relative px-2 leading-[26px]"
>
{" "}
Quá tuyệt vời{" "}
</span>
</div>
<div className="lg:grid grid-cols-2 gap-3">
<textarea
className="w-full block p-3 resize-none h-[100px] outline-none border border-[#DDDDDD] rounded-[12px]"
placeholder="Nhập đánh giá của bạn"
defaultValue={""}
/>
<div className="grid lg:grid-cols-2 gap-2">
<input
type="text"
className="border border-[#DDDDDD] rounded-[8px] px-3"
placeholder="Họ tên*"
/>
<input
type="tel"
className="border border-[#DDDDDD] rounded-[8px] px-3"
inputMode="numeric"
pattern="[0-9]{10,11}"
maxLength={11}
placeholder="Số điện thoại*"
/>
<input
type="text"
className="border border-[#DDDDDD] rounded-[8px] px-3"
placeholder="Email*"
/>
<button
type="button"
className="bg-btn text-white rounded-[8px]"
aria-label="Đánh giá"
>
{" "}
Gửi đánh giá{" "}
</button>
</div>
<p className="red font-600"> </p>
</div>
</div>
<div className="text-14 leading-[18px] mt-4" id="">
<div className="last:border-0 border-b border-[#DDDDDD] py-5">
<div className="flex items-center gap-2 mb-2">
<b className="font-600 capitalize"> tên khách hàng </b>
<i className="bxr bxs-radio-circle text-[7px] text-[#6B7280]" />
<span className="text-[#6B7280]"> 11-11-2025, 11:11 </span>
</div>
<div className="flex flex-wrap gap-3">
<i className="star star-3 scale-[0.8] ml-[-7px]" />
<div className="w-[calc(100%-98px)]">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel
illum deserunt similique cumque accusantium qui assumenda
quod. Saepe illum beatae aspernatur odit, voluptatum voluptate
maiores dolore expedita similique officia consequuntur?
</div>
</div>
</div>
</div>
</div>
</>
)
}

View File

@@ -0,0 +1,101 @@
'use client';
import { useState, Fragment } from 'react';
export default function ReviewForm() {
const [rate, setRate] = useState(5);
const [rateTitle, setRateTitle] = useState('Quá tuyệt vời');
return (
<>
<div className="flex items-center mb-4 gap-4">
<p className="m-0"> Chọn đánh giá của bạn </p>
<div className="rating-comment clearfix">
<CreateStar
rate={rate}
setRate={setRate}
setRateTitle={setRateTitle}
/>
</div>
<span className="star-tip bg-[#2b8ae0] text-white rounded-[3px] px-2 leading-[26px]">
{rateTitle}
</span>
</div>
<div className="lg:grid grid-cols-2 gap-3">
<textarea
className="w-full block p-3 resize-none h-[100px] outline-none border border-[#DDDDDD] rounded-[12px]"
placeholder="Nhập đánh giá của bạn"
defaultValue={""}
/>
<div className="grid lg:grid-cols-2 gap-2">
<input
type="text"
className="border border-[#DDDDDD] rounded-[8px] px-3"
placeholder="Họ tên*"
/>
<input
type="tel"
className="border border-[#DDDDDD] rounded-[8px] px-3"
inputMode="numeric"
pattern="[0-9]{10,11}"
maxLength={11}
placeholder="Số điện thoại*"
/>
<input
type="text"
className="border border-[#DDDDDD] rounded-[8px] px-3"
placeholder="Email*"
/>
<button
type="button"
className="bg-btn text-white rounded-[8px]"
aria-label="Đánh giá"
>
Gửi đánh giá
</button>
</div>
<p className="red font-600"> </p>
</div>
</>
);
}
function CreateStar({ rate, setRate, setRateTitle }) {
const stars = [
{ rate: 5, title: 'Quá tuyệt vời' },
{ rate: 4, title: 'Rất tốt' },
{ rate: 3, title: 'Bình thường' },
{ rate: 2, title: 'Tạm được' },
{ rate: 1, title: 'Không thích' },
];
return (
<>
{stars.map(({ rate: star, title }) => (
<Fragment key={star}>
<input
type="radio"
className="rating-input"
name="user_post[rate]"
id={`rating-${star}`}
value={star}
checked={rate === star}
onChange={() => setRate(star)}
/>
<label
htmlFor={`rating-${star}`}
title={title}
className="rating-star js-rating-star"
onMouseEnter={() => setRateTitle(title)}
onClick={() => setRateTitle(title)}
/>
</Fragment>
))}
</>
);
}

View File

@@ -0,0 +1,38 @@
'use client';
import { useState } from "react";
import ReviewItem from "@/components/shared/ReviewItem";
const REVIEW_PER_PAGE = 5;
export default function ReviewList({ item }: any) {
const total = item?.length;
const [page, setPage] = useState(1);
const displayCount = page * REVIEW_PER_PAGE;
const hasMore = displayCount < total;
const reviewData = item.slice(0, displayCount);
return (
<>
{reviewData &&
reviewData.map((item:any) =>
<ReviewItem key={item.id} item={item} />
)
}
{ hasMore &&
<div className="text-center mt-4">
<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,71 @@
export default function StarPercent({ item }: any) {
const listRate = item?.list_rate || [];
const { count, percent } = getStarPercent(listRate);
return (
<>
{[5, 4, 3, 2, 1].map((star) => {
const starRating = star as StarRating;
return (
<div key={star}
className="flex items-center justify-between gap-2 flex-wrap">
<p className="m-0 flex gap-[3px] w-[30px]">
<span>{star}</span>
<i className="bx bxs-star text-[#FBBF24] text-16" />
</p>
<div className="relative bg-[#E8ECF6] overflow-hidden rounded-[30px] h-3 w-[calc(100%_-_71px)]">
<i
className="max-w-[100%] bg-[#0678DB] absolute inset-0"
style={{ width: `${percent[starRating]}%` }}
/>
</div>
<p className="m-0 text-[#6B7280] w-[25px] text-right"> {count[starRating]} </p>
</div>
);
})}
</>
)
}
type StarRating = 1 | 2 | 3 | 4 | 5;
function getStarPercent(list_rate: any[] = []) {
const result: Record<StarRating, number> = {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
};
let totalCount = 0;
list_rate.forEach(item => {
totalCount += item.total;
result[item.rate as StarRating] = item.total;
});
const percent: Record<StarRating, number> = {
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
};
if (totalCount > 0) {
Object.keys(result).forEach(key => {
percent[key as unknown as StarRating] = Math.round(
(result[key as unknown as StarRating] / totalCount) * 100
);
});
}
return {
count: result,
percent,
totalCount
};
}

View File

@@ -0,0 +1,45 @@
'use client';
import { useState } from "react";
import StarPercent from "./StarPercent";
import ReviewForm from "./Form"
import ReviewList from "./ReviewList";
export default function Review( {item} : any ) {
const [ show, setShow ] = useState(false);
return (
<>
<div className={`pd-rating-conatiner mb-9 ${show ? 'active' : ''}`} id="js-pd-rating">
<div className="flex flex-wrap justify-between gap-6">
<div className="w-[200px] text-center">
<p className="font-600 text-[40px] leading-[48px] mb-2"> {item.summary.avgRate}.0 </p>
<p className="my-2 text-[#6B7280]"> {item.summary.total} lượt đánh giá </p>
<i className={`star star-${item.summary.avgRate}`} />
<button
className="rating-btn block h-10 w-full text-white text-14 font-500 rounded-[30px] bg-btn uppercase mt-3"
type="button"
aria-label="đánh giá"
onClick={ () => setShow(show => !show) }
/>
</div>
<div className="w-[calc(100%_-_224px)] text-14 font-500 leading-[18px] flex flex-col gap-4">
<StarPercent item={item.summary} />
</div>
</div>
<div className="pd-rating-form mt-8 hidden">
<ReviewForm />
</div>
{item.list.length > 0 &&
<div className="text-14 leading-[18px] mt-4">
<ReviewList item={item.list}/>
</div>
}
</div>
</>
)
}

View File

@@ -1,7 +1,7 @@
import parse from 'html-react-parser';
export default function ProductSpec( {item} : any ) {
console.log(item)
return (
<div className="pd-box-group bg-white mb-6 px-4 py-6 rounded-[24px]">
<p className="group-title border-b border-[#D0D8E3] leading-[31px] font-600 text-24 mb-4 pb-4">
@@ -11,14 +11,15 @@ export default function ProductSpec( {item} : any ) {
<div className="pd-spec-group">
{parse(item)}
</div>
<a
href="#fancybox-spec"
data-fancybox=""
className="table m-auto mt-4 text-white leading-10 uppercase rounded-[40px] bg-btn font-500 text-16 px-6"
>
Xem tất cả thông số
</a>
<div
className="pd-spec-group p-3"
id="fancybox-spec"