diff --git a/apps/st/src/components/statistics/total/ExcretaTreatmentFacilityTot.tsx b/apps/st/src/components/statistics/total/ExcretaTreatmentFacilityTot.tsx index e470b07fa..a5c7f2dae 100644 --- a/apps/st/src/components/statistics/total/ExcretaTreatmentFacilityTot.tsx +++ b/apps/st/src/components/statistics/total/ExcretaTreatmentFacilityTot.tsx @@ -1,10 +1,123 @@ +import { useRef, useState } from "react"; + +import { useAlertStore } from "@/shared/lib"; +import { LoadingWithAnimation } from "@common/components"; + import SearchForm from "@/components/module/SearchForm"; +import DataGrid from "@/components/module/DataGrid"; +import type { ColumnInfo } from "@/components/type/DataGrid.type"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { toGridRows } from "@/components/util/grid/gridFunction"; + +// 분리된 분뇨처리시설용 컬럼 구성 임포트 +import { ExcretaTreatmentStatusColumnConfig } from "@/components/util/column/total/SewerExcretaTreatmentStatusColumn"; + +// 집계표(TOTAL) API 및 인터페이스 명세 호출 +import { statisticsTotalStatusApi } from "@/entities/statistics/api/statistics-total-service"; +import type { + ExcretaTreatmentMaintainTotalRequest +} from "@/entities/statistics/model/statistics-total/statistics-excreta-treatment-total-interface"; +import CellColorInfo from "./CellColorInfo"; const ExcretaTreatmentFacilityTot = () => { + const { setMessage: alert } = useAlertStore((state) => state); + + // null 타입 컴파일 에러를 방지하기 위해 엄격하게 정의한 데이터 상태 + const [rowData, setRowData] = useState[]>([]); + const [isLoading, setIsLoading] = useState(false); + const lastSearchedValuesRef = useRef(null); + + const config = ExcretaTreatmentStatusColumnConfig; + + const handleReset = () => { + setRowData([]); + lastSearchedValuesRef.current = null; + }; + + const loadGridData = async (values: SearchFormValues): Promise => { + const param: ExcretaTreatmentMaintainTotalRequest = { + ctpvNm: values.sido === "ALL" ? "" : values.sido, + sggNm: values.gugun === "ALL" ? "" : values.gugun, + sewerBzmnCd: values.bsnmCd, + statsYr: values.year, + rowDataYn: values.isDetail, + summaryYn: values.isSummary !== 'ALL', + summaryYearCnt: values.isSummary !== 'ALL' ? Number(values.isSummary) : undefined + }; + + try { + const response = await statisticsTotalStatusApi.getExcretaTreatmentStatusTotalList(param); + if (response && response.status === "success" && response.data) { + // object[]로 변환하여 주입함으로써 상위 컴포넌트 간 null 에러 완벽 차단 + setRowData(toGridRows(response.data as object[])); + return true; + } + alert(response?.message || "데이터 조회 중 오류가 발생했습니다."); + return false; + } catch { + alert("서버 연결 중 오류가 발생했습니다."); + return false; + } + }; + + const handleSearch = async (values: SearchFormValues) => { + try { + setIsLoading(true); + const ok = await loadGridData(values); + if (ok) { + lastSearchedValuesRef.current = values; + } else { + lastSearchedValuesRef.current = null; + } + } catch { + alert("데이터 조회 중 오류가 발생했습니다."); + lastSearchedValuesRef.current = null; + } finally { + setIsLoading(false); + } + }; + + const gridColumnInfo: ColumnInfo = { + columns: config.columns, + columnLayout: config.columnLayout, + }; + return ( - <> - - +
+ + + {isLoading && ( +
+
+ +
+
+ )} + + + +
+ { + const rowType = String(row.rowType ?? ''); + if (rowType === 'DETAIL') return undefined; + if (rowType === 'BIZ_SUM') return 'rg-cell-rowtype-biz-sum'; + if (rowType === 'SUMMARY') return 'rg-cell-rowtype-summary'; + return 'rg-cell-rowtype-other'; + }} + /> +
+
); }; diff --git a/apps/st/src/components/util/column/total/SewerExcretaTreatmentStatusColumn.ts b/apps/st/src/components/util/column/total/SewerExcretaTreatmentStatusColumn.ts new file mode 100644 index 000000000..0f5ded556 --- /dev/null +++ b/apps/st/src/components/util/column/total/SewerExcretaTreatmentStatusColumn.ts @@ -0,0 +1,63 @@ +import { ValueType } from "realgrid"; + +export const ExcretaTreatmentStatusColumnConfig = { + tabKey: "ST00070001", + tabLabel: "분뇨처리시설", + rowStartNum: 2, + fixedColumns: 2, + columns: [ + // 행정구역 + { name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false }, + { name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false }, + { name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역명" }, editable: false }, + + // 기본 마스터 상세 + { name: "fcltNm", fieldName: "fcltNm", header: { text: "시설명" }, editable: false }, + { name: "fcltPstnCn", fieldName: "fcltPstnCn", header: { text: "소재지" }, editable: false }, + { name: "telNo", fieldName: "telNo", header: { text: "전화번호" }, editable: false }, + { name: "cmptnStrtYmd", fieldName: "cmptnStrtYmd", header: { text: "준공일" }, editable: false }, + { name: "oprtngStrtYmd", fieldName: "oprtngStrtYmd", header: { text: "가동개시일" }, editable: false }, + { name: "wholPjtcoAmt", fieldName: "wholPjtcoAmt", header: { text: "사업비\n(백만원)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "prcsFcltCpct", fieldName: "prcsFcltCpct", header: { text: "시설용량\n(㎥/일)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, + { name: "cpct", fieldName: "cpct", header: { text: "처리량\n(㎥/일)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, + { name: "oprtngDayCnt", fieldName: "oprtngDayCnt", header: { text: "가동일수\n(일/년)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "prcsMthdExpln", fieldName: "prcsMthdExpln", header: { text: "처리공법" }, editable: false }, + { name: "linkTmplntCn", fieldName: "linkTmplntCn", header: { text: "연계처리장명" }, editable: false }, + { name: "linkPrcsQnt", fieldName: "linkPrcsQnt", header: { text: "연계처리량\n(㎥/일)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, + + // 유입수질(mg/L, 개/mL) 그룹 소속 + { name: "inflwBodWqVl", fieldName: "inflwBodWqVl", header: { text: "BOD" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "inflwTocWqVl", fieldName: "inflwTocWqVl", header: { text: "TOC" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "inflwSsWqVl", fieldName: "inflwSsWqVl", header: { text: "SS" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "inflwTnWqVl", fieldName: "inflwTnWqVl", header: { text: "T-N" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "inflwTpWqVl", fieldName: "inflwTpWqVl", header: { text: "T-P" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.000", editable: false }, + { name: "inflwClfgCnt", fieldName: "inflwClfgCnt", header: { text: "대장균\n군수" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + + // 방류수질(mg/L, 개/mL) 그룹 소속 + { name: "dschgBodWqVl", fieldName: "dschgBodWqVl", header: { text: "BOD" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "dschgTocWqVl", fieldName: "dschgTocWqVl", header: { text: "TOC" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "dschgSsWqVl", fieldName: "dschgSsWqVl", header: { text: "SS" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "dschgTnWqVl", fieldName: "dschgTnWqVl", header: { text: "T-N" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + { name: "dschgTpWqVl", fieldName: "dschgTpWqVl", header: { text: "T-P" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.000", editable: false }, + { name: "dschgClfgCnt", fieldName: "dschgClfgCnt", header: { text: "대장균\n군수" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + + // 방류수역 그룹 소속 + { name: "wtsysNm", fieldName: "wtsysNm", header: { text: "수계" }, editable: false }, + { name: "trbtrNm", fieldName: "trbtrNm", header: { text: "지류" }, editable: false }, + { name: "msirbCn", fieldName: "msirbCn", header: { text: "중권역" }, editable: false }, + { name: "ssirbCn", fieldName: "ssirbCn", header: { text: "소권역" }, editable: false }, + + // 단일 미그룹 성격 컬럼들 + { name: "operMthdCdCn", fieldName: "operMthdCdCn", header: { text: "운영주체\n(자체/공기업/\n민간위탁)" }, editable: false }, + { name: "wholNope", fieldName: "wholNope", header: { text: "직원총수\n(명)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "sftyAcdntEvntcsCnt", fieldName: "sftyAcdntEvntcsCnt", header: { text: "안전사고\n건수\n(건/인/년)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false } + ], + columnLayout: [ + { name: "areaGroup", header: { text: "행정구역" }, items: ["ctpvNm", "sggNm", "admdstNm"] }, + "fcltNm", "fcltPstnCn", "telNo", "cmptnStrtYmd", "oprtngStrtYmd", "wholPjtcoAmt", "prcsFcltCpct", "cpct", "oprtngDayCnt", "prcsMthdExpln", "linkTmplntCn", "linkPrcsQnt", + { name: "inflwWqGroup", header: { text: "유입수질(mg/L, 개/mL)" }, items: ["inflwBodWqVl", "inflwTocWqVl", "inflwSsWqVl", "inflwTnWqVl", "inflwTpWqVl", "inflwClfgCnt"] }, + { name: "dschgWqGroup", header: { text: "방류수질(mg/L, 개/mL)" }, items: ["dschgBodWqVl", "dschgTocWqVl", "dschgSsWqVl", "dschgTnWqVl", "dschgTpWqVl", "dschgClfgCnt"] }, + { name: "wtrAreaGroup", header: { text: "방류수역" }, items: ["wtsysNm", "trbtrNm", "msirbCn", "ssirbCn"] }, + "operMthdCdCn", "wholNope", "sftyAcdntEvntcsCnt" + ] +}; \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/statistics-total/statistics-excreta-treatment-total-interface.ts b/apps/st/src/entities/statistics/model/statistics-total/statistics-excreta-treatment-total-interface.ts new file mode 100644 index 000000000..dc9446b32 --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-total/statistics-excreta-treatment-total-interface.ts @@ -0,0 +1,62 @@ +/** 07. 분뇨처리시설 현황 검색 조건 파라미터 DTO */ +export interface ExcretaTreatmentMaintainTotalRequest { + ctpvNm?: string; + sggNm?: string; + statsYr?: string; + swtrmtFcltNm?: string; + sewerBzmnCd?: string; + rowDataYn?: boolean; + summaryYn?: boolean; + summaryYearCnt?: number; +} + +/** 분뇨처리시설 목록 데이터 행 구조 */ +export interface ExcretaTreatmentStatusTotalItem { + ctpvNm: string; + sggNm: string | null; + statsYr: string; + admdstNm: string; + admdstCd: string; + fcltNm: string; + rowType: string; + fcltPstnCn: string; + telNo: string; + cmptnStrtYmd: string; + oprtngStrtYmd: string; + wholPjtcoAmt: number; + prcsFcltCpct: number; + cpct: number; + oprtngDayCnt: number; + prcsMthdExpln: string; + linkTmplntCn: string; + linkPrcsQnt: number; + // 유입수질 + inflwBodWqVl: number; + inflwTocWqVl: number; + inflwSsWqVl: number; + inflwTnWqVl: number; + inflwTpWqVl: number; + inflwClfgCnt: number; + // 방류수질 + dschgBodWqVl: number; + dschgTocWqVl: number; + dschgSsWqVl: number; + dschgTnWqVl: number; + dschgTpWqVl: number; + dschgClfgCnt: number; + // 방류수역 및 기타 정보 + wtsysNm: string; + trbtrNm: string; + msirbCn: string; + ssirbCn: string; + operMthdCdCn: string; + wholNope: number; + sftyAcdntEvntcsCnt: number; +} + +/** 분뇨처리시설 API 응답 인터페이스 */ +export interface ExcretaTreatmentStatusTotalResponse { + status: string; + message?: string; + data: ExcretaTreatmentStatusTotalItem[]; +} \ No newline at end of file