import React, { useState, useRef, useCallback } from 'react'; import { BackgroundService, DEFAULT_BACKGROUND, type BackgroundConfig } from '../services/backgroundService'; interface BackgroundImportProps { open: boolean; onClose: () => void; onApply: (config: BackgroundConfig, image: HTMLImageElement | null) => void; backgroundService: BackgroundService; } const BackgroundImport: React.FC = ({ open, onClose, onApply, backgroundService }) => { const [config, setConfig] = useState({ ...DEFAULT_BACKGROUND }); const [previewUrl, setPreviewUrl] = useState(''); const [calibrationMode, setCalibrationMode] = useState(false); const [calibPoint1, setCalibPoint1] = useState<{ x: number; y: number } | null>(null); const [calibPoint2, setCalibPoint2] = useState<{ x: number; y: number } | null>(null); const [realDistance, setRealDistance] = useState(''); const [unit, setUnit] = useState('m'); const [error, setError] = useState(''); const fileInputRef = useRef(null); const previewCanvasRef = useRef(null); const handleFileSelect = useCallback(async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; setError(''); try { const cfg = await backgroundService.loadFromFile(file); setConfig(cfg); setPreviewUrl(cfg.src); } catch (err) { setError('Fehler beim Laden des Bildes: ' + (err as Error).message); } }, [backgroundService]); const handlePreviewClick = useCallback((e: React.MouseEvent) => { if (!calibrationMode || !previewCanvasRef.current) return; const rect = previewCanvasRef.current.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; if (!calibPoint1) { setCalibPoint1({ x, y }); } else if (!calibPoint2) { setCalibPoint2({ x, y }); } }, [calibrationMode, calibPoint1, calibPoint2]); const handleCalibrate = useCallback(() => { if (!calibPoint1 || !calibPoint2 || !realDistance) return; const dx = calibPoint2.x - calibPoint1.x; const dy = calibPoint2.y - calibPoint1.y; const pixelDist = Math.sqrt(dx * dx + dy * dy); const realDist = parseFloat(realDistance); if (realDist <= 0) { setError('Bitte eine gültige Referenzstrecke eingeben.'); return; } const result = backgroundService.calibrateScale(pixelDist, realDist, unit); setConfig(prev => ({ ...prev, scale: result.scale })); setCalibrationMode(false); setCalibPoint1(null); setCalibPoint2(null); setRealDistance(''); }, [calibPoint1, calibPoint2, realDistance, unit, backgroundService]); const handleApply = useCallback(() => { const cfg = backgroundService.getConfig(); onApply(cfg, backgroundService.getImage()); onClose(); }, [backgroundService, onApply, onClose]); const updateConfig = useCallback((partial: Partial) => { backgroundService.updateConfig(partial); setConfig(backgroundService.getConfig()); }, [backgroundService]); if (!open) return null; return (

Hintergrund importieren

{error && (
{error}
)} {/* File Upload */}
{config.name && ( {config.name} ({config.width}×{config.height}px) )}
{/* Preview */} {previewUrl && (
)} {/* Calibration */} {previewUrl && (
Maßstabs-Kalibrierung
{!calibrationMode ? ( ) : (

Klicken Sie auf zwei Punkte mit bekanntem Abstand im Bild.

{calibPoint1 && !calibPoint2 &&

Erster Punkt gesetzt. Bitte zweiten Punkt klicken.

} {calibPoint1 && calibPoint2 && (
setRealDistance(e.target.value)} style={{ width: '120px', padding: '4px 8px', fontSize: '13px' }} />
)}
)} {config.scale !== 1 && (

Aktueller Maßstab: {config.scale.toFixed(2)} px/mm

)}
)} {/* Controls */} {previewUrl && (
{/* Opacity */} updateConfig({ opacity: parseFloat(e.target.value) })} style={{ width: '100%', marginBottom: '12px' }} /> {/* Position */}
{/* Rotation */} updateConfig({ rotation: parseFloat(e.target.value) })} style={{ width: '100%', marginBottom: '12px' }} /> {/* Scale */} updateConfig({ scale: parseFloat(e.target.value) || 1 })} style={{ width: '120px', padding: '4px' }} /> {/* Visibility */}
)} {/* Actions */}
); }; export default BackgroundImport;