import _ from '@/lib/translate' import { Dispatch, SetStateAction, useCallback } from 'react' import { Accept, useDropzone } from 'react-dropzone' import { cn } from '@/lib/utils' import { formatBytes, getFileExtension } from '@/lib/file' import { Button } from './button' import { Trash2Icon } from 'lucide-react' type Props = { files: File[], setFiles?: Dispatch> accept?: Accept, multiple?: boolean onDrop?: (acceptedFiles: File[]) => void, onUpdate?: VoidFunction className?: string } export const FileDropzone = ({ files, setFiles, accept, multiple = true, onDrop, className, onUpdate }: Props) => { const onFileDrop = useCallback((acceptedFiles: File[]) => { // Do something with the files if (multiple) { setFiles?.((prev) => [...prev, ...acceptedFiles]) } else { setFiles?.(acceptedFiles) } onDrop?.(acceptedFiles) onUpdate?.() }, [setFiles, onDrop, multiple, onUpdate]) const { getRootProps, getInputProps } = useDropzone({ onDrop: onFileDrop, accept, multiple }) return (
{files.length === 0 ?

{multiple ? _("Drop some files here, or click to select files") : _("Drop a file here, or click to select a file")}

: null}
{files.map(f =>
{f.name} {formatBytes(f.size)}
)}
) } interface FileTypeIconProps { fileType: string size?: 'sm' | 'md' | 'lg' | 'xl' className?: string showBackground?: boolean } const sizeClasses = { sm: 'h-8 w-8', md: 'h-10 w-10', lg: 'h-12 w-12', xl: 'h-16 w-16' } const iconSizeClasses = { sm: 'h-5 w-5', md: 'h-6 w-6', lg: 'h-8 w-8', xl: 'h-10 w-10' } // Special sizing for PowerPoint icon due to different viewBox const pptIconSizeClasses = { sm: 'h-3.5 w-3.5', md: 'h-4 w-4', lg: 'h-5 w-5', xl: 'h-6 w-6' } export const FileTypeIcon = ({ fileType, size = 'md', className, showBackground = true }: FileTypeIconProps) => { const containerClass = cn(sizeClasses[size], className) const RenderIcon = ({ className }: { className?: string }) => { switch (fileType.toLowerCase()) { case 'pdf': return ( ) case 'doc': case 'docx': return ( ) case 'xls': case 'xlsx': case 'csv': return ( ) case 'ppt': case 'pptx': return ( ) case 'video': case 'mp4': case 'mov': case 'mkv': case 'avi': case 'webm': return ( ) case 'audio': case 'mp3': case 'wav': case 'ogg': case 'flac': return ( ) case 'image': case 'jpg': case 'jpeg': case 'png': case 'gif': case 'webp': return ( ) case 'zip': case 'rar': case '7z': case 'tar': case 'gz': return ( ) default: return ( ) } } const getBackgroundColor = () => { switch (fileType.toLowerCase()) { case 'pdf': return 'bg-red-700' case 'doc': case 'docx': return 'bg-[#1A5CBD]' case 'xls': case 'xlsx': case 'csv': return 'bg-green-700' case 'ppt': case 'pptx': return 'bg-[#ED6C47]' case 'video': case 'mp4': case 'mov': case 'mkv': case 'avi': case 'webm': return 'bg-purple-600' case 'audio': case 'mp3': case 'wav': case 'ogg': case 'flac': return 'bg-purple-600' case 'image': case 'jpg': case 'jpeg': case 'png': case 'gif': case 'webp': return 'bg-blue-600' case 'zip': case 'rar': case '7z': case 'tar': case 'gz': return 'bg-yellow-600' default: return 'bg-gray-500' } } const getTextColor = () => { switch (fileType.toLowerCase()) { case 'pdf': return 'text-red-700' case 'doc': case 'docx': return 'text-[#1A5CBD]' case 'xls': case 'xlsx': case 'csv': return 'text-green-700 dark:text-green-500' case 'ppt': case 'pptx': return 'text-[#ED6C47]' case 'video': case 'mp4': case 'mov': case 'mkv': case 'avi': case 'webm': return 'text-purple-600' case 'audio': case 'mp3': case 'wav': case 'ogg': case 'flac': return 'text-purple-600' case 'image': case 'jpg': case 'jpeg': case 'png': case 'gif': case 'webp': return 'text-blue-600' case 'zip': case 'rar': case '7z': case 'tar': case 'gz': return 'text-yellow-600' default: return 'text-gray-50' } } if (showBackground) { return (
) } return (
) }