1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
"use client"
import * as React from "react"
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,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
} from "@/components/ui/sheet"
import { type ApprovalTemplate } from "@/lib/approval-template/service"
import { duplicateApprovalTemplate } from "../service"
import { useSession } from "next-auth/react"
const duplicateSchema = z.object({
name: z.string().min(1, "템플릿 이름은 필수입니다").max(100, "100자 이내여야 합니다"),
})
type DuplicateSchema = z.infer<typeof duplicateSchema>
interface DuplicateApprovalTemplateSheetProps extends React.ComponentPropsWithRef<typeof Sheet> {
template: ApprovalTemplate | null
}
export function DuplicateApprovalTemplateSheet({ template, ...props }: DuplicateApprovalTemplateSheetProps) {
const [isPending, startTransition] = React.useTransition()
const router = useRouter()
const { data: session } = useSession()
const form = useForm<DuplicateSchema>({
resolver: zodResolver(duplicateSchema),
defaultValues: { name: "" },
})
React.useEffect(() => {
if (template) {
form.reset({ name: `${template.name} (복사본)` })
}
}, [template, form])
function onSubmit(values: DuplicateSchema) {
startTransition(async () => {
if (!template) return
if (!session?.user?.id) {
toast.error("로그인이 필요합니다")
return
}
const { success, error, data } = await duplicateApprovalTemplate(
template.id,
values.name,
Number(session.user.id),
)
if (!success || error) {
toast.error(error ?? "복제에 실패했습니다")
return
}
toast.success("템플릿이 복제되었습니다")
props.onOpenChange?.(false)
// 상세 페이지로 이동 (id 기반)
if (data?.id) {
router.push(`/evcp/approval/template/${data.id}`)
} else {
window.location.reload()
}
})
}
return (
<Sheet {...props}>
<SheetContent className="flex flex-col gap-6 sm:max-w-md">
<SheetHeader className="text-left">
<SheetTitle>템플릿 복제</SheetTitle>
<SheetDescription>기존 템플릿을 복사하여 새로운 템플릿을 생성합니다.</SheetDescription>
</SheetHeader>
{template && (
<div className="rounded-lg bg-muted p-3">
<h4 className="text-sm font-medium mb-2">원본 템플릿</h4>
<div className="space-y-1 text-xs text-muted-foreground">
<div>이름: {template.name}</div>
<div>ID: <code className="bg-background px-1 rounded">{template.id}</code></div>
<div>카테고리: {template.category ?? "-"}</div>
</div>
</div>
)}
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>새 템플릿 이름</FormLabel>
<FormControl>
<Input placeholder="복제된 템플릿 이름" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<SheetFooter className="gap-2 pt-2 sm:space-x-0">
<SheetClose asChild>
<Button type="button" variant="outline">
취소
</Button>
</SheetClose>
<Button disabled={isPending}>
{isPending && <Loader className="mr-2 size-4 animate-spin" aria-hidden="true" />}
복제하기
</Button>
</SheetFooter>
</form>
</Form>
</SheetContent>
</Sheet>
)
}
|