Spaces:
Running
Running
| import React from 'react'; | |
| import { Upload } from 'lucide-react'; | |
| export interface FileUploaderProps { | |
| accept?: string; | |
| onFileSelect: (file: File) => void; | |
| title?: string; | |
| subtitle?: string; | |
| className?: string; | |
| id?: string; | |
| } | |
| export const FileUploader: React.FC<FileUploaderProps> = ({ | |
| accept = '*', | |
| onFileSelect, | |
| title = '파일 드래그 앤 드롭', | |
| subtitle = 'Excel, CSV 파일 지원', | |
| className = '', | |
| id = 'file-uploader-dropzone', | |
| }) => { | |
| const [isDragging, setIsDragging] = React.useState(false); | |
| const fileInputRef = React.useRef<HTMLInputElement>(null); | |
| const handleDragOver = (e: React.DragEvent) => { | |
| e.preventDefault(); | |
| setIsDragging(true); | |
| }; | |
| const handleDragLeave = () => { | |
| setIsDragging(false); | |
| }; | |
| const handleDrop = (e: React.DragEvent) => { | |
| e.preventDefault(); | |
| setIsDragging(false); | |
| const files = e.dataTransfer.files; | |
| if (files && files.length > 0) { | |
| onFileSelect(files[0]); | |
| } | |
| }; | |
| const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { | |
| const files = e.target.files; | |
| if (files && files.length > 0) { | |
| onFileSelect(files[0]); | |
| } | |
| }; | |
| return ( | |
| <div | |
| onDragOver={handleDragOver} | |
| onDragLeave={handleDragLeave} | |
| onDrop={handleDrop} | |
| onClick={() => fileInputRef.current?.click()} | |
| className={`border-2 border-dashed rounded-xl p-6 text-center cursor-pointer transition-all ${isDragging | |
| ? 'border-orange-500 bg-orange-50/60' | |
| : 'border-slate-200 bg-slate-50/60 hover:border-orange-400 hover:bg-slate-50' | |
| } ${className}`} | |
| id={id} | |
| > | |
| <input | |
| type="file" | |
| ref={fileInputRef} | |
| accept={accept} | |
| onChange={handleFileChange} | |
| className="hidden" | |
| /> | |
| <Upload className="w-5 h-5 mx-auto mb-2 text-orange-500" /> | |
| <p className="text-sm font-bold text-slate-700">{title}</p> | |
| {subtitle && <p className="text-sm text-slate-400 mt-0.5">{subtitle}</p>} | |
| </div> | |
| ); | |
| }; | |