fix(deploy): add nginx healthcheck and ensure nginx listens on all interfaces
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Send, Loader2 } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useToast } from '@/components/ui/use-toast';
|
||||
|
||||
const ContactForm = () => {
|
||||
const { toast } = useToast();
|
||||
const form = useRef();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [formData, setFormData] = useState({
|
||||
nombre: '', email: '', telefono: '', empresa: '', asunto: '', mensaje: ''
|
||||
});
|
||||
const [errors, setErrors] = useState({});
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors = {};
|
||||
if (!formData.nombre.trim()) newErrors.nombre = 'El nombre es requerido';
|
||||
if (!formData.email.trim()) newErrors.email = 'El email es requerido';
|
||||
else if (!/\S+@\S+\.\S+/.test(formData.email)) newErrors.email = 'Email inválido';
|
||||
if (!formData.telefono.trim()) newErrors.telefono = 'El teléfono es requerido';
|
||||
if (!formData.asunto.trim()) newErrors.asunto = 'El asunto es requerido';
|
||||
if (!formData.mensaje.trim()) newErrors.mensaje = 'El mensaje es requerido';
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({ ...prev, [name]: value }));
|
||||
if (errors[name]) setErrors(prev => ({ ...prev, [name]: '' }));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
if (!validateForm()) {
|
||||
toast({ title: "Error de validación", description: "Por favor complete todos los campos requeridos.", variant: "destructive" });
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
toast({ title: "¡Mensaje enviado!", description: "Gracias por contactarnos. Le responderemos pronto." });
|
||||
setFormData({ nombre: '', email: '', telefono: '', empresa: '', asunto: '', mensaje: '' });
|
||||
} catch (error) {
|
||||
toast({ title: "Error", description: "Hubo un problema. Intente de nuevo.", variant: "destructive" });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const inputClasses = (error) => `w-full px-4 py-3 bg-blanco border ${error ? 'border-red-500' : 'border-azulClaro'} rounded-lg text-azulOscuro placeholder-grisMedio focus:outline-none focus:ring-2 focus:ring-azulClaro focus:border-azulPrincipal transition-colors`;
|
||||
|
||||
return (
|
||||
<motion.form
|
||||
ref={form}
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
onSubmit={handleSubmit}
|
||||
className="bg-grisClaro backdrop-blur-sm border border-azulMedio/30 rounded-xl p-8 shadow-xl"
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||||
<div>
|
||||
<label htmlFor="nombre" className="block text-sm font-medium text-azulPrincipal mb-2">Nombre <span className="text-naranjaAccento">*</span></label>
|
||||
<input type="text" id="nombre" name="nombre" value={formData.nombre} onChange={handleChange} className={inputClasses(errors.nombre)} placeholder="Su nombre completo" />
|
||||
{errors.nombre && <p className="mt-1 text-sm text-red-500">{errors.nombre}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium text-azulPrincipal mb-2">Email <span className="text-naranjaAccento">*</span></label>
|
||||
<input type="email" id="email" name="email" value={formData.email} onChange={handleChange} className={inputClasses(errors.email)} placeholder="correo@ejemplo.com" />
|
||||
{errors.email && <p className="mt-1 text-sm text-red-500">{errors.email}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="telefono" className="block text-sm font-medium text-azulPrincipal mb-2">Teléfono <span className="text-naranjaAccento">*</span></label>
|
||||
<input type="tel" id="telefono" name="telefono" value={formData.telefono} onChange={handleChange} className={inputClasses(errors.telefono)} placeholder="0414-1234567" />
|
||||
{errors.telefono && <p className="mt-1 text-sm text-red-500">{errors.telefono}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="empresa" className="block text-sm font-medium text-azulPrincipal mb-2">Empresa <span className="text-grisMedio text-xs font-normal">(Opcional)</span></label>
|
||||
<input type="text" id="empresa" name="empresa" value={formData.empresa} onChange={handleChange} className={inputClasses(false)} placeholder="Nombre de su empresa" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<label htmlFor="asunto" className="block text-sm font-medium text-azulPrincipal mb-2">Asunto <span className="text-naranjaAccento">*</span></label>
|
||||
<input type="text" id="asunto" name="asunto" value={formData.asunto} onChange={handleChange} className={inputClasses(errors.asunto)} placeholder="Asunto de su consulta" />
|
||||
{errors.asunto && <p className="mt-1 text-sm text-red-500">{errors.asunto}</p>}
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<label htmlFor="mensaje" className="block text-sm font-medium text-azulPrincipal mb-2">Mensaje <span className="text-naranjaAccento">*</span></label>
|
||||
<textarea id="mensaje" name="mensaje" value={formData.mensaje} onChange={handleChange} rows={6} className={`${inputClasses(errors.mensaje)} resize-none`} placeholder="Escriba su mensaje aquí..." />
|
||||
{errors.mensaje && <p className="mt-1 text-sm text-red-500">{errors.mensaje}</p>}
|
||||
</div>
|
||||
|
||||
<Button type="submit" variant="cta" disabled={loading} className="w-full py-6 text-lg rounded-lg shadow-lg">
|
||||
{loading ? <><Loader2 className="w-5 h-5 mr-2 animate-spin" /> Enviando...</> : <><Send className="w-5 h-5 mr-2" /> Enviar Mensaje</>}
|
||||
</Button>
|
||||
</motion.form>
|
||||
);
|
||||
};
|
||||
|
||||
export default ContactForm;
|
||||
Reference in New Issue
Block a user