southernmonsarysupply/components/testimonials-carousel.tsx

77 lines
2.0 KiB
TypeScript

"use client";
import { motion } from "framer-motion";
type Review = {
name: string;
rating: string;
dateLabel: string;
quote: string;
};
type Props = {
reviews: Review[];
};
function StarRating({ rating }: { rating: string }) {
const score = parseFloat(rating);
const full = Math.floor(score);
return (
<div className="tc-stars" aria-label={`${rating} stars`}>
{Array.from({ length: 5 }).map((_, i) => (
<span key={i} className={i < full ? "tc-star filled" : "tc-star"}>
</span>
))}
</div>
);
}
function ReviewCard({ review }: { review: Review }) {
return (
<motion.article
className="tc-card"
whileHover={{ y: -6, boxShadow: "0 20px 40px rgba(0,0,0,0.12)" }}
transition={{ duration: 0.25, ease: "easeOut" }}
>
<div className="tc-card-top">
<StarRating rating={review.rating} />
<span className="tc-date">{review.dateLabel}</span>
</div>
<blockquote className="tc-quote">"{review.quote}"</blockquote>
<footer className="tc-author">
<div className="tc-avatar" aria-hidden="true">
{review.name[0]}
</div>
<div>
<strong className="tc-name">{review.name}</strong>
<span className="tc-source">Google Review</span>
</div>
</footer>
</motion.article>
);
}
export function TestimonialsCarousel({ reviews }: Props) {
// Triple the items for a seamless infinite loop at any scroll speed
const tripled = [...reviews, ...reviews, ...reviews];
return (
<div className="tc-wrapper">
<div className="tc-track-container">
<div className="tc-track">
{tripled.map((review, i) => (
<div className="tc-slide" key={i}>
<ReviewCard review={review} />
</div>
))}
</div>
</div>
{/* Edge fade overlays */}
<div className="tc-fade-left" aria-hidden="true" />
<div className="tc-fade-right" aria-hidden="true" />
</div>
);
}