import { FileArchive, Loader2, UploadCloud, X } from 'lucide-react' import { useRef, useState } from 'react' interface StagedFile { id: string name: string size: number status: 'idle' | 'uploading' | 'done' | 'error' error: string } function formatSize(bytes: number) { if (bytes < 1024) return `${bytes} B` if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB` return `${(bytes / (1024 * 1024)).toFixed(1)} MB` } function FilePartsArea({ onLog, onUploaded, vaultReady }: { onLog: (msg: string) => void onUploaded: () => void vaultReady: boolean }) { const [files, setFiles] = useState([]) const [dragOver, setDragOver] = useState(false) const inputRef = useRef(null) const storedRef = useRef<{ id: string; file: File }[]>([]) const capture = (list: FileList | null) => { if (!list) return const refs = Array.from(list).map(f => ({ id: `${f.name}-${f.size}-${Date.now()}-${Math.random()}`, file: f, })) storedRef.current.push(...refs) setFiles(prev => [...prev, ...refs.map(r => ({ id: r.id, name: r.file.name, size: r.file.size, status: 'idle' as const, error: '' }))]) } const removeFile = (id: string) => { storedRef.current = storedRef.current.filter(f => f.id !== id) setFiles(prev => prev.filter(f => f.id !== id)) } const uploadFile = async (id: string) => { const ref = storedRef.current.find(r => r.id === id) if (!ref) return const fd = new FormData() fd.append('file', ref.file) setFiles(prev => prev.map(f => (f.id === id ? { ...f, status: 'uploading', error: '' } : f))) try { const res = await fetch('/api/warehouse/upload', { method: 'POST', body: fd }) const data = await res.json() if (res.ok) { setFiles(prev => prev.map(f => (f.id === id ? { ...f, status: 'done' } : f))) onLog(`Uploaded ${ref.file.name} to warehouse.`) onUploaded() } else { setFiles(prev => prev.map(f => (f.id === id ? { ...f, status: 'error', error: data.detail ?? 'upload failed' } : f))) onLog(`Upload failed: ${data.detail ?? 'unknown'}`) } } catch (e) { setFiles(prev => prev.map(f => (f.id === id ? { ...f, status: 'error', error: String(e) } : f))) onLog(`Upload error: ${e}`) } } const uploadAll = async () => { if (!vaultReady) { onLog('Unlock the vault before uploading.'); return } for (const f of files) { if (f.status !== 'done') await uploadFile(f.id) } } const pendingCount = files.filter(f => f.status !== 'done').length return (
Reference library parts {!vaultReady && vault locked}
{files.length === 0 ? (

No parts staged yet

) : ( files.map(f => (
{f.status === 'uploading' ? ( ) : f.status === 'done' ? ( ) : f.status === 'error' ? ( ) : ( )} {f.name}
{formatSize(f.size)} {f.error && {f.error}} {f.status !== 'uploading' && ( )}
)) )}
) } export default FilePartsArea