Files
techzaa-frontend/src/components/TestimonialsSection.tsx
T

208 lines
8.1 KiB
TypeScript
Raw Normal View History

2026-03-30 20:20:21 +06:00
import { useState, useEffect, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Star, ChevronLeft, ChevronRight, Quote } from 'lucide-react';
import { Button } from '@/components/ui/button';
import useEmblaCarousel from 'embla-carousel-react';
import Autoplay from 'embla-carousel-autoplay';
2026-04-04 23:46:10 +06:00
import { useReviews } from '@/hooks/queires/useReviews';
2026-03-30 20:20:21 +06:00
const testimonials = [
{
id: 1,
name: 'Jennifer Martinez',
role: 'CEO, InnovateTech',
avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=150&h=150&fit=crop&crop=face',
rating: 5,
quote: 'TechZaa transformed our entire digital infrastructure. Their AI solutions increased our operational efficiency by 40%. Absolutely incredible team to work with!',
},
{
id: 2,
name: 'Michael Chen',
role: 'CTO, FutureScale',
avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=150&h=150&fit=crop&crop=face',
rating: 5,
quote: 'The mobile app they developed for us exceeded all expectations. User engagement increased by 200% within the first month. Highly recommend their services.',
},
{
id: 3,
name: 'Sarah Thompson',
role: 'Director of Operations, CloudFirst',
avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=150&h=150&fit=crop&crop=face',
rating: 5,
quote: 'Their cloud migration expertise saved us countless hours and reduced our infrastructure costs by 35%. Professional, efficient, and always available.',
},
{
id: 4,
name: 'David Rodriguez',
role: 'Founder, StartupLabs',
avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop&crop=face',
rating: 5,
quote: 'From concept to launch, TechZaa was with us every step. Their attention to detail and innovative approach made our product stand out in a crowded market.',
},
{
id: 5,
name: 'Emily Watson',
role: 'VP Engineering, DataFlow',
avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=150&h=150&fit=crop&crop=face',
rating: 5,
quote: 'The best tech partner we\'ve ever worked with. Their team understood our vision and delivered a solution that perfectly aligned with our business goals.',
},
];
export default function TestimonialsSection() {
2026-04-04 23:46:10 +06:00
const {data: reveiwsData} = useReviews();
const testimonials = reveiwsData?.data.data;
2026-03-30 20:20:21 +06:00
const [emblaRef, emblaApi] = useEmblaCarousel(
{ loop: true, align: 'center' },
[Autoplay({ delay: 5000, stopOnInteraction: false })]
);
const [selectedIndex, setSelectedIndex] = useState(0);
const scrollPrev = useCallback(() => emblaApi?.scrollPrev(), [emblaApi]);
const scrollNext = useCallback(() => emblaApi?.scrollNext(), [emblaApi]);
const onSelect = useCallback(() => {
if (!emblaApi) return;
setSelectedIndex(emblaApi.selectedScrollSnap());
}, [emblaApi]);
useEffect(() => {
if (!emblaApi) return;
onSelect();
emblaApi.on('select', onSelect);
return () => {
emblaApi.off('select', onSelect);
};
}, [emblaApi, onSelect]);
return (
<section id="testimonials" className="py-24 relative overflow-hidden">
{/* Background */}
<div className="absolute inset-0">
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-primary/10 rounded-full blur-3xl" />
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-neon-purple/10 rounded-full blur-3xl" />
</div>
<div className="container mx-auto px-4 relative z-10">
{/* Section Header */}
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-16"
>
<span className="inline-block px-4 py-2 rounded-full glass text-primary text-sm font-medium mb-4">
Client Stories
</span>
<h2 className="text-4xl md:text-5xl font-bold mb-6">
What Our <span className="text-primary neon-text-glow">Clients Say</span>
</h2>
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
Don't just take our word for it - hear from the amazing companies we've had the pleasure of working with.
</p>
</motion.div>
{/* Carousel */}
<div className="relative max-w-5xl mx-auto">
{/* Navigation Buttons */}
<Button
variant="outline"
size="icon"
onClick={scrollPrev}
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-4 z-10 rounded-full glass border-primary/30 hover:neon-glow hidden md:flex"
>
<ChevronLeft className="w-5 h-5" />
</Button>
<Button
variant="outline"
size="icon"
onClick={scrollNext}
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-4 z-10 rounded-full glass border-primary/30 hover:neon-glow hidden md:flex"
>
<ChevronRight className="w-5 h-5" />
</Button>
{/* Carousel Container */}
<div className="overflow-hidden" ref={emblaRef}>
<div className="flex">
2026-04-04 23:46:10 +06:00
{testimonials?.map((testimonial, index) => (
2026-03-30 20:20:21 +06:00
<div
2026-04-04 23:46:10 +06:00
key={testimonial._id}
2026-03-30 20:20:21 +06:00
className="flex-[0_0_100%] min-w-0 px-4 md:flex-[0_0_80%] lg:flex-[0_0_60%]"
>
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{
opacity: selectedIndex === index ? 1 : 0.5,
scale: selectedIndex === index ? 1 : 0.9,
}}
transition={{ duration: 0.4 }}
className="glass-strong rounded-3xl p-8 md:p-10 relative"
>
{/* Quote Icon */}
<div className="absolute -top-4 -left-4 w-12 h-12 rounded-full bg-primary flex items-center justify-center neon-glow">
<Quote className="w-6 h-6 text-primary-foreground" />
</div>
{/* Stars */}
<div className="flex gap-1 mb-6">
2026-04-04 23:46:10 +06:00
{[...Array(testimonial.rating)]?.map((_, i) => (
2026-03-30 20:20:21 +06:00
<Star
key={i}
className="w-5 h-5 fill-primary text-primary"
/>
))}
</div>
{/* Quote */}
<p className="text-lg md:text-xl text-foreground/90 mb-8 leading-relaxed">
2026-04-04 23:46:10 +06:00
"{testimonial.review}"
2026-03-30 20:20:21 +06:00
</p>
{/* Author */}
<div className="flex items-center gap-4">
<img
2026-04-04 23:46:10 +06:00
src={testimonial.thumbnail}
alt={testimonial.client_name}
2026-03-30 20:20:21 +06:00
className="w-14 h-14 rounded-full object-cover border-2 border-primary/50"
/>
<div>
<h4 className="font-bold text-foreground">
2026-04-04 23:46:10 +06:00
{testimonial.client_name}
2026-03-30 20:20:21 +06:00
</h4>
<p className="text-sm text-muted-foreground">
2026-04-04 23:46:10 +06:00
{testimonial.designation}
2026-03-30 20:20:21 +06:00
</p>
</div>
</div>
</motion.div>
</div>
))}
</div>
</div>
{/* Dots Indicator */}
<div className="flex justify-center gap-2 mt-8">
2026-04-04 23:46:10 +06:00
{testimonials?.map((_, index) => (
2026-03-30 20:20:21 +06:00
<button
key={index}
onClick={() => emblaApi?.scrollTo(index)}
className={`w-2 h-2 rounded-full transition-all duration-300 ${
selectedIndex === index
? 'w-8 bg-primary neon-glow'
: 'bg-muted-foreground/30 hover:bg-muted-foreground/50'
}`}
aria-label={`Go to slide ${index + 1}`}
/>
))}
</div>
</div>
</div>
</section>
);
}