/** * Document Uploader Component * Agent 3: File Upload & Storage System * * Upload interface for documents (PDF, DOC, etc.) */ import React, { useState, useCallback, useRef } from 'react'; import type { FileCategory } from '../../lib/storage/types'; import ProgressBar from './ProgressBar'; interface UploadedDocument { id: string; url: string; size: number; mimeType: string; originalName: string; } interface DocumentUploaderProps { category?: FileCategory; plantId?: string; farmId?: string; userId?: string; onUpload?: (file: UploadedDocument) => void; onError?: (error: string) => void; accept?: string; className?: string; } export function DocumentUploader({ category = 'document', plantId, farmId, userId, onUpload, onError, accept = '.pdf,.doc,.docx', className = '', }: DocumentUploaderProps) { const [isUploading, setIsUploading] = useState(false); const [progress, setProgress] = useState(0); const [error, setError] = useState(); const [uploadedFile, setUploadedFile] = useState(null); const fileInputRef = useRef(null); const uploadFile = async (file: File) => { setIsUploading(true); setProgress(10); setError(undefined); const formData = new FormData(); formData.append('file', file); formData.append('category', category); if (plantId) formData.append('plantId', plantId); if (farmId) formData.append('farmId', farmId); if (userId) formData.append('userId', userId); try { setProgress(30); const response = await fetch('/api/upload/document', { method: 'POST', body: formData, }); setProgress(80); const data = await response.json(); if (!data.success) { throw new Error(data.error || 'Upload failed'); } setProgress(100); setUploadedFile(data.file); onUpload?.(data.file); } catch (error) { const message = error instanceof Error ? error.message : 'Upload failed'; setError(message); onError?.(message); } finally { setIsUploading(false); } }; const handleFileChange = useCallback( async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { await uploadFile(file); } }, [] ); const handleClick = () => { fileInputRef.current?.click(); }; const handleRemove = () => { setUploadedFile(null); setProgress(0); setError(undefined); if (fileInputRef.current) { fileInputRef.current.value = ''; } }; const getFileIcon = (mimeType: string) => { if (mimeType === 'application/pdf') { return ( ); } return ( ); }; const formatFileSize = (bytes: number): string => { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; }; return (
{uploadedFile ? (
{getFileIcon(uploadedFile.mimeType)}

{uploadedFile.originalName}

{formatFileSize(uploadedFile.size)}

) : ( )} {isUploading && (

Uploading...

)} {error && (

{error}

)}
); } export default DocumentUploader;