From 678ae77e04517ddc7f9b73e9336868cda3586bcb Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Sat, 30 Aug 2025 10:03:34 +0530 Subject: [PATCH 1/2] Newsletter --- src/components/Footer.jsx | 236 +++++++++++++++++++++++++++++++------- yarn.lock | 3 +- 2 files changed, 197 insertions(+), 42 deletions(-) diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx index 05e8a92..955207b 100644 --- a/src/components/Footer.jsx +++ b/src/components/Footer.jsx @@ -1,11 +1,11 @@ import { useState, useEffect, useCallback } from "react"; -import { - Github, - Info, - ShieldCheck, - ScrollText, - Star, - UsersIcon, +import { + Github, + Info, + ShieldCheck, + ScrollText, + Star, + UsersIcon, ArrowUpRight, MapPin, Heart, @@ -13,7 +13,9 @@ import { Zap, Mail, Phone, - MessageSquare + MessageSquare, + Send, + CheckCircle, } from "lucide-react"; import { Link } from "react-router-dom"; import logoF from "../assets/logo.png"; @@ -24,6 +26,9 @@ const Footer = () => { const [feedbackText, setFeedbackText] = useState(""); const [message, setMessage] = useState(""); const [isVisible, setIsVisible] = useState(false); + const [email, setEmail] = useState(""); + const [isSubscribed, setIsSubscribed] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false); // Performance optimization: Memoize social links const socialLinks = [ @@ -40,34 +45,84 @@ const Footer = () => { title: "Civix", icon: Sparkles, links: [ - { name: "About", href: "/about", icon: Info, description: "Learn about our mission" }, - { name: "Features", href: "/#features", icon: Star, description: "Explore platform features" }, - { name: "Feedback", href: "/feedback", icon: MessageSquare, description: "Share your feedback" }, + { + name: "About", + href: "/about", + icon: Info, + description: "Learn about our mission", + }, + { + name: "Features", + href: "/#features", + icon: Star, + description: "Explore platform features", + }, + { + name: "Feedback", + href: "/feedback", + icon: MessageSquare, + description: "Share your feedback", + }, ], }, { title: "Legal", icon: ShieldCheck, links: [ - { name: "Privacy", href: "/privacy", icon: ShieldCheck, description: "Privacy policy" }, - { name: "Terms", href: "/terms", icon: ScrollText, description: "Terms of service" }, - { name: "Contributors", href: "/contributors", icon: UsersIcon, description: "Meet our team" }, + { + name: "Privacy", + href: "/privacy", + icon: ShieldCheck, + description: "Privacy policy", + }, + { + name: "Terms", + href: "/terms", + icon: ScrollText, + description: "Terms of service", + }, + { + name: "Contributors", + href: "/contributors", + icon: UsersIcon, + description: "Meet our team", + }, ], }, ]; const emojis = [ - { emoji: "😡", label: "Very Dissatisfied", color: "hover:bg-red-100 dark:hover:bg-red-900/20" }, - { emoji: "😕", label: "Dissatisfied", color: "hover:bg-orange-100 dark:hover:bg-orange-900/20" }, - { emoji: "😐", label: "Neutral", color: "hover:bg-yellow-100 dark:hover:bg-yellow-900/20" }, - { emoji: "🙂", label: "Satisfied", color: "hover:bg-green-100 dark:hover:bg-green-900/20" }, - { emoji: "😍", label: "Very Satisfied", color: "hover:bg-purple-100 dark:hover:bg-purple-900/20" }, + { + emoji: "😡", + label: "Very Dissatisfied", + color: "hover:bg-red-100 dark:hover:bg-red-900/20", + }, + { + emoji: "😕", + label: "Dissatisfied", + color: "hover:bg-orange-100 dark:hover:bg-orange-900/20", + }, + { + emoji: "😐", + label: "Neutral", + color: "hover:bg-yellow-100 dark:hover:bg-yellow-900/20", + }, + { + emoji: "🙂", + label: "Satisfied", + color: "hover:bg-green-100 dark:hover:bg-green-900/20", + }, + { + emoji: "😍", + label: "Very Satisfied", + color: "hover:bg-purple-100 dark:hover:bg-purple-900/20", + }, ]; // Performance optimization: Debounced feedback submission const handleSubmitFeedback = useCallback(() => { if (!selectedRating && !feedbackText.trim()) return; - + setMessage("Thanks for your feedback! 💚"); setFeedbackText(""); setSelectedRating(null); @@ -75,6 +130,35 @@ const Footer = () => { setTimeout(() => setMessage(""), 3000); }, [selectedRating, feedbackText]); + // Handle newsletter subscription + const handleNewsletterSubmit = useCallback( + (e) => { + e.preventDefault(); + if (!email.trim()) return; + + setIsSubmitting(true); + + // Simulate API call + setTimeout(() => { + setIsSubmitting(false); + setIsSubscribed(true); + setEmail(""); + + // Show success message + setMessage("Successfully subscribed to our newsletter! 🎉"); + + // Reset subscription status after some time + setTimeout(() => { + setIsSubscribed(false); + }, 3000); + + // Hide the message after 3 seconds + setTimeout(() => setMessage(""), 3000); + }, 1000); + }, + [email] + ); + // Intersection Observer for animations useEffect(() => { const observer = new IntersectionObserver( @@ -86,7 +170,7 @@ const Footer = () => { { threshold: 0.1 } ); - const footer = document.querySelector('#footer'); + const footer = document.querySelector("#footer"); if (footer) { observer.observe(footer); } @@ -95,10 +179,10 @@ const Footer = () => { }, []); return ( -