diff --git a/frontend/src/LandingPage.jsx b/frontend/src/LandingPage.jsx index b1a2e52..ada6118 100644 --- a/frontend/src/LandingPage.jsx +++ b/frontend/src/LandingPage.jsx @@ -243,58 +243,29 @@ const LandingPage = () => { const [activeStep, setActiveStep] = useState(1); const [showScrollTop, setShowScrollTop] = useState(false); - const [visibleCards, setVisibleCards] = useState(3); - const [currentIndex, setCurrentIndex] = useState(0); const [isPaused, setIsPaused] = useState(false); - useEffect(() => { - const handleResize = () => { - if (window.innerWidth < 640) { - setVisibleCards(1); - } else if (window.innerWidth < 1024) { - setVisibleCards(2); - } else { - setVisibleCards(3); - } - }; - handleResize(); - window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, []); - - useEffect(() => { - const maxIndex = Math.max(0, TESTIMONIALS.length - visibleCards); - if (currentIndex > maxIndex) { - setCurrentIndex(maxIndex); - } - }, [visibleCards, currentIndex]); - - useEffect(() => { - if (isPaused) return; - const interval = setInterval(() => { - setCurrentIndex((prevIndex) => { - const nextIndex = prevIndex + 1; - const maxIndex = TESTIMONIALS.length - visibleCards; - return nextIndex > maxIndex ? 0 : nextIndex; - }); - }, 4000); - return () => clearInterval(interval); - }, [visibleCards, isPaused]); - - const handlePrev = () => { - setCurrentIndex((prevIndex) => { - const nextIndex = prevIndex - 1; - const maxIndex = TESTIMONIALS.length - visibleCards; - return nextIndex < 0 ? maxIndex : nextIndex; - }); + // Hero parallax + const heroRef = useRef(null); + const statsRef = useRef(null); + const mouseX = useMotionValue(0); + const mouseY = useMotionValue(0); + const springX = useSpring(mouseX, { stiffness: 60, damping: 20, mass: 0.4 }); + const springY = useSpring(mouseY, { stiffness: 60, damping: 20, mass: 0.4 }); + const blobX1 = useTransform(springX, [-0.5, 0.5], [-20, 20]); + const blobY1 = useTransform(springY, [-0.5, 0.5], [-20, 20]); + const blobX2 = useTransform(springX, [-0.5, 0.5], [16, -16]); + const blobY2 = useTransform(springY, [-0.5, 0.5], [16, -16]); + + const handleHeroMouseMove = (e) => { + if (!heroRef.current) return; + const rect = heroRef.current.getBoundingClientRect(); + mouseX.set((e.clientX - rect.left) / rect.width - 0.5); + mouseY.set((e.clientY - rect.top) / rect.height - 0.5); }; - const handleNext = () => { - setCurrentIndex((prevIndex) => { - const nextIndex = prevIndex + 1; - const maxIndex = TESTIMONIALS.length - visibleCards; - return nextIndex > maxIndex ? 0 : nextIndex; - }); + const scrollToStats = () => { + statsRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }); }; const handleCTA = () => { @@ -822,114 +793,35 @@ const LandingPage = () => { {/* ───────────────────────────────── TESTIMONIALS – auto-scrolling carousel ───────────────────────────────── */} -
-
- - - What Our Users Say - -

- Trusted by{" "} - - Thousands of Developers - -

-
- - {/* Testimonials Scroller */} -
setIsPaused(true)} - onMouseLeave={() => setIsPaused(false)} - > - {/* Fading overlays */} -
-
- - {/* Slider Track Wrapper */} -
-
- {TESTIMONIALS.map((testimonial) => ( -
- -
- ))} -
-
- - {/* Navigation Arrows and Dot Indicators */} -
- - - {/* Dots indicators */} -
- {Array.from({ length: TESTIMONIALS.length - visibleCards + 1 }).map((_, idx) => ( -
- - -
-
-
-
- - {/* ───────────────────────────────── - CTA FOOTER BANNER - ───────────────────────────────── */} -
-
-
-
- -

- Ready to Ace Your{" "} - - Next Interview? - -

-

- Join thousands of learners who have transformed their interview - preparation with PrepPilot AI. -

- -
-
+ {/* Testimonials Scroller */} +
setIsPaused(true)} + onMouseLeave={() => setIsPaused(false)} +> + {/* Left Fade */} +
+ + {/* Right Fade */} +
+ +
+
+ {[...TESTIMONIALS, ...TESTIMONIALS].map((testimonial, index) => ( +
+ +
+ ))} +
+
+
{/* ───────────────────────────────── FOOTER diff --git a/frontend/src/index.css b/frontend/src/index.css index 2c35d10..393bbb7 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -385,3 +385,21 @@ html.dark { } } +/* Infinite Testimonials */ + +@keyframes marquee { + from { + transform: translateX(0%); + } + to { + transform: translateX(-50%); + } +} + +.animate-marquee { + animation: marquee 30s linear infinite; +} + +.animate-marquee.paused { + animation-play-state: paused; +} \ No newline at end of file