"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 file name validation function * Format: [ignore] [document_number_token1] [document_number_token2] ... [revision_number].[extension] * Example: "testfile GTT DE 007 R01.pdf" → DrawingNo: "GTT-DE-007", RevNo: "R01" * - First token is ignored * - Last token is RevNo * - Middle tokens are joined with "-" to create DrawingNo */ export function validateB4FileName(fileName: string): { valid: boolean; parsed?: ParsedFileInfo; error?: string; } { try { // Separate extension const lastDotIndex = fileName.lastIndexOf("."); if (lastDotIndex === -1) { return { valid: false, error: "File has no extension", }; } const nameWithoutExt = fileName.substring(0, lastDotIndex); // Split by spaces const parts = nameWithoutExt.split(" ").filter(p => p.trim() !== ""); // At least 3 parts required: [ignore], [document_number_token], [RevNo] if (parts.length < 3) { return { valid: false, error: `At least 2 spaces required (current: ${parts.length - 1}). Format: [ignore] [document_tokens...] [RevNo].[extension]`, }; } // First token is ignored // Last token is RevNo // Middle tokens are joined with "-" to create DrawingNo const revNo = parts[parts.length - 1]; const drawingTokens = parts.slice(1, parts.length - 1); const drawingNo = drawingTokens.join("-"); // Check that required fields are not empty if (!drawingNo || drawingNo.trim() === "") { return { valid: false, error: "Drawing number (DrawingNo) is empty", }; } if (!revNo || revNo.trim() === "") { return { valid: false, error: "Revision number (RevNo) is empty", }; } return { valid: true, parsed: { drawingNo: drawingNo.trim(), revNo: revNo.trim(), fileName: fileName, }, }; } catch (error) { return { valid: false, error: error instanceof Error ? error.message : "Unknown error", }; } } /** * B4 file validation dialog before upload */ 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 Bulk Upload Validation Validates file name format and mapping availability for selected files
{/* Summary statistics */}
Total
{validationResults.length}
Ready to Upload
{validFiles.length}
Drawing Not Found
{notFoundFiles.length}
Format Error
{invalidFiles.length}
{/* Warning messages */} {validFiles.length === 0 && ( No files available for upload. Please check the file name format or exclude already mapped files. )} {(notFoundFiles.length > 0 || invalidFiles.length > 0) && validFiles.length > 0 && ( Some files have issues. Only {validFiles.length} file(s) will be uploaded. )} {/* File list */}
{/* Files ready to upload */} {validFiles.length > 0 && (

Ready to Upload ({validFiles.length})

{validFiles.map((result, index) => (
{result.file.name}
{result.parsed && (
Drawing: {result.parsed.drawingNo} Rev: {result.parsed.revNo} {result.drawingName && ( {result.drawingName} )}
)}
))}
)} {/* Files with drawing not found */} {notFoundFiles.length > 0 && (

Drawing Not Found ({notFoundFiles.length})

{notFoundFiles.map((result, index) => (
{result.file.name}
✗ This drawing number is not registered in the project
{result.parsed && (
Drawing: {result.parsed.drawingNo} Rev: {result.parsed.revNo}
)}
))}
)} {/* Files with format errors */} {invalidFiles.length > 0 && (

File Name Format Error ({invalidFiles.length})

{invalidFiles.map((result, index) => (
{result.file.name}
{result.error && (
✗ {result.error}
)}
))}
)}
{/* Format guide */}
📋 Correct File Name Format
[fileName(without blanks)] [document_token1] [document_token2] ... [RevNo].[extension]
Example: testfile GTT DE 007 R01.pdf → DrawingNo: GTT-DE-007, Rev: R01
※ The last word is the revision number (RevNo)
※ All middle words are connected with "-" to become the document number (DrawingNo)
); }