|
|
|
@@ -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 <div className="text-center">-</div>;
|
|
|
|
|
const status = row.atrzPrgrsSttsComCd ?? "";
|
|
|
|
|
const statusMap: Record<string, { label: string; badgeClass: string; icon: string }> = {
|
|
|
|
|
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 (
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<div className="font-semibold">{row.aprvrUuidNm ?? "-"}</div>
|
|
|
|
|
<div className="text-[0.95rem] text-gray-500">
|
|
|
|
|
{row.ognzNm ? `${row.ognzNm}` : ""}
|
|
|
|
|
{row.jbpsSeNm || row.jbgdSeNm ? ` · ${row.jbpsSeNm ?? ""}${row.jbgdSeNm ? ` ${row.jbgdSeNm}` : ""}` : ""}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="text-[0.9rem] mt-1 flex items-center justify-center gap-2">
|
|
|
|
|
{row.atrzDt ? <span className="text-gray-400">{dayjs(row.atrzDt).format("YYYY-MM-DD HH:mm:ss")}</span> : null}
|
|
|
|
|
{st.label ? (
|
|
|
|
|
<span
|
|
|
|
|
title={`${row.atrzPrgrsSttsComNm ?? st.label}${row.rjctRsn ? ` — 사유: ${row.rjctRsn}` : ""}${row.atrzDt ? ` · ${dayjs(row.atrzDt).format("YYYY-MM-DD HH:mm:ss")}` : ""}`}
|
|
|
|
|
className={`inline-flex items-center px-2 py-0.5 rounded-md text-xs font-semibold ml-1 ${st.badgeClass}`}
|
|
|
|
|
>
|
|
|
|
|
<span className="mr-1">{st.icon}</span>
|
|
|
|
|
<span>{st.label}</span>
|
|
|
|
|
</span>
|
|
|
|
|
) : null}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
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 <div className="text-center">-</div>;
|
|
|
|
|
const status = row.atrzPrgrsSttsComCd ?? "";
|
|
|
|
|
const statusMap: Record<string, { label: string; badgeClass: string; icon: string }> = {
|
|
|
|
|
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 (
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<div className="font-semibold">{row.aprvrUuidNm ?? "-"}</div>
|
|
|
|
|
<div className="text-[0.95rem] text-gray-500">
|
|
|
|
|
{row.ognzNm ? `${row.ognzNm}` : ""}
|
|
|
|
|
{row.jbpsSeNm || row.jbgdSeNm ? ` · ${row.jbpsSeNm ?? ""}${row.jbgdSeNm ? ` ${row.jbgdSeNm}` : ""}` : ""}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="text-[0.9rem] mt-1 flex items-center justify-center gap-2">
|
|
|
|
|
{row.atrzDt ? <span className="text-gray-400">{dayjs(row.atrzDt).format("YYYY-MM-DD HH:mm:ss")}</span> : null}
|
|
|
|
|
{st.label ? (
|
|
|
|
|
<>
|
|
|
|
|
<span
|
|
|
|
|
title={`${row.atrzPrgrsSttsComNm ?? st.label}${row.rjctRsn ? ` — 사유: ${row.rjctRsn}` : ""}${row.atrzDt ? ` · ${dayjs(row.atrzDt).format("YYYY-MM-DD HH:mm:ss")}` : ""}`}
|
|
|
|
|
className={`inline-flex items-center px-2 py-0.5 rounded-md text-xs font-semibold ml-1 ${st.badgeClass}`}
|
|
|
|
|
>
|
|
|
|
|
<span className="mr-1">{st.icon}</span>
|
|
|
|
|
<span>{st.label}</span>
|
|
|
|
|
</span>
|
|
|
|
|
{status === "ATRZ_PRGRS_002" && userInfo?.userUnqId === row.aprvrUuid ? (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={() => handleApproveClick(row.elaprPrgrsId, row.atrzSeComCd)}
|
|
|
|
|
className="ml-2 px-2 py-1 bg-blue-500 text-white text-xs rounded"
|
|
|
|
|
>
|
|
|
|
|
결제
|
|
|
|
|
</button>
|
|
|
|
|
) : null}
|
|
|
|
|
</>
|
|
|
|
|
) : null}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
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 (
|
|
|
|
|
<div className="mt-6 space-y-4">
|
|
|
|
|
{/* orderedApprovers.length > 0 && ( */ }
|
|
|
|
|
<div className="cnfm-card p-4">
|
|
|
|
|
<h3 className="text-[1.5rem] font-semibold">결재 정보</h3>
|
|
|
|
|
<div className="cnfm-table-wrap mt-3">
|
|
|
|
|
<table className="cnfm-table w-full">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
{orderedApprovers.length === 0 ? (
|
|
|
|
|
<>
|
|
|
|
|
<th className="text-center">접수자</th>
|
|
|
|
|
<th className="text-center">검토자</th>
|
|
|
|
|
<th className="text-center">승인자</th>
|
|
|
|
|
<th className="text-center">최종승인자</th>
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
orderedApprovers.map((r: any) => (
|
|
|
|
|
<th key={String(r.elaprPrgrsId ?? r.atrzSeComCd)} className="text-center">
|
|
|
|
|
{r.atrzSeComNm ?? r.atrzSeComCd}
|
|
|
|
|
</th>
|
|
|
|
|
))
|
|
|
|
|
)}
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
{orderedApprovers.length === 0 ? (
|
|
|
|
|
<>
|
|
|
|
|
<td>{renderApproverCell("ATRZ01")}</td>
|
|
|
|
|
<td>{renderApproverCell("ATRZ02")}</td>
|
|
|
|
|
<td>{renderApproverCell("ATRZ03")}</td>
|
|
|
|
|
<td>{renderApproverCell("ATRZ99")}</td>
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
orderedApprovers.map((r: any) => (
|
|
|
|
|
<td key={String(r.elaprPrgrsId ?? r.atrzSeComCd)}>{renderApproverRow(r)}</td>
|
|
|
|
|
))
|
|
|
|
|
)}
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{/* )} */}
|
|
|
|
|
<div className="cnfm-card p-4">
|
|
|
|
|
<h2 className="cnfm-section-title">설치인가 상세보기</h2>
|
|
|
|
|
<p className="mt-2 text-[1.3rem] text-gray-600">문서번호: <strong>{det.instlSncnDocNo}</strong></p>
|
|
|
|
|