"use client" import * as React from "react" import { type TemplateListView } from "@/db/schema/template-views" import { zodResolver } from "@hookform/resolvers/zod" import { Loader } from "lucide-react" import { useForm } from "react-hook-form" import { toast } from "sonner" import { z } from "zod" import { useRouter } from "next/navigation" import { Button } from "@/components/ui/button" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescription, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@/components/ui/sheet" import { duplicateTemplate } from "../service" // Validation Schema const duplicateTemplateSchema = z.object({ name: z.string().min(1, "템플릿 이름은 필수입니다").max(100, "템플릿 이름은 100자 이하여야 합니다"), slug: z.string() .min(1, "Slug는 필수입니다") .max(50, "Slug는 50자 이하여야 합니다") .regex(/^[a-z0-9-]+$/, "Slug는 소문자, 숫자, 하이픈만 사용 가능합니다"), }) type DuplicateTemplateSchema = z.infer interface DuplicateTemplateSheetProps extends React.ComponentPropsWithRef { template: TemplateListView | null } export function DuplicateTemplateSheet({ template, ...props }: DuplicateTemplateSheetProps) { const [isDuplicatePending, startDuplicateTransition] = React.useTransition() const router = useRouter() const form = useForm({ resolver: zodResolver(duplicateTemplateSchema), defaultValues: { name: "", slug: "", }, }) React.useEffect(() => { if (template) { const copyName = `${template.name} (복사본)` const copySlug = `${template.slug}-copy-${Date.now()}` form.reset({ name: copyName, slug: copySlug, }) } }, [template, form]) // 이름 입력 시 자동으로 slug 생성 const watchedName = form.watch("name") React.useEffect(() => { if (watchedName && !form.formState.dirtyFields.slug) { const autoSlug = watchedName .toLowerCase() .replace(/[^a-z0-9\s-]/g, '') .replace(/\s+/g, '-') .replace(/-+/g, '-') .trim() .slice(0, 50) form.setValue("slug", autoSlug, { shouldValidate: false }) } }, [watchedName, form]) function onSubmit(input: DuplicateTemplateSchema) { startDuplicateTransition(async () => { if (!template) return // 현재 사용자 ID (실제로는 인증에서 가져와야 함) const currentUserId = "current-user-id" // TODO: 실제 사용자 ID로 교체 const { error, data } = await duplicateTemplate( template.id, input.name, input.slug, currentUserId ) if (error) { toast.error(error) return } form.reset() props.onOpenChange?.(false) toast.success("템플릿이 복제되었습니다") // 복제된 템플릿의 세부 페이지로 이동 if (data?.slug) { router.push(`/evcp/templates/${data.slug}`) } else { window.location.reload() } }) } return ( 템플릿 복제 기존 템플릿을 복사하여 새로운 템플릿을 생성합니다. 모든 내용과 변수가 복제됩니다. {template && (

원본 템플릿

이름: {template.name}
Slug: {template.slug}
카테고리: {template.categoryDisplayName}
변수: {template.variableCount}개
)}
( 새 템플릿 이름 )} /> ( 새 Slug 고유한 식별자여야 합니다. 소문자, 숫자, 하이픈만 사용 가능합니다. )} />
) }