* feat: setup openapi libs for landing * feat: seperate landing layouts * feat: movee landing providers * feat: add auth layout * feat: implement cookie management for access and refresh tokens * feat: replace Inter font with Bai Jamjuree in layout and add font utility * feat: add signin * feat: add Poppins font to the font utility * feat: expand theme colors in index.css for improved styling options * feat: update dependencies and enhance button and form components with new variants and context * feat: move old components to __old__ dir * feat: add react query support * feat: hide the footer * fix: header style * feat: replace Image component with LogoSimple in Header and update Logo component to accept props * fix: update label for tutorial stat in hero-stats.json * feat: implement EventsPage component with event listing and details * feat: add signup button and page * feat: add HERO_CONTENT data and integrate into Hero component * fix: update navigations import to uppercase and add missing Testimoni entry * feat: implement testimonials display and add submission page * fix: correct link path for testimonial submission * feat: add communites component and integrate social links from JSON data * fix: adjust grid gap in Communities component for better layout * fix: update font imports in layout components for consistency * fix: replace text logo with LogoSimple component in Footer and restore Footer in Layout * feat: add TestimonialSection component and update testimonials data * fix: update section ID from 'komunitas' to 'community' for consistency * feat: add CTASection component with interactive elements and background pattern * fix: update join URL in hero content for consistency * fix: update text in CTASection for improved emphasis and consistency * feat: add CommunitySection component and integrate it into the main page * feat: update Footer component to use dynamic navigation and social links * feat: implement HeroSection component with dynamic content and animations * refactor: replace hardcoded testimonials with dynamic data from JSON * feat: add signup page * feat: integrate Turnstile captcha verification in signup process * feat: implement verification page * feat: add signin link to the signup page * feat: add "Forgot Password?" link to the signin form * refactor: clean up unused ThemeProvider code and CSS variables * feat: add base styles for borders and background to improve UI consistency * feat: implement forgot password functionality with validation and UI components * fix: update password validation rules for clarity and consistency * feat: enable rich colors for Toaster component in layout * feat: implement reset password functionality with validation and UI components * feat: implement Turnstile captcha verification for forgot password and signup actions * refactor: remove console log and enhance error handling in signin and resend OTP actions * feat: add navigation entries for Roadmap and Artikel sections * feat: create initial Page component for articles section * feat: update footer component with additional social media links and icons * feat: remove all unused components in landing * chore: add @radix-ui/react-label deps * feat: wrap VerificationTabs in Suspense * feat: update .env.example to include TURNSTILE_SECRET_KEY and correct NEXT_PUBLIC_TURNSTILE_SITEKEY
103 lines
3.2 KiB
TypeScript
103 lines
3.2 KiB
TypeScript
'use client';
|
|
|
|
import TESTIMONIALS from '@/data/testimonials.json';
|
|
import { buttonVariants } from '@components';
|
|
import { motion, useInView } from 'framer-motion';
|
|
import Image from 'next/image';
|
|
import Link from 'next/link';
|
|
import { useRef } from 'react';
|
|
import { FaQuoteLeft } from 'react-icons/fa';
|
|
|
|
export function TestimonialSection() {
|
|
const ref = useRef(null);
|
|
const isInView = useInView(ref, { once: true, amount: 0.1 });
|
|
|
|
const containerVariants = {
|
|
hidden: { opacity: 0 },
|
|
visible: {
|
|
opacity: 1,
|
|
transition: {
|
|
staggerChildren: 0.1,
|
|
delayChildren: 0.2,
|
|
},
|
|
},
|
|
};
|
|
|
|
const itemVariants = {
|
|
hidden: { y: 20, opacity: 0 },
|
|
visible: {
|
|
y: 0,
|
|
opacity: 1,
|
|
transition: {
|
|
duration: 0.4,
|
|
ease: [0.25, 0.46, 0.45, 0.94],
|
|
},
|
|
},
|
|
};
|
|
|
|
return (
|
|
<section className="w-full py-20 md:py-28 bg-gray-50">
|
|
<div className="container" ref={ref}>
|
|
<div className="flex flex-col items-center justify-center space-y-4 text-center mb-16">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
|
transition={{ duration: 0.4 }}
|
|
>
|
|
<h2 className="text-3xl font-semibold tracking-tight md:text-4xl">
|
|
Apa Kata Mereka Tentang
|
|
<span className="block mt-2 text-primary-500">
|
|
Komunitas Kami?
|
|
</span>
|
|
</h2>
|
|
</motion.div>
|
|
</div>
|
|
|
|
<motion.div
|
|
className="grid gap-8 md:gap-6 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 mb-16"
|
|
variants={containerVariants}
|
|
initial="hidden"
|
|
animate={isInView ? 'visible' : 'hidden'}
|
|
>
|
|
{TESTIMONIALS.map((testimonial) => (
|
|
<motion.div
|
|
key={testimonial.id}
|
|
variants={itemVariants}
|
|
className="p-6 bg-white rounded-xl shadow-sm hover:shadow-md transition-shadow duration-300"
|
|
>
|
|
<div className="flex flex-col space-y-4">
|
|
<div className="flex items-center gap-4">
|
|
<Image
|
|
src={testimonial.image}
|
|
alt={testimonial.name}
|
|
width={48}
|
|
height={48}
|
|
className="w-12 h-12 rounded-full object-cover"
|
|
unoptimized
|
|
/>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900">
|
|
{testimonial.name}
|
|
</h4>
|
|
<p className="text-sm text-gray-600">{testimonial.role}</p>
|
|
</div>
|
|
</div>
|
|
<div className="text-gray-600 relative">
|
|
<FaQuoteLeft className="text-primary-500/30 w-6 h-6 mb-2" />
|
|
<p className="text-sm/relaxed">{testimonial.text}</p>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</motion.div>
|
|
|
|
<div className="flex justify-center">
|
|
<Link href="/testimonials" className={buttonVariants({ size: 'lg' })}>
|
|
Tulis Testimonimu
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|