diff options
Diffstat (limited to 'lib/gtc-contract/status/create-new-revision-dialog.tsx')
| -rw-r--r-- | lib/gtc-contract/status/create-new-revision-dialog.tsx | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/lib/gtc-contract/status/create-new-revision-dialog.tsx b/lib/gtc-contract/status/create-new-revision-dialog.tsx new file mode 100644 index 00000000..e18e6352 --- /dev/null +++ b/lib/gtc-contract/status/create-new-revision-dialog.tsx @@ -0,0 +1,157 @@ +"use client" + +import * as React from "react" +import { useForm } from "react-hook-form" +import { zodResolver } from "@hookform/resolvers/zod" +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { Textarea } from "@/components/ui/textarea" + +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" +import { Loader } from "lucide-react" +import { toast } from "sonner" + +import { createNewRevisionSchema, type CreateNewRevisionSchema } from "@/lib/gtc-contract/validations" +import { createNewRevision } from "@/lib/gtc-contract/service" +import { type GtcDocumentWithRelations } from "@/db/schema/gtc" + +interface CreateNewRevisionDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + originalDocument: GtcDocumentWithRelations | null +} + +export function CreateNewRevisionDialog({ + open, + onOpenChange, + originalDocument, +}: CreateNewRevisionDialogProps) { + const [isCreatePending, startCreateTransition] = React.useTransition() + + const form = useForm<CreateNewRevisionSchema>({ + resolver: zodResolver(createNewRevisionSchema), + defaultValues: { + editReason: "", + }, + }) + + // 다이얼로그가 열릴 때마다 폼 초기화 + React.useEffect(() => { + if (open && originalDocument) { + form.reset({ + editReason: "", + }) + } + }, [open, originalDocument, form]) + + async function onSubmit(data: CreateNewRevisionSchema) { + if (!originalDocument) { + toast.error("원본 문서 정보가 없습니다.") + return + } + + startCreateTransition(async () => { + try { + const result = await createNewRevision(originalDocument.id, data) + + if (result.error) { + toast.error(`에러: ${result.error}`) + return + } + + form.reset() + onOpenChange(false) + toast.success(`새 리비전 v${result.revision}이 생성되었습니다.`) + } catch (error) { + toast.error("리비전 생성 중 오류가 발생했습니다.") + } + }) + } + + function handleDialogOpenChange(nextOpen: boolean) { + if (!nextOpen) { + form.reset() + } + onOpenChange(nextOpen) + } + + if (!originalDocument) return null + + return ( + <Dialog open={open} onOpenChange={handleDialogOpenChange}> + <DialogContent className="max-w-md"> + <DialogHeader> + <DialogTitle>Create New Revision</DialogTitle> + <DialogDescription> + 기존 문서의 새로운 리비전을 생성합니다. + </DialogDescription> + </DialogHeader> + + {/* 원본 문서 정보 표시 */} + <div className="space-y-2 p-3 bg-muted/50 rounded-lg"> + <div className="text-sm font-medium">원본 문서 정보</div> + <div className="text-xs text-muted-foreground space-y-1"> + <div>구분: {originalDocument.type === "standard" ? "표준" : "프로젝트"}</div> + {originalDocument.project && ( + <div>프로젝트: {originalDocument.project.name} ({originalDocument.project.code})</div> + )} + <div>현재 리비전: v{originalDocument.revision}</div> + </div> + </div> + + <Form {...form}> + <form onSubmit={form.handleSubmit(onSubmit)}> + <div className="space-y-4 py-4"> + {/* 편집 사유 (필수) */} + <FormField + control={form.control} + name="editReason" + render={({ field }) => ( + <FormItem> + <FormLabel>편집 사유 *</FormLabel> + <FormControl> + <Textarea + placeholder="새 리비전 생성 사유를 입력하세요..." + {...field} + rows={3} + required + /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + </div> + + <DialogFooter> + <Button + type="button" + variant="outline" + onClick={() => onOpenChange(false)} + disabled={isCreatePending} + > + Cancel + </Button> + <Button type="submit" disabled={isCreatePending}> + {isCreatePending && ( + <Loader + className="mr-2 size-4 animate-spin" + aria-hidden="true" + /> + )} + Create Revision + </Button> + </DialogFooter> + </form> + </Form> + </DialogContent> + </Dialog> + ) +}
\ No newline at end of file |
