diff --git a/apps/as/src/pages/instl-sncn/ui/cnfm-modify-page.tsx b/apps/as/src/pages/instl-sncn/ui/cnfm-modify-page.tsx index 854d2515d..0aaf6de0e 100644 --- a/apps/as/src/pages/instl-sncn/ui/cnfm-modify-page.tsx +++ b/apps/as/src/pages/instl-sncn/ui/cnfm-modify-page.tsx @@ -1,17 +1,16 @@ "use client"; -import { useRouter } from "next/navigation"; import { useQuery } from "@tanstack/react-query"; -import { Button, Input } from "@common/components"; +import { CnfmRegistPage } from "./cnfm-regist-page"; import { InstlSncnApi } from "@/entities/instl-sncn"; import "./cnfm-page.css"; function CnfmModifyPage({ id }: { id: string }) { - const router = useRouter(); const query = useQuery({ - queryKey: ["instl-sncn-modify", id], + // share cache with view page + queryKey: ["instl-sncn-detail", id], queryFn: () => InstlSncnApi.getById(id), }); @@ -25,53 +24,11 @@ function CnfmModifyPage({ id }: { id: string }) { const data = query.data; + if (!data) return
수정 대상을 찾을 수 없습니다.
; + return ( -
-
-

설치인가 수정

-

- 상세 조회 API 데이터를 기반으로 수정 화면을 구성했습니다. -

-
- -
-

기본 정보

- - - - - - - - - - - - - - - - - - - - - -
문서번호{data.instlSncnDocNo}진행상태{data.prgrsSttsCdNm || data.prgrsSttsComCd || "-"}
사업명 - - 사업내용 - -
설계자명 - - 설계자 연락처 - -
-
- -
- - -
+
+
); } diff --git a/apps/as/src/pages/instl-sncn/ui/cnfm-regist-page.tsx b/apps/as/src/pages/instl-sncn/ui/cnfm-regist-page.tsx index aab93e671..9dc5cb8fc 100644 --- a/apps/as/src/pages/instl-sncn/ui/cnfm-regist-page.tsx +++ b/apps/as/src/pages/instl-sncn/ui/cnfm-regist-page.tsx @@ -1,4 +1,5 @@ "use client"; +/* eslint-disable @typescript-eslint/no-explicit-any */ import { useEffect, useMemo, useRef, useState } from "react"; import { useRouter } from "next/navigation"; @@ -76,7 +77,7 @@ import { NumCell, ReadCell, PrivacyConsent, EtcAttachments } from '@/widgets/cnf /* ------------------------------------------------------------------ */ /* 메인 컴포넌트 */ /* ------------------------------------------------------------------ */ -function CnfmRegistPage() { +function CnfmRegistPage({ initialData }: { initialData?: any } = {}) { const router = useRouter(); const userInfo = useUserStore((state) => state.userInfo); const alert = useAlertStore((state) => state.setMessage); @@ -112,6 +113,12 @@ function CnfmRegistPage() { const [dsgnrTelno, setDsgnrTelno] = useState(""); const [dsgnrEmlAddr, setDsgnrEmlAddr] = useState(""); + /* ── 신청자 정보 (수정 모드 매핑용) ── */ + const [aplcntNm, setAplcntNm] = useState(""); + const [aplcntMblTelno, setAplcntMblTelno] = useState(""); + const [aplcntOgdpNm, setAplcntOgdpNm] = useState(""); + const [aplcntEmlAddr, setAplcntEmlAddr] = useState(""); + /* ── 개인정보 동의 ── */ const [privacyAgree, setPrivacyAgree] = useState<"Y" | "N">("N"); @@ -222,6 +229,122 @@ function CnfmRegistPage() { const [etcUploading, setEtcUploading] = useState(false); const etcFileGroupIdRef = useRef(""); + // 초기 데이터가 주어지면 폼 상태로 매핑 (수정 모드에서 사용) + useEffect(() => { + if (!initialData) return; + + try { + const det = (initialData.detDto ?? initialData) as any; + + const bizSclList = initialData.bizSclList ?? []; + const bizCstList = initialData.bizCstList ?? []; + const cklstResultList = initialData.cklstResultList ?? []; + const esntlFileList = initialData.esntlFileList ?? []; + const etcFileList = initialData.etcFileList ?? []; + + + // 기본 정보 및 설계자 정보 + setBzNm(det.bizNm ?? ""); + setBzBgngYr(det.bizBgngYr ?? ""); + setBzEndYr(det.bizEndYr ?? ""); + setBzCn(det.bizCn ?? ""); + setInstlCnfmApr(det.envoSeComCd ?? det.envoSeCd ?? "CNFM"); + + // 설계자 + setDsgnrNm(det.dsgnrNm ?? ""); + setDsgnrPsitn(det.dsgnrOgdpNm ?? ""); + setDsgnrTelno(det.dsgnrTelno ?? ""); + setDsgnrEmlAddr(det.dsgnrEmlAddr ?? ""); + + // 개인정보 동의 + if (det.privacyAgree) setPrivacyAgree(det.privacyAgree === "Y" ? "Y" : "N"); + + // 신청자 + setAplcntNm(det.aplcntNm ?? ""); + setAplcntMblTelno(det.aplcntMblTelno ?? ""); + setAplcntOgdpNm(det.aplcntOgdpNm ?? ""); + setAplcntEmlAddr(det.aplcntEmlAddr ?? ""); + + // 기타첨부파일 + if (Array.isArray(etcFileList)) { + setEtcFiles( + etcFileList + .filter((f: any) => f && typeof f === "object") + .map((f: any) => ({ + id: f.atflId ?? String(Math.random()), + name: f.orgnlFileNm ?? f.physFileNm ?? "", + ext: "", + size: f.atflFlieSz ?? 0, + uploader: f.upldUserNm ?? "", + atflCd: f.atflCd ?? "", + atflId: f.atflId ?? "", + })), + ); + } + + // 필수첨부파일: requiredFiles는 requiredAttachmentDefs 로 초기화되므로 atflCd/atflId만 덮어쓴다 + if (Array.isArray(esntlFileList)) { + setRequiredFiles((prev) => { + const next = { ...prev }; + for (const f of esntlFileList) { + if (!f || typeof f !== "object") continue; + const key = f.esntlAtchFileId ?? f.esntlAtchFileId; + if (!key) continue; + const existing = next[key] ?? { + key, + esntlAtchFileNm: f.esntlAtchFileNm ?? "", + esntlAtchYn: f.esntlAtchYn ?? "N", + esntlAtchFileRmrk: "", + atflCd: "", + atflId: "", + fileName: "", + uploading: false, + }; + + next[key] = { + ...existing, + atflCd: f.atflCd ?? existing.atflCd, + atflId: f.atflId ?? existing.atflId, + fileName: f.orgnlFileNm ?? existing.fileName, + uploading: false, + }; + } + return next; + }); + } + + // 사업규모 매핑 + if (Array.isArray(bizSclList)) { + const map: Record = {}; + for (const row of bizSclList) { + if (!row.cnstpSeCd) continue; + map[row.cnstpSeCd] = { + bscPl: String(row.bscPl ?? row.bscPlanQty ?? ""), + budgetReflct: String(row.budgetReflct ?? row.bgtRfltQty ?? ""), + thtiDsgn: String(row.thtiDsgn ?? row.tstmDesignQty ?? ""), + }; + } + setBzScaleMap(map); + } + + // 총사업비 매핑 + if (Array.isArray(bizCstList)) { + const map: Record = {}; + for (const row of bizCstList) { + if (!row.acntgSeCd) continue; + map[row.acntgSeCd] = { + bscPl: String(row.bscPlanAmt ?? row.bscPl ?? ""), + budgetReflct: String(row.bgtRfltAmt ?? row.budgetReflct ?? ""), + thtiDsgn: String(row.tstmDesignAmt ?? row.thtiDsgn ?? ""), + }; + } + setAmtMap(map); + } + } catch (err) { + console.error("initialData 매핑 실패", err); + } + }, [initialData]); + /** 기타첨부파일 삭제 핸들러: 백엔드에 DELETE 요청을 보내 소프트삭제 처리 후 상태 갱신 */ const handleDeleteEtcFile = async (fileId: string, atflId: string) => { try { @@ -425,6 +548,34 @@ function CnfmRegistPage() { }); }, [cklstRows]); + // 수정 모드에서 서버의 체크리스트 결과값을 폼 상태로 반영 + useEffect(() => { + if (!initialData || cklstRows.length === 0) return; + const det = (initialData.detDto ?? initialData) as any; + if (!Array.isArray(det.cklstResultList)) return; + + const lookup = new Map(); + for (const r of det.cklstResultList) { + // 서버의 결과에 cklstSn, cklstArtclSn, cklstRvwSn 조합이 있다면 key 생성 + const key = `${r.cklstSn}_${r.cklstArtclSn ?? ""}_${r.cklstRvwSn}`; + if (r.rvwRsltAnmlyYn === "Y" || r.rvwRsltAnmlyYn === "N") lookup.set(key, r.rvwRsltAnmlyYn); + } + + setCheckResults((prev) => { + const next = { ...prev }; + let changed = false; + for (const row of cklstRows) { + const k = cklstKey(row); + const v = lookup.get(k); + if (v && next[k] !== v) { + next[k] = v as CheckResultVal; + changed = true; + } + } + return changed ? next : prev; + }); + }, [initialData, cklstRows]); + const cklstStats = useMemo(() => { const total = cklstRows.length; const completed = cklstRows.reduce((acc, row) => { @@ -663,10 +814,10 @@ function CnfmRegistPage() { bizBgngYr: bzBgngYr, bizEndYr: bzEndYr, bizCn: bzCn, - aplcntNm: "", - aplcntMblTelno: "", - aplcntOgdpNm: "", - aplcntEmlAddr: "", + aplcntNm: aplcntNm || userInfo?.userName || "", + aplcntMblTelno: aplcntMblTelno || (userInfo?.mphn ?? userInfo?.telno ?? ""), + aplcntOgdpNm: aplcntOgdpNm || (userInfo?.instSeNm ?? ""), + aplcntEmlAddr: aplcntEmlAddr || (userInfo?.email ?? ""), dsgnrNm, dsgnrTelno, dsgnrOgdpNm: dsgnrPsitn, @@ -852,22 +1003,22 @@ function CnfmRegistPage() { 신청자 이름 - {userInfo?.userName ?? "\u00A0"} + {aplcntNm || userInfo?.userName || "\u00A0"} 전화번호 - {userInfo?.mphn ?? userInfo?.telno ?? "\u00A0"} + {aplcntMblTelno || userInfo?.mphn || userInfo?.telno || "\u00A0"} 부서 - {userInfo?.instSeNm ?? "\u00A0"} + {aplcntOgdpNm || userInfo?.instSeNm || "\u00A0"} 이메일 - {userInfo?.email ?? "\u00A0"} + {aplcntEmlAddr || userInfo?.email || "\u00A0"}