Files
reui-blocks/blocks/reviews1.tsx
T

177 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
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.
import { BadgeCheck } from "lucide-react";
import { Rating } from "@/components/shadcnblocks/rating";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";
interface Review {
id: string;
rating: number;
title: string;
content: string;
author: {
name: string;
avatar?: string;
};
date: string;
verified?: boolean;
}
const DEFAULT_REVIEWS: Review[] = [
{
id: "1",
rating: 5,
title: "فراتر از انتظارم بود",
content:
"اول کمی تردید داشتم، ولی این محصول واقعاً جواب داد. کیفیت ساخت عالی است و زودتر از موعد به دستم رسید. اگر هنوز مردد هستید، حتماً پیشنهاد می‌کنم امتحان کنید.",
author: {
name: "سارا احمدی",
avatar: "/block-media/shadcnblocks/block/avatar-1.webp",
},
date: "۲۰ آذر ۱۴۰۳",
verified: true,
},
{
id: "2",
rating: 4,
title: "ارزش خرید بالا",
content:
"به‌طور کلی محصول خوبی است و دقیقاً همان کاری را می‌کند که باید. یک ستاره کم کردم چون بسته‌بندی می‌توانست بهتر باشد، ولی خود محصول عالی است.",
author: {
name: "مازیار رضایی",
avatar: "/block-media/shadcnblocks/block/avatar-2.webp",
},
date: "۱۸ آذر ۱۴۰۳",
verified: true,
},
{
id: "3",
rating: 5,
title: "عالی برای استفاده روزمره",
content:
"یک ماه است هر روز از آن استفاده می‌کنم و هنوز مثل روز اول به نظر می‌رسد و درست کار می‌کند. با این قیمت، کیفیت ساخت واقعاً قابل تحسین است. برای خواهرم هم یکی خریدم.",
author: {
name: "نیلوفر حسینی",
avatar: "/block-media/shadcnblocks/block/avatar-3.webp",
},
date: "۱۵ آذر ۱۴۰۳",
verified: true,
},
{
id: "4",
rating: 4,
title: "خوب، ولی کامل نیست",
content:
"محصول خوب است و درست کار می‌کند. تنها نکته کوچک این است که رنگ کمی با عکس‌ها فرق دارد، ولی در مجموع خرید رضایت‌بخشی بود.",
author: {
name: "امیر محمدی",
},
date: "۱۲ آذر ۱۴۰۳",
verified: false,
},
{
id: "5",
rating: 5,
title: "بهترین خرید امسالم",
content:
"واقعاً عاشقش شدم! به جزئیات با دقت زیادی توجه شده. وقتی سوال داشتم، پشتیبانی هم بسیار مفید بود. از هر نظر پنج ستاره.",
author: {
name: "رؤیا کاظمی",
avatar: "/block-media/shadcnblocks/block/avatar-7.webp",
},
date: "۸ آذر ۱۴۰۳",
verified: true,
},
];
interface Reviews1Props {
reviews?: Review[];
title?: string;
className?: string;
}
const Reviews1 = ({
reviews = DEFAULT_REVIEWS,
title = "نظرات مشتریان",
className,
}: Reviews1Props) => {
const averageRating =
reviews.reduce((sum, review) => sum + review.rating, 0) / reviews.length;
const formattedAverage = averageRating.toLocaleString("fa-IR", {
minimumFractionDigits: 1,
maximumFractionDigits: 1,
});
const reviewCountLabel = `${reviews.length.toLocaleString("fa-IR")} نظر`;
return (
<section
dir="rtl"
lang="fa"
className={cn("py-16 md:py-24", className)}
>
<div className="container max-w-3xl">
<div className="mb-8">
<h2 className="text-xl font-semibold tracking-tight md:text-3xl">
{title}
</h2>
<div className="mt-2 flex items-center gap-3">
<Rating rate={averageRating} className="[&_svg]:size-5" />
<span className="text-sm text-muted-foreground">
{formattedAverage} از ۵ · {reviewCountLabel}
</span>
</div>
</div>
<div className="space-y-0">
{reviews.map((review, index) => (
<div key={review.id}>
{index > 0 && <Separator className="my-6" />}
<div className="space-y-3">
<div>
<Rating rate={review.rating} className="[&_svg]:size-4" />
<h3 className="mt-2 font-medium">{review.title}</h3>
</div>
<p className="text-sm leading-relaxed text-muted-foreground">
{review.content}
</p>
<div className="flex items-center gap-3">
<Avatar className="size-8">
<AvatarImage
src={review.author.avatar}
alt={review.author.name}
/>
<AvatarFallback className="text-xs">
{review.author.name
.split(/\s+/)
.slice(0, 2)
.map((part) => part[0])
.join("")}
</AvatarFallback>
</Avatar>
<div className="flex items-center gap-2 text-sm">
<span className="font-medium">{review.author.name}</span>
{review.verified && (
<span className="flex items-center gap-1 text-emerald-600">
<BadgeCheck className="size-4" />
<span className="text-xs">خرید تأییدشده</span>
</span>
)}
<span className="text-muted-foreground">·</span>
<span className="text-muted-foreground">{review.date}</span>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</section>
);
};
export { Reviews1 };