"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 { ValidationMessage } from "@/components/common/ValidationMessage"; import { useCreateCategory, useUpdateCategory } from "@/hooks/queries/useCategories"; import type { CodeCategory } from "@/types/commonCode"; import { useCheckCategoryDuplicate } from "@/hooks/queries/useValidation"; import { useFormValidation } from "@/hooks/useFormValidation"; import { createCategorySchema, updateCategorySchema, type CreateCategoryData, type UpdateCategoryData, } from "@/lib/schemas/commonCode"; interface CodeCategoryFormModalProps { isOpen: boolean; onClose: () => void; editingCategoryCode?: string; categories: CodeCategory[]; } export function CodeCategoryFormModal({ isOpen, onClose, editingCategoryCode, categories, }: CodeCategoryFormModalProps) { const createCategoryMutation = useCreateCategory(); const updateCategoryMutation = useUpdateCategory(); const isEditing = !!editingCategoryCode; const editingCategory = categories.find((c) => c.category_code === editingCategoryCode); // 검증 상태 관리 const formValidation = useFormValidation({ fields: ["categoryCode", "categoryName", "categoryNameEng", "description"], }); // 중복 검사 훅들 const categoryCodeCheck = useCheckCategoryDuplicate( "categoryCode", formValidation.getFieldValue("categoryCode"), isEditing ? editingCategoryCode : undefined, formValidation.isFieldValidated("categoryCode"), ); const categoryNameCheck = useCheckCategoryDuplicate( "categoryName", formValidation.getFieldValue("categoryName"), isEditing ? editingCategoryCode : undefined, formValidation.isFieldValidated("categoryName"), ); const categoryNameEngCheck = useCheckCategoryDuplicate( "categoryNameEng", formValidation.getFieldValue("categoryNameEng"), isEditing ? editingCategoryCode : undefined, formValidation.isFieldValidated("categoryNameEng"), ); // 중복 검사 결과 확인 (수정 시에는 카테고리 코드 검사 제외) const hasDuplicateErrors = (!isEditing && categoryCodeCheck.data?.isDuplicate && formValidation.isFieldValidated("categoryCode")) || (categoryNameCheck.data?.isDuplicate && formValidation.isFieldValidated("categoryName")) || (categoryNameEngCheck.data?.isDuplicate && formValidation.isFieldValidated("categoryNameEng")); // 중복 검사 로딩 중인지 확인 (수정 시에는 카테고리 코드 검사 제외) const isDuplicateChecking = (!isEditing && categoryCodeCheck.isLoading) || categoryNameCheck.isLoading || categoryNameEngCheck.isLoading; // 필수 필드들이 모두 검증되었는지 확인 (생성 시에만 적용) // 생성과 수정을 위한 별도 폼 설정 const createForm = useForm({ resolver: zodResolver(createCategorySchema), mode: "onChange", defaultValues: { categoryCode: "", categoryName: "", categoryNameEng: "", description: "", sortOrder: 1, }, }); const updateForm = useForm({ resolver: zodResolver(updateCategorySchema), mode: "onChange", defaultValues: { categoryName: "", categoryNameEng: "", description: "", sortOrder: 1, isActive: "Y", }, }); // 폼은 조건부로 직접 사용 // 편집 모드일 때 기존 데이터 로드 useEffect(() => { if (isOpen) { if (isEditing && editingCategory) { // 수정 모드: 기존 데이터 로드 updateForm.reset({ categoryName: editingCategory.category_name, categoryNameEng: editingCategory.category_name_eng || "", description: editingCategory.description || "", sortOrder: editingCategory.sort_order, isActive: editingCategory.is_active as "Y" | "N", // 타입 안전한 캐스팅 }); } else { // 새 카테고리 모드: 자동 순서 계산 const maxSortOrder = categories.length > 0 ? Math.max(...categories.map((c) => c.sort_order)) : 0; createForm.reset({ categoryCode: "", categoryName: "", categoryNameEng: "", description: "", sortOrder: maxSortOrder + 1, }); } } }, [isOpen, isEditing, editingCategory, categories]); const handleSubmit = isEditing ? updateForm.handleSubmit(async (data) => { try { await updateCategoryMutation.mutateAsync({ categoryCode: editingCategoryCode!, data: data as UpdateCategoryData, }); onClose(); updateForm.reset(); } catch (error) { console.error("카테고리 수정 실패:", error); } }) : createForm.handleSubmit(async (data) => { try { await createCategoryMutation.mutateAsync(data as CreateCategoryData); onClose(); createForm.reset(); } catch (error) { console.error("카테고리 생성 실패:", error); } }); const isLoading = createCategoryMutation.isPending || updateCategoryMutation.isPending; return ( {isEditing ? "카테고리 수정" : "새 카테고리"}
{/* 카테고리 코드 */} {!isEditing && (
{createForm.formState.errors.categoryCode && (

{createForm.formState.errors.categoryCode.message}

)} {!createForm.formState.errors.categoryCode && ( )}
)} {/* 카테고리 코드 표시 (수정 시) */} {isEditing && editingCategory && (

카테고리 코드는 수정할 수 없습니다.

)} {/* 카테고리명 */}
{isEditing ? updateForm.formState.errors.categoryName && (

{updateForm.formState.errors.categoryName.message}

) : createForm.formState.errors.categoryName && (

{createForm.formState.errors.categoryName.message}

)} {!(isEditing ? updateForm.formState.errors.categoryName : createForm.formState.errors.categoryName) && ( )}
{/* 영문명 */}
{isEditing ? updateForm.formState.errors.categoryNameEng && (

{updateForm.formState.errors.categoryNameEng.message}

) : createForm.formState.errors.categoryNameEng && (

{createForm.formState.errors.categoryNameEng.message}

)} {!(isEditing ? updateForm.formState.errors.categoryNameEng : createForm.formState.errors.categoryNameEng) && ( )}
{/* 설명 */}