diff --git a/app/about/AboutContent.js b/app/about/AboutContent.js index 986304f..23dd3c7 100644 --- a/app/about/AboutContent.js +++ b/app/about/AboutContent.js @@ -1,9 +1,11 @@ 'use client' +import { useEffect, useState } from "react" import Link from "next/link" import { Swiper, SwiperSlide } from "swiper/react" import { Autoplay, Pagination, Navigation } from "swiper/modules" import GallerySlider1 from '@/components/slider/GallerySlider1' +import GoogleReviewsBranding from "@/components/GoogleReviewsBranding" const swiperOptions = { modules: [Autoplay, Pagination, Navigation], @@ -24,7 +26,83 @@ const swiperOptions = { }, } +const testimonialSwiperOptions = { + modules: [Autoplay], + slidesPerView: 3, + spaceBetween: 20, + loop: true, + autoplay: { + delay: 2000, + disableOnInteraction: false, + pauseOnMouseEnter: false, + }, + breakpoints: { + 0: { slidesPerView: 1 }, + 768: { slidesPerView: 2 }, + 1024: { slidesPerView: 3 }, + }, +}; + export default function AboutContent() { + const [reviews, setReviews] = useState([]); + const [loading, setLoading] = useState(true); + const [expandedReview, setExpandedReview] = useState(null); + const [isClient, setIsClient] = useState(false); + + useEffect(() => { + setIsClient(true); + }, []); + + 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("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) => ( + + )); + } + + 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 "/default-user.png"; + return url.startsWith("http") ? url : `https://lh3.googleusercontent.com/${url}`; + } + return ( <> @@ -130,88 +208,83 @@ export default function AboutContent() {
Loading reviews...
} + + {!loading && isClient && displayedReviews.length > 0 && ( ++ {isExpanded ? fullText : truncateText(fullText)} +
+ + {r.images && + r.images.length > 0 && + r.images.some(img => img && img !== "ky") && ( +