function Contact() { const [form, setForm] = React.useState({ name: "", role: "sindico", units: "", city: "", phone: "", email: "", current: "", message: "" }); const [errors, setErrors] = React.useState({}); const [touched, setTouched] = React.useState({}); // ─── Brazilian phone formatter (auto-mask: (XX) XXXXX-XXXX ou (XX) XXXX-XXXX) ─── const formatPhone = (raw) => { const d = (raw || "").replace(/\D/g, "").slice(0, 11); if (d.length === 0) return ""; if (d.length <= 2) return `(${d}`; if (d.length <= 6) return `(${d.slice(0, 2)}) ${d.slice(2)}`; if (d.length <= 10) return `(${d.slice(0, 2)}) ${d.slice(2, 6)}-${d.slice(6)}`; return `(${d.slice(0, 2)}) ${d.slice(2, 7)}-${d.slice(7)}`; }; // ─── Validators ──────────────────────────────────────────────────────── const validateEmail = (v) => { if (!v) return "Informe o e-mail."; // RFC 5322 simplificado, mas suficiente: usuário@domínio.tld + ao menos 2 letras no TLD const re = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/; if (!re.test(v)) return "E-mail inválido. Ex.: nome@dominio.com"; return ""; }; const validatePhone = (v) => { if (!v) return "Informe o WhatsApp."; const d = v.replace(/\D/g, ""); // Brasil: DDD válido (11–99) + 9 dígitos (celular) ou 8 dígitos (fixo) if (d.length < 10 || d.length > 11) return "WhatsApp deve ter 10 ou 11 dígitos com DDD."; const ddd = parseInt(d.slice(0, 2), 10); if (ddd < 11 || ddd > 99) return "DDD inválido."; if (d.length === 11 && d[2] !== "9") return "Celular deve começar com 9 após o DDD."; return ""; }; const validateName = (v) => { if (!v || v.trim().length < 2) return "Informe o nome completo."; return ""; }; const validators = { name: validateName, email: validateEmail, phone: validatePhone, }; // ─── Handlers ────────────────────────────────────────────────────────── const handle = (k) => (e) => { let val = e.target.value; if (k === "phone") val = formatPhone(val); setForm({ ...form, [k]: val }); // limpa erro do campo enquanto digita (re-valida só ao sair) if (errors[k] && validators[k]) { const next = validators[k](val); if (!next) setErrors({ ...errors, [k]: "" }); } }; const handleBlur = (k) => () => { setTouched({ ...touched, [k]: true }); if (validators[k]) { const err = validators[k](form[k]); setErrors({ ...errors, [k]: err }); } }; // Intercepta o submit para validar tudo antes de deixar o form ir const handleSubmit = (e) => { const nameErr = validateName(form.name); const emailErr = validateEmail(form.email); const phoneErr = validatePhone(form.phone); if (nameErr || emailErr || phoneErr) { e.preventDefault(); setErrors({ name: nameErr, email: emailErr, phone: phoneErr }); setTouched({ name: true, email: true, phone: true }); // Foca no primeiro campo com erro const firstError = nameErr ? "name" : emailErr ? "email" : "phone"; const el = document.querySelector(`[data-field="${firstError}"]`); if (el) el.focus(); } }; const roleLabel = { sindico: "Síndico(a) do condomínio", conselho: "Conselheiro(a) fiscal", condomino: "Condômino interessado", incorporadora: "Incorporadora / construtora", outro: "Outro" }[form.role] || form.role; // Endpoint próprio na Hostinger (PHP). Substitui o FormSubmit, que tinha // dependência externa e podia cair (erro 522). Agora o e-mail sai pela // própria infra da Hostinger via PHP mail(). const FORM_ACTION = "/enviar.php"; return (
Vamos conversar?

Fale com a Condominize. Sem compromisso.

Conversa inicial sem compromisso. A gente conhece o seu condomínio, entende o que está acontecendo hoje e mostra como pode melhorar — com clareza e sem pressão.

{/* honeypot anti-spam — bots preenchem, humanos ignoram */}
{errors.name && {errors.name}}
{errors.phone && {errors.phone}}
{errors.email && {errors.email}}