org-network / frontend /src /components /common /FileUploader.tsx
5minbetter's picture
deploy: initial clean workspace without lfs history
33d9e63
Raw
History Blame Contribute Delete
2.02 kB
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>
);
};