From d015432fc692a107dda15558fa2a3f4297cc59be Mon Sep 17 00:00:00 2001 From: ljpark Date: Thu, 30 Apr 2026 15:51:41 +0900 Subject: [PATCH] =?UTF-8?q?dm:=20=EB=AC=BC=EC=9E=AC=EC=9D=B4=EC=9A=A9=20?= =?UTF-8?q?=ED=98=84=ED=99=A9=20=EC=A4=91=EC=88=98=EB=8F=84=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components/GreywaterStatusSection.tsx | 201 ++++++++++-------- apps/dm/app/common/transValueFormat.tsx | 7 + apps/dm/app/store/dm-status/type.ts | 31 ++- 3 files changed, 154 insertions(+), 85 deletions(-) diff --git a/apps/dm/app/(with-layout)/status/_components/GreywaterStatusSection.tsx b/apps/dm/app/(with-layout)/status/_components/GreywaterStatusSection.tsx index 1f5f93b44..d6affe1c2 100644 --- a/apps/dm/app/(with-layout)/status/_components/GreywaterStatusSection.tsx +++ b/apps/dm/app/(with-layout)/status/_components/GreywaterStatusSection.tsx @@ -1,7 +1,17 @@ "use client"; import React from "react"; - +import { useEffect, useMemo } from "react"; +// import SubPageHeader from "@/components/SubPageHeader"; +import { useDmStore } from "@/app/store"; +import { formatUsage } from "@/app/common/transValueFormat"; +import type { + DmStatusLawYearsType, + DmStatusUsgBildTpType, + DmStatusUsgYearsType, + TableHeaderType, +} from "@/app/store/dm-status/type"; +import { Col2Name } from "@/app/store/dm-status/type"; function SectionTitle({ children }: { children: React.ReactNode }) { return (
@@ -15,13 +25,6 @@ function Hr({ className = "" }: { className?: string }) { return
; } -function SourceText() { - return ( -

- 자료: 환경부(2024), 「2023 하수도 통계」 -

- ); -} const tableStyles = { container: "w-[1000px] mx-auto overflow-hidden", @@ -31,7 +34,107 @@ const tableStyles = { headerBg: "bg-[#E3E7EA]", }; +const headerColors6 = [ + "bg-[#01ACE5]", + "bg-[#17AFC7]", + "bg-[#2CB2A9]", + "bg-[#42B58B]", + "bg-[#57B86D]", + "bg-[#81C784]", +]; + export default function GreywaterStatusSection() { + const getRswtrByLawYears = useDmStore((state) => state.getRswtrByLawYears); + const rswtrYears = useDmStore((state) => state.rswtr.rswtrYears); + const selectYear = rswtrYears.slice(-1)[0]; + const rswtrByLawYearsHeader = useDmStore((state) => state.rswtr.rswtrByLawYearsHeader); + const rswtrByLawYears = useDmStore((state) => state.rswtr.rswtrByLawYears); + + // 출처 텍스트 + function SourceText() { + return ( +

+ 자료: 환경부(2024), 「{selectYear} 하수도 통계」 +

+ ); + } + + useEffect(() => { + void getRswtrByLawYears('nofactory'); + }, [getRswtrByLawYears]); + + const renderPartHeaders = (headers: string[], headerColors: string[]) => { + return headers.map((header, index) => ( + + {header} + + )); + }; + + const renderCells = ( + rowIdx: number, + row: DmStatusLawYearsType, + data: DmStatusLawYearsType[], + headers: TableHeaderType[] + ) => { + const rowData = row as Record; + const currentCol1 = String(rowData["COL1"] ?? ""); + + // 이전 값 + const prevCol1 = rowIdx > 0 ? data[rowIdx - 1]?.COL1 : null; + + // 현재 그룹의 rowspan 계산 + const getRowSpan = () => { + let count = 0; + for (let i = rowIdx; i < data.length; i++) { + if (data[i]?.COL1 === currentCol1) count++; + else break; + } + return count; + }; + + return headers.map((header, index) => { + const value = rowData[header.id]; + + // COL1 처리 (rowspan 핵심) + if (header.id === "COL1") { + // 이전과 같으면 렌더링 안함 + if (currentCol1 === prevCol1) return null; + + return ( + + {value} + + ); + } else if (header.id === "COL2") { + return ( + + ); + } + + return ( + + {String(rowData["COL2"]).indexOf("시설수") > -1 + ? Number(value).toLocaleString("ko-KR") + : formatUsage(value as string | number, 10000, 1) } + + ); + }); + }; const title = "중수도(현황)"; return ( @@ -73,84 +176,14 @@ export default function GreywaterStatusSection() { > 구분 - - 2018 - - - 2019 - - - 2020 - - - 2021 - - - 2022 - - - 2023 - + {renderPartHeaders(rswtrYears, headerColors6)} - {[ - { - group: "전체", - rows: [ - ["시설수 (개소)", "576", "633", "682", "740", "819", "842"], - ["건축연면적 (만m²)", "1,494.2", "1,514.4", "1,524.9", "989.1", "1,104.3", "1,015.4"], - ["처리용량 (만m³/일)", "39.6", "40.0", "51.1", "47.1", "48.9", "50.7"], - ["사용량 (만m³/년)", "2,223.4", "1,165.2", "6,713.0", "4,681.7", "3,918.2", "898.4"], - ], - }, - { - group: "법적 대상", - rows: [ - ["시설수 (개소)", "146", "154", "156", "170", "166", "169"], - ["건축연면적 (만m²)", "674.9", "682.4", "736.1", "421.1", "434.9", "465.5"], - ["처리용량 (만m³/일)", "20.0", "20.1", "31.2", "22.8", "21.2", "24.7"], - ["사용량 (만m³/년)", "1,819.4", "712.8", "6,479.9", "4,416.8", "3,663.1", "616.1"], - ], - }, - { - group: "법적 비대상", - rows: [ - ["시설수 (개소)", "430", "479", "526", "570", "653", "673"], - ["건축연면적 (만m²)", "819.3", "832.0", "788.8", "568.0", "669.4", "549.9"], - ["처리용량 (만m³/일)", "19.6", "19.5", "19.9", "24.3", "27.7", "26.0"], - ["사용량 (만m³/년)", "404.0", "452.4", "233.1", "264.9", "255.1", "282.3"], - ], - }, - ].map((section, sIdx) => ( - - {section.rows.map((row, rIdx) => ( - - {rIdx === 0 && ( - - {section.group} - - )} - {row.map((val, i) => { - const isFirstCol = i === 0; - const isHighlightedCol = [1, 3, 5].includes(i); - - return ( - - ); - })} - - ))} - + {rswtrByLawYears.map((row, idx, arr) => ( + + {renderCells(idx, row, arr, rswtrByLawYearsHeader)} + ))} @@ -458,4 +491,4 @@ export default function GreywaterStatusSection() {
); -} \ No newline at end of file +} diff --git a/apps/dm/app/common/transValueFormat.tsx b/apps/dm/app/common/transValueFormat.tsx index a9120d695..4486d7d93 100644 --- a/apps/dm/app/common/transValueFormat.tsx +++ b/apps/dm/app/common/transValueFormat.tsx @@ -25,6 +25,13 @@ export default function TransValueFormat({value='', format=''}: CommonProps) { ) } +/** + * 천,만 등의 단위 변경 && 반올림 및 소숫점 자리수 지정 + * @param value + * @param unitSize 단위 변경 1000 인 경우, 100,000 -> 100 으로 변경 + * @param decimalPlaces 어느 자리수에서 반올림할지 지정 1이면 소수 두번째 자리에서 반올림 + * @returns + */ export const formatUsage = ( value: string | number, unitSize: number = 1, diff --git a/apps/dm/app/store/dm-status/type.ts b/apps/dm/app/store/dm-status/type.ts index 986471d83..c9d8986e9 100644 --- a/apps/dm/app/store/dm-status/type.ts +++ b/apps/dm/app/store/dm-status/type.ts @@ -140,7 +140,8 @@ export const rainyByUsgYearsInit: DmStatusUsgYearsType[] = [ // 전체 중수도 설치 및 이용 현황 (공장 및 발전시설 제외) export const rswtrByLawYearsHeader: TableHeaderType[] = [ - { id: "BILD_TP", title: "구분", row: 0, widthPercent: 15 }, + { id: "COL1", title: "구분", row: 0, widthPercent: 15 }, + { id: "COL2", title: "구분", row: 0, widthPercent: 15 }, { id: "Y1", title: "2019", row: 1, widthPercent: 5 }, { id: "Y2", title: "2020", row: 1, widthPercent: 5 }, { id: "Y3", title: "2021", row: 1, widthPercent: 5 }, @@ -149,6 +150,34 @@ export const rswtrByLawYearsHeader: TableHeaderType[] = [ { id: "Y6", title: "2024", row: 1, widthPercent: 5 }, ]; +export const rswtrByLawYearsInit: DmStatusLawYearsType[] = [ + { COL1: "전체", COL2: "시설수 (개소)", Y1: "576", Y2: "633", Y3: "682", Y4: "740", Y5: "819", Y6: "842" }, + { COL1: "전체", COL2: "건축연면적 (만m²)", Y1: "1,494.2", Y2: "1,514.4", Y3: "1,524.9", Y4: "989.1", Y5: "1,104.3", Y6: "1,015.4" }, + { COL1: "전체", COL2: "처리용량 (만m³/일)", Y1: "39.6", Y2: "40.0", Y3: "51.1", Y4: "47.1", Y5: "48.9", Y6: "50.7" }, + { COL1: "전체", COL2: "사용량 (만m³/년)", Y1: "2,223.4", Y2: "1,165.2", Y3: "6,713.0", Y4: "4,681.7", Y5: "3,918.2", Y6: "898.4" }, + { COL1: "법적 대상", COL2: "시설수 (개소)", Y1: "146", Y2: "154", Y3: "156", Y4: "170", Y5: "166", Y6: "169" }, + { COL1: "법적 대상", COL2: "건축연면적 (만m²)", Y1: "674.9", Y2: "682.4", Y3: "736.1", Y4: "421.1", Y5: "434.9", Y6: "465.5" }, + { COL1: "법적 대상", COL2: "처리용량 (만m³/일)", Y1: "20.0", Y2: "20.1", Y3: "31.2", Y4: "22.8", Y5: "21.2", Y6: "24.7" }, + { COL1: "법적 대상", COL2: "사용량 (만m³/년)", Y1: "1,819.4", Y2: "712.8", Y3: "6,479.9", Y4: "4,416.8", Y5: "3,663.1", Y6: "616.1" }, + { COL1: "법적 미대상", COL2: "시설수 (개소)", Y1: "430", Y2: "479", Y3: "526", Y4: "570", Y5: "653", Y6: "673" }, + { COL1: "법적 미대상", COL2: "건축연면적 (만m²)", Y1: "819.3", Y2: "832.0", Y3: "788.8", Y4: "568.0", Y5: "669.4", Y6: "549.9" }, + { COL1: "법적 미대상", COL2: "처리용량 (만m³/일)", Y1: "19.6", Y2: "19.5", Y3: "19.9", Y4: "24.3", Y5: "27.7", Y6: "26.0" }, + { COL1: "법적 미대상", COL2: "사용량 (만m³/년)", Y1: "404.0", Y2: "452.4", Y3: "233.1", Y4: "264.9", Y5: "255.1", Y6: "282.3" }, +]; + +export const Col2Name: Record = + { CNT: "시설수 (개소)", + TOTAR: "건축연면적 (만m²)", + PROCCPCTY: "처리용량 (만m³/일)", + USECPCTY: "사용량 (만m³/년)", + TPUTTOTAL: "하수처리량 (백만m³/년)", + USEAMNT: "재이용량 (백만m³/년)", + REUSERT: "재이용률 (%)", + FCT_CPC: "시설용량 (만m³/일)", + TOT_TPUT_AVE: "처리용량 (만m³/일)", + }; + + export const rswtrByBildTpYearsHeader: TableHeaderType[] = [ { id: "BILD_TP", title: "구분", row: 0, widthPercent: 15 }, { id: "Y1", title: "2019", row: 1, widthPercent: 5 },