// QUOTE page — multi-section quote form const { useState: useStateQ } = React; function QuoteApp() { const [lang, setLang] = useLang(); const t = mergeT(lang); const qp = t.quote_page; const f = qp.form; const [submitted, setSubmitted] = useStateQ(false); const [submitting, setSubmitting] = useStateQ(false); const [error, setError] = useStateQ(""); const [files, setFiles] = useStateQ([]); const onFiles = (list) => setFiles(Array.from(list || []).map(x => x.name)); const ICN = { Mail: Icon.Mail, Calendar: Icon.Calendar, Clipboard: Icon.Clipboard }; return ( <> { e.preventDefault(); setError(""); setSubmitting(true); const fd = new FormData(e.target); const timeline = fd.get("timeline") || ""; const budget = fd.get("budget") || ""; const payload = { name: fd.get("name") || "", phone: fd.get("phone") || "", email: fd.get("email") || "", address: fd.get("zip") || "", projectType: fd.get("projectType") || "", message: fd.get("message") || "", timeline: timeline, budget: budget, }; try { const res = await fetch("/api/remodeling-quote", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }); const j = await res.json(); if (j.success) { setSubmitted(true); window.scrollTo({ top: 0, behavior: "smooth" }); } else { setError(j.error || "Submission failed."); } } catch (err) { setError(lang === "en" ? "Network error. Please call (737) 354-7787." : "Error de red. Llama (737) 354-7787."); } finally { setSubmitting(false); } }}> {submitted && ( ✓ {lang === 'en' ? "Thanks — your request is in. Expect to hear from us within one business day." : "Gracias — recibimos tu solicitud. Te contactamos en menos de un día hábil."} )} {error && ( ⚠️ {error} )} {f.h} {f.step1} {f.name} {f.phone} {f.email} {f.zip} {f.step2} {f.type} {f.type_options.map((o, i) => {o})} {f.message} {f.step3} {f.timeline} {f.timeline_options.map((o, i) => ( {o.l} ))} {f.budget} {f.budget_options.map((o, i) => ( {o.l} ))} {f.scheduling} {f.scheduling_options.map((o, i) => ( {o.l} ))} {f.step4} e.preventDefault()} onDrop={(e) => { e.preventDefault(); onFiles(e.dataTransfer.files); }}> onFiles(e.target.files)} /> {f.upload_lbl} {f.upload_sub} {files.length > 0 && ( {files.length} {lang === 'en' ? 'file(s) selected' : 'archivo(s) seleccionado(s)'}: {files.join(", ")} )} {f.submit} {f.consent} > ); } ReactDOM.createRoot(document.getElementById("app")).render();
{f.consent}