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 606c9c31c..1f5d867d0 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 @@ -55,6 +55,13 @@ const getRoleStepCount = (dtlInstCd?: string): number => { return mapped ? REVIEW_STEP_ROLE_RANK[mapped] : 0; }; +// 업무구분 코드 -> 표시명 매핑 (체크리스트 그룹 표시용) +const TASK_CODE_LABELS: Record = { + RE: "재이용수", + SP: "하수관로", + SF: "하수처리시설", +}; + const normalizeChecklistResultMap = ( raw: unknown, ): Record => { @@ -122,6 +129,13 @@ function CnfmViewPage({ id }: { id: string }) { [visibleStepCount], ); const [selectedReviewStep, setSelectedReviewStep] = useState("LOCAL"); + // selected task code for header filtering (null = none selected) + const [selectedTaskCode, setSelectedTaskCode] = useState(null); + + // derive available task codes from checklist results + const taskCodes = useMemo(() => { + return Array.from(new Set((cklstAll ?? []).map((r: any) => (r as any).taskSeComCd).filter(Boolean))); + }, [cklstAll]); useEffect(() => { if (visibleReviewStepCodes.length === 0) return; @@ -130,10 +144,28 @@ function CnfmViewPage({ id }: { id: string }) { } }, [selectedReviewStep, visibleReviewStepCodes]); + // when checklist result task codes change, default selectedTaskCode to first available code + useEffect(() => { + if (!taskCodes || taskCodes.length === 0) { + if (selectedTaskCode !== null) setSelectedTaskCode(null); + return; + } + if (!selectedTaskCode || !taskCodes.includes(selectedTaskCode)) { + setSelectedTaskCode(taskCodes[0]); + } + }, [taskCodes, selectedTaskCode]); + const selectedChecklistRows = useMemo(() => { if (visibleReviewStepCodes.length === 0) return []; - return cklstResultMap[selectedReviewStep] ?? []; - }, [cklstResultMap, selectedReviewStep, visibleReviewStepCodes.length]); + const rows = (cklstResultMap[selectedReviewStep] ?? []).filter((r: any) => + selectedTaskCode ? (r.taskSeComCd ?? "") === selectedTaskCode : true, + ); + return rows + .slice() + .sort((a: any, b: any) => + (a.cklstArtclSn ?? 0) - (b.cklstArtclSn ?? 0) || (a.sortSeq ?? 0) - (b.sortSeq ?? 0) || (a.cklstRvwSn ?? 0) - (b.cklstRvwSn ?? 0), + ); + }, [cklstResultMap, selectedReviewStep, visibleReviewStepCodes.length, selectedTaskCode]); const [viewCheckResults, setViewCheckResults] = useState>({}); const [viewCheckComments, setViewCheckComments] = useState>({}); @@ -142,7 +174,7 @@ function CnfmViewPage({ id }: { id: string }) { const results: Record = {}; const comments: Record = {}; (selectedChecklistRows ?? []).forEach((row: any) => { - const key = `${row.cklstSn}_${row.cklstRvwSn}_${row.rvwStpComCd ?? "LOCAL"}`; + const key = `${row.taskSeComCd ?? ""}_${row.cklstSn}_${row.cklstArtclSn ?? ""}_${row.cklstRvwSn}_${row.rvwStpComCd ?? "LOCAL"}`; if (row.rvwRsltAnmlyYn === "Y" || row.rvwRsltAnmlyYn === "N") results[key] = row.rvwRsltAnmlyYn; if (row.picRvwCn) comments[key] = String(row.picRvwCn); }); @@ -387,6 +419,24 @@ function CnfmViewPage({ id }: { id: string }) { {/* 체크리스트 */}

체크리스트

+
+ {Array.from(new Set(taskCodes)).map((code) => { + const name = TASK_CODE_LABELS[code] ?? code; + const active = selectedTaskCode === code; + return ( + + ); + })} +
{visibleReviewStepCodes.length === 0 ? ( @@ -446,7 +496,7 @@ function CnfmViewPage({ id }: { id: string }) { ) : ( selectedChecklistRows.map((row: any) => { - const key = `${row.cklstSn}_${row.cklstRvwSn}_${row.rvwStpComCd ?? "LOCAL"}`; + const key = `${row.taskSeComCd ?? ""}_${row.cklstSn}_${row.cklstArtclSn ?? ""}_${row.cklstRvwSn}_${row.rvwStpComCd ?? "LOCAL"}`; const hasResult = row.rvwRsltAnmlyYn === "Y" || row.rvwRsltAnmlyYn === "N"; const showRadios = row.bchckUseYn === "Y" ;