/* eslint-disable react-hooks/rules-of-hooks */ "use client"; import Image from "next/image"; import React, { useState, useEffect } from "react"; import { RiTwitterXLine } from "react-icons/ri"; import { motion, Variants } from "framer-motion"; import { useInView } from "react-intersection-observer"; type Mode = "light" | "dark"; interface Testimonial { image?: string; name: string; jobtitle: string; text: string; audio?: string; social?: string; } interface VoiceTestimonialProps { mode: Mode; testimonials: Testimonial[]; } type WaveVariant = Variants; const generateWaveVariants = (): WaveVariant[] => { const waveVariants: WaveVariant[] = []; for (let i = 0; i < 30; i++) { waveVariants.push({ initial: { scaleY: 1.5, transition: { duration: 0.5, }, }, animate: { scaleY: [1, Math.random() * 1.2 + 1, 1], transition: { duration: Math.random() * 0.5 + 0.5, repeat: Infinity, ease: "easeInOut", delay: Math.random() * 0.5, }, }, }); } return waveVariants; }; const waveVariants = generateWaveVariants(); const VoiceTestimonialAnimate: React.FC = ({ mode, testimonials, }) => { const [currentPlayingIndex, setCurrentPlayingIndex] = useState( null ); const [audioElements, setAudioElements] = useState< (HTMLAudioElement | null)[] >([]); const [showAll, setShowAll] = useState(false); useEffect(() => { const elements: (HTMLAudioElement | null)[] = []; testimonials.forEach((testimonial) => { if (testimonial.audio) { const audio = new Audio(`/audio/${testimonial.audio}`); audio.addEventListener("ended", handleAudioEnded); elements.push(audio); } else { elements.push(null); } }); setAudioElements(elements); return () => { elements.forEach((audio) => { if (audio) { audio.pause(); audio.removeEventListener("ended", handleAudioEnded); } }); }; }, [testimonials]); const handlePlay = (index: number) => { if (currentPlayingIndex !== null && currentPlayingIndex !== index) { stopAudio(currentPlayingIndex); } const audio = audioElements[index]; if (audio) { audio .play() .catch((error) => console.error("Audio playback error:", error)); setCurrentPlayingIndex(index); } }; const stopAudio = (index: number) => { const audio = audioElements[index]; if (audio) { audio.pause(); audio.currentTime = 0; setCurrentPlayingIndex(null); } }; const handlePause = (index: number) => { stopAudio(index); }; const handleAudioEnded = () => { setCurrentPlayingIndex(null); }; const handleLoadMore = () => { setShowAll(true); }; const openInNewTab = (url: string) => { const win = window.open(url, "_blank"); if (win) { win.focus(); } }; const shouldShowLoadMore = testimonials.length > 6; return (
Read what people are saying Dummy feedback from virtual customers
using our component library.{" "}
{shouldShowLoadMore && !showAll && (
)} {testimonials.map((testimonial, index) => { const { ref, inView } = useInView({ triggerOnce: true, threshold: 0.1, }); return ( = 6 ? "testimonial-partially-visible" : "" } }`} >
openInNewTab(testimonial.social || "")} className="absolute top-5 right-5" >
profile
{testimonial.name} {testimonial.jobtitle}
{testimonial.text}
{currentPlayingIndex !== index ? ( handlePlay(index)}> ) : ( handlePause(index)}> )}
{waveVariants.map((variant, i) => ( ))}
); })}
{shouldShowLoadMore && !showAll && (
)}
); }; export default VoiceTestimonialAnimate;