import { useEffect, useRef, useState } from 'react'; import { Camera, CameraOff, RefreshCcw, CheckCircle2 } from 'lucide-react'; import styles from './CameraCapture.module.css'; export default function CameraCapture({ onCapture }) { const videoRef = useRef(null); const canvasRef = useRef(null); const streamRef = useRef(null); const [status, setStatus] = useState('idle'); // idle | requesting | ready | error const [error, setError] = useState(''); useEffect(() => { return () => { if (streamRef.current) { streamRef.current.getTracks().forEach((track) => track.stop()); } }; }, []); useEffect(() => { const video = videoRef.current; const stream = streamRef.current; if (!video || !stream) return; let cancelled = false; const attachStream = async () => { try { video.srcObject = stream; await video.play(); } catch (cameraError) { if (!cancelled) { setStatus('error'); setError(cameraError?.message || 'Unable to render camera preview'); } } }; attachStream(); return () => { cancelled = true; }; }, [status]); const startCamera = async () => { setStatus('requesting'); setError(''); try { if (streamRef.current) { streamRef.current.getTracks().forEach((track) => track.stop()); } const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user', width: { ideal: 1280 }, height: { ideal: 720 }, }, audio: false, }); streamRef.current = stream; setStatus('ready'); } catch (cameraError) { setStatus('error'); setError(cameraError?.message || 'Camera access failed'); } }; const stopCamera = () => { if (streamRef.current) { streamRef.current.getTracks().forEach((track) => track.stop()); streamRef.current = null; } if (videoRef.current) { videoRef.current.srcObject = null; } setStatus('idle'); }; const capturePhoto = async () => { if (!videoRef.current || !canvasRef.current) return; const video = videoRef.current; const canvas = canvasRef.current; canvas.width = video.videoWidth || 1280; canvas.height = video.videoHeight || 720; const context = canvas.getContext('2d'); if (!context) return; context.drawImage(video, 0, 0, canvas.width, canvas.height); const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/png', 0.95)); if (!blob) return; const file = new File([blob], `uaide-capture-${Date.now()}.png`, { type: 'image/png' }); onCapture(file); }; return (
Capture a live image for immediate forensic analysis.
{error}
> )}