178 lines
6.7 KiB
JavaScript
178 lines
6.7 KiB
JavaScript
"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 lot’s 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;
|