2025-12-26 13:56:59 +05:30

178 lines
6.7 KiB
JavaScript
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.

"use client";
import { sliderProps } from "@/utility/sliderProps";
import Slider from "react-slick";
import { useEffect, useState } from "react";
import Link from "next/link";
const Testimonial = () => {
const [reviews, setReviews] = useState([]);
const [loading, setLoading] = useState(true);
const [expandedReview, setExpandedReview] = useState(null);
useEffect(() => {
async function loadReviews() {
try {
const res = await fetch("/api/reviews");
const data = await res.json();
const cleaned = (data.reviews || []).filter(r =>
(r.text || r.description || r.snippet || r.review_text || r.body || r.content) &&
r.rating >= 4
);
setReviews(cleaned);
} catch (error) {
console.error("Home: Failed to fetch reviews", error);
} finally {
setLoading(false);
}
}
loadReviews();
}, []);
function renderStars(rating) {
return [...Array(5)].map((_, i) => (
<i key={i} className={`fa fa-star ${i < rating ? "text-warning" : "text-white"}`}></i>
));
}
function getReviewText(r) {
return r.text || r.description || r.snippet || r.review_text || r.body || r.content || "";
}
function truncateText(text) {
return text.length > 200 ? text.substring(0, 200) + "..." : text;
}
function getProfileImage(r) {
const url = r.profile_photo_url || r.author_profile_photo_url || r.user?.thumbnail;
if (!url) return null;
return url.startsWith("http") ? url : `https://lh3.googleusercontent.com/${url}`;
}
function getInitials(name) {
if (!name) return "U";
return name.split(' ').map(n => n[0]).join('').substring(0, 2).toUpperCase();
}
return (
<section
className="testimonials-two bgc-primary"
style={{
backgroundImage: "url(/assets/images/testimonials/testimonials-two-bg.png)",
}}
>
<div className="row align-items-center">
<div className="col-lg-6">
<div className="why-choose-two-image">
<img
src="/assets/images/home/home-testi.webp"
alt="Testimonials" loading="lazy"
/>
</div>
</div>
<div className="col-lg-6">
<div className="testimonials-two-content rel z-1 text-center text-white p-45 rpy-55">
<div
className="section-title mb-20"
data-aos="fade-up"
data-aos-duration={1500}
data-aos-offset={50}
>
<span className="sub-title mb-5">customer feedback</span>
<h2>what have lots off happy customer explore feedback</h2>
</div>
<span className="marquee-wrap style-two">
<span className="marquee-inner left">review </span>
<span className="marquee-inner left">review </span>
<span className="marquee-inner left">review </span>
</span>
{loading ? (
<div className="text-center">
<p>Loading reviews...</p>
</div>
) : (
<Slider
{...sliderProps.testimonialsTwoCarousel}
className="testimonials-two-carousel"
data-aos="fade-up"
data-aos-delay={50}
data-aos-duration={1500}
data-aos-offset={50}
>
{reviews.map((r, index) => {
const name = r.user?.name || r.author_name || "Customer";
const profileImg = getProfileImage(r);
const fullText = getReviewText(r);
const isExpanded = expandedReview === index;
return (
<div key={index} className="testimonial-two-item">
<div className="google-review-header-flex">
<div className="google-avatar" style={{
width: '75px',
height: '75px',
minWidth: '75px',
borderRadius: '50%',
overflow: 'hidden',
background: '#eee',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: '2px solid #fff'
}}>
{profileImg ? (
<img
src={profileImg}
alt={name}
onError={(e) => (e.target.style.display = 'none')}
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
/>
) : (
<span style={{ fontSize: '24px', fontWeight: 'bold', color: '#555' }}>{getInitials(name)}</span>
)}
</div>
<div className="google-info-right">
<span className="google-name">{name}</span>
<div className="ratting">
{renderStars(r.rating)}
</div>
</div>
</div>
<div className="text">
{isExpanded ? fullText : truncateText(fullText)}
</div>
{fullText.length > 200 && (
<button
className="read-more-btn"
onClick={(e) => {
e.stopPropagation();
setExpandedReview(isExpanded ? null : index);
}}
>
{isExpanded ? "Read Less" : "Read More"}
</button>
)}
</div>
);
})}
</Slider>
)}
<div className="new-button d-flex justify-content-center pt-30">
<Link
legacyBehavior
href="https://www.google.com/maps/place/SHIVA+SAKTHI+RESTAURANT/@43.70693,-79.6499035,17z/data=!4m8!3m7!1s0x882b3ba1c0c9271b:0x7a783eaad5a6af6e!8m2!3d43.70693!4d-79.6473286!9m1!1b1!16s%2Fg%2F11wh3sh7p4?entry=ttu&g_ep=EgoyMDI1MTIwOS4wIKXMDSoASAFQAw%3D%3D"
>
<a target="_blank" className="theme-btn style-three">Review us on Google</a>
</Link>
</div>
<div className="shape">
<img src="assets/images/shapes/tomato.png" alt="Shape" loading="lazy" />
</div>
</div>
</div>
</div>
</section>
);
};
export default Testimonial;