diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-evl-dialog.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-evl-dialog.tsx index a48242a96..1a82159dd 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-evl-dialog.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-evl-dialog.tsx @@ -33,6 +33,9 @@ import { interface PwrkCnsltnDocEvlDialogProps { open: boolean; pwrkCnsltnDocNo: string; + /** 평가 저장 성공 시 호출 (이후 웹기안기 문서 저장이 진행된다) */ + onSaved: () => void; + /** 평가 없이 닫을 때 호출 (웹기안기 문서는 저장되지 않는다) */ onClose: () => void; } @@ -41,7 +44,12 @@ const DEFAULT_VALUES: Partial = { pwrkCnsltnDocEvlCn: "", }; -function PwrkCnsltnDocEvlDialog({ open, pwrkCnsltnDocNo, onClose }: PwrkCnsltnDocEvlDialogProps) { +function PwrkCnsltnDocEvlDialog({ + open, + pwrkCnsltnDocNo, + onSaved, + onClose, +}: PwrkCnsltnDocEvlDialogProps) { const alert = useAlertStore((state) => state.setMessage); const { mutateAsync: saveEvl, isPending } = useSavePwrkCnsltnDocEvl(); @@ -65,8 +73,7 @@ function PwrkCnsltnDocEvlDialog({ open, pwrkCnsltnDocNo, onClose }: PwrkCnsltnDo try { const payload = buildPwrkCnsltnDocEvlSavePayload(pwrkCnsltnDocNo, values); await saveEvl(payload); - alert("AI 초안 만족도 평가를 등록했습니다."); - onClose(); + onSaved(); } catch (error) { console.error("AI 초안 만족도 평가 등록 실패:", error); alert("AI 초안 만족도 평가 등록에 실패했습니다."); diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx index 078853132..c2125d608 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import dynamic from "next/dynamic"; import { useQuery, useQueryClient } from "@tanstack/react-query"; @@ -46,6 +46,7 @@ const HangulGiangi = dynamic( const PWRK_ATCH_FILE_KEY_PREFIX = "pwrk-cnsltn-doc::"; +/** 현재 버전이 이 값보다 작으면(AI 초안 상태) 저장 전에 만족도 평가를 먼저 받는다. */ const AI_DRAFT_EVL_MAX_VER_SN = 2; const APPROVER_ATRZ_SE_COM_CDS = new Set(["ATRZ03", "ATRZ99"]); @@ -88,6 +89,8 @@ function PwrkCnsltnDocMngDialog({ const [uploadedFiles, setUploadedFiles] = useState([]); const [isPjtcoAjmtTableOpen, setIsPjtcoAjmtTableOpen] = useState(false); const [isEvlDialogOpen, setIsEvlDialogOpen] = useState(false); + // 평가 모달 결과(평가 저장 여부)를 저장 흐름으로 돌려주는 resolver + const evlResolverRef = useRef<((isEvlSaved: boolean) => void) | null>(null); const { mutate: downloadByAtflId } = useDownloadAttachmentByAtflId(); const { @@ -145,6 +148,8 @@ function PwrkCnsltnDocMngDialog({ setAtchFileGroupId(""); setUploadedFiles([]); setIsEvlDialogOpen(false); + evlResolverRef.current?.(false); + evlResolverRef.current = null; return; } @@ -178,9 +183,32 @@ function PwrkCnsltnDocMngDialog({ if (!nextOpen) onClose(); } + function requestEvl() { + return new Promise((resolve) => { + evlResolverRef.current = resolve; + setIsEvlDialogOpen(true); + }); + } + + function resolveEvl(isEvlSaved: boolean) { + setIsEvlDialogOpen(false); + evlResolverRef.current?.(isEvlSaved); + evlResolverRef.current = null; + } + async function handleSaveDocument(file: Blob) { if (!completedDraft) throw new Error("저장할 실무협의서 초안이 없습니다."); + // AI 초안(버전 < 2) 저장 시에는 만족도 평가를 먼저 저장해야 웹기안기 문서가 저장된다. + const currentVerSn = completedDraft.crtRslt?.verSn ?? 0; + if (currentVerSn < AI_DRAFT_EVL_MAX_VER_SN) { + const isEvlSaved = await requestEvl(); + if (!isEvlSaved) { + alert("AI 초안 만족도 평가를 등록해야 실무협의서가 저장됩니다."); + return; + } + } + const saveDto = pwrkCnsltnDocCrtRsltSaveRequestSchema.parse({ crtDmndUuid: completedDraft.crtDmndUuid, pwrkCnsltnDocNo: completedDraft.pwrkCnsltnDocNo, @@ -201,10 +229,6 @@ function PwrkCnsltnDocMngDialog({ }), ]); alert(`실무협의서를 저장했습니다. (버전 ${savedDocument.verSn})`); - - if (savedDocument.verSn <= AI_DRAFT_EVL_MAX_VER_SN) { - setIsEvlDialogOpen(true); - } } async function handleDownload() { @@ -386,7 +410,8 @@ function PwrkCnsltnDocMngDialog({ setIsEvlDialogOpen(false)} + onSaved={() => resolveEvl(true)} + onClose={() => resolveEvl(false)} /> ) : null}