Files
shop-front/src/app/product/components/Reviews.tsx
T
hamid zarghami 554312ddc6 add comments
2025-09-07 15:37:00 +03:30

128 lines
6.4 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import { FC, useMemo, useState } from 'react'
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import { Star1 } from 'iconsax-react'
import { Product, Review } from '@/types/product.types'
import AddComment from './AddComment'
interface ReviewsProps {
product: Product
reviews?: Review[]
}
const Reviews: FC<ReviewsProps> = ({ reviews = [] }) => {
const [sort, setSort] = useState<'new' | 'helpful'>('new')
const [open, setOpen] = useState(false)
const sortedReviews = useMemo(() => {
if (sort === 'new') {
return [...reviews].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
}
return [...reviews].sort((a, b) => b.helpful - a.helpful)
}, [sort, reviews])
const average = useMemo(() => {
if (reviews.length === 0) return '0.0'
const sum = reviews.reduce((acc, r) => acc + r.rating, 0)
return (sum / reviews.length).toFixed(1)
}, [reviews])
const formatDate = (dateString: string) => {
const date = new Date(dateString)
return date.toLocaleDateString('fa-IR')
}
return (
<div className="mt-12 sm:mt-16 w-full">
<div className="flex items-center justify-end gap-3 flex-row-reverse">
<h2 className="text-primary text-base sm:text-lg">نظرات خریداران</h2>
<div className="w-1 h-6 bg-primary rounded"></div>
</div>
<div className="mt-4 sm:mt-6 grid grid-cols-12 gap-4 sm:gap-6">
<div className="col-span-12 md:col-span-9 md:order-last">
<div className="flex flex-col sm:flex-row sm:items-center justify-start gap-2 sm:gap-4 text-xs sm:text-sm text-[#7F7F7F]">
<span>مرتب سازی بر اساس:</span>
<div className="flex items-center gap-4 sm:gap-6">
<button
type="button"
onClick={() => setSort('new')}
className={
sort === 'new' ? 'text-primary font-medium' : 'text-[#B2B2B2] hover:text-primary'
}
>
جدیدترین
</button>
<button
type="button"
onClick={() => setSort('helpful')}
className={
sort === 'helpful' ? 'text-primary font-medium' : 'text-[#B2B2B2] hover:text-primary'
}
>
مفیدترین
</button>
</div>
</div>
<div className="mt-4 sm:mt-6 rounded-xl bg-white">
{sortedReviews.length > 0 ? (
sortedReviews.map((review, idx) => (
<div key={review._id} className="px-4 sm:px-6 py-4 sm:py-5">
<div className="flex flex-col sm:flex-row sm:items-center justify-start gap-2 sm:gap-3">
<div className="px-2 py-0.5 rounded-full bg-[#02A55A] text-white text-xs w-fit">
{review.rating.toFixed(1)}
</div>
<div className="flex flex-wrap items-center gap-1 sm:gap-2 text-xs text-[#999999]">
{review.isVerified && (
<span className="px-2 py-0.5 rounded bg-[#F1F1F1] text-[#7F7F7F]">خریدار</span>
)}
<span className="size-1.5 rounded-full bg-[#E5E5E5]"></span>
<span>{formatDate(review.date)}</span>
<span className="size-1.5 rounded-full bg-[#E5E5E5]"></span>
<span>{review.user.name}</span>
</div>
</div>
<div className="mt-3 text-[#333333] text-xs sm:text-sm leading-6 sm:leading-7 text-right">
{review.comment}
</div>
{idx !== sortedReviews.length - 1 && <div className="mt-4 sm:mt-5"> <Separator /> </div>}
</div>
))
) : (
<div className="px-4 sm:px-6 py-8 text-center text-[#999999] text-sm">
هنوز نظری ثبت نشده است
</div>
)}
</div>
</div>
<div className="col-span-12 md:col-span-3 order-first md:order-first">
<div className="rounded-[10px] p-4 sm:p-6 h-fit md:sticky md:top-[170px]">
<div className="text-primary text-xs sm:text-sm">نظرات خریداران</div>
<div className="mt-3 sm:mt-4 flex items-center justify-end gap-2">
<Star1 size={16} color="#FFC107" variant="Bold" className="sm:w-[18px] sm:h-[18px]" />
<div className="text-xs sm:text-sm">
<span className="font-medium">{average}</span>
<span className="text-[#7F7F7F]"> / 5</span>
</div>
</div>
<div className="mt-3 sm:mt-4 text-xs text-[#7F7F7F] leading-5 sm:leading-6 text-justify">
شما هم درباره این کالا نظر خود را ثبت کنید. نظر شما پس از بررسی و تایید نمایش داده میشود.
</div>
<Button className="w-full mt-4 sm:mt-5 text-xs sm:text-sm" onClick={() => setOpen(true)}>ثبت دیدگاه</Button>
</div>
</div>
</div>
<AddComment open={open} close={() => setOpen(false)} />
</div>
)
}
export default Reviews