import React, { useRef, useState } from 'react' import { Button } from './Button' // ─── DropZone ───────────────────────────────────────────────────────────────── export interface DropZoneProps { onFileSelect?: (files: FileList) => void accept?: string multiple?: boolean label?: string description?: string className?: string disabled?: boolean isLoading?: boolean } export const DropZone: React.FC = ({ onFileSelect, accept, multiple = false, label = '파일을 드래그하거나 클릭하여 업로드', description = 'CSV, XLSX (최대 10MB)', className = '', disabled = false, isLoading = false, }) => { const [isDragging, setIsDragging] = useState(false) const inputRef = useRef(null) const isDisabled = disabled || isLoading const handleDrop = (e: React.DragEvent) => { e.preventDefault() setIsDragging(false) if (isDisabled) return if (e.dataTransfer.files.length > 0) onFileSelect?.(e.dataTransfer.files) } const handleChange = (e: React.ChangeEvent) => { if (e.target.files?.length) onFileSelect?.(e.target.files) } return (
!isDisabled && inputRef.current?.click()} onDragOver={(e) => { e.preventDefault(); if (!isDisabled) setIsDragging(true) }} onDragLeave={() => setIsDragging(false)} onDrop={handleDrop} className={` border-2 border-dashed rounded-[14px] p-8 flex flex-col items-center justify-center text-center transition-all duration-150 ${isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'} ${isDragging ? 'border-teal-400 bg-teal-50/30' : 'border-slate-200 hover:border-teal-300 hover:bg-teal-50/20' } ${className} `} > {isLoading ? ( <> progress_activity

업로드 중...

) : ( <>
{isDragging ? 'download' : 'upload_file'}
{isDragging ? (

여기에 놓으세요

) : ( <>

{label}

{description}

)} )}
) } // ─── FileItem ───────────────────────────────────────────────────────────────── export type FileItemStatus = 'uploading' | 'complete' | 'error' export interface FileItemProps { name: string size?: string status?: FileItemStatus progress?: number onRemove?: () => void } export const FileItem: React.FC = ({ name, size, status = 'complete', progress, onRemove, }) => (
description

{name}

{size &&

{size}

}
{status === 'complete' && ( check_circle )} {status === 'error' && ( error )} {onRemove && (
{status === 'uploading' && progress != null && (
)}
)