"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 * as z from "zod" import { Button } from "@/components/ui/button" import { Switch } from "@/components/ui/switch" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescription, } from "@/components/ui/form" import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@/components/ui/sheet" import { Dropzone, DropzoneZone, DropzoneUploadIcon, DropzoneTitle, DropzoneDescription, DropzoneInput } from "@/components/ui/dropzone" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { updateTemplate } from "../service" import { GeneralContractTemplate } from "@/db/schema" // 업데이트 스키마: 계약종류, 계약문서명, 법무검토, 파일(선택) export const updateTemplateSchema = z.object({ contractTemplateType: z .string() .min(2, "계약 종류는 2자리 영문입니다.") .max(2, "계약 종류는 2자리 영문입니다.") .regex(/^[A-Za-z]{2}$/, "영문 2자리로 입력하세요."), contractTemplateName: z.string().min(1, "계약 문서명을 입력하세요."), legalReviewRequired: z.boolean(), file: z .instanceof(File, { message: "파일을 업로드해주세요." }) .refine((file) => file.size <= 100 * 1024 * 1024, { message: "파일 크기는 100MB 이하여야 합니다.", }) .refine( (file) => file.type === 'application/msword' || file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', { message: "워드 파일(.doc, .docx)만 업로드 가능합니다." } ) .optional(), }); export type UpdateTemplateSchema = z.infer interface UpdateTemplateSheetProps extends React.ComponentPropsWithRef { template: GeneralContractTemplate | null onSuccess?: () => void } export function UpdateTemplateSheet({ template, onSuccess, ...props }: UpdateTemplateSheetProps) { const [isUpdatePending, startUpdateTransition] = React.useTransition() const [selectedFile, setSelectedFile] = React.useState(null) const form = useForm({ resolver: zodResolver(updateTemplateSchema), defaultValues: { contractTemplateType: template?.contractTemplateType ?? "", contractTemplateName: template?.contractTemplateName ?? "", legalReviewRequired: template?.legalReviewRequired ?? false, }, mode: "onChange" }) // 파일 선택 핸들러 const handleFileChange = (files: File[]) => { if (files.length > 0) { const file = files[0]; setSelectedFile(file); form.setValue("file", file); } }; // 템플릿 변경 시 폼 값 업데이트 React.useEffect(() => { if (template) { form.reset({ contractTemplateType: template.contractTemplateType ?? "", contractTemplateName: template.contractTemplateName ?? "", legalReviewRequired: template.legalReviewRequired ?? false, }); } }, [template, form]); function onSubmit(input: UpdateTemplateSchema) { startUpdateTransition(async () => { if (!template) return // FormData 객체 생성하여 파일과 데이터를 함께 전송 const formData = new FormData(); formData.append("contractTemplateType", input.contractTemplateType); formData.append("contractTemplateName", input.contractTemplateName); formData.append("legalReviewRequired", input.legalReviewRequired.toString()); // basic-contract와 동일하게 리비전은 서버에서 증가 처리 if (input.file) { formData.append("file", input.file); } try { // 서비스 함수 호출 const { error } = await updateTemplate({ id: template.id, formData, }); if (error) { toast.error(error); return; } form.reset(); setSelectedFile(null); props.onOpenChange?.(false); toast.success("일반계약 템플릿이 성공적으로 업데이트되었습니다."); onSuccess?.(); } catch (error) { console.error("Update error:", error); toast.error("일반계약 템플릿 업데이트 중 오류가 발생했습니다."); } }); } if (!template) return null; return ( {/* 고정된 헤더 */} 일반계약 템플릿 수정 계약 기본정보를 수정하고 파일을 교체할 수 있습니다 {/* 스크롤 가능한 컨텐츠 영역 */}
{/* 1. 계약 종류 */} 계약 종류 ( 계약 종류 field.onChange(e.target.value.toUpperCase().slice(0, 2))} maxLength={2} /> )} /> {/* 2. 계약 문서명 */} 계약 문서명 ( 계약 문서명 )} /> {/* 3. 법무 검토 */} 법무 검토 (
법무검토 필요 법무팀 검토가 필요한 템플릿인지 설정
)} />
{/* 4. 파일 업데이트 */} 파일 업데이트 새로운 템플릿 파일을 업로드하세요 ( 새 템플릿 파일 (선택사항) {selectedFile ? selectedFile.name : "새 워드 파일을 드래그하세요"} {selectedFile ? `파일 크기: ${(selectedFile.size / (1024 * 1024)).toFixed(2)} MB` : "또는 클릭하여 워드 파일(.doc, .docx)을 선택하세요 (최대 100MB)"} 파일을 업로드하지 않으면 기존 파일이 유지됩니다 )} />
{/* 고정된 푸터 */}
) }