import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import type { CarouselApi } from '@/components/ui/carousel';
import { Carousel, CarouselContent, CarouselItem } from '@/components/ui/carousel';
import { ArrowLeft, ArrowRight, Star } from 'lucide-react';
import { useCallback, useState } from 'react';
interface Testimonial {
id: number;
name: string;
role: string;
avatar: string;
rating: number;
feedback: string;
}
const testimonials: Testimonial[] = [
{
id: 1,
name: 'Sarah Chen',
role: 'Marketing Director',
avatar: 'https://blookie.io/stock/person1.webp',
rating: 5,
feedback:
'This platform has completely transformed how we manage our campaigns. The analytics are really intuative and definitely actionable.',
},
{
id: 2,
name: 'Michael Rodriguez',
role: 'Software Engineer',
avatar: 'https://blookie.io/stock/person2.webp',
rating: 4,
feedback:
'Clean, efficient, and well-documented. Integration was seamless and the API is really developer-friendly. I recommend this product.',
},
{
id: 3,
name: 'David Park',
role: 'Operations Manager',
avatar: 'https://blookie.io/stock/person3.webp',
rating: 5,
feedback:
'Outstanding customer support and the automation features have saved us countless hours every week. A game changer for our business.',
},
{
id: 4,
name: 'Emily Thompson',
role: 'Creative Director',
avatar: 'https://blookie.io/stock/person4.webp',
rating: 4,
feedback:
'The design tools are intuitive and powerful. Our team productivity has increased significantly and we will continue using this product.',
},
];
export default function TestimonialCarousel() {
const [api, setApi] = useState<CarouselApi>();
const scrollPrev = useCallback(() => {
api?.scrollPrev();
}, [api]);
const scrollNext = useCallback(() => {
api?.scrollNext();
}, [api]);
return (
<section className="py-16 lg:py-32">
<div className="mx-auto w-full max-w-2xl px-6 lg:max-w-7xl">
<div className="flex flex-col items-center justify-between gap-6 sm:flex-row">
<h2 className="text-3xl/tight font-semibold tracking-tight sm:text-4xl/tight">What Users Say</h2>
<div className="space-x-4">
<Button onClick={scrollPrev} variant="outline" size="icon">
<ArrowLeft />
</Button>
<Button onClick={scrollNext} variant="outline" size="icon">
<ArrowRight />
</Button>
</div>
</div>
<Carousel
setApi={setApi}
opts={{
align: 'start',
loop: true,
dragFree: true,
}}
className="mt-12 w-full"
>
<CarouselContent className="-ml-4 lg:-ml-6">
{testimonials.map((testimonial) => (
<CarouselItem key={testimonial.id} className="basis-full pl-4 sm:basis-1/2 lg:basis-1/3 lg:pl-6">
<Card className="hover:border-primary h-full transition-all duration-300 hover:shadow-md">
<CardContent className="flex h-full flex-col">
<div className="flex items-center gap-2">
{[...Array(5)].map((_, i) => (
<Star
key={i}
className={`size-4 ${i < testimonial.rating ? 'fill-amber-400 text-amber-400' : 'text-gray-300'}`}
/>
))}
</div>
<p className="text-muted-foreground mt-4 mb-4 flex-grow text-sm/6">{testimonial.feedback}</p>
<div className="mt-auto flex items-center gap-4">
<Avatar className="size-10">
<AvatarImage src={testimonial.avatar || '/placeholder.svg'} alt={testimonial.name} />
<AvatarFallback className="text-sm sm:text-base">{testimonial.name.charAt(0)}</AvatarFallback>
</Avatar>
<div className="flex flex-col gap-0.5">
<span className="text-sm font-semibold">{testimonial.name}</span>
<span className="text-muted-foreground text-xs">{testimonial.role}</span>
</div>
</div>
</CardContent>
</Card>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
</div>
</section>
);
}