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;
|