'use client'; import { useRef, useState } from 'react'; import { AttachFileInfo, deleteFile, downloadFile, downloadZip, formatFileSize, uploadFiles, } from '@/lib/api/attach'; interface Props { atchNo?: string; division?: string; initialFiles?: AttachFileInfo[]; onChange?: (atchNo: string, files: AttachFileInfo[]) => void; maxFiles?: number; readOnly?: boolean; } export default function FileUpload({ atchNo: initialAtchNo, division, initialFiles = [], onChange, maxFiles = 10, readOnly = false, }: Props) { const [files, setFiles] = useState(initialFiles); const [atchNo, setAtchNo] = useState(initialAtchNo); const [uploading, setUploading] = useState(false); const [dragOver, setDragOver] = useState(false); const inputRef = useRef(null); const handleUpload = async (selected: FileList | null) => { if (!selected || selected.length === 0) return; if (files.length + selected.length > maxFiles) { alert(`최대 ${maxFiles}개까지 업로드할 수 있습니다.`); return; } setUploading(true); try { const uploaded = await uploadFiles(Array.from(selected), atchNo, division); const newAtchNo = uploaded[0]?.atchNo ?? atchNo; const newFiles = [...files, ...uploaded]; setAtchNo(newAtchNo); setFiles(newFiles); onChange?.(newAtchNo!, newFiles); } catch (e: any) { alert(e?.response?.data?.message ?? '업로드 중 오류가 발생했습니다.'); } finally { setUploading(false); if (inputRef.current) inputRef.current.value = ''; } }; const handleDelete = async (atchfileNo: string) => { if (!confirm('파일을 삭제하시겠습니까?')) return; try { await deleteFile(atchfileNo); const newFiles = files.filter((f) => f.atchfileNo !== atchfileNo); setFiles(newFiles); onChange?.(atchNo!, newFiles); } catch (e: any) { alert(e?.response?.data?.message ?? '삭제 중 오류가 발생했습니다.'); } }; return (
{/* 드롭존 */} {!readOnly && (
inputRef.current?.click()} onDragOver={(e) => { e.preventDefault(); setDragOver(true); }} onDragLeave={() => setDragOver(false)} onDrop={(e) => { e.preventDefault(); setDragOver(false); handleUpload(e.dataTransfer.files); }} > handleUpload(e.target.files)} /> {uploading ? (

업로드 중...

) : (

클릭하거나 파일을 드래그하세요 (최대 {maxFiles}개, 30MB 이하)

)}
)} {/* 파일 목록 헤더 */} {files.length > 1 && atchNo && (
)} {/* 파일 목록 */} {files.length > 0 && (
    {files.map((f) => (
  • ({formatFileSize(f.atchFileMg)})
    {!readOnly && ( )}
  • ))}
)}
); } function FileIcon({ contentType }: { contentType: string }) { const isImage = contentType?.startsWith('image'); const isPdf = contentType === 'application/pdf'; return ( {isImage ? '🖼' : isPdf ? '📄' : '📎'} ); }