From 9694acd0ec21b3f50a8bd65d3a328befd85cbbee Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Sun, 2 Nov 2025 17:42:18 +0900 Subject: (김준회) dolce: GTT(B4) 일괄업로드 drag&drop 오류 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ship/bulk-b4-upload-dialog.tsx | 72 ++++++++++++++++++---- 1 file changed, 61 insertions(+), 11 deletions(-) (limited to 'lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx') diff --git a/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx b/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx index db0fa08e..52252e14 100644 --- a/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx +++ b/lib/vendor-document-list/ship/bulk-b4-upload-dialog.tsx @@ -32,14 +32,11 @@ import { SelectValue, } from "@/components/ui/select" import { ScrollArea } from "@/components/ui/scroll-area" -import { Separator } from "@/components/ui/separator" import { Badge } from "@/components/ui/badge" import { Upload, X, Loader2, - FileSpreadsheet, - Files, CheckCircle2, AlertCircle, AlertTriangle, @@ -76,7 +73,7 @@ function parseFileName(fileName: string): { docNumber: string | null; revision: /\b([A-Za-z]{2,3})\s+([A-Za-z]{2,3})\s+([A-Za-z0-9]{2,4})\b/, ] - let docNumber = null + let docNumber: string | null = null for (const pattern of docNumberPatterns) { const match = normalizedName.match(pattern) || cleanedName.match(pattern) if (match) { @@ -115,6 +112,7 @@ export function BulkB4UploadDialog({ }: BulkB4UploadDialogProps) { const [isUploading, setIsUploading] = React.useState(false) const [parsedFiles, setParsedFiles] = React.useState([]) + const [isDragging, setIsDragging] = React.useState(false) const router = useRouter() // 프로젝트 ID 추출 @@ -158,6 +156,40 @@ export function BulkB4UploadDialog({ form.setValue("files", newParsedFiles.map(pf => pf.file)) } + // Drag & Drop 핸들러 + const handleDragEnter = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + setIsDragging(true) + } + + const handleDragLeave = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + // 자식 요소로 이동할 때도 leave가 발생하므로 실제로 영역을 벗어날 때만 처리 + if (e.currentTarget === e.target) { + setIsDragging(false) + } + } + + const handleDragOver = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + // 드롭 가능하도록 설정 + e.dataTransfer.dropEffect = 'copy' + } + + const handleDrop = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + setIsDragging(false) + + const droppedFiles = Array.from(e.dataTransfer.files) + if (droppedFiles.length > 0) { + handleFilesChange(droppedFiles) + } + } + // 업로드 처리 async function onSubmit(values: z.infer) { setIsUploading(true) @@ -225,7 +257,7 @@ export function BulkB4UploadDialog({ : pf )) } - } catch (error) { + } catch { toast.error("업로드 중 오류가 발생했습니다") setParsedFiles(prev => prev.map(pf => pf.status === 'uploading' @@ -242,6 +274,7 @@ export function BulkB4UploadDialog({ if (!open) { form.reset() setParsedFiles([]) + setIsDragging(false) } }, [open, form]) @@ -255,7 +288,7 @@ export function BulkB4UploadDialog({ B4 Document Bulk Upload Document numbers and revisions will be automatically extracted from file names. - Example: "agadfg de na oc R01.pdf" → Document Number: DE-NA-OC, Revision: R01 + Example: "agadfg de na oc R01.pdf" → Document Number: DE-NA-OC, Revision: R01 @@ -288,7 +321,17 @@ export function BulkB4UploadDialog({
Select Files -
+
handleFilesChange(Array.from(e.target.files || []))} className="hidden" id="file-upload" + disabled={isUploading} />