/* ============================================================ Ueber mich — About Thomas Basting Cyan-on-dark, fits Smartmacherei brand ============================================================ */ const UM_PALETTE = { bg: "#071520", card: "#0D2030", accent: "#3ABDD0", soft: "#8DDBEA", ink: "#ffffff", muted: "rgba(141,219,234,0.55)", line: "rgba(141,219,234,0.16)", }; const UM_TIMELINE = [ { year: "Seit 2024", role: "Smartmacherei", org: "Selbständig · Edt bei Lambach", body: "Smart-Home- und Gebäudeautomations-Integration für Altbau, Neubau und kleine Gewerbebetriebe. Fokus auf Home Assistant, Loxone, Energiemanagement und Netzwerk.", accent: true, }, { year: "2021 — 2024", role: "Peneder Bau-Elemente", org: "Produktentwicklung → Vertrieb", body: "Mitentwicklung und Markteinführung einer Türhardware-Produktlinie inkl. Smart-Home-Integration.", }, { year: "2017 — 2021", role: "KUKA CEE GmbH", org: "Anwendungsingenieur → Teamleiter Engineering", body: "Roboter-Projekte von Konzept bis Schulung. Führung des Engineering-Teams, Standardisierung von Pflichtenheften.", }, { year: "2016 — 2017", role: "GTech Automatisierungstechnik", org: "SPS-Programmierer", body: "Steuerungsentwicklung in Siemens TIA / Step 7, Funktionsprüfung und Inbetriebnahme.", }, { year: "2014 — 2016", role: "TGW Mechanics GmbH", org: "Inbetriebnahmeingenieur", body: "Europaweite Inbetriebnahme hochautomatisierter Logistikanlagen.", }, { year: "2007 — 2013", role: "HTL Wels", org: "Mechatronik · Schwerpunkt Automatisierung", body: "Technische Grundausbildung — SPS, Robotik, Elektrotechnik, CAD.", }, ]; const UM_SKILLS = [ { group: "Smart Building", items: ["Home Assistant", "Loxone Planung & Integration", "KNX-Grundlagen", "Matter / Thread / Zigbee"] }, { group: "Automatisierung", items: ["SPS · SIMATIC S7 / TIA", "Industrierobotik · KUKA", "Modbus / MQTT / APIs", "Inbetriebnahme & Schulung"] }, { group: "Energie & Netzwerk", items: ["PV / Wärmepumpe / Wallbox", "Energie-Dashboards", "UniFi / Netzwerk-Planung", "Dokumentation & Backup"] }, { group: "Projekt & Beratung", items: ["Pflichtenheft & Anforderung", "Technische Kundenberatung", "Schnittstellenplanung", "Teamführung"] }, ]; function ContactForm() { const [data, setData] = React.useState({ name: '', email: '', phone: '', path: '', subject: '', message: '', }); const [status, setStatus] = React.useState({ kind: 'idle', msg: '' }); const [floorplanToken, setFloorplanToken] = React.useState(null); const set = (k) => (e) => setData({ ...data, [k]: e.target.value }); // Bei Splash-Auswahl ist der Pfad in localStorage. Vorbelegen, falls vorhanden. // Auch: floorplan-Token vom Konfigurator-Upload anzeigen. // Plus: Konfigurator-Summary aus localStorage in die Nachricht uebernehmen // wenn der User "Termin vereinbaren" geklickt hat. const readKfgSummary = () => { try { const summary = window.localStorage.getItem('sm-kfg-summary'); const kfgPath = window.localStorage.getItem('sm-kfg-path'); if (summary) { setData((d) => { const alreadyHas = d.message && d.message.includes('Konfigurator-Empfehlung'); return { ...d, message: alreadyHas ? d.message : ( `Hallo Thomas,\n\nich habe deinen Konfigurator durchlaufen — hier die Zusammenfassung:\n\n${summary}\n\nKönnen wir dazu einen Termin vereinbaren?` ), path: d.path || kfgPath || '', subject: d.subject || 'Termin-Anfrage aus Konfigurator', }; }); } } catch (e) { /* private mode */ } }; // Paket-CTA aus PaketeSection: subject + Vorlage-Message vorbelegen. // force=true bei explizitem Klick (Event) -- überschreibt auch ein // bereits gesetztes Subject. force=false beim ersten Mount -- nur // wenn der User selbst noch nichts geschrieben hat. const readPaketSubject = (force) => { try { const subj = window.localStorage.getItem('sm-paket-subject'); if (!subj) return; setData((d) => { if (!force && d.subject) return d; const intro = `Hallo Thomas,\n\nich interessiere mich für "${subj.replace(/^Paket-Anfrage:\s*/,'')}".\n\nKurz zur Ausgangssituation:\n\n\nBitte um Rückmeldung — danke!`; return { ...d, subject: subj, message: d.message ? d.message : intro, }; }); } catch (e) { /* private mode */ } }; React.useEffect(() => { try { const saved = window.localStorage.getItem('sm-path'); if (saved && !data.path) setData((d) => ({ ...d, path: saved })); const tok = window.localStorage.getItem('sm-floorplan-token'); if (tok) setFloorplanToken(tok); } catch (e) { /* localStorage in some private modes throws */ } // Beim Mount Summary lesen + auf Custom-Event reagieren wenn Konfigurator // gerade "Termin vereinbaren" geklickt hat (Form ist evtl. schon im DOM). readKfgSummary(); // Paket-CTA prefill (sofort + auf Click-Event aus PaketCard). readPaketSubject(false); const handler = () => readKfgSummary(); const paketHandler = () => readPaketSubject(true); window.addEventListener('sm-kfg-summary-updated', handler); window.addEventListener('sm-paket-cta', paketHandler); return () => { window.removeEventListener('sm-kfg-summary-updated', handler); window.removeEventListener('sm-paket-cta', paketHandler); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // UTM-Attribution aus localStorage (von track.js gesetzt) holen. // Wird mit jeder Anfrage mitgesendet, damit Conversions Kampagnen // zugeordnet werden koennen. const readAttribution = () => { try { const raw = window.localStorage.getItem('sm-attr'); if (!raw) return {}; const a = JSON.parse(raw); const out = {}; ['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach((k) => { if (a[k]) out[k] = a[k]; }); if (a.landing) out.landing_page = a.landing; return out; } catch (e) { return {}; } }; const submit = async (e) => { e.preventDefault(); if (!data.name.trim() || !data.email.trim() || !data.message.trim()) { setStatus({ kind: 'err', msg: 'Bitte Name, E-Mail und Nachricht ausfüllen.' }); return; } setStatus({ kind: 'sending', msg: '' }); try { const payload = { ...data, ...readAttribution(), source: 'website-kontakt', sentAt: new Date().toISOString(), userAgent: navigator.userAgent, }; if (floorplanToken) payload.floorplan_token = floorplanToken; const r = await fetch('/api/anfrage', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); if (!r.ok) throw new Error(`HTTP ${r.status}`); const json = await r.json().catch(() => ({})); setStatus({ kind: 'ok', msg: json.message + (json.floorplan_attached ? ' Dein Plan wurde mitgeschickt.' : ''), }); setData({ name: '', email: '', phone: '', path: '', subject: '', message: '' }); // Token nach erfolgreichem Versand lokal entfernen -- Server hat den Plan // bereits geloescht (DSGVO). Auch den Konfigurator-Summary kicken. try { window.localStorage.removeItem('sm-floorplan-token'); window.localStorage.removeItem('sm-kfg-summary'); window.localStorage.removeItem('sm-kfg-path'); } catch (e) {} setFloorplanToken(null); // Conversion an Marketing-Pixel + eigenes Reichweiten-Logging // schicken — beide ruhen still wenn Consent fehlt bzw. DNT gesetzt ist. try { if (typeof window.smConvert === 'function') { window.smConvert('lead', { content_category: data.path || 'unknown' }); } if (navigator.sendBeacon) { const ev = JSON.stringify({ event: 'conversion', path: location.pathname, ...readAttribution(), }); navigator.sendBeacon('/api/track', new Blob([ev], { type: 'application/json' })); } } catch (e) { /* fail-quiet */ } } catch (err) { setStatus({ kind: 'err', msg: 'Senden hat gerade nicht geklappt. Schreib mir bitte direkt an thobasting@gmail.com.', }); } }; const sending = status.kind === 'sending'; return (
Ich komme aus der Automatisierungstechnik. Dort zählt nicht, ob ein System auf dem Papier modern klingt — sondern ob es zuverlässig läuft, verständlich bedienbar ist und im Alltag keine Probleme macht.
Genau diesen Anspruch bringe ich in Wohnhäuser und kleine Gewerbebetriebe.
Meine Basis ist die HTL Mechatronik in Wels mit Schwerpunkt Automatisierung. Danach war ich über zehn Jahre in der Industrie-Automatisierung tätig — unter anderem als SPS-Programmierer, Anwendungsingenieur und später im Engineering bei KUKA. Ich habe Anlagen geplant, programmiert, in Betrieb genommen, Fehler gesucht, Kunden geschult und Technik so aufgebaut, dass sie im Betrieb funktioniert.
Heute übertrage ich dieses Denken auf Smart Home und Energiemanagement: klare Struktur, robuste Basistechnik, offene Schnittstellen und eine Bedienung, die man auch wirklich nutzt.
Home Assistant ist dabei für mich nicht „noch eine App", sondern die offene Ebene, die bestehende Systeme zusammenführt: Loxone, KNX, Matter/Thread, Zigbee, Modbus, PV, Wärmepumpe, Wallbox, Speicher, Netzwerk und Hersteller-APIs.
Mein Schwerpunkt liegt auf Planung, Integration, Visualisierung, Automationslogik, Energiemanagement, Netzwerk und Dokumentation. Elektroinstallationen, Verteilerarbeiten, Schutzmaßnahmen und Abnahmen erfolgen gemeinsam mit konzessionierten Elektrotechnik-Partnerbetrieben.
{row.org}
{row.body}
Egal ob Altbau-Sanierung, Neubau oder Gewerbe — ein erstes Gespräch ist unverbindlich. Schreib mir kurz, worum es geht, dann melde ich mich innerhalb von zwei Werktagen.