공통코드 관리 시스템 개선 완료
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
@@ -11,7 +11,9 @@ 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 { useCodes, useCreateCode, useUpdateCode } from "@/hooks/queries/useCodes";
|
||||
import { useCheckCodeDuplicate } from "@/hooks/queries/useValidation";
|
||||
import { createCodeSchema, updateCodeSchema, type CreateCodeData, type UpdateCodeData } from "@/lib/schemas/commonCode";
|
||||
import type { CodeInfo } from "@/types/commonCode";
|
||||
import type { FieldError } from "react-hook-form";
|
||||
@@ -37,6 +39,47 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode }: Co
|
||||
|
||||
const isEditing = !!editingCode;
|
||||
|
||||
// 검증 상태 관리
|
||||
const [validationStates, setValidationStates] = useState({
|
||||
codeValue: { enabled: false, value: "" },
|
||||
codeName: { enabled: false, value: "" },
|
||||
codeNameEng: { enabled: false, value: "" },
|
||||
});
|
||||
|
||||
// 중복 검사 훅들
|
||||
const codeValueCheck = useCheckCodeDuplicate(
|
||||
categoryCode,
|
||||
"codeValue",
|
||||
validationStates.codeValue.value,
|
||||
isEditing ? editingCode?.code_value : undefined,
|
||||
validationStates.codeValue.enabled,
|
||||
);
|
||||
|
||||
const codeNameCheck = useCheckCodeDuplicate(
|
||||
categoryCode,
|
||||
"codeName",
|
||||
validationStates.codeName.value,
|
||||
isEditing ? editingCode?.code_value : undefined,
|
||||
validationStates.codeName.enabled,
|
||||
);
|
||||
|
||||
const codeNameEngCheck = useCheckCodeDuplicate(
|
||||
categoryCode,
|
||||
"codeNameEng",
|
||||
validationStates.codeNameEng.value,
|
||||
isEditing ? editingCode?.code_value : undefined,
|
||||
validationStates.codeNameEng.enabled,
|
||||
);
|
||||
|
||||
// 중복 검사 결과 확인
|
||||
const hasDuplicateErrors =
|
||||
(codeValueCheck.data?.isDuplicate && validationStates.codeValue.enabled) ||
|
||||
(codeNameCheck.data?.isDuplicate && validationStates.codeName.enabled) ||
|
||||
(codeNameEngCheck.data?.isDuplicate && validationStates.codeNameEng.enabled);
|
||||
|
||||
// 중복 검사 로딩 중인지 확인
|
||||
const isDuplicateChecking = codeValueCheck.isLoading || codeNameCheck.isLoading || codeNameEngCheck.isLoading;
|
||||
|
||||
// 폼 스키마 선택 (생성/수정에 따라)
|
||||
const schema = isEditing ? updateCodeSchema : createCodeSchema;
|
||||
|
||||
@@ -126,10 +169,26 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode }: Co
|
||||
disabled={isLoading || isEditing} // 수정 시에는 비활성화
|
||||
placeholder="코드값을 입력하세요"
|
||||
className={(form.formState.errors as any)?.codeValue ? "border-red-500" : ""}
|
||||
onBlur={(e) => {
|
||||
const value = e.target.value.trim();
|
||||
if (value && !isEditing) {
|
||||
setValidationStates((prev) => ({
|
||||
...prev,
|
||||
codeValue: { enabled: true, value },
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{(form.formState.errors as any)?.codeValue && (
|
||||
<p className="text-sm text-red-600">{getErrorMessage((form.formState.errors as any)?.codeValue)}</p>
|
||||
)}
|
||||
{!isEditing && !(form.formState.errors as any)?.codeValue && (
|
||||
<ValidationMessage
|
||||
message={codeValueCheck.data?.message}
|
||||
isValid={!codeValueCheck.data?.isDuplicate}
|
||||
isLoading={codeValueCheck.isLoading}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 코드명 */}
|
||||
@@ -141,10 +200,26 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode }: Co
|
||||
disabled={isLoading}
|
||||
placeholder="코드명을 입력하세요"
|
||||
className={form.formState.errors.codeName ? "border-red-500" : ""}
|
||||
onBlur={(e) => {
|
||||
const value = e.target.value.trim();
|
||||
if (value) {
|
||||
setValidationStates((prev) => ({
|
||||
...prev,
|
||||
codeName: { enabled: true, value },
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{form.formState.errors.codeName && (
|
||||
<p className="text-sm text-red-600">{getErrorMessage(form.formState.errors.codeName)}</p>
|
||||
)}
|
||||
{!form.formState.errors.codeName && (
|
||||
<ValidationMessage
|
||||
message={codeNameCheck.data?.message}
|
||||
isValid={!codeNameCheck.data?.isDuplicate}
|
||||
isLoading={codeNameCheck.isLoading}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 영문명 */}
|
||||
@@ -156,10 +231,26 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode }: Co
|
||||
disabled={isLoading}
|
||||
placeholder="코드 영문명을 입력하세요"
|
||||
className={form.formState.errors.codeNameEng ? "border-red-500" : ""}
|
||||
onBlur={(e) => {
|
||||
const value = e.target.value.trim();
|
||||
if (value) {
|
||||
setValidationStates((prev) => ({
|
||||
...prev,
|
||||
codeNameEng: { enabled: true, value },
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{form.formState.errors.codeNameEng && (
|
||||
<p className="text-sm text-red-600">{getErrorMessage(form.formState.errors.codeNameEng)}</p>
|
||||
)}
|
||||
{!form.formState.errors.codeNameEng && (
|
||||
<ValidationMessage
|
||||
message={codeNameEngCheck.data?.message}
|
||||
isValid={!codeNameEngCheck.data?.isDuplicate}
|
||||
isLoading={codeNameEngCheck.isLoading}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 설명 */}
|
||||
@@ -212,7 +303,10 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode }: Co
|
||||
<Button type="button" variant="outline" onClick={onClose} disabled={isLoading}>
|
||||
취소
|
||||
</Button>
|
||||
<Button type="submit" disabled={isLoading || !form.formState.isValid}>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isLoading || !form.formState.isValid || hasDuplicateErrors || isDuplicateChecking}
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<LoadingSpinner size="sm" className="mr-2" />
|
||||
|
||||
Reference in New Issue
Block a user