shivas-dosa/components/TestimonialAbout.js
2025-12-26 14:05:50 +05:30

279 lines
9.9 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 { useEffect, useState } from "react";
import Slider from "react-slick";
function TestimonialAbout() {
const [nav1, setNav1] = useState(null);
const [nav2, setNav2] = useState(null);
const [slider1, setSlider1] = useState(null);
const [slider2, setSlider2] = useState(null);
const [reviews, setReviews] = useState([]);
const [loading, setLoading] = useState(true);
const [expandedReview, setExpandedReview] = useState(null);
useEffect(() => {
setNav1(slider1);
setNav2(slider2);
}, [slider1, slider2]);
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("About: Failed to fetch reviews", error);
} finally {
setLoading(false);
}
}
loadReviews();
}, []);
const displayedReviews = reviews.length > 0 && reviews.length < 3
? [...reviews, ...reviews, ...reviews]
: reviews;
function renderStars(rating) {
return [...Array(5)].map((_, i) => (
<i key={i} className={`fa fa-star ${i < rating ? "text-warning" : ""}`} style={{ marginRight: '5px' }}></i>
));
}
function getReviewText(r) {
return r.text || r.description || r.snippet || r.review_text || r.body || r.content || "";
}
function truncateText(text) {
return text.length > 150 ? text.substring(0, 150) + "..." : 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();
}
const link = "https://www.google.com/maps/place/Shivas+Dosa+Restaurant/@43.4056825,-80.5035997,17z/data=!4m8!3m7!1s0x882bf579045db13b:0x258e9b3ccf2549d4!8m2!3d43.4056825!4d-80.5010248!9m1!1b1!16s%2Fg%2F11tj6q0n1j?entry=ttu&g_ep=EgoyMDI1MTIwOS4wIKXMDSoASAFQAw%3D%3D";
const thumbs = {
dots: false,
arrows: false,
speed: 800,
autoplay: true,
focusOnSelect: true,
slidesToShow: 3,
slidesToScroll: 1,
};
const slider = {
arrows: false,
dots: false,
infinite: false,
autoplay: true,
speed: 500,
fade: true,
slidesToShow: 1,
slidesToScroll: 1,
};
return (
<section className="testimonials-five rel z-1 py-130 rpy-100">
<div className="container rel">
<div className="row text-center justify-content-center">
<div className="col-xl-6 col-lg-7 col-md-8">
<div
className="section-title mb-50"
data-aos="fade-up"
data-aos-duration={1500}
data-aos-offset={50}
>
<span className="sub-title mb-5">Customer Feedback</span>
<h2>what our customers say us</h2>
</div>
{/* <Slider
asNavFor={nav1}
ref={(slider) => setSlider2(slider)}
{...sliderProps.testimonialsFiveAuthors}
className="testimonials-five-authors mb-20"
data-aos="fade-up"
data-aos-delay={50}
data-aos-duration={1500}
data-aos-offset={50}
>
<div className="testimonial-five-author-item">
<img
src="assets/images/testimonials/testi-author-five1.jpg"
alt="Author"
/>
</div>
<div className="testimonial-five-author-item">
<img
src="assets/images/testimonials/testi-author-five2.jpg"
alt="Author"
/>
</div>
<div className="testimonial-five-author-item">
<img
src="assets/images/testimonials/testi-author-five3.jpg"
alt="Author"
/>
</div>
<div className="testimonial-five-author-item">
<img
src="assets/images/testimonials/testi-author-five2.jpg"
alt="Author"
/>
</div>
</Slider> */}
<Slider
className="testimonials-five-content"
asNavFor={nav2}
ref={(slider) => setSlider1(slider)}
{...sliderProps.testimonialsFiveContent}
data-aos="fade-up"
data-aos-delay={100}
data-aos-duration={1500}
data-aos-offset={50}
>
{loading ? (
<div className="testimonial-five-item">
<div className="text text-center">Loading reviews...</div>
</div>
) : displayedReviews.length > 0 ? (
displayedReviews.map((r, index) => {
const fullText = getReviewText(r);
const isExpanded = expandedReview === index;
const profileImg = getProfileImage(r);
const name = r.user?.name || r.author_name || "Customer";
return (
<div key={index} className="testimonial-five-item">
<div className="google-review-header d-flex align-items-center mb-15">
<div className="google-avatar" style={{
width: '55px',
height: '55px',
minWidth: '55px',
borderRadius: '50%',
overflow: 'hidden',
background: '#f8f9fa',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: '1px solid #eee'
}}>
{profileImg ? (
<img
src={profileImg}
alt={name}
onError={(e) => (e.target.style.display = 'none')}
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
/>
) : (
<span style={{ fontSize: '18px', fontWeight: 'bold', color: '#555' }}>{getInitials(name)}</span>
)}
</div>
<div className="google-user-info" style={{ marginLeft: '15px', textAlign: 'left' }}>
<h4 className="google-name" style={{ fontSize: '18px', fontWeight: '700', margin: 0, color: '#333' }}>
{name}
</h4>
<div className="google-stars" style={{ fontSize: '14px', marginTop: '4px' }}>
{renderStars(r.rating)}
</div>
</div>
</div>
<div className="text" style={{ textAlign: 'left' }}>
{isExpanded ? fullText : truncateText(fullText)}
</div>
{fullText.length > 200 && (
<button
className="read-more-btn"
onClick={(e) => {
e.stopPropagation();
setExpandedReview(isExpanded ? null : index);
}}
style={{ textAlign: 'left', width: 'auto', padding: '10px 0 0 0' }}
>
{isExpanded ? "Read Less" : "Read More"}
</button>
)}
</div>
);
})
) : (
<div className="testimonial-five-item">
<div className="text text-center">No reviews available.</div>
</div>
)}
</Slider>
<div className="new-button pt-30">
<a href={link} className="theme-btn" target="_blank" rel="noopener noreferrer">
Review us on Google <i className="far fa-arrow-alt-right" />
</a>
</div>
</div>
</div>
<div className="testimonials-five-shapes">
<div
className="shape left"
data-aos="fade-left"
data-aos-delay={150}
data-aos-duration={1500}
data-aos-offset={50}
>
<img
src="/assets/images/about/fourth-section/left.webp"
alt="Left" loading="lazy"
/>
</div>
<div
className="shape right"
data-aos="fade-right"
data-aos-delay={150}
data-aos-duration={1500}
data-aos-offset={50}
>
<img
src="/assets/images/about/fourth-section/right.webp"
alt="right" loading="lazy"
/>
</div>
</div>
</div>
<div className="testimonials-shapes">
<div className="shape one-1">
<img
src="/assets/images/about/fourth-section/bottom.webp"
alt="Shape" loading="lazy"
/>
</div>
{/* <div className="shape three">
<img
src="/assets/images/about/fourth-section/testi-1.webp"
alt="Shape"
/>
</div> */}
<div className="shape four">
<img
src="/assets/images/about/fourth-section/chicken-right.webp"
alt="Shape" loading="lazy"
/>
</div>
</div>
</section>
);
}
export default TestimonialAbout;