import React from "react" import { z } from "zod" import { Input } from "@/components/ui/input" import { Alert, AlertDescription } from "@/components/ui/alert" import { Info } from "lucide-react" // 파일 검증 스키마 export const MAX_FILE_SIZE = 1024 * 1024 * 1024 // 1GB // B3 리비전 검증 함수 export const validateB3Revision = (value: string) => { // B3 리비전 패턴: 단일 알파벳(A-Z) 또는 R01-R99 const alphabetPattern = /^[A-Z]$/ const numericPattern = /^R(0[1-9]|[1-9][0-9])$/ return alphabetPattern.test(value) || numericPattern.test(value) } // B4 리비전 검증 함수 export const validateB4Revision = (value: string) => { // B4 리비전 패턴: R01-R99 const numericPattern = /^R(0[1-9]|[1-9][0-9])$/ return numericPattern.test(value) } // 리비전 검증 함수 (drawingKind에 따라) export const validateRevision = (value: string, drawingKind: string) => { if (drawingKind === 'B3') { return validateB3Revision(value) } else { return validateB4Revision(value) } } // 리비전 수정용 스키마 생성 export const createEditRevisionSchema = (drawingKind: string) => { const baseSchema = { usage: z.string().min(1, "Please select a usage"), comment: z.string().optional(), } // drawingKind에 따른 리비전 검증 추가 const revisionField = drawingKind === 'B3' ? z.string() .min(1, "Please enter a revision") .max(3, "Revision must be 3 characters or less") .refine( validateB3Revision, "Invalid format. Use A-Z or R01-R99" ) : z.string() .min(1, "Please enter a revision") .max(3, "Revision must be 3 characters or less") .refine( validateB4Revision, "Invalid format. Use R01-R99" ) // B3인 경우에만 usageType 필드 추가 if (drawingKind === 'B3') { return z.object({ ...baseSchema, revision: revisionField, usageType: z.string().min(1, "Please select a usage type"), }) } else { return z.object({ ...baseSchema, revision: revisionField, usageType: z.string().optional(), }) } } // 리비전 업로드용 스키마 생성 export const createUploadRevisionSchema = (drawingKind: string) => { const baseSchema = { usage: z.string().min(1, "Please select a usage"), comment: z.string().optional(), attachments: z .array(z.instanceof(File)) .min(1, "Please upload at least 1 file") .refine( (files) => files.every((file) => file.size <= MAX_FILE_SIZE), "File size must be 50MB or less" ), } // drawingKind에 따른 리비전 검증 추가 const revisionField = drawingKind === 'B3' ? z.string() .min(1, "Please enter a revision") .max(3, "Revision must be 3 characters or less") .refine( validateB3Revision, "Invalid format. Use A-Z or R01-R99" ) : z.string() .min(1, "Please enter a revision") .max(3, "Revision must be 3 characters or less") .refine( validateB4Revision, "Invalid format. Use R01-R99" ) // B3인 경우에만 usageType 필드 추가 if (drawingKind === 'B3') { return z.object({ ...baseSchema, revision: revisionField, usageType: z.string().min(1, "Please select a usage type"), }) } else { return z.object({ ...baseSchema, revision: revisionField, usageType: z.string().optional(), }) } } // drawingKind에 따른 용도 옵션 export const getUsageOptions = (drawingKind: string) => { switch (drawingKind) { case 'B3': return [ { value: "Approval", label: "Approval" }, { value: "Working", label: "Working" }, { value: "Comments", label: "Comments" }, ] case 'B4': return [ { value: "Pre", label: "Pre" }, { value: "Working", label: "Working" }, ] case 'B5': return [ { value: "Pre", label: "Pre" }, { value: "Working", label: "Working" }, ] default: return [ { value: "Pre", label: "Pre" }, { value: "Working", label: "Working" }, ] } } // B3 전용 용도 타입 옵션 export const getUsageTypeOptions = (usage: string) => { switch (usage) { case 'Approval': return [ { value: "Full", label: "Full" }, { value: "Partial", label: "Partial" }, ] case 'Working': return [ { value: "Full", label: "Full" }, { value: "Partial", label: "Partial" }, ] case 'Comments': return [ { value: "Comments", label: "Comments" }, ] default: return [] } } // 리비전 형식 가이드 생성 export const getRevisionGuide = (drawingKind: string) => { if (drawingKind === 'B3') { return { placeholder: "e.g., A, B, C or R01, R02", helpText: "Use single letter (A-Z) or R01-R99 format", examples: [ "A, B, C, ... Z (alphabetic revisions)", "R01, R02, ... R99 (numeric revisions)" ] } } return { placeholder: "e.g., R01, R02, R03", helpText: "Enter in R01, R02, R03... format", examples: ["R01, R02, R03, ... R99"] } } // B3 리비전 자동 포맷팅 함수 export const formatB3RevisionInput = (value: string): string => { // 입력값을 대문자로 변환 const upperValue = value.toUpperCase() // 단일 알파벳인 경우 if (/^[A-Z]$/.test(upperValue)) { return upperValue } // R로 시작하는 경우 if (upperValue.startsWith('R')) { // R 뒤의 숫자 추출 const numPart = upperValue.slice(1).replace(/\D/g, '') if (numPart) { const num = parseInt(numPart, 10) // 1-99 범위 체크 if (num >= 1 && num <= 99) { // 01-09는 0을 붙이고, 10-99는 그대로 return `R${num.toString().padStart(2, '0')}` } } } return upperValue } // B3 리비전 입력 컴포넌트 export function B3RevisionInput({ value, onChange, error }: { value: string onChange: (value: string) => void error?: string }) { const handleInputChange = (e: React.ChangeEvent) => { const rawValue = e.target.value.toUpperCase() // 길이 제한 (알파벳은 1자, R숫자는 3자) if (rawValue.length <= 3) { onChange(rawValue) } } const handleBlur = () => { // blur 시점에 포맷팅 적용 const formattedValue = formatB3RevisionInput(value) onChange(formattedValue) } const revisionGuide = getRevisionGuide('B3') return (
{revisionGuide.helpText}
{revisionGuide.examples.map((example, idx) => (
• {example}
))}
) }