From 5331e10c96aae8dabc4a81eced9dd3c17a50c4d2 Mon Sep 17 00:00:00 2001 From: yangsein Date: Wed, 30 Sep 2026 16:59:05 +0900 Subject: [PATCH] =?UTF-8?q?[refactor]=20=EB=8C=80=EC=8B=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20-=20=ED=86=B5=EA=B3=84=EC=B2=98=EB=A6=AC=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EB=B0=98=EB=A0=A4=EB=90=98=EC=96=B4=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=EC=A4=91=EC=9D=B8=20=EC=83=81=ED=83=9C=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84=20=EC=B2=98=EB=A6=AC=20=ED=8F=AC=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/dashboard/dashboard-interface.ts | 3 + .../ui/panels/three-stage-status-panel.tsx | 144 ++++++++++++++---- 2 files changed, 120 insertions(+), 27 deletions(-) diff --git a/apps/st/src/entities/statistics/model/dashboard/dashboard-interface.ts b/apps/st/src/entities/statistics/model/dashboard/dashboard-interface.ts index cb3d69db7..603c7f103 100644 --- a/apps/st/src/entities/statistics/model/dashboard/dashboard-interface.ts +++ b/apps/st/src/entities/statistics/model/dashboard/dashboard-interface.ts @@ -69,10 +69,13 @@ export interface ThreeStageStatusResponse { statsYr: string; laeStatusCd: string; laeStatusNm: string; + laeRejected: boolean; ctpvStatusCd: string; ctpvStatusNm: string; + ctpvRejected: boolean; pbcpStatusCd: string; pbcpStatusNm: string; + pbcpRejected: boolean; } export interface DashboardService { diff --git a/apps/st/src/pages/statistics/ui/panels/three-stage-status-panel.tsx b/apps/st/src/pages/statistics/ui/panels/three-stage-status-panel.tsx index ac914a93f..d90ced782 100644 --- a/apps/st/src/pages/statistics/ui/panels/three-stage-status-panel.tsx +++ b/apps/st/src/pages/statistics/ui/panels/three-stage-status-panel.tsx @@ -15,26 +15,62 @@ interface StepDef { label: string; subLabel: string; description: string; + rejectedDescription: string; } const STEPS: StepDef[] = [ - { key: "input", label: "입력", subLabel: "작성자", description: "담당자가 통계 자료를 입력합니다." }, - { key: "submit", label: "제출", subLabel: "작성자", description: "입력을 마친 자료를 제출합니다." }, - { key: "approve", label: "승인", subLabel: "승인자", description: "지자체 승인자가 제출 내용을 승인합니다." }, - { key: "review", label: "검토", subLabel: "시도", description: "광역시도 담당자가 자료를 검토합니다." }, - { key: "verify", label: "검증", subLabel: "공단", description: "환경공단이 최종 검증을 진행합니다." }, + { + key: "input", + label: "입력", + subLabel: "작성자", + description: "담당자가 통계 자료를 입력합니다.", + rejectedDescription: "반려된 자료에 대한 수정보완 후 제출합니다.", + }, + { + key: "submit", + label: "제출", + subLabel: "작성자", + description: "입력을 마친 자료를 제출합니다.", + rejectedDescription: "반려된 자료에 대한 수정보완 후 제출합니다.", + }, + { + key: "approve", + label: "승인", + subLabel: "승인자", + description: "지자체 승인자가 제출 내용을 승인합니다.", + rejectedDescription: "반려된 자료에 대한 수정보완 후 제출합니다.", + }, + { + key: "review", + label: "검토", + subLabel: "시도", + description: "광역시도 담당자가 자료를 검토합니다.", + rejectedDescription: "반려된 자료에 대한 수정보완 후 재검토를 요청합니다.", + }, + { + key: "verify", + label: "검증", + subLabel: "공단", + description: "환경공단이 최종 검증을 진행합니다.", + rejectedDescription: "반려된 자료에 대한 수정보완 후 재검증을 요청합니다.", + }, ]; +interface ThreeStageData { + laeStatusCd: string; + laeRejected: boolean; + ctpvStatusCd: string; + ctpvRejected: boolean; + pbcpStatusCd: string; + pbcpRejected: boolean; +} + /** * lae_sbmsn_stts_cd(지자체) : 0=미작성 1=작성중 2=제출완료 3=승인 * stat_pic_sbmsn_stts_cd(광역시도), pbcp_sbmsn_stts_cd(공단) 도 동일 코드 도메인 가정 * - 실제 코드값 의미는 STINPUTSTP 코드 그룹 기준 재확인 필요 */ -function resolveCheckedSteps(data?: { - laeStatusCd: string; - ctpvStatusCd: string; - pbcpStatusCd: string; -}): boolean[] { +function resolveCheckedSteps(data?: ThreeStageData): boolean[] { if (!data) return STEPS.map(() => false); const lae = Number(data.laeStatusCd); @@ -50,6 +86,18 @@ function resolveCheckedSteps(data?: { ]; } +// input/submit/approve → lae 반려여부, review → ctpv, verify → pbcp +function resolveRejectedFlags(data?: ThreeStageData): boolean[] { + if (!data) return STEPS.map(() => false); + return [ + data.laeRejected, + data.laeRejected, + data.laeRejected, + data.ctpvRejected, + data.pbcpRejected, + ]; +} + interface ThreeStageStatusPanelProps { params: DashboardSearchParams | null; } @@ -59,10 +107,23 @@ export function ThreeStageStatusPanel({ params }: ThreeStageStatusPanelProps) { const { data, isLoading, isFetching } = useDashboardThreeStageStatus(params); const checkedList = resolveCheckedSteps(data); + const rejectedFlags = resolveRejectedFlags(data); const currentIndex = checkedList.findIndex((v) => !v); const isAllDone = currentIndex === -1; const currentStep = STEPS[isAllDone ? STEPS.length - 1 : currentIndex]!; - const currentLabel = isAllDone ? "전 단계 완료" : `${currentStep.label} 대기중`; + const isCurrentRejected = !isAllDone && rejectedFlags[currentIndex]; + + const currentLabel = isAllDone + ? "전 단계 완료" + : isCurrentRejected + ? `${currentStep.label} 반려` + : `${currentStep.label} 대기중`; + + const currentDescription = isAllDone + ? "모든 절차가 완료되었습니다." + : isCurrentRejected + ? currentStep.rejectedDescription + : currentStep.description; return (
@@ -76,7 +137,9 @@ export function ThreeStageStatusPanel({ params }: ThreeStageStatusPanelProps) { className={`rounded-full px-4 py-1.5 text-base font-medium ${ isAllDone ? "bg-blue-50 text-blue-600" - : "bg-amber-50 text-amber-600" + : isCurrentRejected + ? "bg-red-50 text-red-600" + : "bg-amber-50 text-amber-600" }`} > {currentLabel} @@ -94,6 +157,7 @@ export function ThreeStageStatusPanel({ params }: ThreeStageStatusPanelProps) { {STEPS.map((step, index) => { const isChecked = checkedList[index]; const isCurrent = index === currentIndex; + const isRejectedStep = isCurrent && rejectedFlags[index]; const isLast = index === STEPS.length - 1; const lineFilled = checkedList[index]; @@ -101,16 +165,29 @@ export function ThreeStageStatusPanel({ params }: ThreeStageStatusPanelProps) {
- {isCurrent && ( + {isRejectedStep && ( +
+ + 반려 + + +
+ )} + {isCurrent && !isRejectedStep && ( )} + {isRejectedStep && ( + + )}
{isChecked ? ( @@ -128,7 +205,11 @@ export function ThreeStageStatusPanel({ params }: ThreeStageStatusPanelProps) { ) : ( )} @@ -139,9 +220,11 @@ export function ThreeStageStatusPanel({ params }: ThreeStageStatusPanelProps) { className={`text-xl font-bold ${ isChecked ? "text-blue-700" - : isCurrent - ? "text-blue-600" - : "text-gray-400" + : isRejectedStep + ? "text-red-600" + : isCurrent + ? "text-blue-600" + : "text-gray-400" }`} > {step.label} @@ -164,15 +247,22 @@ export function ThreeStageStatusPanel({ params }: ThreeStageStatusPanelProps) { })}
-
-

+

+

{isAllDone ? "현재 단계" : "다음 진행 단계"} · {currentStep.label} + {isCurrentRejected ? " (반려)" : ""}

-

- {isAllDone - ? "모든 절차가 완료되었습니다." - : currentStep.description} -

+

{currentDescription}