'use client' import { useState, useRef, useCallback } from 'react' import { Button } from '@/components/ui/button' import { Progress } from '@/components/ui/progress' import { Card, CardContent } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { useFileUpload, type UploadOptions, type UploadResult } from '@/hooks/use-file-upload' import { Upload, X, FileImage, File as FileIcon, Trash2, Eye } from 'lucide-react' import { cn } from '@/lib/utils' import Image from 'next/image' interface FileUploadProps { onUploadComplete?: (results: UploadResult[]) => void onFilesChange?: (files: File[]) => void onDelete?: (url: string) => void options?: UploadOptions multiple?: boolean accept?: string disabled?: boolean className?: string showPreview?: boolean existingFiles?: string[] } export function FileUpload({ onUploadComplete, onFilesChange, onDelete, options = {}, multiple = true, accept = 'image/*', disabled = false, className, showPreview = true, existingFiles = [] }: FileUploadProps) { const [selectedFiles, setSelectedFiles] = useState([]) const [uploadedFiles, setUploadedFiles] = useState(existingFiles) const [dragOver, setDragOver] = useState(false) const fileInputRef = useRef(null) const { uploadFiles, deleteFile, uploading, progress } = useFileUpload() const handleFileSelect = useCallback((files: FileList | null) => { if (!files) return const fileArray = Array.from(files) setSelectedFiles(prev => multiple ? [...prev, ...fileArray] : fileArray) onFilesChange?.(fileArray) }, [multiple, onFilesChange]) const handleDrop = useCallback((e: React.DragEvent) => { e.preventDefault() setDragOver(false) if (disabled) return const files = e.dataTransfer.files handleFileSelect(files) }, [disabled, handleFileSelect]) const handleDragOver = useCallback((e: React.DragEvent) => { e.preventDefault() if (!disabled) setDragOver(true) }, [disabled]) const handleDragLeave = useCallback((e: React.DragEvent) => { e.preventDefault() setDragOver(false) }, []) const removeSelectedFile = useCallback((index: number) => { setSelectedFiles(prev => prev.filter((_, i) => i !== index)) }, []) const handleUpload = useCallback(async () => { if (selectedFiles.length === 0) return try { const results = await uploadFiles(selectedFiles, options) const urls = results.map(r => r.url) setUploadedFiles(prev => [...prev, ...urls]) setSelectedFiles([]) onUploadComplete?.(results) } catch (error) { console.error('Upload failed:', error) } }, [selectedFiles, uploadFiles, options, onUploadComplete]) const handleDeleteUploadedFile = useCallback(async (url: string) => { try { await deleteFile(url) setUploadedFiles(prev => prev.filter(f => f !== url)) onDelete?.(url) } catch (error) { console.error('Delete failed:', error) } }, [deleteFile, onDelete]) const getFileIcon = (file: File) => { if (file.type.startsWith('image/')) { return } return } const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 Bytes' const k = 1024 const sizes = ['Bytes', 'KB', 'MB', 'GB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i] } return (
{/* Upload Area */} !disabled && fileInputRef.current?.click()} >

{dragOver ? 'Drop files here' : 'Click to upload or drag & drop'}

{accept === 'image/*' ? 'Images only' : 'Various file types supported'} {options.maxSize && ` • Max ${options.maxSize}MB per file`} {options.maxFiles && ` • Max ${options.maxFiles} files`}

handleFileSelect(e.target.files)} className="hidden" disabled={disabled} /> {/* Selected Files */} {selectedFiles.length > 0 && (

Selected Files ({selectedFiles.length})

{uploading && (

{progress}% uploaded

)}
{selectedFiles.map((file, index) => (
{getFileIcon(file)}

{file.name}

{formatFileSize(file.size)}

))}
)} {/* Uploaded Files */} {uploadedFiles.length > 0 && showPreview && (

Uploaded Files ({uploadedFiles.length})

{uploadedFiles.map((url, index) => (
{url.match(/\.(jpg|jpeg|png|gif|webp)$/i) ? (
Uploaded file
) : ( )}

{url.split('/').pop()?.split('?')[0] || 'Uploaded file'}

Uploaded
))}
)}
) }