"use client"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { LoadingSpinner } from "@/components/common/LoadingSpinner"; import { useCodes, useCreateCode, useUpdateCode } from "@/hooks/queries/useCodes"; import { createCodeSchema, updateCodeSchema, type CreateCodeData, type UpdateCodeData } from "@/lib/schemas/commonCode"; import type { CodeInfo } from "@/types/commonCode"; import type { FieldError } from "react-hook-form"; interface CodeFormModalProps { isOpen: boolean; onClose: () => void; categoryCode: string; editingCode?: CodeInfo | null; } // 에러 메시지를 안전하게 문자열로 변환하는 헬퍼 함수 const getErrorMessage = (error: FieldError | undefined): string => { if (!error) return ""; if (typeof error === "string") return error; return error.message || ""; }; export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode }: CodeFormModalProps) { const { data: codes = [] } = useCodes(categoryCode); const createCodeMutation = useCreateCode(); const updateCodeMutation = useUpdateCode(); const isEditing = !!editingCode; // 폼 스키마 선택 (생성/수정에 따라) const schema = isEditing ? updateCodeSchema : createCodeSchema; const form = useForm({ resolver: zodResolver(schema), mode: "onChange", // 실시간 검증 활성화 defaultValues: { codeValue: "", codeName: "", codeNameEng: "", description: "", sortOrder: 1, ...(isEditing && { isActive: "Y" as const }), }, }); // 편집 모드일 때 기존 데이터 로드 useEffect(() => { if (isOpen) { if (isEditing && editingCode) { // 수정 모드: 기존 데이터 로드 (codeValue는 표시용으로만 설정) form.reset({ codeName: editingCode.code_name, codeNameEng: editingCode.code_name_eng || "", description: editingCode.description || "", sortOrder: editingCode.sort_order, isActive: editingCode.is_active as "Y" | "N", // 타입 캐스팅 }); // codeValue는 별도로 설정 (표시용) form.setValue("codeValue" as any, editingCode.code_value); } else { // 새 코드 모드: 자동 순서 계산 const maxSortOrder = codes.length > 0 ? Math.max(...codes.map((c) => c.sort_order)) : 0; form.reset({ codeValue: "", codeName: "", codeNameEng: "", description: "", sortOrder: maxSortOrder + 1, }); } } }, [isOpen, isEditing, editingCode, codes, form]); const handleSubmit = form.handleSubmit(async (data) => { try { if (isEditing && editingCode) { // 수정 await updateCodeMutation.mutateAsync({ categoryCode, codeValue: editingCode.code_value, data: data as UpdateCodeData, }); } else { // 생성 await createCodeMutation.mutateAsync({ categoryCode, data: data as CreateCodeData, }); } onClose(); form.reset(); } catch (error) { console.error("코드 저장 실패:", error); } }); const isLoading = createCodeMutation.isPending || updateCodeMutation.isPending; return ( {isEditing ? "코드 수정" : "새 코드"}
{/* 코드값 */}
{(form.formState.errors as any)?.codeValue && (

{getErrorMessage((form.formState.errors as any)?.codeValue)}

)}
{/* 코드명 */}
{form.formState.errors.codeName && (

{getErrorMessage(form.formState.errors.codeName)}

)}
{/* 영문명 */}
{form.formState.errors.codeNameEng && (

{getErrorMessage(form.formState.errors.codeNameEng)}

)}
{/* 설명 */}