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}