import React, { useState, useRef } from 'react'; import { AlertCircle, CheckCircle2, Copy, File, FileText, Image as ImageIcon, Loader2, RefreshCw, Upload, X } from 'lucide-react'; import { api, resolveMediaUrl } from '../../api'; interface FileUploadPanelProps { onUploadSuccess?: (url: string) => void; label?: string; accept?: string; currentUrl?: string; className?: string; } export default function FileUploadPanel({ onUploadSuccess, label = 'Upload Media Asset', accept = 'image/*', currentUrl = '', className = '', }: FileUploadPanelProps) { const [file, setFile] = useState(null); const [preview, setPreview] = useState(currentUrl ? resolveMediaUrl(currentUrl) : null); const [uploadedUrl, setUploadedUrl] = useState(currentUrl); const [isUploading, setIsUploading] = useState(false); const [error, setError] = useState(null); const [copied, setCopied] = useState(false); const [isDragging, setIsDragging] = useState(false); const fileInputRef = useRef(null); const handleFileSelect = (selectedFile: File) => { setError(null); setFile(selectedFile); if (selectedFile.type.startsWith('image/')) { const objectUrl = URL.createObjectURL(selectedFile); setPreview(objectUrl); } else { setPreview(null); } }; const handleInputChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files[0]) { handleFileSelect(e.target.files[0]); } }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); if (e.dataTransfer.files && e.dataTransfer.files[0]) { handleFileSelect(e.dataTransfer.files[0]); } }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }; const handleDragLeave = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); }; const uploadFile = async () => { if (!file) return; setIsUploading(true); setError(null); try { const formData = new FormData(); formData.append('file', file); const res = await api.post('/api/upload', formData, { headers: { 'Content-Type': undefined }, }); if (res.data && res.data.success && res.data.url) { const url = res.data.url; setUploadedUrl(url); if (onUploadSuccess) { onUploadSuccess(url); } } else { throw new Error(res.data?.msg || 'Failed to upload asset'); } } catch (err: any) { setError(err?.response?.data?.msg || err?.message || 'File upload failed. Please try again.'); } finally { setIsUploading(false); } }; const handleCopy = () => { if (!uploadedUrl) return; const fullUrl = resolveMediaUrl(uploadedUrl); navigator.clipboard.writeText(fullUrl); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const handleReset = () => { setFile(null); setPreview(null); setUploadedUrl(''); setError(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } }; return (
{uploadedUrl && ( Ready )}
{!file && !uploadedUrl ? (
fileInputRef.current?.click()} className={`border-2 border-dashed rounded-lg p-6 text-center cursor-pointer transition-colors ${ isDragging ? 'border-[#B93812] bg-orange-50/50' : 'border-slate-300 hover:border-slate-400 bg-[#F8F7F4]/50' }`} >

Click to select or drag and drop image file

JPG, PNG, WebP up to 10MB

) : (
{preview ? (
Selected asset preview
) : (

{file ? file.name : 'Uploaded File'}

{file && (

{(file.size / 1024).toFixed(1)} KB

)}
)} {file && !uploadedUrl && ( )} {uploadedUrl && (
{uploadedUrl}
)}
)} {error && (
{error}
)}
); }