/* Logik Systems — Angebots-/Anfrage-Wizard (dedicated page) */ const { useState, useEffect, useRef, useMemo } = React; /* ---- small inline icon set (stroke = currentColor) ---- */ function Ic(props) { var p = { gear: "M10 1.8l1 .15.5 2.1 1.6.66 1.9-1 .9.9-1 1.9.66 1.6 2.1.5.15 1v1l-.15 1-2.1.5-.66 1.6 1 1.9-.9.9-1.9-1-1.6.66-.5 2.1-1 .15h-1l-1-.15-.5-2.1-1.6-.66-1.9 1-.9-.9 1-1.9-.66-1.6-2.1-.5L1.8 11v-1l.15-1 2.1-.5.66-1.6-1-1.9.9-.9 1.9 1 1.6-.66.5-2.1 1-.15z", factory: "M2 18V9l5 3V9l5 3V5l6 0v13z", bolt: "M11 1L3 11h6l-1 8 8-11h-6z", sofa: "M3 11V8a2 2 0 012-2h10a2 2 0 012 2v3M2 11h16v5H2zM4 16v2M16 16v2", cross: "M8 2h4v6h6v4h-6v6H8v-6H2V8h6z", truck: "M1 5h11v9H1zM12 8h4l3 3v3h-7zM5 14a2 2 0 11-4 0 2 2 0 014 0zM17 14a2 2 0 11-4 0 2 2 0 014 0z", window: "M3 3h14v14H3zM10 3v14M3 10h14", dots: "M5 10h.01M10 10h.01M15 10h.01", rocket: "M10 1c3 2 4 5 4 8l-2 4H8l-2-4c0-3 1-6 4-8zM10 7.5a1.5 1.5 0 100 3 1.5 1.5 0 000-3zM6 14l-2 4M14 14l2 4", clock: "M10 4a6 6 0 100 12 6 6 0 000-12zM10 7v3l2 1.5", check2: "M4 10.5l4 4 8-9", chip: "M6 6h8v8H6zM3 8h3M3 12h3M14 8h3M14 12h3M8 3v3M12 3v3M8 14v3M12 14v3", plug: "M6 2v5M14 2v5M4 7h12v3a6 6 0 01-12 0zM10 16v3", cube: "M10 2l7 4v8l-7 4-7-4V6zM3 6l7 4 7-4M10 10v8", target: "M10 3a7 7 0 100 14 7 7 0 000-14zM10 7a3 3 0 100 6 3 3 0 000-6zM10 10h.01", chat: "M3 4h14v9H8l-4 3v-3H3z", compass: "M10 2a8 8 0 100 16 8 8 0 000-16zM13 7l-2 4-4 2 2-4z" }; var d = p[props.n] || p.dots; return React.createElement("svg", { width: 22, height: 22, viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" }, React.createElement("path", { d: d })); } const QUESTIONS = [ { key: "branche", kind: "single", variant: "grid", eyebrow: "Ihr Unternehmen", q: "In welcher Branche sind Sie tätig?", helper: "Wählen Sie, was am besten passt.", options: [ { v: "Maschinenbau", icon: "gear" }, { v: "Anlagenbau", icon: "factory" }, { v: "Elektrotechnik", icon: "bolt" }, { v: "Möbel & Interior", icon: "sofa" }, { v: "Medizintechnik", icon: "cross" }, { v: "Fahrzeugbau", icon: "truck" }, { v: "Fenster & Fassade", icon: "window" }, { v: "Sonstiges", icon: "dots" } ] }, { key: "mitarbeitende", kind: "single", variant: "num", eyebrow: "Ihr Unternehmen", q: "Wie viele Mitarbeitende hat Ihr Unternehmen?", helper: "Eine grobe Einschätzung genügt.", options: [{ v: "1–50" }, { v: "51–250" }, { v: "251–1.000" }, { v: "1.000+" }] }, { key: "erp", kind: "single", variant: "grid", eyebrow: "Ihre Systeme", q: "Welches ERP-System nutzen Sie?", helper: "Tippen Sie einfach auf Ihr System.", options: [ { v: "ProAlpha", icon: "chip" }, { v: "SAP", icon: "chip" }, { v: "Sage", icon: "chip" }, { v: "Microsoft Dynamics", icon: "chip" }, { v: "Anderes", icon: "plug" }, { v: "Keins / unsicher", icon: "dots" } ] }, { key: "varianten", kind: "single", variant: "num", eyebrow: "Ihre Produkte", q: "Wie viele Produktvarianten bieten Sie an? (ca.)", helper: "Wählen Sie den ungefähren Bereich.", options: [{ v: "bis 50" }, { v: "bis 500" }, { v: "bis 5.000" }, { v: "5.000+" }, { v: "weiß ich nicht" }] }, { key: "ziele", kind: "multi", variant: "list", eyebrow: "Ihre Ziele", q: "Was ist Ihnen am wichtigsten?", helper: "Mehrfachauswahl möglich.", options: [ { v: "Schnellere Angebote", s: "Zügiger von Anfrage zu validem Angebot", icon: "rocket" }, { v: "Weniger Fehler", s: "Konsistente Konfiguration, Kalkulation und Stückliste", icon: "check2" }, { v: "Durchgängige ERP-Prozesse", s: "Keine manuelle Übertragung mehr", icon: "plug" }, { v: "CAD-Anbindung", s: "Zeichnungen und Stücklisten automatisch erzeugen", icon: "cube" } ] }, { key: "interesse", kind: "single", variant: "list", eyebrow: "Ihr Interesse", q: "Woran sind Sie interessiert?", helper: "Was passt am ehesten?", options: [ { v: "Individueller Konfigurator", s: "Maßgeschneiderte Lösung für komplexe Produkte", icon: "gear" }, { v: "PK-Easy", s: "Sofort einsatzbereites Konfigurator-Produkt", icon: "rocket" }, { v: "ERP-Integration", s: "Konfiguration durchgängig ins ERP bringen", icon: "plug" }, { v: "Allgemeine Beratung", s: "Erst einmal Möglichkeiten ausloten", icon: "chat" } ] }, { key: "zeitraum", kind: "single", variant: "grid", eyebrow: "Ihr Projekt", q: "Wann möchten Sie starten?", helper: "Eine grobe Einschätzung genügt.", options: [{ v: "So schnell wie möglich" }, { v: "1–3 Monate" }, { v: "3–6 Monate" }, { v: "Über 6 Monate" }] } ]; /* full ordered screen list */ const SCREENS = QUESTIONS.map(function (q) { return q.key; }) .concat(["message", "auswertung", "kontakt", "review"]); function stepLabel(i) { if (i < 7) return "Frage " + (i + 1) + " / 7"; var k = SCREENS[i]; if (k === "message") return "Fast geschafft"; if (k === "auswertung") return "Ihre Auswertung"; if (k === "kontakt") return "Ihre Kontaktdaten"; if (k === "review") return "Letzter Schritt"; return ""; } function Wizard() { var params = useMemo(function () { return new URLSearchParams(location.search); }, []); var [step, setStep] = useState(0); var [done, setDone] = useState(false); var [ans, setAns] = useState(function () { var init = { ziele: [], message: "", consent: false, captcha: false, kontakt: { anrede: "", firma: "", vorname: "", nachname: "", email: "", telefon: "", funktion: "" } }; var presetMap = { "pk-easy": "PK-Easy", "konfigurator": "Individueller Konfigurator", "erp": "ERP-Integration", "beratung": "Allgemeine Beratung" }; var pi = (params.get("interesse") || "").toLowerCase(); if (presetMap[pi]) init.interesse = presetMap[pi]; var pb = params.get("branche"); if (pb) init.branche = pb; var pe = params.get("erp"); if (pe) init.erp = pe; return init; }); var headingRef = useRef(null); var liveRef = useRef(null); var startedAt = useRef(Date.now()); var [submitting, setSubmitting] = useState(false); var [submitError, setSubmitError] = useState(""); useEffect(function () { if (headingRef.current) headingRef.current.focus(); if (liveRef.current) liveRef.current.textContent = done ? "Anfrage gesendet" : stepLabel(step); var main = document.getElementById("wizMain"); if (main) main.scrollTop = 0; }, [step, done]); var totalForBar = SCREENS.length; // questions+message+auswertung+kontakt+review var progress = done ? 100 : Math.min(100, Math.round((step / totalForBar) * 100) + 6); function setQ(key, val) { setAns(function (a) { var n = Object.assign({}, a); n[key] = val; return n; }); } function toggleMulti(key, val) { setAns(function (a) { var arr = a[key].slice(); var idx = arr.indexOf(val); if (idx >= 0) arr.splice(idx, 1); else arr.push(val); var n = Object.assign({}, a); n[key] = arr; return n; }); } function setK(field, val) { setAns(function (a) { return Object.assign({}, a, { kontakt: Object.assign({}, a.kontakt, (function () { var o = {}; o[field] = val; return o; })()) }); }); } function go(n) { setStep(Math.max(0, Math.min(SCREENS.length - 1, n))); } function next() { go(step + 1); } function back() { go(step - 1); } function pickSingle(key, val) { setQ(key, val); setTimeout(function () { setStep(function (s) { return Math.min(SCREENS.length - 1, s + 1); }); }, 230); } var emailOk = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(ans.kontakt.email); var kontaktValid = ans.kontakt.anrede && ans.kontakt.firma.trim() && ans.kontakt.vorname.trim() && ans.kontakt.nachname.trim() && emailOk && ans.kontakt.telefon.trim(); /* ---------- render helpers ---------- */ function Eyebrow(txt) { return React.createElement("p", { className: "wiz-eyebrow" }, txt); } function renderQuestion(q, i) { var selected = ans[q.key]; return React.createElement("div", { className: "wiz-step", key: q.key }, React.createElement("p", { className: "wiz-eyebrow" }, "— " + q.eyebrow.toUpperCase()), React.createElement("h1", { className: "wiz-q", tabIndex: -1, ref: headingRef }, q.q), React.createElement("p", { className: "wiz-helper" }, q.helper), React.createElement("div", { className: "wiz-cards " + q.variant }, q.options.map(function (o) { var isSel = q.kind === "multi" ? ans[q.key].indexOf(o.v) >= 0 : selected === o.v; return React.createElement("button", { key: o.v, type: "button", className: "wiz-card" + (o.s ? " has-sub" : "") + (isSel ? " sel" : ""), "aria-pressed": isSel, onClick: function () { q.kind === "multi" ? toggleMulti(q.key, o.v) : pickSingle(q.key, o.v); } }, o.icon ? React.createElement("span", { className: "wiz-ic" }, React.createElement(Ic, { n: o.icon })) : null, React.createElement("span", { className: "wiz-card-main" }, React.createElement("span", { className: "wiz-card-t" + (q.variant === "num" ? " big" : "") }, o.v), o.s ? React.createElement("span", { className: "wiz-card-s" }, o.s) : null ), q.kind === "multi" ? React.createElement("span", { className: "wiz-check" }) : null ); }) ), React.createElement(Footer, { onBack: i > 0 ? back : null, onNext: q.kind === "multi" ? next : null, nextDisabled: q.kind === "multi" && ans[q.key].length === 0, nextLabel: "Weiter" }) ); } function renderMessage() { return React.createElement("div", { className: "wiz-step", key: "message" }, React.createElement("p", { className: "wiz-eyebrow" }, "— FAST GESCHAFFT"), React.createElement("h1", { className: "wiz-q", tabIndex: -1, ref: headingRef }, "Besondere Wünsche?"), React.createElement("p", { className: "wiz-helper" }, "Optional – alles, was wir vorab wissen sollten."), React.createElement("textarea", { className: "wiz-textarea", value: ans.message, placeholder: "z. B. konkrete Produkte, Schnittstellen, mehrere Standorte, Fragen zur Umsetzung …", onChange: function (e) { setQ("message", e.target.value); } }), React.createElement(Footer, { onBack: back, onNext: next, nextLabel: ans.message.trim() ? "Weiter" : "Überspringen" }) ); } function renderAuswertung() { var erp = ans.erp && ans.erp !== "Keins / unsicher" && ans.erp !== "Anderes" ? ans.erp : "Ihr ERP-System"; var ziel = (ans.ziele && ans.ziele[0]) || "schnellere, fehlerfreie Angebote"; var cards = [ { t: "Hohes Automatisierungspotenzial", s: "Viele Varianten und manuelle Angebote lassen sich gut automatisieren." }, { t: "ERP-Anbindung möglich", s: erp + " lässt sich in einen Konfigurator integrieren." }, { t: "Schnelle Erfolge realistisch", s: "Ihr Ziel „" + ziel + "“ ist mit einem Konfigurator gut erreichbar." } ]; return React.createElement("div", { className: "wiz-step wiz-eval", key: "auswertung" }, React.createElement("span", { className: "wiz-eval-ic" }, React.createElement("svg", { width: 30, height: 30, viewBox: "0 0 30 30", fill: "none", stroke: "currentColor", strokeWidth: 2.4, strokeLinecap: "round", strokeLinejoin: "round" }, React.createElement("path", { d: "M8 15.5l4.5 4.5L22 9.5" }))), React.createElement("h1", { className: "wiz-q center", tabIndex: -1, ref: headingRef }, "Gute Voraussetzungen für einen Produktkonfigurator."), React.createElement("p", { className: "wiz-helper center" }, "Auf Basis Ihrer Angaben – die Details klären wir im Gespräch."), React.createElement("div", { className: "wiz-eval-cards" }, cards.map(function (c, idx) { return React.createElement("div", { className: "wiz-eval-card", key: idx }, React.createElement("span", { className: "wiz-eval-chk" }, React.createElement("svg", { width: 16, height: 16, viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round" }, React.createElement("path", { d: "M4 10.5l4 4 8-9" }))), React.createElement("div", null, React.createElement("h3", null, c.t), React.createElement("p", null, c.s))); }) ), React.createElement(Footer, { onBack: back, onNext: next, nextLabel: "Weiter zu Ihren Daten" }) ); } function field(label, fieldKey, type, req, ph, auto) { var val = ans.kontakt[fieldKey]; var bad = req && (!val.trim() || (fieldKey === "email" && !emailOk)); return React.createElement("div", { className: "wiz-field" + (bad && showKErr ? " err" : "") }, React.createElement("label", null, label, req ? React.createElement("span", { className: "req" }, " *") : null), React.createElement("input", { type: type || "text", value: val, placeholder: ph || "", autoComplete: auto || "off", onChange: function (e) { setK(fieldKey, e.target.value); } }) ); } var [showKErr, setShowKErr] = useState(false); function renderKontakt() { var anreden = ["Herr", "Frau", "Keine Angabe"]; var funktionen = ["Geschäftsführung", "Vertrieb", "IT", "Konstruktion", "Sonstiges"]; return React.createElement("div", { className: "wiz-step", key: "kontakt" }, React.createElement("p", { className: "wiz-eyebrow" }, "— IHRE KONTAKTDATEN"), React.createElement("h1", { className: "wiz-q", tabIndex: -1, ref: headingRef }, "Wie erreichen wir Sie?"), React.createElement("p", { className: "wiz-helper" }, "Wir melden uns zeitnah – ohne Verpflichtung."), field("Firma", "firma", "text", true, "Unternehmen", "organization"), React.createElement("div", { className: "wiz-field" + (showKErr && !ans.kontakt.anrede ? " err" : "") }, React.createElement("label", null, "Anrede ", React.createElement("span", { className: "req" }, "*")), React.createElement("div", { className: "wiz-toggle" }, anreden.map(function (a) { return React.createElement("button", { key: a, type: "button", className: "wiz-tg" + (ans.kontakt.anrede === a ? " sel" : ""), onClick: function () { setK("anrede", a); } }, a); })) ), React.createElement("div", { className: "wiz-row2" }, field("Vorname", "vorname", "text", true, "Vorname", "given-name"), field("Nachname", "nachname", "text", true, "Nachname", "family-name")), React.createElement("div", { className: "wiz-row2" }, field("E-Mail", "email", "email", true, "name@firma.de", "email"), field("Telefon", "telefon", "tel", true, "+49 …", "tel")), React.createElement("div", { className: "wiz-field" }, React.createElement("label", null, "Ihre Funktion"), React.createElement("div", { className: "wiz-toggle wrap" }, funktionen.map(function (f) { return React.createElement("button", { key: f, type: "button", className: "wiz-tg" + (ans.kontakt.funktion === f ? " sel" : ""), onClick: function () { setK("funktion", ans.kontakt.funktion === f ? "" : f); } }, f); })) ), React.createElement(Footer, { onBack: back, onNext: function () { if (!kontaktValid) { setShowKErr(true); return; } next(); }, nextDisabled: false, nextLabel: "Weiter" }) ); } function summaryRows() { var k = ans.kontakt; var rows = [ ["Branche", ans.branche, 0], ["Mitarbeitende", ans.mitarbeitende, 1], ["ERP-System", ans.erp, 2], ["Produktvarianten", ans.varianten, 3], ["Ziele", (ans.ziele || []).join(", "), 4], ["Interesse", ans.interesse, 5], ["Zeitraum", ans.zeitraum, 6], ["Kontakt", [k.anrede, k.vorname, k.nachname].filter(Boolean).join(" "), 9], ["Firma", k.firma, 9], ["E-Mail", k.email, 9], ["Telefon", k.telefon, 9] ]; if (k.funktion) rows.push(["Funktion", k.funktion, 9]); if (ans.message.trim()) rows.push(["Anmerkungen", ans.message, 7]); return rows.filter(function (r) { return r[1]; }); } /* ---------- Absenden an das CMS (Modul LOGIK_FORMS, Formular "angebot") ---------- */ function buildPayload() { var k = ans.kontakt; var name = [k.vorname, k.nachname].filter(function (x) { return x && x.trim(); }).join(" ").trim(); // Die Wizard-Antworten als zusätzliche Label/Wert-Paare (extra_fields) mitschicken. var extra = []; function add(label, val) { var v = Array.isArray(val) ? val.join(", ") : val; if (v && String(v).trim()) extra.push({ label: label, value: String(v) }); } add("Anrede", k.anrede); add("Branche", ans.branche); add("Mitarbeitende", ans.mitarbeitende); add("ERP-System", ans.erp); add("Produktvarianten", ans.varianten); add("Ziele", ans.ziele); add("Interesse", ans.interesse); add("Zeitraum", ans.zeitraum); add("Funktion", k.funktion); return { form: "angebot", name: name, firma: k.firma, email: k.email, telefon: k.telefon, nachricht: ans.message, datenschutz: ans.consent ? "1" : "", extra_fields: JSON.stringify(extra), _elapsed: Date.now() - startedAt.current, page_url: location.href, language: (document.documentElement.getAttribute("lang") || "").slice(0, 8) }; } function submitAngebot() { if (submitting) return; setSubmitting(true); setSubmitError(""); fetch("/api/forms/submit", { method: "POST", headers: { "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest" }, credentials: "same-origin", body: JSON.stringify(buildPayload()) }) .then(function (r) { return r.json().catch(function () { return {}; }); }) .then(function (data) { if (data && data.ok) { try { var u = new URL(location.href); u.searchParams.set("angebot_success", "1"); history.replaceState(null, "", u); } catch (e) {} if (window.dataLayer) window.dataLayer.push({ event: "angebot_success" }); setDone(true); } else { setSubmitError((data && data.message) || "Die Anfrage konnte nicht gesendet werden. Bitte versuchen Sie es erneut."); } }) .catch(function () { setSubmitError("Verbindungsproblem. Bitte versuchen Sie es erneut oder schreiben Sie uns direkt per E-Mail."); }) .then(function () { setSubmitting(false); }); } function renderReview() { return React.createElement("div", { className: "wiz-step", key: "review" }, React.createElement("p", { className: "wiz-eyebrow" }, "— LETZTER SCHRITT"), React.createElement("h1", { className: "wiz-q", tabIndex: -1, ref: headingRef }, "Passt alles?"), React.createElement("p", { className: "wiz-helper" }, "Kurzer Blick auf Ihre Angaben, dann absenden."), React.createElement("dl", { className: "wiz-summary" }, summaryRows().map(function (r, idx) { return React.createElement("div", { className: "wiz-srow", key: idx }, React.createElement("dt", null, r[0]), React.createElement("dd", null, r[1], React.createElement("button", { type: "button", className: "wiz-edit", onClick: function () { go(r[2]); } }, "Ändern"))); }) ), React.createElement("label", { className: "wiz-consent" + (showKErr && !ans.consent ? " err" : "") }, React.createElement("input", { type: "checkbox", checked: ans.consent, onChange: function (e) { setQ("consent", e.target.checked); } }), React.createElement("span", null, "Ich habe die ", React.createElement("a", { href: "#" }, "Datenschutzerklärung"), " gelesen und stimme der Verarbeitung meiner Daten zu.")), React.createElement("label", { className: "wiz-consent captcha" + (showKErr && !ans.captcha ? " err" : "") }, React.createElement("input", { type: "checkbox", checked: ans.captcha, onChange: function (e) { setQ("captcha", e.target.checked); } }), React.createElement("span", null, "Ich bestätige, dass ich ein Mensch bin.", React.createElement("span", { className: "wiz-captcha-badge" }, "Captcha"))), submitError ? React.createElement("p", { className: "wiz-submit-error", role: "alert", style: { color: "#c0392b", fontSize: "14px", lineHeight: 1.5, margin: "10px 0 0" } }, submitError) : null, React.createElement(Footer, { onBack: submitting ? null : back, onNext: function () { if (!ans.consent || !ans.captcha) { setShowKErr(true); return; } submitAngebot(); }, nextDisabled: submitting, nextLabel: submitting ? "Wird gesendet …" : "Anfrage senden", primaryWide: true }) ); } function renderSuccess() { return React.createElement("div", { className: "wiz-step wiz-eval", key: "success" }, React.createElement("span", { className: "wiz-eval-ic" }, React.createElement("svg", { width: 32, height: 32, viewBox: "0 0 30 30", fill: "none", stroke: "currentColor", strokeWidth: 2.4, strokeLinecap: "round", strokeLinejoin: "round" }, React.createElement("path", { d: "M8 15.5l4.5 4.5L22 9.5" }))), React.createElement("h1", { className: "wiz-q center", tabIndex: -1, ref: headingRef }, "Vielen Dank!"), React.createElement("p", { className: "wiz-helper center" }, "Wir melden uns innerhalb von 1 Werktag mit den nächsten Schritten."), React.createElement("a", { className: "btn btn-primary", href: "index.html#top", style: { marginTop: "12px" } }, "Zurück zur Startseite") ); } var content; if (done) content = renderSuccess(); else { var key = SCREENS[step]; if (step < 7) content = renderQuestion(QUESTIONS[step], step); else if (key === "message") content = renderMessage(); else if (key === "auswertung") content = renderAuswertung(); else if (key === "kontakt") content = renderKontakt(); else content = renderReview(); } return React.createElement(React.Fragment, null, React.createElement("div", { className: "wiz-top" }, React.createElement("div", { className: "wiz-progress" }, React.createElement("i", { style: { width: progress + "%" } })), React.createElement("span", { className: "wiz-steplabel" }, done ? "Abgeschlossen" : stepLabel(step)) ), React.createElement("div", { className: "wiz-canvas" }, content), React.createElement("div", { className: "wiz-live", "aria-live": "polite", ref: liveRef }) ); } function Footer(props) { return React.createElement("div", { className: "wiz-foot" }, props.onBack ? React.createElement("button", { type: "button", className: "wiz-back", onClick: props.onBack, "aria-label": "Zurück" }, "←") : React.createElement("span", null), props.onNext ? React.createElement("button", { type: "button", className: "btn btn-primary wiz-next" + (props.primaryWide ? " wide" : ""), disabled: props.nextDisabled, onClick: props.onNext }, props.nextLabel, " ", React.createElement("span", { className: "arr" }, "→")) : null ); } ReactDOM.createRoot(document.getElementById("wizMount")).render(React.createElement(Wizard));