"use client" import * as React from "react" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { Button } from "@/components/ui/button" import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "@/components/ui/sheet" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Textarea } from "@/components/ui/textarea" import { Separator } from "@/components/ui/separator" import { toast } from "sonner" import { Loader2, Edit } from "lucide-react" import { updateApprovalLine, type ApprovalLine } from "../service" import { type ApprovalLineFormData, ApprovalLineSchema } from "../validations" import { OrganizationManagerSelector, type OrganizationManagerItem } from "@/components/common/organization/organization-manager-selector" import { useSession } from "next-auth/react" import { ApprovalLineSelector } from "@/components/knox/approval/ApprovalLineSelector" interface UpdateApprovalLineSheetProps { open: boolean onOpenChange: (open: boolean) => void line: ApprovalLine | null } // 최소 형태의 Apln 아이템 타입 (line.aplns JSON 구조 대응) interface MinimalAplnItem { id: string epId?: string userId?: string emailAddress?: string name?: string deptName?: string role: "0" | "1" | "2" | "3" | "4" | "7" | "9" seq: string opinion?: string [key: string]: unknown } export function UpdateApprovalLineSheet({ open, onOpenChange, line }: UpdateApprovalLineSheetProps) { const { data: session } = useSession(); const [isSubmitting, setIsSubmitting] = React.useState(false); // 고유 ID 생성 함수 (조직 관리자 추가 시 사용) const generateUniqueId = () => `apln-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`; const form = useForm({ resolver: zodResolver(ApprovalLineSchema), defaultValues: { name: "", category: "", description: "", aplns: [], }, }); // line이 변경될 때 폼 초기화 React.useEffect(() => { if (line) { const existingAplns = (line.aplns as unknown as MinimalAplnItem[]) || []; // 기안자가 없으면 추가 const hasDraft = existingAplns.some((a) => String(a.seq) === "0"); let nextAplns: MinimalAplnItem[] = existingAplns; if (!hasDraft) { nextAplns = [ { id: generateUniqueId(), epId: undefined, userId: undefined, emailAddress: undefined, name: "기안자", deptName: undefined, role: "0", seq: "0", opinion: "", }, ...existingAplns, ]; } form.reset({ name: line.name, category: line.category || "", description: line.description || "", aplns: nextAplns as ApprovalLineFormData["aplns"], }); } }, [line, form]); const aplns = form.watch("aplns"); // 조직 관리자 추가 (공용 선택기 외 보조 입력 경로) const addOrganizationManagers = (managers: OrganizationManagerItem[]) => { const next = [...aplns]; const uniqueSeqs = Array.from(new Set(next.map((a) => parseInt(a.seq)))); const maxSeq = uniqueSeqs.length ? Math.max(...uniqueSeqs) : 0; managers.forEach((manager, idx) => { const exists = next.findIndex((a) => a.epId === manager.managerId); if (exists === -1) { const newSeqNum = Math.max(1, maxSeq + 1 + idx); const newSeq = newSeqNum.toString(); next.push({ id: generateUniqueId(), epId: manager.managerId, userId: undefined, emailAddress: undefined, name: manager.managerName, deptName: manager.departmentName, role: "1", seq: newSeq, opinion: "", }); } }); form.setValue("aplns", next, { shouldDirty: true }); }; const onSubmit = async (data: ApprovalLineFormData) => { if (!line || !session?.user?.id) { toast.error("수정할 결재선이 없거나 로그인이 필요합니다."); return; } setIsSubmitting(true); try { await updateApprovalLine(line.id, { name: data.name, category: data.category || null, description: data.description, aplns: data.aplns, updatedBy: Number(session.user.id), }); toast.success("결재선이 성공적으로 수정되었습니다."); onOpenChange(false); } catch { toast.error("결재선 수정 중 오류가 발생했습니다."); } finally { setIsSubmitting(false); } }; if (!line) return null; return ( 결재선 수정 "{line.name}" 결재선을 수정합니다. 결재자를 추가하고 순서를 조정할 수 있습니다.
{/* 기본 정보 */}
( 결재선 이름 * )} /> ( 카테고리 )} /> ( 설명