dm: 물재이용 현황 중수도 작업 중

This commit is contained in:
2026-04-30 15:51:41 +09:00
parent 9b4d373f7d
commit d015432fc6
3 changed files with 154 additions and 85 deletions
@@ -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 (
<div className="flex items-center gap-3">
@@ -15,13 +25,6 @@ function Hr({ className = "" }: { className?: string }) {
return <div className={`h-[2px] w-full bg-black/10 ${className}`} />;
}
function SourceText() {
return (
<p className="mt-7 text-center text-[13px] text-neutral-500">
자료: 환경부(2024), 「2023 하수도 통계」
</p>
);
}
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 (
<p className="mt-7 text-center text-[13px] text-neutral-500">
자료: 환경부(2024), 「{selectYear} 하수도 통계」
</p>
);
}
useEffect(() => {
void getRswtrByLawYears('nofactory');
}, [getRswtrByLawYears]);
const renderPartHeaders = (headers: string[], headerColors: string[]) => {
return headers.map((header, index) => (
<th
key={header}
className={`${tableStyles.th} ${headerColors[index] ?? "bg-[#81C784]"} text-white`}
>
{header}
</th>
));
};
const renderCells = (
rowIdx: number,
row: DmStatusLawYearsType,
data: DmStatusLawYearsType[],
headers: TableHeaderType[]
) => {
const rowData = row as Record<string, string | number>;
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 (
<td
key={`${rowIdx}-${header.id}`}
rowSpan={getRowSpan()}
className={`${tableStyles.td} !font-bold !text-neutral-900`}
>
{value}
</td>
);
} else if (header.id === "COL2") {
return (
<td
key={`${rowIdx}-${header.id}`}
className={`${tableStyles.td} !font-bold !text-neutral-900`}
dangerouslySetInnerHTML={{ __html: Col2Name[value as string] ?? "" }}
/>
);
}
return (
<td
key={`${rowIdx}-${header.id}`}
className={`${tableStyles.td} ${[1, 3, 5].includes(index) ? "bg-[#EAF5F5]" : ""}`}
>
{String(rowData["COL2"]).indexOf("시설수") > -1
? Number(value).toLocaleString("ko-KR")
: formatUsage(value as string | number, 10000, 1) }
</td>
);
});
};
const title = "중수도(현황)";
return (
@@ -73,84 +176,14 @@ export default function GreywaterStatusSection() {
>
구분
</th>
<th className={`${tableStyles.th} bg-[#01ACE5] text-white`}>
2018
</th>
<th className={`${tableStyles.th} bg-[#14AFCD] text-white`}>
2019
</th>
<th className={`${tableStyles.th} bg-[#28B2B4] text-white`}>
2020
</th>
<th className={`${tableStyles.th} bg-[#3CB59A] text-white`}>
2021
</th>
<th className={`${tableStyles.th} bg-[#50B880] text-white`}>
2022
</th>
<th className={`${tableStyles.th} bg-[#6DBB4F] text-white`}>
2023
</th>
{renderPartHeaders(rswtrYears, headerColors6)}
</tr>
</thead>
<tbody>
{[
{
group: "전체",
rows: [
["시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>", "576", "633", "682", "740", "819", "842"],
["건축연면적 <span class='text-[13px] font-normal text-[#767676]'>(만m²)</span>", "1,494.2", "1,514.4", "1,524.9", "989.1", "1,104.3", "1,015.4"],
["처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>", "39.6", "40.0", "51.1", "47.1", "48.9", "50.7"],
["사용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/년)</span>", "2,223.4", "1,165.2", "6,713.0", "4,681.7", "3,918.2", "898.4"],
],
},
{
group: "법적 대상",
rows: [
["시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>", "146", "154", "156", "170", "166", "169"],
["건축연면적 <span class='text-[13px] font-normal text-[#767676]'>(만m²)</span>", "674.9", "682.4", "736.1", "421.1", "434.9", "465.5"],
["처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>", "20.0", "20.1", "31.2", "22.8", "21.2", "24.7"],
["사용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/년)</span>", "1,819.4", "712.8", "6,479.9", "4,416.8", "3,663.1", "616.1"],
],
},
{
group: "법적 비대상",
rows: [
["시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>", "430", "479", "526", "570", "653", "673"],
["건축연면적 <span class='text-[13px] font-normal text-[#767676]'>(만m²)</span>", "819.3", "832.0", "788.8", "568.0", "669.4", "549.9"],
["처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>", "19.6", "19.5", "19.9", "24.3", "27.7", "26.0"],
["사용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/년)</span>", "404.0", "452.4", "233.1", "264.9", "255.1", "282.3"],
],
},
].map((section, sIdx) => (
<React.Fragment key={sIdx}>
{section.rows.map((row, rIdx) => (
<tr key={`${sIdx}-${rIdx}`} className="bg-white">
{rIdx === 0 && (
<td
rowSpan={section.rows.length}
className={`${tableStyles.td} ${tableStyles.headerBg} !text-[18px] !font-bold !text-neutral-900`}
>
{section.group}
</td>
)}
{row.map((val, i) => {
const isFirstCol = i === 0;
const isHighlightedCol = [1, 3, 5].includes(i);
return (
<td
key={i}
className={`${tableStyles.td} ${
isFirstCol ? "!font-bold !text-neutral-900" : ""
} ${isHighlightedCol ? "bg-[#EAF5F5]" : ""}`}
dangerouslySetInnerHTML={{ __html: val }}
/>
);
})}
</tr>
))}
</React.Fragment>
{rswtrByLawYears.map((row, idx, arr) => (
<tr key={idx}>
{renderCells(idx, row, arr, rswtrByLawYearsHeader)}
</tr>
))}
</tbody>
</table>
@@ -458,4 +491,4 @@ export default function GreywaterStatusSection() {
</div>
</div>
);
}
}
+7
View File
@@ -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,
+30 -1
View File
@@ -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: "시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>", Y1: "576", Y2: "633", Y3: "682", Y4: "740", Y5: "819", Y6: "842" },
{ COL1: "전체", COL2: "건축연면적 <span class='text-[13px] font-normal text-[#767676]'>(만m²)</span>", 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: "처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>", Y1: "39.6", Y2: "40.0", Y3: "51.1", Y4: "47.1", Y5: "48.9", Y6: "50.7" },
{ COL1: "전체", COL2: "사용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/년)</span>", 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: "시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>", Y1: "146", Y2: "154", Y3: "156", Y4: "170", Y5: "166", Y6: "169" },
{ COL1: "법적 대상", COL2: "건축연면적 <span class='text-[13px] font-normal text-[#767676]'>(만m²)</span>", Y1: "674.9", Y2: "682.4", Y3: "736.1", Y4: "421.1", Y5: "434.9", Y6: "465.5" },
{ COL1: "법적 대상", COL2: "처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>", Y1: "20.0", Y2: "20.1", Y3: "31.2", Y4: "22.8", Y5: "21.2", Y6: "24.7" },
{ COL1: "법적 대상", COL2: "사용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/년)</span>", Y1: "1,819.4", Y2: "712.8", Y3: "6,479.9", Y4: "4,416.8", Y5: "3,663.1", Y6: "616.1" },
{ COL1: "법적 미대상", COL2: "시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>", Y1: "430", Y2: "479", Y3: "526", Y4: "570", Y5: "653", Y6: "673" },
{ COL1: "법적 미대상", COL2: "건축연면적 <span class='text-[13px] font-normal text-[#767676]'>(만m²)</span>", Y1: "819.3", Y2: "832.0", Y3: "788.8", Y4: "568.0", Y5: "669.4", Y6: "549.9" },
{ COL1: "법적 미대상", COL2: "처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>", Y1: "19.6", Y2: "19.5", Y3: "19.9", Y4: "24.3", Y5: "27.7", Y6: "26.0" },
{ COL1: "법적 미대상", COL2: "사용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/년)</span>", Y1: "404.0", Y2: "452.4", Y3: "233.1", Y4: "264.9", Y5: "255.1", Y6: "282.3" },
];
export const Col2Name: Record<string, string> =
{ CNT: "시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>",
TOTAR: "건축연면적 <span class='text-[13px] font-normal text-[#767676]'>(만m²)</span>",
PROCCPCTY: "처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
USECPCTY: "사용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/년)</span>",
TPUTTOTAL: "하수처리량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
USEAMNT: "재이용량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
REUSERT: "재이용률 <span class='text-[13px] font-normal text-[#767676]'>(%)</span>",
FCT_CPC: "시설용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
TOT_TPUT_AVE: "처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
};
export const rswtrByBildTpYearsHeader: TableHeaderType[] = [
{ id: "BILD_TP", title: "구분", row: 0, widthPercent: 15 },
{ id: "Y1", title: "2019", row: 1, widthPercent: 5 },