'use client' import { useState, useRef, useCallback } from 'react' import { useTheme } from '@/lib/ThemeContext' interface UploadedDocument { id: string name: string originalName: string size: number type: string uploadedAt: Date status: 'uploading' | 'processing' | 'complete' | 'error' progress: number url?: string error?: string } interface DocumentUploadProps { onUploadComplete?: (documents: UploadedDocument[]) => void className?: string } // Formatiere Dateigroesse const formatFileSize = (bytes: number): string => { if (bytes === 0) return '0 B' const k = 1024 const sizes = ['B', 'KB', 'MB', 'GB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i] } export function DocumentUpload({ onUploadComplete, className = '' }: DocumentUploadProps) { const { isDark } = useTheme() const [documents, setDocuments] = useState([]) const [isDragging, setIsDragging] = useState(false) const [editingId, setEditingId] = useState(null) const [editName, setEditName] = useState('') const fileInputRef = useRef(null) // Echter Upload mit lokalem Blob URL fuer Vorschau const uploadFile = useCallback((file: File): Promise => { return new Promise(async (resolve, reject) => { const doc: UploadedDocument = { id: `doc-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, name: file.name, originalName: file.name, size: file.size, type: file.type, uploadedAt: new Date(), status: 'uploading', progress: 0 } // Dokument sofort zur Liste hinzufuegen setDocuments(prev => [...prev, doc]) try { // Fortschritt auf 30% setzen (Datei wird gelesen) setDocuments(prev => prev.map(d => d.id === doc.id ? { ...d, progress: 30 } : d)) // Blob URL fuer lokale Vorschau erstellen const blobUrl = URL.createObjectURL(file) // Fortschritt auf 60% setzen setDocuments(prev => prev.map(d => d.id === doc.id ? { ...d, progress: 60 } : d)) // Kurze Verzoegerung fuer visuelles Feedback await new Promise(r => setTimeout(r, 300)) // Fortschritt auf 100% setzen const completedDoc = { ...doc, status: 'complete' as const, progress: 100, url: blobUrl } setDocuments(prev => prev.map(d => d.id === doc.id ? completedDoc : d)) resolve(completedDoc) } catch (error) { console.error('Upload error:', error) setDocuments(prev => prev.map(d => d.id === doc.id ? { ...d, status: 'error' as const, error: 'Upload fehlgeschlagen' } : d )) reject(error) } }) }, []) // Dateien verarbeiten const handleFiles = useCallback(async (files: FileList | null) => { if (!files || files.length === 0) return const fileArray = Array.from(files) const validFiles = fileArray.filter(f => f.type === 'application/pdf' || f.type.startsWith('image/') || f.name.endsWith('.pdf') || f.name.endsWith('.jpg') || f.name.endsWith('.jpeg') || f.name.endsWith('.png') ) if (validFiles.length === 0) { alert('Bitte nur PDF- oder Bilddateien hochladen.') return } const uploadedDocs = await Promise.all(validFiles.map(f => uploadFile(f))) onUploadComplete?.(uploadedDocs) }, [uploadFile, onUploadComplete]) // Drag & Drop Handler const handleDragOver = useCallback((e: React.DragEvent) => { e.preventDefault() setIsDragging(true) }, []) const handleDragLeave = useCallback((e: React.DragEvent) => { e.preventDefault() setIsDragging(false) }, []) const handleDrop = useCallback((e: React.DragEvent) => { e.preventDefault() setIsDragging(false) handleFiles(e.dataTransfer.files) }, [handleFiles]) // Dokument loeschen const handleDelete = useCallback((id: string) => { setDocuments(prev => prev.filter(d => d.id !== id)) }, []) // Dokument umbenennen starten const handleStartRename = useCallback((doc: UploadedDocument) => { setEditingId(doc.id) setEditName(doc.name.replace(/\.[^/.]+$/, '')) // Name ohne Extension }, []) // Umbenennen speichern const handleSaveRename = useCallback((id: string) => { if (editName.trim()) { setDocuments(prev => prev.map(d => { if (d.id === id) { const ext = d.originalName.split('.').pop() return { ...d, name: `${editName.trim()}.${ext}` } } return d })) } setEditingId(null) setEditName('') }, [editName]) // Datei-Icon basierend auf Typ const getFileIcon = (type: string) => { if (type === 'application/pdf') return '📄' if (type.startsWith('image/')) return '🖼️' return '📎' } return (
{/* Upload-Bereich */}
fileInputRef.current?.click()} className={`relative border-2 border-dashed rounded-3xl p-8 text-center cursor-pointer transition-all ${ isDragging ? isDark ? 'border-blue-400 bg-blue-500/20' : 'border-blue-500 bg-blue-50' : isDark ? 'border-white/20 bg-white/5 hover:bg-white/10 hover:border-white/30' : 'border-slate-300 bg-slate-50 hover:bg-slate-100 hover:border-slate-400' }`} > handleFiles(e.target.files)} className="hidden" />

{isDragging ? 'Dateien hier ablegen' : 'Dokumente hochladen'}

Ziehen Sie Dateien hierher oder klicken Sie zum Auswaehlen

PDF, JPG, PNG - max. 50 MB pro Datei

{/* Hochgeladene Dokumente */} {documents.length > 0 && (

Hochgeladene Dokumente ({documents.length})

{documents.map((doc) => (
{/* Icon */}
{getFileIcon(doc.type)}
{/* Info */}
{editingId === doc.id ? (
setEditName(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSaveRename(doc.id)} onBlur={() => handleSaveRename(doc.id)} autoFocus className={`flex-1 px-2 py-1 rounded border text-sm ${ isDark ? 'bg-white/10 border-white/20 text-white' : 'bg-white border-slate-300 text-slate-900' }`} /> .{doc.originalName.split('.').pop()}
) : (

{doc.name}

)}
{formatFileSize(doc.size)} {doc.status === 'complete' && ( Hochgeladen )} {doc.status === 'uploading' && ( {Math.round(doc.progress)}% )} {doc.status === 'error' && ( Fehler )}
{/* Progress Bar */} {doc.status === 'uploading' && (
)}
{/* Aktionen */} {doc.status === 'complete' && (
{/* Umbenennen */} {/* Oeffnen/Vorschau */} {doc.url && ( )} {/* Loeschen */}
)}
))}
)}
) }