From 0647df733a963b580b9e269be355261345d2a2b1 Mon Sep 17 00:00:00 2001 From: jangwoong Date: Thu, 11 Jun 2026 19:00:22 +0900 Subject: [PATCH] =?UTF-8?q?[as=20frontend]=20=EA=B2=B0=EC=A0=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/as/src/entities/instl-sncn/index.ts | 1 + .../instl-sncn/model/instl-sncn-interface.ts | 23 +++ .../pages/instl-sncn/ui/cnfm-list-page.tsx | 2 +- .../pages/instl-sncn/ui/cnfm-view-page.tsx | 150 ++++++++++++++++++ 4 files changed, 175 insertions(+), 1 deletion(-) diff --git a/apps/as/src/entities/instl-sncn/index.ts b/apps/as/src/entities/instl-sncn/index.ts index 5da39b459..cd340d42d 100644 --- a/apps/as/src/entities/instl-sncn/index.ts +++ b/apps/as/src/entities/instl-sncn/index.ts @@ -8,4 +8,5 @@ export { type InstlSncnMng, type InstlSncnMngSearchParams, type SpringPage, + type ElaprDocPrgrsClientResponseDto, } from "./model/instl-sncn-interface"; diff --git a/apps/as/src/entities/instl-sncn/model/instl-sncn-interface.ts b/apps/as/src/entities/instl-sncn/model/instl-sncn-interface.ts index b3e363aef..81c769f98 100644 --- a/apps/as/src/entities/instl-sncn/model/instl-sncn-interface.ts +++ b/apps/as/src/entities/instl-sncn/model/instl-sncn-interface.ts @@ -110,6 +110,28 @@ export interface InstlSncnApplySaveRequestDto { export type ReviewStepCode = "LOCAL" | "ENV" | "KECO"; + + +/** 전자결재 진행상태 (클라이언트 응답용) */ +export interface ElaprDocPrgrsClientResponseDto { + elaprDocNo?: string; + elaprDmndId?: string; + elaprPrgrsId?: string; + atrzSeqNo?: number; + atrzSeComCd?: string; + atrzSeComNm?: string; + aprvrUuid?: string; + aprvrUuidNm?: string; + atrzPrgrsSttsComCd?: string; + atrzPrgrsSttsComNm?: string; + rjctRsn?: string | null; + atrzDt?: string | null; + jbpsSeNm?: string; + jbgdSeNm?: string; + ognzNm?: string; +} + +// det 응답에 전자결재 진행상태 목록을 포함 export interface InstlSncnMngDetResponse { detDto: InstlSncnMng; bizSclList: any[]; @@ -117,6 +139,7 @@ export interface InstlSncnMngDetResponse { cklstResultList?: any[]; esntlFileList: any[]; etcFileList: any[]; + elaprDocPrgrsList?: ElaprDocPrgrsClientResponseDto[] | null; } export interface InstlSncnMngService { diff --git a/apps/as/src/pages/instl-sncn/ui/cnfm-list-page.tsx b/apps/as/src/pages/instl-sncn/ui/cnfm-list-page.tsx index 555813889..8597baf69 100644 --- a/apps/as/src/pages/instl-sncn/ui/cnfm-list-page.tsx +++ b/apps/as/src/pages/instl-sncn/ui/cnfm-list-page.tsx @@ -231,7 +231,7 @@ function CnfmListPage() { 담당자 해당기관 진행상황 - 시행일 + 신청일 diff --git a/apps/as/src/pages/instl-sncn/ui/cnfm-view-page.tsx b/apps/as/src/pages/instl-sncn/ui/cnfm-view-page.tsx index d68347c60..6ef71fd74 100644 --- a/apps/as/src/pages/instl-sncn/ui/cnfm-view-page.tsx +++ b/apps/as/src/pages/instl-sncn/ui/cnfm-view-page.tsx @@ -124,6 +124,113 @@ function CnfmViewPage({ id }: { id: string }) { }, [cklstAll]); const esntlFileList = data.esntlFileList ?? []; const etcFileList = data.etcFileList ?? []; + const elaprDocPrgrsList = (data.elaprDocPrgrsList ?? []) as any[]; + const renderApproverCell = (code: string) => { + const row = elaprDocPrgrsList.find((r) => r.atrzSeComCd === code); + if (!row) return
-
; + const status = row.atrzPrgrsSttsComCd ?? ""; + const statusMap: Record = { + ATRZ_PRGRS_001: { label: "대기", badgeClass: "bg-gray-100 text-gray-700", icon: "⏳" }, + ATRZ_PRGRS_002: { label: "요청", badgeClass: "bg-yellow-100 text-yellow-800", icon: "📨" }, + ATRZ_PRGRS_003: { label: "승인", badgeClass: "bg-green-100 text-green-800", icon: "✔️" }, + ATRZ_PRGRS_004: { label: "반려", badgeClass: "bg-red-100 text-red-800", icon: "✖️" }, + }; + const st = statusMap[status] ?? { label: status || "", badgeClass: "bg-gray-100 text-gray-700", icon: "" }; + return ( +
+
{row.aprvrUuidNm ?? "-"}
+
+ {row.ognzNm ? `${row.ognzNm}` : ""} + {row.jbpsSeNm || row.jbgdSeNm ? ` · ${row.jbpsSeNm ?? ""}${row.jbgdSeNm ? ` ${row.jbgdSeNm}` : ""}` : ""} +
+
+ {row.atrzDt ? {dayjs(row.atrzDt).format("YYYY-MM-DD HH:mm:ss")} : null} + {st.label ? ( + + {st.icon} + {st.label} + + ) : null} +
+
+ ); + }; + const orderedApprovers = useMemo(() => { + return (elaprDocPrgrsList ?? []).slice().sort((a: any, b: any) => { + const A = Number(a?.atrzSeqNo ?? 0); + const B = Number(b?.atrzSeqNo ?? 0); + return A - B; + }); + }, [elaprDocPrgrsList]); + + const handleApproveClick = async (elaprPrgrsId: any, atrzSeComCd: any) => { + if (!elaprPrgrsId) { + alert("결재 정보가 올바르지 않습니다."); + return; + } + const url = `${PROXY_HOST}/as-elapr-service/api/v1/elapr-prgrs-stts/${elaprPrgrsId}/process`; + const body = { atrzPrgrsSttsComCd: "ATRZ_STTS_003" }; // 승인 처리 + try { + await axios.put(url, body); + alert("결재가 완료되었습니다."); + try { + await query.refetch(); + } catch (e) { + /* ignore refetch errors */ + } + } catch (err: any) { + console.error("결재 처리 실패", err); + const msg = axios.isAxiosError(err) && err.response?.data?.message ? err.response.data.message : "결재 처리 중 오류가 발생했습니다."; + alert(msg); + } + }; + + const renderApproverRow = (row: any) => { + if (!row) return
-
; + const status = row.atrzPrgrsSttsComCd ?? ""; + const statusMap: Record = { + ATRZ_PRGRS_001: { label: "대기", badgeClass: "bg-gray-100 text-gray-700", icon: "⏳" }, + ATRZ_PRGRS_002: { label: "요청", badgeClass: "bg-yellow-100 text-yellow-800", icon: "📨" }, + ATRZ_PRGRS_003: { label: "승인", badgeClass: "bg-green-100 text-green-800", icon: "✔️" }, + ATRZ_PRGRS_004: { label: "반려", badgeClass: "bg-red-100 text-red-800", icon: "✖️" }, + }; + const st = statusMap[status] ?? { label: status || "", badgeClass: "bg-gray-100 text-gray-700", icon: "" }; + return ( +
+
{row.aprvrUuidNm ?? "-"}
+
+ {row.ognzNm ? `${row.ognzNm}` : ""} + {row.jbpsSeNm || row.jbgdSeNm ? ` · ${row.jbpsSeNm ?? ""}${row.jbgdSeNm ? ` ${row.jbgdSeNm}` : ""}` : ""} +
+
+ {row.atrzDt ? {dayjs(row.atrzDt).format("YYYY-MM-DD HH:mm:ss")} : null} + {st.label ? ( + <> + + {st.icon} + {st.label} + + {status === "ATRZ_PRGRS_002" && userInfo?.userUnqId === row.aprvrUuid ? ( + + ) : null} + + ) : null} +
+
+ ); + }; const currentPrgrsSttsComCd = (det.prgrsSttsComCd as string | undefined) ?? "ST"; const roleBasedMaxStepCount = getRoleStepCount(userInfo?.dtlInstCd); const progressBasedMaxStepCount = getProgressStepCount(currentPrgrsSttsComCd); @@ -267,6 +374,49 @@ function CnfmViewPage({ id }: { id: string }) { return (
+ {/* orderedApprovers.length > 0 && ( */ } +
+

결재 정보

+
+ + + + {orderedApprovers.length === 0 ? ( + <> + + + + + + ) : ( + orderedApprovers.map((r: any) => ( + + )) + )} + + + + + {orderedApprovers.length === 0 ? ( + <> + + + + + + ) : ( + orderedApprovers.map((r: any) => ( + + )) + )} + + +
접수자검토자승인자최종승인자 + {r.atrzSeComNm ?? r.atrzSeComCd} +
{renderApproverCell("ATRZ01")}{renderApproverCell("ATRZ02")}{renderApproverCell("ATRZ03")}{renderApproverCell("ATRZ99")}{renderApproverRow(r)}
+
+
+ {/* )} */}

설치인가 상세보기

문서번호: {det.instlSncnDocNo}