'use client' import * as React from 'react' import { Upload, X, FileText } from 'lucide-react' import { Button } from './button' import { cn } from '@/lib/utils' interface FileUploadProps { value: File[] onChange: (files: File[]) => void accept?: Record maxSize?: number maxFiles?: number placeholder?: string disabled?: boolean className?: string } export function FileUpload({ value = [], onChange, accept, maxSize = 10 * 1024 * 1024, // 10MB maxFiles = 5, placeholder = '파일을 선택하거나 드래그하세요', disabled = false, className }: FileUploadProps) { const [isDragOver, setIsDragOver] = React.useState(false) const fileInputRef = React.useRef(null) const handleFileSelect = (files: FileList | null) => { if (!files || disabled) return const fileArray = Array.from(files) const validFiles = fileArray.filter(file => { // 파일 크기 검증 if (file.size > maxSize) { console.warn(`파일 ${file.name}이(가) 최대 크기(${maxSize / 1024 / 1024}MB)를 초과합니다.`) return false } // 파일 타입 검증 if (accept) { const fileType = file.type const fileName = file.name.toLowerCase() const isAccepted = Object.entries(accept).some(([mimeType, extensions]) => { if (fileType && mimeType !== '*/*') { return fileType.startsWith(mimeType.split('/')[0]) } return extensions.some(ext => fileName.endsWith(ext.toLowerCase())) }) if (!isAccepted) { console.warn(`파일 ${file.name}이(가) 지원되지 않는 형식입니다.`) return false } } return true }) const newFiles = [...value, ...validFiles].slice(0, maxFiles) onChange(newFiles) } const handleInputChange = (event: React.ChangeEvent) => { handleFileSelect(event.target.files) // Reset input value to allow re-uploading the same file event.target.value = '' } const handleDrop = (event: React.DragEvent) => { event.preventDefault() setIsDragOver(false) handleFileSelect(event.dataTransfer.files) } const handleDragOver = (event: React.DragEvent) => { event.preventDefault() if (!disabled) { setIsDragOver(true) } } const handleDragLeave = () => { setIsDragOver(false) } const removeFile = (index: number) => { const newFiles = value.filter((_, i) => i !== index) onChange(newFiles) } 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 (
{/* Drop zone */}
!disabled && fileInputRef.current?.click()} >

{placeholder}

최대 {maxFiles}개 파일, 각 파일 {formatFileSize(maxSize)}까지

{/* Hidden file input */} {/* File list */} {value.length > 0 && (
{value.map((file, index) => (

{file.name}

{formatFileSize(file.size)}

))}
)}
) }