/* Powermieter — shared UI primitives (global). */ const { useRef: _useRef, useState: _useState, useEffect: _useEffect } = React; function Logo({ size = 32 }) { /* Prefers the brand asset assets/logo.svg (drop in the real Powerhouse 360 logo there); falls back to a theme-adaptive wordmark if it is missing. */ const [imgOk, setImgOk] = _useState(true); if (imgOk) { return Powerhouse 360 setImgOk(false)} />; } const m = Math.round(size * 0.92); return ( Powerhouse 360 ); } const STEPS = ['Interesse', 'Daten', 'SEPA-Mandat', 'Vertrag']; function ProcessNav({ current, maxReached = 1, onJump }) { return (
{STEPS.map((label, i) => { const n = i + 1; const done = n < current, active = n === current; const clickable = onJump && n <= maxReached && n !== current; return (
onJump(n) : undefined}> {done ? : n} {label} {n < STEPS.length && }
); })}
); } function Field({ label, name, value, onChange, error, type = 'text', placeholder, optional, hint, inputMode, autoComplete, col2 }) { return ( ); } function Select({ label, name, value, onChange, options, error, optional, col2 }) { return ( ); } function Consent({ name, checked, onChange, error, children }) { return ( ); } function Button({ kind = 'primary', lg, block, busy, children, ...rest }) { return ( ); } function Note({ children }) { return
{children}
; } /* ---- Meter-reading photo (camera on mobile, downscaled client-side) ---- */ function PhotoCapture({ value, onChange, error }) { const inputRef = _useRef(null); const onFile = (e) => { const file = e.target.files && e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = () => { const img = new Image(); img.onload = () => { const max = 1280; let { width, height } = img; if (width > max || height > max) { const r = Math.min(max / width, max / height); width = Math.round(width * r); height = Math.round(height * r); } const c = document.createElement('canvas'); c.width = width; c.height = height; c.getContext('2d').drawImage(img, 0, 0, width, height); onChange(c.toDataURL('image/jpeg', 0.7)); }; img.src = reader.result; }; reader.readAsDataURL(file); }; return (
{value ? (
Zählerstand
Foto erfasst
) : ( )} {error && {error}}
); } /* ---- Signature pad (built-in SES; mouse + touch) ---- */ function SignaturePad({ onChange, error }) { const canvasRef = _useRef(null); const [signed, setSigned] = _useState(false); const drawing = _useRef(false); const hasDrawn = _useRef(false); const last = _useRef(null); _useEffect(() => { const c = canvasRef.current; const ratio = window.devicePixelRatio || 1; const resize = () => { const r = c.getBoundingClientRect(); c.width = r.width * ratio; c.height = r.height * ratio; const ctx = c.getContext('2d'); ctx.scale(ratio, ratio); ctx.lineWidth = 2.2; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.strokeStyle = getComputedStyle(document.documentElement).getPropertyValue('--text').trim() || '#0F1A2E'; }; resize(); window.addEventListener('resize', resize); return () => window.removeEventListener('resize', resize); }, []); const pos = (e) => { const r = canvasRef.current.getBoundingClientRect(); const t = e.touches ? e.touches[0] : e; return { x: t.clientX - r.left, y: t.clientY - r.top }; }; const start = (e) => { e.preventDefault(); drawing.current = true; last.current = pos(e); }; const move = (e) => { if (!drawing.current) return; e.preventDefault(); const ctx = canvasRef.current.getContext('2d'); const p = pos(e); ctx.beginPath(); ctx.moveTo(last.current.x, last.current.y); ctx.lineTo(p.x, p.y); ctx.stroke(); last.current = p; hasDrawn.current = true; if (!signed) setSigned(true); }; const end = () => { if (!drawing.current) return; drawing.current = false; if (hasDrawn.current) onChange(canvasRef.current.toDataURL('image/png')); }; const clear = () => { const c = canvasRef.current; c.getContext('2d').clearRect(0, 0, c.width, c.height); hasDrawn.current = false; setSigned(false); onChange(''); }; return (
Hier mit dem Finger oder der Maus unterschreiben
{signed ? 'Unterschrift erfasst' : 'Rechtsgültige elektronische Unterschrift'} {signed && }
{error && {error}}
); } window.Logo = Logo; window.ProcessNav = ProcessNav; window.Field = Field; window.Select = Select; window.Consent = Consent; window.Button = Button; window.Note = Note; window.PhotoCapture = PhotoCapture; window.SignaturePad = SignaturePad;