import { useState, useCallback, memo, useMemo } from "react"; import { motion } from "framer-motion"; import { useTranslation } from "react-i18next"; import emailjs from "emailjs-com"; import { BsGithub, BsInstagram, BsLinkedin, BsTwitterX } from "react-icons/bs"; import PropTypes from 'prop-types'; import GlassBackground from "./GlassBackground"; // Componente optimizado para los iconos de redes sociales con glassmorphism const SocialIcon = memo(({ href, icon: Icon, hoverColor }) => ( {/* Glow effect on hover */}
)); SocialIcon.displayName = 'SocialIcon'; SocialIcon.propTypes = { href: PropTypes.string.isRequired, icon: PropTypes.elementType.isRequired, hoverColor: PropTypes.string.isRequired }; const socialNetworks = [ { id: 1, href: "https://www.instagram.com/radiocreep95", icon: BsInstagram, hoverColor: "text-pink-500 dark:text-pink-500 light:text-pink-600" }, { id: 2, href: "https://www.linkedin.com/in/never130/", icon: BsLinkedin, hoverColor: "text-blue-500 dark:text-blue-500 light:text-blue-600" }, { id: 3, href: "https://x.com/never130", icon: BsTwitterX, hoverColor: "text-adaptive" }, { id: 4, href: "https://github.com/never130", icon: BsGithub, hoverColor: "text-orange-500 dark:text-orange-500 light:text-orange-600" } ]; const Contact = () => { const { t } = useTranslation(); const [formData, setFormData] = useState({ name: "", email: "", message: "" }); const [errors, setErrors] = useState({}); const [status, setStatus] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); const validateForm = useCallback(() => { const newErrors = {}; if (!formData.name.trim()) newErrors.name = t("contact.errors.name"); if (!formData.email.trim()) { newErrors.email = t("contact.errors.email"); } else { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(formData.email)) { newErrors.email = t("contact.errors.emailInvalid"); } } if (!formData.message.trim()) newErrors.message = t("contact.errors.message"); setErrors(newErrors); return Object.keys(newErrors).length === 0; }, [formData.name, formData.email, formData.message, t]); const handleChange = useCallback((e) => { const { name, value } = e.target; setFormData(prevData => ({ ...prevData, [name]: value })); // Limpiar error del campo cuando el usuario empieza a escribir if (errors[name]) { setErrors(prevErrors => ({ ...prevErrors, [name]: "" })); } }, [errors]); const handleSubmit = useCallback((e) => { e.preventDefault(); if (!validateForm()) return; setIsSubmitting(true); setStatus(""); setErrors({}); // Verificar que EmailJS esté configurado const serviceId = "service_4zzkduf"; const templateId = "template_pahpa4c"; const userId = "SJFGZonkWvf5RR9h7"; if (!serviceId || !templateId || !userId) { console.error("EmailJS configuration missing"); setStatus("error"); setIsSubmitting(false); return; } emailjs.sendForm(serviceId, templateId, e.target, userId) .then( (result) => { console.log("Email sent successfully:", result.text); setStatus("success"); setFormData({ name: "", email: "", message: "" }); setErrors({}); }, (error) => { console.error("EmailJS Error:", error); setStatus("error"); } ) .finally(() => setIsSubmitting(false)); }, [validateForm]); // Animaciones const containerVariants = useMemo(() => ({ hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.1, delayChildren: 0.2 } } }), []); const itemVariants = useMemo(() => ({ hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5 } } }), []); return (
{/* Sección izquierda: Título + Descripción + Redes Sociales */} {t("contact.title")}
{t("contact.description")} {socialNetworks.map((network) => ( ))}
{/* Sección derecha: Formulario con glassmorphism */}

{t("contact.button")}

{errors.name && ( {errors.name} )}
{errors.email && ( {errors.email} )}
{errors.message && ( {errors.message} )}
{/* Shimmer effect */}
{isSubmitting ? t("contact.sending") : t("contact.submit")}
{status && ( {t(`contact.${status}`)} )}
); }; export default Contact;