// Upload Modal Component for ID Card Extraction const { useState, useRef } = React; const UploadModal = ({ onClose, onExtracted }) => { const toast = useToast(); const [mode, setMode] = useState('single'); // 'single' or 'split' const [singleFile, setSingleFile] = useState(null); const [files, setFiles] = useState({ front: null, back: null }); const [extracting, setExtracting] = useState(false); const singleInputRef = useRef(); const frontInputRef = useRef(); const backInputRef = useRef(); const hasSingleFile = !!singleFile; const hasFront = !!files.front; const hasBack = !!files.back; const hasAnyImage = mode === 'single' ? hasSingleFile : (hasFront || hasBack); const validateFile = (file) => { if (!file) return false; const validTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif']; if (!validTypes.includes(file.type)) { toast('Formato file non valido. Usa JPG, PNG, WebP o GIF', 'error'); return false; } if (file.size > 10 * 1024 * 1024) { toast('File troppo grande. Massimo 10 MB', 'error'); return false; } return true; }; const handleSingleFileSelect = (file) => { if (!validateFile(file)) return; setSingleFile(file); toast('Immagine selezionata', 'info'); }; const handleFileSelect = (side, file) => { if (!validateFile(file)) return; setFiles(prev => ({ ...prev, [side]: file })); toast(`Immagine ${side === 'front' ? 'fronte' : 'retro'} selezionata`, 'info'); }; const handleRemoveFile = (side) => { setFiles(prev => ({ ...prev, [side]: null })); }; const handleExtract = async () => { if (!hasAnyImage) { toast('Carica almeno un\'immagine del documento', 'error'); return; } setExtracting(true); const formData = new FormData(); if (mode === 'single') { formData.append('files', singleFile); } else { // Add files in order: front first, then back if (files.front) { formData.append('files', files.front); } if (files.back) { formData.append('files', files.back); } } try { const response = await fetch('/extract', { method: 'POST', body: formData }); const data = await response.json(); if (data.status === 'success') { toast('Dati estratti con successo!', 'success'); onExtracted(data); } else if (data.status === 'empty') { toast('Nessun dato estratto dalle immagini', 'warning'); onExtracted(data); } else { toast(data.message || 'Estrazione fallita', 'error'); } } catch (error) { toast(`Errore: ${error.message}`, 'error'); } finally { setExtracting(false); } }; const DropZone = ({ side, file, inputRef }) => { const label = side === 'front' ? 'Fronte' : 'Retro'; const hasImage = !!file; return (
Trascina o clicca
Max 10 MB
handleFileSelect(side, e.target.files[0])} className="hidden" />Trascina o clicca per caricare
JPG, PNG, WebP, GIF - Max 10 MB
handleSingleFileSelect(e.target.files[0])} className="hidden" />Carica le immagini del documento per estrarre automaticamente i dati.
{/* Mode Toggle */}