From fb20768fa881841d3f80d12a276a9445feb6f514 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Tue, 30 Sep 2025 05:04:33 +0000 Subject: (고건) 이메일 템플릿 정보 수정/복제 기능 에러 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table/duplicate-template-sheet.tsx | 142 ++++++++++----------- 1 file changed, 71 insertions(+), 71 deletions(-) (limited to 'lib/email-template/table/duplicate-template-sheet.tsx') diff --git a/lib/email-template/table/duplicate-template-sheet.tsx b/lib/email-template/table/duplicate-template-sheet.tsx index 767a8bb6..d59d80f0 100644 --- a/lib/email-template/table/duplicate-template-sheet.tsx +++ b/lib/email-template/table/duplicate-template-sheet.tsx @@ -1,15 +1,8 @@ -"use client" +'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 */ +import { Button } from '@/components/ui/button'; +import { duplicateTemplate, getCurrentUserId } from '../service'; import { Form, FormControl, @@ -18,8 +11,10 @@ import { FormLabel, FormMessage, FormDescription, -} from "@/components/ui/form" -import { Input } from "@/components/ui/input" +} from '@/components/ui/form'; +import { getCategoryDisplayName } from '../validations'; +import { Input } from '@/components/ui/input'; +import { Loader } from 'lucide-react'; import { Sheet, SheetClose, @@ -28,53 +23,59 @@ import { SheetFooter, SheetHeader, SheetTitle, -} from "@/components/ui/sheet" - -import { duplicateTemplate } from "../service" - -// Validation Schema +} from '@/components/ui/sheet'; +import { toast } from 'sonner'; +import { type ComponentPropsWithRef, useEffect, useTransition } from 'react'; +import { type TemplateListView } from '@/db/schema'; +import { useForm } from 'react-hook-form'; +import { useRouter } from 'next/navigation'; +import { z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; + +// ---------------------------------------------------------------------------------------------------- + +/* TYPES */ const duplicateTemplateSchema = z.object({ - name: z.string().min(1, "템플릿 이름은 필수입니다").max(100, "템플릿 이름은 100자 이하여야 합니다"), + 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 + .min(1, 'Slug는 필수입니다.') + .max(50, 'Slug는 50자 이하여야 합니다.') + .regex(/^[a-z0-9-]+$/, 'Slug는 소문자, 숫자, 하이픈만 사용 가능합니다.'), +}); +type DuplicateTemplateSchema = z.infer; +interface DuplicateTemplateSheetProps extends ComponentPropsWithRef { + template: TemplateListView | null; } -export function DuplicateTemplateSheet({ template, ...props }: DuplicateTemplateSheetProps) { - const [isDuplicatePending, startDuplicateTransition] = React.useTransition() - const router = useRouter() +// ---------------------------------------------------------------------------------------------------- +/* DUPLICATE EMAIL TEMPLATE SHEET COMPONENT */ +function DuplicateTemplateSheet({ template, ...props }: DuplicateTemplateSheetProps) { + const [isDuplicatePending, startDuplicateTransition] = useTransition(); const form = useForm({ resolver: zodResolver(duplicateTemplateSchema), defaultValues: { - name: "", - slug: "", + name: '', + slug: '', }, }) + const router = useRouter(); + const watchedName = form.watch('name'); - React.useEffect(() => { + useEffect(() => { if (template) { - const copyName = `${template.name} (복사본)` - const copySlug = `${template.slug}-copy-${Date.now()}` - + const copyName = `${template.name} (복사본)`; + const copySlug = `${template.slug}-copy-${Date.now()}`; form.reset({ name: copyName, slug: copySlug, - }) + }); } - }, [template, form]) + }, [template, form]); - // 이름 입력 시 자동으로 slug 생성 - const watchedName = form.watch("name") - React.useEffect(() => { + useEffect(() => { if (watchedName && !form.formState.dirtyFields.slug) { const autoSlug = watchedName .toLowerCase() @@ -82,42 +83,40 @@ export function DuplicateTemplateSheet({ template, ...props }: DuplicateTemplate .replace(/\s+/g, '-') .replace(/-+/g, '-') .trim() - .slice(0, 50) - - form.setValue("slug", autoSlug, { shouldValidate: false }) + .slice(0, 50); + form.setValue('slug', autoSlug, { shouldValidate: false }); } - }, [watchedName, form]) + }, [watchedName, form]); function onSubmit(input: DuplicateTemplateSchema) { startDuplicateTransition(async () => { - if (!template) return - - // 현재 사용자 ID (실제로는 인증에서 가져와야 함) - const currentUserId = "current-user-id" // TODO: 실제 사용자 ID로 교체 + if (!template) { + return; + } + const currentUserId = await getCurrentUserId(); const { error, data } = await duplicateTemplate( template.id, input.name, input.slug, - currentUserId - ) + currentUserId, + ); if (error) { - toast.error(error) - return + toast.error(error); + return; } - form.reset() - props.onOpenChange?.(false) - toast.success("템플릿이 복제되었습니다") + form.reset(); + props.onOpenChange?.(false); + toast.success('템플릿이 복제되었습니다.'); - // 복제된 템플릿의 세부 페이지로 이동 if (data?.slug) { - router.push(`/evcp/templates/${data.slug}`) + router.push(`/evcp/email-template/${data.slug}`); } else { - window.location.reload() + window.location.reload(); } - }) + }); } return ( @@ -129,19 +128,17 @@ export function DuplicateTemplateSheet({ template, ...props }: DuplicateTemplate 기존 템플릿을 복사하여 새로운 템플릿을 생성합니다. 모든 내용과 변수가 복제됩니다. - {template && (

원본 템플릿

이름: {template.name}
Slug: {template.slug}
-
카테고리: {template.categoryDisplayName}
+
카테고리: {getCategoryDisplayName(template.category)}
변수: {template.variableCount}개
)} -
새 템플릿 이름 @@ -163,7 +160,6 @@ export function DuplicateTemplateSheet({ template, ...props }: DuplicateTemplate )} /> - 새 Slug @@ -183,7 +179,6 @@ export function DuplicateTemplateSheet({ template, ...props }: DuplicateTemplate )} /> -