187 lines
6.0 KiB
TypeScript
187 lines
6.0 KiB
TypeScript
"use client";
|
||
|
||
import { Marquee } from "@/components/ui/logo-marquee";
|
||
import { TestimonialCard } from "@/components/ui/testimonial-marquee";
|
||
import { useEffect, useRef } from "react";
|
||
import gsap from "gsap";
|
||
import SplitText from "gsap/SplitText";
|
||
import ScrollTrigger from "gsap/ScrollTrigger";
|
||
import Headline from "@/components/ui/headline";
|
||
import { useSplitHeading } from "@/lib/useTextRevealHeading";
|
||
gsap.registerPlugin(SplitText, ScrollTrigger);
|
||
|
||
const testimonials = [
|
||
{
|
||
id: 1,
|
||
name: "Dazzle Healer",
|
||
role: "Front End Developer",
|
||
avatar: "/images/png/Avatar.png",
|
||
|
||
message:
|
||
"I've used other kits, but this one is the best. The attention to detail and usability are truly amazing for all designers. I highly recommend it for any type of project.",
|
||
},
|
||
{
|
||
id: 2,
|
||
name: "Ammy Johnson",
|
||
role: "Scientific Advisor",
|
||
avatar: "/images/png/Avatar (2).png",
|
||
|
||
message:
|
||
"The level of accuracy and precision in the data analytics blew me away. Whispering Tree makes environmental monitoring so much easier for our teams.",
|
||
},
|
||
{
|
||
id: 3,
|
||
name: "Leo Smith",
|
||
role: "Urban Planner",
|
||
avatar: "/images/png/Avatar (1).png",
|
||
|
||
message:
|
||
"Integrating the IoT sensors into our city’s green spaces helped us reduce water usage by over 30%. It’s a game-changer for sustainable urban development.",
|
||
},
|
||
{
|
||
id: 4,
|
||
name: "Sofia Martins",
|
||
role: "Research Scientist",
|
||
avatar: "/images/png/Avatar (3).png",
|
||
message:
|
||
"Real-time health insights from trees have opened a whole new perspective for environmental research. It’s efficient, reliable, and visually elegant.",
|
||
},
|
||
{
|
||
id: 5,
|
||
name: "Michael Chen",
|
||
role: "Environmental Engineer",
|
||
avatar: "/images/png/Avatar (4).png",
|
||
message:
|
||
"Our city parks have become smarter and greener since adopting Whispering Tree. The platform’s clarity in reports is unmatched.",
|
||
},
|
||
{
|
||
id: 6,
|
||
name: "Laura Green",
|
||
role: "Sustainability Consultant",
|
||
avatar: "/images/png/Avatar (1).png",
|
||
message:
|
||
"It’s refreshing to see technology being used for nature’s benefit. The dashboards are intuitive and provide deep insights for eco-management.",
|
||
},
|
||
{
|
||
id: 7,
|
||
name: "David Kim",
|
||
role: "IoT Solutions Architect",
|
||
avatar: "/images/png/Avatar (4).png",
|
||
message:
|
||
"The ease of integrating sensors into existing infrastructure made implementation seamless. Great work by the Whispering Tree team!",
|
||
},
|
||
{
|
||
id: 8,
|
||
name: "Priya Nair",
|
||
role: "Climate Research Analyst",
|
||
avatar: "/images/png/Avatar.png",
|
||
message:
|
||
"This platform allows us to visualize and act on real environmental data in real time. The insights are helping cities adapt sustainably.",
|
||
},
|
||
];
|
||
const Testimonial = () => {
|
||
const headingRef = useRef<HTMLHeadingElement | null>(null);
|
||
const paraRef = useRef<HTMLParagraphElement | null>(null);
|
||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||
|
||
useSplitHeading(headingRef, paraRef);
|
||
const middleIndex = Math.ceil(testimonials.length / 2);
|
||
const firstHalf = testimonials.slice(0, middleIndex);
|
||
const secondHalf = testimonials.slice(middleIndex);
|
||
|
||
useEffect(() => {
|
||
gsap.registerPlugin(ScrollTrigger);
|
||
|
||
const cards = gsap.utils.toArray<HTMLDivElement>(".test-card");
|
||
|
||
gsap.from(cards, {
|
||
y: 100,
|
||
opacity: 0,
|
||
duration: 1.2,
|
||
ease: "power3.out",
|
||
stagger: 0.19,
|
||
scrollTrigger: {
|
||
trigger: ".test-wrapper",
|
||
start: "top 80%",
|
||
end: "bottom 60%",
|
||
toggleActions: "play none none none",
|
||
},
|
||
});
|
||
|
||
return () => {
|
||
ScrollTrigger.getAll().forEach((st) => st.kill());
|
||
};
|
||
}, []);
|
||
|
||
return (
|
||
<section
|
||
ref={containerRef}
|
||
className="tab:px-6 mx-auto flex h-full w-full max-w-[1420px] flex-col items-center justify-start gap-12 py-8 sm:px-2.5 lg:px-0"
|
||
>
|
||
<div className="tab:w-9/12 flex flex-col items-center justify-center gap-4 sm:w-full md:w-6/12">
|
||
<Headline text="Feedback" />
|
||
<h1
|
||
ref={headingRef}
|
||
className="font-switzer text-h-mobile-30 leading-h5 tab:text-h-2-60 tab:leading-h2 text-center font-semibold text-black"
|
||
>
|
||
Powered by{" "}
|
||
<span className="font-playfair text-brand font-semibold italic">
|
||
Trust.
|
||
</span>
|
||
<br />
|
||
Proven by{" "}
|
||
<span className="font-playfair text-brand font-semibold italic">
|
||
Nature.
|
||
</span>
|
||
</h1>
|
||
<p
|
||
ref={paraRef}
|
||
className="text-b-3-16 leading-b3 font-mium-reg text-center tracking-[-0.8px] text-black"
|
||
>
|
||
See how municipalities and partners use FalktronTrees to make smarter,
|
||
data-driven decisions for urban green spaces.
|
||
</p>
|
||
</div>
|
||
<div className="test-wrapper relative w-full overflow-hidden">
|
||
<Marquee gap="1rem" className="test-card max-w-full [--duration:120s]">
|
||
{firstHalf.map((test, idx) => (
|
||
<TestimonialCard
|
||
key={idx}
|
||
img={test.avatar}
|
||
id={idx + 1}
|
||
name={test.name}
|
||
title={test.role}
|
||
body={test.message}
|
||
/>
|
||
))}
|
||
</Marquee>
|
||
<Marquee
|
||
gap="1rem"
|
||
className="test-card max-w-full [--duration:120s]"
|
||
reverse
|
||
pauseOnHover
|
||
>
|
||
{secondHalf.map((test, idx) => (
|
||
<TestimonialCard
|
||
key={idx}
|
||
img={test.avatar}
|
||
id={idx + 1}
|
||
name={test.name}
|
||
title={test.role}
|
||
body={test.message}
|
||
/>
|
||
))}
|
||
</Marquee>
|
||
|
||
{/* left gradient fade */}
|
||
<div className="pointer-events-none absolute inset-y-0 left-0 h-full w-1/4 bg-gradient-to-r from-white to-transparent"></div>
|
||
|
||
{/* right gradient fade */}
|
||
<div className="pointer-events-none absolute inset-y-0 right-0 h-full w-1/4 bg-gradient-to-l from-white to-transparent"></div>
|
||
</div>
|
||
</section>
|
||
);
|
||
};
|
||
|
||
export default Testimonial;
|