//React import { useState, useEffect, useContext } from "react"; //Framer Motion import { motion } from "framer-motion"; //API import { postData } from "../../api"; //Utils import { LoadingContext } from "../utils/LoadingContext"; import Heading from "../Heading"; import NavigationDots from "../utils/NavigationDots"; //CSS import styles from "./Contact.module.css"; const Contact = ({ isVisible, contactData }) => { const [formData, setFormData] = useState({ name: "", email: "", message: "", }); const [error, setError] = useState(""); const [success, setSuccess] = useState(""); const { isLoading } = useContext(LoadingContext); // Use the global loading state if (isLoading) return <div>Loading...</div>; // Automatically clear success/error message after 5 seconds useEffect(() => { if (success || error) { const timer = setTimeout(() => { setSuccess(""); setError(""); }, 5000); return () => clearTimeout(timer); // Cleanup on unmount } }, [success, error]); const handleChange = (e) => { setFormData({ ...formData, [e.target.name]: e.target.value }); setError(""); }; const handleSubmit = async (e) => { e.preventDefault(); if (!formData.name || !formData.email || !formData.message) { setError("All fields are required."); return; } if (!/\S+@\S+\.\S+/.test(formData.email)) { setError("Please enter a valid email."); return; } try { const response = await postData("send", formData); setSuccess(response.success); setFormData({ name: "", email: "", message: "" }); } catch (error) { setError(error.message || "Failed to send message."); } }; return ( <motion.div id="contact" className="pt-2 sm:pt-10" initial={{ opacity: 0, y: 100 }} // Start off-screen animate={isVisible ? { opacity: 1, y: 0 } : { opacity: 0, y: 100 }} // Slide-in when visible transition={{ duration: 0.2, ease: "easeOut" }} > <div className="relative rounded-lg z-10 min-h-screen"> <Heading title="Contact Me Anytime!" highlightWords={[{ word: "Contact Me", color: "text-orange-500" }]} /> <NavigationDots currentSectionId="contact" /> <div className="sm:max-w-lg md:max-w-2xl lg:max-w-4xl xl:max-w-6xl 2xl:max-w-full 2xl:px-60 mx-auto px-8"> {/* Social Media Buttons */} <div className="flex justify-center gap-6 lg:gap-12 flex-wrap mb-8"> {contactData.map((contact) => ( <a key={contact.id} href={ contact.name === "gmail" ? `mailto:${contact.username}` : contact.url } target={contact.name === "gmail" ? "_self" : "_blank"} rel="noopener noreferrer" className={`${styles["social-button"]} flex items-center justify-center gap-2.5`} > <img src={contact.logo} alt={contact.name} className="w-8 h-8 rounded-full" /> <span className="text-md md:text-base lg:text-lg xl:text-xl font-bold"> {contact.username} </span> </a> ))} </div> <form onSubmit={handleSubmit} className="flex flex-col space-y-4"> <input type="text" name="name" placeholder="Your Name" value={formData.name} onChange={handleChange} className={`${styles["input-field"]} p-2 rounded-md`} required /> <input type="email" name="email" placeholder="Your Email" value={formData.email} onChange={handleChange} className={`${styles["input-field"]} p-2 rounded-md`} required /> <textarea name="message" placeholder="Your Message" value={formData.message} onChange={handleChange} className={`${styles["input-field"]} p-2 rounded-md`} rows="4" required ></textarea> {/* Success/Error Message Below Message Field */} <div className="h-4 flex items-center"> {error && <p className="text-red-500 text-sm">{error}</p>} {success && <p className="text-green-500 text-sm">{success}</p>} </div> <div className="flex justify-center"> <button type="submit" className={`${styles["submit-button"]} px-4 py-2 rounded-lg`} > Send Message </button> </div> </form> {/* Disclaimer */} <p className="text-sm text-gray-400 text-center mt-4"> Disclaimer: Please avoid sharing sensitive or confidential information in your message. </p> </div> </div> {/* Rights */} <p className="text-md text-gray-400 text-center mt-10"> @2025 Nuno Teixeira <br /> All rights reserved </p> </motion.div> ); }; export default Contact;