"use client" import * as React from "react" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { toast } from "sonner" import { Plus, Loader2 } from "lucide-react" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { createCodeGroup } from "@/lib/docu-list-rule/code-groups/service" import { useParams } from "next/navigation" import { z } from "zod" const createCodeGroupSchema = z.object({ description: z.string().min(1, "Description은 필수입니다."), codeFormat: z.string().optional().refine((val) => { if (!val) return true; // 빈 값은 허용 return /^[ANX]*$/.test(val); }, "Code Format은 A(영어 대문자), N(숫자), X(영어/숫자)만 입력 가능합니다."), controlType: z.string().min(1, "Control Type은 필수입니다."), }) type CreateCodeGroupFormValues = z.infer interface CodeGroupsAddDialogProps { onSuccess?: () => void } export function CodeGroupsAddDialog({ onSuccess }: CodeGroupsAddDialogProps) { const params = useParams() const projectId = Number(params?.projectId) const [open, setOpen] = React.useState(false) const [isLoading, setIsLoading] = React.useState(false) const form = useForm({ resolver: zodResolver(createCodeGroupSchema), defaultValues: { description: "", codeFormat: "", controlType: "", }, }) // Code Format을 기반으로 정규식 자동 생성 함수 const generateExpression = (codeFormat: string): string => { if (!codeFormat) return '' let expression = '^' let currentChar = codeFormat[0] let count = 1 for (let i = 1; i < codeFormat.length; i++) { if (codeFormat[i] === currentChar) { count++ } else { // 이전 문자에 대한 정규식 추가 if (currentChar === 'A') { expression += `[A-Z]{${count}}` } else if (currentChar === 'N') { expression += `[0-9]{${count}}` } else if (currentChar === 'X') { expression += `[A-Z0-9]{${count}}` } currentChar = codeFormat[i] count = 1 } } // 마지막 문자 처리 if (currentChar === 'A') { expression += `[A-Z]{${count}}` } else if (currentChar === 'N') { expression += `[0-9]{${count}}` } else if (currentChar === 'X') { expression += `[A-Z0-9]{${count}}` } expression += '$' return expression } const handleOpenChange = (newOpen: boolean) => { setOpen(newOpen) if (!newOpen) { form.reset() } } const handleCancel = () => { form.reset() setOpen(false) } const onSubmit = async (data: CreateCodeGroupFormValues) => { setIsLoading(true) try { // Expression 자동 생성 const expressions = generateExpression(data.codeFormat || "") const result = await createCodeGroup({ projectId: projectId, description: data.description, codeFormat: data.codeFormat, expressions: expressions, controlType: data.controlType, }) if (result.success) { toast.success("Code Group이 성공적으로 생성되었습니다.") form.reset() setOpen(false) onSuccess?.() } else { toast.error(result.error || "생성 중 오류가 발생했습니다.") } } catch (error) { console.error("Code Group 생성 오류:", error) toast.error("Code Group 생성에 실패했습니다.") } finally { setIsLoading(false) } } return ( Code Group 생성 새로운 Code Group을 생성합니다. * 표시된 항목은 필수 입력사항입니다.
( Description * )} /> ( Code Format form.trigger('codeFormat')} /> A: 영어 대문자, N: 숫자, X: 영어 대문자 또는 숫자 )} /> ( Control Type )} />
) }