// wizard.jsx — 3-step anfrage wizard (Was → Wo + Anzahl → Kontakt) // Drops into a section as . // // SPAM PROTECTION (3 layers): // 1. Honeypot field "_gotcha" — hidden via CSS, bots fill it // 2. Time gate — submission < 3s after form first interaction = rejected // 3. Web3Forms built-in spam filter (server-side) // // CONFIG: replace WEB3FORMS_KEY with your access key from web3forms.com const WEB3FORMS_KEY = "282be147-dbbc-4f57-91c8-1be06384cc7f"; const WEB3FORMS_ENDPOINT = "https://api.web3forms.com/submit"; const TYPE_LABELS = { sektional: "Sektionaltore (elektrische Hub-/Schiebetore)", roll: "Rolltore / Rollgitter", schnelllauf: "Schnelllauftore (hochfrequente Verladetore)", schiebe: "Schiebe- / Drehtore (Außen-Toranlagen)", brand: "Brandschutztüren (T30/T90, Türschließer)", gemischt: "Verschiedene Tor-Typen (gemischt)" }; function Wizard() { const [step, setStep] = React.useState(0); const [data, setData] = React.useState({ type: "", qty: "", city: "", name: "", company: "", phone: "", email: "", _gotcha: "" // honeypot — must stay empty }); const [submitting, setSubmitting] = React.useState(false); const [error, setError] = React.useState(null); const formOpenedAt = React.useRef(Date.now()); const set = (k, v) => setData((d) => ({ ...d, [k]: v })); const types = [ { id: "sektional", title: "Sektionaltore", desc: "Elektrische Hub-/Schiebetore" }, { id: "roll", title: "Rolltore", desc: "Rolltore, Rollgitter" }, { id: "schnelllauf", title: "Schnelllauftore", desc: "Hochfrequente Verladetore" }, { id: "schiebe", title: "Schiebe-/Drehtore", desc: "Außen-Toranlagen" }, { id: "brand", title: "Brandschutztüren", desc: "T30/T90, Türschließer" }, { id: "gemischt", title: "Verschiedene Tor-Typen", desc: "Mehrere Tor-Arten gleichzeitig" } ]; const ok2 = data.type; const ok3 = data.city && data.qty; const okSubmit = data.name && data.phone; const submit = async () => { setError(null); // ── SPAM CHECK 1 — honeypot must stay empty if (data._gotcha) { // silently "succeed" so bot doesn't retry setStep(3); return; } // ── SPAM CHECK 2 — time gate: humans take > 3s const elapsed = Date.now() - formOpenedAt.current; if (elapsed < 3000) { setError("Bitte einen Moment — und nochmal absenden."); formOpenedAt.current = Date.now() - 3500; return; } setSubmitting(true); try { // ── Build a human-readable subject + structured body const typeLabel = TYPE_LABELS[data.type] || data.type; const subject = `Prüfanfrage TP Seitz — ${data.qty}× ${typeLabel} · ${data.city}`; const payload = { access_key: WEB3FORMS_KEY, subject, from_name: "TP Seitz Website · Anfrageformular", // The fields Web3Forms emails out as a table: "Tortyp": typeLabel, "Anzahl Tore/Türen": data.qty, "Standort / PLZ": data.city, "Name": data.name, "Unternehmen": data.company || "—", "Telefon": data.phone, "E-Mail": data.email || "—", "Zeitstempel": new Date().toLocaleString("de-DE", { timeZone: "Europe/Berlin" }), "Ausfüll-Dauer (Sek.)": Math.round(elapsed / 1000), // honeypot — Web3Forms also recognizes this field botcheck: data._gotcha }; const res = await fetch(WEB3FORMS_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify(payload) }); const json = await res.json().catch(() => ({})); if (res.ok && json.success) { setStep(3); } else { // If access key is the placeholder, simulate success in preview mode if (WEB3FORMS_KEY === "REPLACE_WITH_YOUR_WEB3FORMS_ACCESS_KEY") { console.warn("[TP Seitz] Web3Forms key not configured — simulating success for preview."); setStep(3); } else { setError(json.message || "Die Anfrage konnte nicht gesendet werden. Bitte rufen Sie uns kurz an: +49 173 5285068."); } } } catch (e) { // Network error — in preview/dev mode still show success if (WEB3FORMS_KEY === "REPLACE_WITH_YOUR_WEB3FORMS_ACCESS_KEY") { console.warn("[TP Seitz] Preview-Modus — Anfrage wird in Produktion an kontakt@tp-seitz.de versendet."); setStep(3); } else { setError("Verbindung fehlgeschlagen. Bitte rufen Sie uns kurz an: +49 173 5285068."); } } finally { setSubmitting(false); } }; return (
Anfrage

Drei Schritte zum Prüftermin.

Was — wo — wer. In 60 Sekunden ausgefüllt, am selben Werktag eine Rückmeldung mit konkretem Termin und Preisrahmen.

{[0, 1, 2, 3].map((i) => ( ))}
{step === 0 && ( <>

Schritt 01 von 03

Welche Tore oder Türen sollen geprüft werden?

{types.map((t) => ( ))}
Auswahl genügt — Details klären wir telefonisch.
)} {step === 1 && ( <>

Schritt 02 von 03

Wo stehen die Tore und wie viele sind es?

set("city", e.target.value)} /> set("qty", e.target.value)} />
Wir fahren bis 150 km von Bonstetten / Augsburg aus. Falls Ihr Standort außerhalb liegt, sagen wir Ihnen das direkt — kein Vertrösten.
)} {step === 2 && ( <>

Schritt 03 von 03

Wer bekommt die Rückmeldung?

set("name", e.target.value)} /> set("company", e.target.value)} /> set("phone", e.target.value)} /> set("email", e.target.value)} />
{/* HONEYPOT — bots fill it, humans never see it */}
Mit dem Absenden stimmen Sie zu, dass wir Ihre Daten zur Bearbeitung Ihrer Anfrage verwenden. Keine Werbung, keine Weitergabe an Dritte. Details in der {" "}Datenschutzerklärung.
{error && (
{error}
)}
)} {step === 3 && (

Danke — Anfrage ist da.

Wir melden uns am selben oder spätestens nächsten Werktag mit einem konkreten Terminvorschlag und einer Kostenschätzung. Bei Eilbedarf rufen Sie uns direkt an: +49 173 5285068.

)}
); } Object.assign(window, { Wizard });