"use client"; import { useEffect } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { ResizableDialog, ResizableDialogContent, ResizableDialogHeader, DialogTitle } from "@/components/ui/resizable-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 { useState } from "react"; 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 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", }, }); // 필드 검증 상태 관리 const [validatedFields, setValidatedFields] = useState>(new Set()); // 필드 검증 처리 함수 const handleFieldBlur = (fieldName: string) => { setValidatedFields((prev) => new Set(prev).add(fieldName)); }; // 중복 검사 훅들 const categoryCodeCheck = useCheckCategoryDuplicate( "categoryCode", isEditing ? "" : createForm.watch("categoryCode"), isEditing ? editingCategoryCode : undefined, validatedFields.has("categoryCode"), ); const categoryNameCheck = useCheckCategoryDuplicate( "categoryName", isEditing ? updateForm.watch("categoryName") : createForm.watch("categoryName"), isEditing ? editingCategoryCode : undefined, validatedFields.has("categoryName"), ); const categoryNameEngCheck = useCheckCategoryDuplicate( "categoryNameEng", isEditing ? updateForm.watch("categoryNameEng") : createForm.watch("categoryNameEng"), isEditing ? editingCategoryCode : undefined, validatedFields.has("categoryNameEng"), ); // 중복 검사 결과 확인 (수정 시에는 카테고리 코드 검사 제외) const hasDuplicateErrors = (!isEditing && categoryCodeCheck.data?.isDuplicate && validatedFields.has("categoryCode")) || (categoryNameCheck.data?.isDuplicate && validatedFields.has("categoryName")) || (categoryNameEngCheck.data?.isDuplicate && validatedFields.has("categoryNameEng")); // 중복 검사 로딩 중인지 확인 (수정 시에는 카테고리 코드 검사 제외) const isDuplicateChecking = (!isEditing && categoryCodeCheck.isLoading) || categoryNameCheck.isLoading || categoryNameEngCheck.isLoading; // 폼은 조건부로 직접 사용 // 편집 모드일 때 기존 데이터 로드 useEffect(() => { if (isOpen) { // 검증 상태 초기화 setValidatedFields(new Set()); 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, createForm, updateForm]); 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 && (
handleFieldBlur("categoryCode")} /> {createForm.formState.errors.categoryCode && (

{createForm.formState.errors.categoryCode.message}

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

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

)} {/* 카테고리명 */}
handleFieldBlur("categoryName")} /> {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) && ( )}
{/* 영문명 */}
handleFieldBlur("categoryNameEng")} /> {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) && ( )}
{/* 설명 */}