"use client" import React, { useRef, useState } from "react" import { Button } from "@/components/ui/button" import { X, FileText, Image, File, Upload, Plus, Music, Video } from "lucide-react" interface FileUploadProps { files: File[] onFilesChange: (files: File[]) => void maxFiles?: number maxSizeMB?: number enableMedia?: boolean // Enable audio/video support enableDocuments?: boolean // Enable large document support } const ALLOWED_TYPES = { // Documents "application/pdf": [".pdf"], "text/plain": [".txt"], "text/markdown": [".md"], // Images "image/png": [".png"], "image/jpeg": [".jpg", ".jpeg"], "image/gif": [".gif"], "image/webp": [".webp"], } // Extended document types for WeKnora knowledge base ingestion const DOCUMENT_TYPES = { "application/msword": [".doc"], "application/vnd.openxmlformats-officedocument.wordprocessingml.document": [".docx"], "application/vnd.ms-excel": [".xls"], "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [".xlsx"], "text/csv": [".csv"], "application/json": [".json"], "application/rtf": [".rtf"], "text/html": [".html", ".htm"], } const MEDIA_TYPES = { // Audio "audio/mpeg": [".mp3"], "audio/wav": [".wav"], "audio/mp4": [".m4a"], "audio/ogg": [".ogg"], "audio/flac": [".flac"], "audio/aac": [".aac"], // Video "video/mp4": [".mp4"], "video/quicktime": [".mov"], "video/x-msvideo": [".avi"], "video/x-matroska": [".mkv"], "video/webm": [".webm"], "video/x-m4v": [".m4v"], } export function FileUpload({ files, onFilesChange, maxFiles = 10, maxSizeMB = 50, // Increased for larger documents enableMedia = true, enableDocuments = true, // Enable extended document types by default }: FileUploadProps) { const fileInputRef = useRef(null) const [dragActive, setDragActive] = useState(false) const [imagePreviews, setImagePreviews] = useState>(new Map()) // Combine allowed types based on flags const getAllowedTypes = () => { let types = { ...ALLOWED_TYPES } if (enableDocuments) { types = { ...types, ...DOCUMENT_TYPES } } if (enableMedia) { types = { ...types, ...MEDIA_TYPES } } return types } const handleFiles = (fileList: FileList | null) => { if (!fileList) return const newFiles: File[] = [] const maxSize = maxSizeMB * 1024 * 1024 const allowedTypes = getAllowedTypes() Array.from(fileList).forEach((file) => { // Check file count if (files.length + newFiles.length >= maxFiles) { return } // Check file size if (file.size > maxSize) { alert(`File ${file.name} exceeds ${maxSizeMB}MB limit`) return } // Check file type const isValidType = Object.keys(allowedTypes).some((mimeType) => { const extensions = allowedTypes[mimeType as keyof typeof allowedTypes] return extensions.some((ext) => file.name.toLowerCase().endsWith(ext)) }) if (!isValidType) { alert(`File type not supported: ${file.name}`) return } newFiles.push(file) }) if (newFiles.length > 0) { const updatedFiles = [...files, ...newFiles] onFilesChange(updatedFiles) // Generate image previews for new image files newFiles.forEach((file) => { if (file.type.startsWith("image/")) { const fileKey = `${file.name}-${file.size}` const reader = new FileReader() reader.onload = (e) => { if (e.target?.result) { setImagePreviews(prev => new Map(prev).set(fileKey, e.target!.result as string)) } } reader.readAsDataURL(file) } }) } } const handleDrag = (e: React.DragEvent) => { e.preventDefault() e.stopPropagation() if (e.type === "dragenter" || e.type === "dragover") { setDragActive(true) } else if (e.type === "dragleave") { setDragActive(false) } } const handleDrop = (e: React.DragEvent) => { e.preventDefault() e.stopPropagation() setDragActive(false) if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { handleFiles(e.dataTransfer.files) } } const removeFile = (index: number) => { const fileToRemove = files[index] const newFiles = files.filter((_, i) => i !== index) onFilesChange(newFiles) // Clean up preview for removed file if (fileToRemove) { const fileKey = `${fileToRemove.name}-${fileToRemove.size}` setImagePreviews(prev => { const newMap = new Map(prev) newMap.delete(fileKey) return newMap }) } } const getFileIcon = (file: File) => { if (file.type === "application/pdf") { return } else if (file.type.startsWith("image/")) { return } else if (file.type.startsWith("audio/")) { return } else if (file.type.startsWith("video/")) { return