Files
reui-blocks/blocks/testimonial1.tsx
T

226 lines
9.4 KiB
TypeScript

import { Avatar, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardFooter } from "@/components/ui/card";
import { cn } from "@/lib/utils";
const testimonials = [
{
name: "سارا احمدی",
role: "مدیرعامل و بنیان‌گذار",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar9.jpg",
content:
"این کتابخانه کامپوننت، روش ساخت محصولات ما را متحول کرد. کل داشبورد را در نصف زمانی که معمولاً لازم بود، تحویل دادیم.",
},
{
name: "مازیار رضایی",
role: "مدیر فناوری",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar7.jpg",
content:
"توجه به دسترس‌پذیری و عملکرد قابل تحسین است. امتیاز ابزار تحلیل عملکرد ما پس از استفاده از این کامپوننت‌ها به‌طور محسوسی بهبود یافت.",
},
{
name: "نیلوفر حسینی",
role: "مدیر محصول",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar10.jpg",
content:
"بالاخره یک سیستم طراحی که توسعه‌دهندگان واقعاً دوست دارند از آن استفاده کنند. مستندات روشن است، کامپوننت‌ها انعطاف‌پذیرند و مقادیر پیش‌فرض منطقی‌اند. کم پیش می‌آید هر سه را با هم ببینید.",
},
{
name: "امیر محمدی",
role: "سرپرست فنی",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar7.webp",
content:
"سال‌ها کتابخانه‌های مختلف رابط کاربری را امتحان کردیم. این یکی تعادل عالی بین پیش‌فرض‌های مشخص و انعطاف سفارشی‌سازی برقرار می‌کند.",
},
{
name: "رؤیا کاظمی",
role: "طراح ارشد",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar2.webp",
content:
"به‌عنوان طراح، قدردانم که کامپوننت‌ها به‌طور دقیق با طرح‌های طراحی رابط ما هم‌خوان‌اند. تحویل از طراحی به توسعه هرگز این‌قدر روان نبوده. هر پیکسل هدفمند است و سیستم فاصله‌گذاری حفظ یکنواختی در صفحات را آسان می‌کند. با کتابخانه‌های زیادی کار کرده‌ام، اما این اولین بار است که مجبور نیستم مدام استایل‌ها را بازنویسی کنم.",
},
{
name: "پارسا موسوی",
role: "توسعه‌دهنده فول‌استک",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar11.jpg",
content:
"پشتیبانی زبان نوع‌ایمن عالی است. تکمیل خودکار بدون دردسر کار می‌کند و خطاها را پیش از رسیدن به محیط تولید می‌گیرم. تجربه توسعه در سطح بالایی است.",
},
{
name: "مهسا نوری",
role: "مهندس تجربه کاربری",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar2.jpg",
content:
"این کامپوننت‌ها موارد خاصی را پوشش می‌دهند که حتی از وجودشان بی‌خبر بودم. حالت تاریک، پشتیبانی راست‌به‌چپ و ناوبری با صفحه‌کلید همه از پیش آماده‌اند.",
},
{
name: "علی رحمانی",
role: "مدیر مهندسی",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar12.jpg",
content:
"سرعت تیم ما پس از استفاده از این کتابخانه به‌طور محسوسی افزایش یافت. زمان کمتر برای کدهای تکراری رابط کاربری یعنی زمان بیشتر برای منطق کسب‌وکار.",
},
];
interface Testimonial1Props {
className?: string;
}
const Testimonial1 = ({ className }: Testimonial1Props) => {
const getColumns = (count: number) => {
return Array.from({ length: count }, (_, colIdx) =>
testimonials.filter((_, i) => i % count === colIdx),
);
};
const mobileColumns = getColumns(2);
const tabletColumns = getColumns(3);
const desktopColumns = getColumns(4);
return (
<section
dir="rtl"
lang="fa"
className={cn("overflow-hidden border-b pt-32", className)}
>
<div className="container">
<div className="flex flex-col items-center gap-6">
<Badge variant="outline">نظرات مشتریان</Badge>
<h2 className="text-center text-3xl tracking-tight lg:text-2xll">
با مشتریان راضی ما آشنا شوید
</h2>
<p className="text-center text-muted-foreground lg:text-lg">
تجربه تیم‌هایی را بخوانید که با کامپوننت‌های ما گردش کار خود را
متحول کرده‌اند.
</p>
</div>
</div>
<div className="container mt-10 h-[450px] md:h-[500px] lg:h-[522px]">
{/* Mobile: 2 columns */}
<div className="flex gap-4 md:hidden">
{mobileColumns.map((column, colIdx) => (
<div
key={colIdx}
className={cn(
"flex w-1/2 flex-col gap-4",
colIdx === 1 && "mt-8",
)}
>
{column.map((testimonial, idx) => (
<Card key={idx}>
<CardContent className="px-4 text-sm leading-6 text-muted-foreground">
<q>{testimonial.content}</q>
</CardContent>
<CardFooter className="px-4">
<div className="flex gap-3 leading-5">
<Avatar className="size-8 rounded-full ring-1 ring-input">
<AvatarImage
src={testimonial.avatar}
alt={testimonial.name}
/>
</Avatar>
<div className="text-xs">
<p className="font-medium">{testimonial.name}</p>
<p className="text-muted-foreground">
{testimonial.role}
</p>
</div>
</div>
</CardFooter>
</Card>
))}
</div>
))}
</div>
{/* Tablet: 3 columns */}
<div className="hidden gap-4 md:flex lg:hidden">
{tabletColumns.map((column, colIdx) => (
<div
key={colIdx}
className={cn(
"flex w-1/3 flex-col gap-4",
colIdx === 1 && "mt-10",
colIdx === 2 && "mt-20",
)}
>
{column.map((testimonial, idx) => (
<Card key={idx}>
<CardContent className="px-6 leading-7 text-muted-foreground">
<q>{testimonial.content}</q>
</CardContent>
<CardFooter>
<div className="flex gap-4 leading-5">
<Avatar className="size-9 rounded-full ring-1 ring-input">
<AvatarImage
src={testimonial.avatar}
alt={testimonial.name}
/>
</Avatar>
<div className="text-sm">
<p className="font-medium">{testimonial.name}</p>
<p className="text-muted-foreground">
{testimonial.role}
</p>
</div>
</div>
</CardFooter>
</Card>
))}
</div>
))}
</div>
{/* Desktop: 4 columns */}
<div className="hidden gap-4 lg:flex">
{desktopColumns.map((column, colIdx) => (
<div
key={colIdx}
className={cn(
"flex w-1/4 flex-col gap-4",
colIdx === 1 && "mt-10",
colIdx === 2 && "mt-20",
)}
>
{column.map((testimonial, idx) => (
<Card key={idx}>
<CardContent className="px-6 leading-7 text-muted-foreground">
<q>{testimonial.content}</q>
</CardContent>
<CardFooter>
<div className="flex gap-4 leading-5">
<Avatar className="size-9 rounded-full ring-1 ring-input">
<AvatarImage
src={testimonial.avatar}
alt={testimonial.name}
/>
</Avatar>
<div className="text-sm">
<p className="font-medium">{testimonial.name}</p>
<p className="text-muted-foreground">
{testimonial.role}
</p>
</div>
</div>
</CardFooter>
</Card>
))}
</div>
))}
</div>
</div>
</section>
);
};
export { Testimonial1 };