"use client"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { CheckCircle2, XCircle, AlertCircle, Upload } from "lucide-react"; export interface ParsedFileInfo { drawingNo: string; revNo: string; fileName: string; } export interface FileValidationResult { file: File; valid: boolean; parsed?: ParsedFileInfo; error?: string; mappingStatus?: "available" | "not_found"; drawingName?: string; registerGroupId?: number; } interface B4UploadValidationDialogProps { open: boolean; onOpenChange: (open: boolean) => void; validationResults: FileValidationResult[]; onConfirmUpload: (validFiles: FileValidationResult[]) => void; isUploading: boolean; } /** * B4 파일명 검증 함수 * 형식: [버림] [DrawingNo] [RevNo].[확장자] * 예시: "testfile GTT-DE-007 R01.pdf" → DrawingNo: "GTT-DE-007", RevNo: "R01" */ export function validateB4FileName(fileName: string): { valid: boolean; parsed?: ParsedFileInfo; error?: string; } { try { // 확장자 분리 const lastDotIndex = fileName.lastIndexOf("."); if (lastDotIndex === -1) { return { valid: false, error: "파일 확장자가 없습니다", }; } const extension = fileName.substring(lastDotIndex + 1); const nameWithoutExt = fileName.substring(0, lastDotIndex); // 공백으로 분리 const parts = nameWithoutExt.split(" ").filter(p => p.trim() !== ""); // 최소 3개 파트 필요: [버림], DrawingNo, RevNo if (parts.length < 3) { return { valid: false, error: `공백이 최소 2개 있어야 합니다 (현재: ${parts.length - 1}개). 형식: [버림] [DrawingNo] [RevNo].[확장자]`, }; } // 첫 번째 토큰은 버림 const drawingNo = parts[1]; const revNo = parts[2]; // 필수 항목이 비어있지 않은지 확인 if (!drawingNo || drawingNo.trim() === "") { return { valid: false, error: "도면번호(DrawingNo)가 비어있습니다", }; } if (!revNo || revNo.trim() === "") { return { valid: false, error: "리비전 번호(RevNo)가 비어있습니다", }; } return { valid: true, parsed: { drawingNo: drawingNo.trim(), revNo: revNo.trim(), fileName: fileName, }, }; } catch (error) { return { valid: false, error: error instanceof Error ? error.message : "알 수 없는 오류", }; } } /** * B4 업로드 전 파일 검증 다이얼로그 */ export function B4UploadValidationDialog({ open, onOpenChange, validationResults, onConfirmUpload, isUploading, }: B4UploadValidationDialogProps) { const validFiles = validationResults.filter((r) => r.valid && r.mappingStatus === "available"); const notFoundFiles = validationResults.filter((r) => r.valid && r.mappingStatus === "not_found"); const invalidFiles = validationResults.filter((r) => !r.valid); const handleUpload = () => { if (validFiles.length > 0) { onConfirmUpload(validFiles); } }; const handleCancel = () => { if (!isUploading) { onOpenChange(false); } }; return ( B4 일괄 업로드 검증 선택한 파일의 파일명 형식과 매핑 가능 여부를 검증합니다
{/* 요약 통계 */}
전체
{validationResults.length}
업로드 가능
{validFiles.length}
도면 없음
{notFoundFiles.length}
형식 오류
{invalidFiles.length}
{/* 경고 메시지 */} {validFiles.length === 0 && ( 업로드 가능한 파일이 없습니다. 파일명 형식을 확인하거나 이미 매핑된 파일은 제외해주세요. )} {(notFoundFiles.length > 0 || invalidFiles.length > 0) && validFiles.length > 0 && ( 일부 파일에 문제가 있습니다. 업로드 가능한 {validFiles.length}개 파일만 업로드됩니다. )} {/* 파일 목록 */}
{/* 업로드 가능 파일 */} {validFiles.length > 0 && (

업로드 가능 ({validFiles.length}개)

{validFiles.map((result, index) => (
{result.file.name}
{result.parsed && (
도면: {result.parsed.drawingNo} Rev: {result.parsed.revNo} {result.drawingName && ( {result.drawingName} )}
)}
))}
)} {/* 도면을 찾을 수 없는 파일 */} {notFoundFiles.length > 0 && (

도면을 찾을 수 없음 ({notFoundFiles.length}개)

{notFoundFiles.map((result, index) => (
{result.file.name}
✗ 해당 도면번호가 프로젝트에 등록되어 있지 않습니다
{result.parsed && (
도면: {result.parsed.drawingNo} Rev: {result.parsed.revNo}
)}
))}
)} {/* 형식 오류 파일 */} {invalidFiles.length > 0 && (

파일명 형식 오류 ({invalidFiles.length}개)

{invalidFiles.map((result, index) => (
{result.file.name}
{result.error && (
✗ {result.error}
)}
))}
)}
{/* 형식 안내 */}
📋 올바른 파일명 형식
[버림] [DrawingNo] [RevNo].[확장자]
예: testfile GTT-DE-007 R01.pdf
※ 첫 번째 단어는 무시되며, 공백으로 구분됩니다
※ 네 번째 이상의 단어가 있으면 무시됩니다
); }