diff options
Diffstat (limited to 'lib/dolce/dialogs/add-detail-drawing-dialog.tsx')
| -rw-r--r-- | lib/dolce/dialogs/add-detail-drawing-dialog.tsx | 136 |
1 files changed, 95 insertions, 41 deletions
diff --git a/lib/dolce/dialogs/add-detail-drawing-dialog.tsx b/lib/dolce/dialogs/add-detail-drawing-dialog.tsx index 34d06368..48614ecf 100644 --- a/lib/dolce/dialogs/add-detail-drawing-dialog.tsx +++ b/lib/dolce/dialogs/add-detail-drawing-dialog.tsx @@ -26,6 +26,12 @@ import { v4 as uuidv4 } from "uuid"; import { useFileUploadWithProgress } from "../hooks/use-file-upload-with-progress"; import { uploadFilesWithProgress } from "../utils/upload-with-progress"; import { FileUploadProgressList } from "../components/file-upload-progress-list"; +import { + getB3DrawingUsageOptions, + getB3RegisterKindOptions, + getB4DrawingUsageOptions, + getB4RegisterKindOptions +} from "../utils/code-translator"; interface AddDetailDrawingDialogProps { open: boolean; @@ -36,38 +42,10 @@ interface AddDetailDrawingDialogProps { userName: string; userEmail: string; onComplete: () => void; - drawingKind: "B3" | "B4"; // 추가 + drawingKind: "B3" | "B4"; + lng?: string; // i18n support } -// B3 벤더의 선택 옵션 -const B3_DRAWING_USAGE_OPTIONS = [ - { value: "APP", label: "APPROVAL (승인용)" }, - { value: "WOR", label: "WORKING (작업용)" }, -]; - -const B3_REGISTER_KIND_OPTIONS: Record<string, Array<{ value: string; label: string; revisionRule: string }>> = { - APP: [ - { value: "APPR", label: "승인용 도면 (Full)", revisionRule: "예: A, B, C 또는 R00, R01, R02" }, - { value: "APPR-P", label: "승인용 도면 (Partial)", revisionRule: "예: A, B, C 또는 R00, R01, R02" }, - ], - WOR: [ - { value: "WORK", label: "작업용 입수도면 (Full)", revisionRule: "예: A, B, C 또는 R00, R01, R02" }, - { value: "WORK-P", label: "작업용 입수도면 (Partial)", revisionRule: "예: A, B, C 또는 R00, R01, R02" }, - ], -}; - -// B4 벤더(GTT)의 선택 옵션 -const B4_DRAWING_USAGE_OPTIONS = [ - { value: "REC", label: "RECEIVE (입수용)" }, -]; - -const B4_REGISTER_KIND_OPTIONS: Record<string, Array<{ value: string; label: string; revisionRule: string }>> = { - REC: [ - { value: "RECP", label: "Pre. 도면입수", revisionRule: "예: R00, R01, R02, R03" }, - { value: "RECW", label: "Working 도면입수", revisionRule: "예: R00, R01, R02, R03" }, - ], -}; - export function AddDetailDrawingDialog({ open, onOpenChange, @@ -78,12 +56,29 @@ export function AddDetailDrawingDialog({ userEmail, onComplete, drawingKind, + lng = "ko", }: AddDetailDrawingDialogProps) { const [drawingUsage, setDrawingUsage] = useState<string>(""); const [registerKind, setRegisterKind] = useState<string>(""); const [revision, setRevision] = useState<string>(""); + const [revisionError, setRevisionError] = useState<string>(""); const [isSubmitting, setIsSubmitting] = useState(false); + // 옵션 생성 (다국어 지원) + const drawingUsageOptions = drawingKind === "B3" + ? getB3DrawingUsageOptions(lng) + : getB4DrawingUsageOptions(lng); + + const registerKindOptions = drawingKind === "B3" + ? getB3RegisterKindOptions(drawingUsage, lng).map(opt => ({ + ...opt, + revisionRule: lng === "ko" ? "예: A, B, C 또는 R00, R01, R02" : "e.g. A, B, C or R00, R01, R02" + })) + : getB4RegisterKindOptions(drawingUsage, lng).map(opt => ({ + ...opt, + revisionRule: lng === "ko" ? "예: R00, R01, R02, R03" : "e.g. R00, R01, R02, R03" + })); + // 파일 업로드 훅 사용 (진행도 추적) const { fileProgresses, @@ -96,11 +91,47 @@ export function AddDetailDrawingDialog({ isDragActive, } = useFileUploadWithProgress(); + // Revision 유효성 검증 함수 + const validateRevision = (value: string): string => { + if (!value.trim()) { + return "Revision을 입력하세요"; + } + + const upperValue = value.toUpperCase().trim(); + + // A-Z 패턴 (단일 알파벳) + if (/^[A-Z]$/.test(upperValue)) { + return ""; + } + + // R00-R99 패턴 + if (/^R\d{2}$/.test(upperValue)) { + return ""; + } + + return "올바른 형식이 아닙니다 (A-Z 또는 R00-R99)"; + }; + + // Revision 입력 핸들러 + const handleRevisionChange = (value: string) => { + const processedValue = value.toUpperCase(); + setRevision(processedValue); + + // 값이 있을 때만 validation + if (processedValue.trim()) { + const error = validateRevision(processedValue); + setRevisionError(error); + } else { + setRevisionError(""); + } + }; + // 폼 초기화 const resetForm = () => { setDrawingUsage(""); setRegisterKind(""); setRevision(""); + setRevisionError(""); clearFiles(); }; @@ -119,8 +150,18 @@ export function AddDetailDrawingDialog({ } if (!revision.trim()) { toast.error("Revision을 입력하세요"); + setRevisionError("Revision을 입력하세요"); return; } + + // Revision 형식 검증 + const revisionValidationError = validateRevision(revision); + if (revisionValidationError) { + toast.error(revisionValidationError); + setRevisionError(revisionValidationError); + return; + } + if (files.length === 0) { toast.error("최소 1개 이상의 파일을 첨부해야 합니다"); return; @@ -222,19 +263,21 @@ export function AddDetailDrawingDialog({ const handleDrawingUsageChange = (value: string) => { setDrawingUsage(value); setRegisterKind(""); + setRevision(""); + setRevisionError(""); }; - // 현재 선택 가능한 DrawingUsage 및 RegisterKind 옵션 - const drawingUsageOptions = drawingKind === "B4" ? B4_DRAWING_USAGE_OPTIONS : B3_DRAWING_USAGE_OPTIONS; - const registerKindOptionsMap = drawingKind === "B4" ? B4_REGISTER_KIND_OPTIONS : B3_REGISTER_KIND_OPTIONS; - - const registerKindOptions = drawingUsage - ? registerKindOptionsMap[drawingUsage] || [] - : []; - // 선택된 RegisterKind의 Revision Rule const revisionRule = registerKindOptions.find((opt) => opt.value === registerKind)?.revisionRule || ""; + // 추가 버튼 활성화 조건 + const isFormValid = + drawingUsage.trim() !== "" && + registerKind.trim() !== "" && + revision.trim() !== "" && + !revisionError && + files.length > 0; + return ( <Dialog open={open} onOpenChange={onOpenChange}> <DialogContent className="max-w-2xl"> @@ -302,10 +345,21 @@ export function AddDetailDrawingDialog({ <Label>Revision</Label> <Input value={revision} - onChange={(e) => setRevision(e.target.value)} + onChange={(e) => handleRevisionChange(e.target.value)} placeholder="예: A, B, R00, R01" disabled={!registerKind} + className={revisionError ? "border-red-500 focus-visible:ring-red-500" : ""} /> + {revisionError && ( + <p className="text-sm text-red-500 flex items-center gap-1"> + {revisionError} + </p> + )} + {!revisionError && revision && ( + <p className="text-sm text-green-600 flex items-center gap-1"> + ✓ 올바른 형식입니다 + </p> + )} </div> {/* 파일 업로드 */} @@ -366,7 +420,7 @@ export function AddDetailDrawingDialog({ 전체 제거 </Button> </div> - <div className="max-h-48 overflow-auto space-y-2"> + <div className="max-h-60 overflow-y-auto space-y-2"> {files.map((file, index) => ( <div key={index} @@ -400,7 +454,7 @@ export function AddDetailDrawingDialog({ <Button variant="outline" onClick={handleCancel} disabled={isSubmitting}> 취소 </Button> - <Button onClick={handleSubmit} disabled={isSubmitting}> + <Button onClick={handleSubmit} disabled={isSubmitting || !isFormValid}> {isSubmitting ? "처리 중..." : "추가"} </Button> </DialogFooter> |
