@@ -1,7 +1,10 @@
|
||||
/**
|
||||
* 중수도
|
||||
*/
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useEffect } from "react";
|
||||
// import SubPageHeader from "@/components/SubPageHeader";
|
||||
import Image from "next/image";
|
||||
import { useDmStore } from "@/app/store";
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
/**
|
||||
* 하수처리수
|
||||
*/
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { useEffect } from "react";
|
||||
import { useDmStore } from "@/app/store";
|
||||
import { formatUsage } from "@/app/common/transValueFormat";
|
||||
import type {
|
||||
DmStatusLawYearsType,
|
||||
DmStatusBildTpYearsType,
|
||||
DmStatusUsgYearsType,
|
||||
DmStatusSidoUsgType,
|
||||
TableHeaderType,
|
||||
} from "@/app/store/dm-status/type";
|
||||
import { Col2Name } from "@/app/store/dm-status/type";
|
||||
|
||||
function SectionTitle({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
@@ -16,14 +30,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>
|
||||
);
|
||||
}
|
||||
|
||||
function SewageIntroSummary() {
|
||||
const items = [
|
||||
{
|
||||
@@ -113,7 +119,217 @@ const tableStyles = {
|
||||
headerBg: "bg-[#E3E7EA]",
|
||||
};
|
||||
|
||||
const headerColors6 = [
|
||||
"bg-[#01ACE5]",
|
||||
"bg-[#17AFC7]",
|
||||
"bg-[#2CB2A9]",
|
||||
"bg-[#42B58B]",
|
||||
"bg-[#57B86D]",
|
||||
"bg-[#81C784]",
|
||||
];
|
||||
|
||||
export default function SewageStatusSection() {
|
||||
const getPbnstByLawYears = useDmStore((state) => state.getPbnstByLawYears);
|
||||
const getPbnstByUsgYears = useDmStore((state) => state.getPbnstByUsgYears);
|
||||
const getPbnstByCpcYears = useDmStore((state) => state.getPbnstByCpcYears);
|
||||
const getPbnstBySidoYears = useDmStore((state) => state.getPbnstBySidoYears);
|
||||
const pbnstYears = useDmStore((state) => state.pbnst.pbnstYears);
|
||||
const selectYear = pbnstYears.slice(-1)[0];
|
||||
const pbnstByLawYearsHeader = useDmStore((state) => state.pbnst.pbnstByLawYearsHeader);
|
||||
const pbnstByLawYears = useDmStore((state) => state.pbnst.pbnstByLawYears);
|
||||
const pbnstByUsgYearsHeader = useDmStore((state) => state.pbnst.pbnstByUsgYearsHeader);
|
||||
const pbnstByUsgYears = useDmStore((state) => state.pbnst.pbnstByUsgYears);
|
||||
const pbnstByCpcYearsHeader = useDmStore((state) => state.pbnst.pbnstByCpcYearsHeader);
|
||||
const pbnstByCpcYears = useDmStore((state) => state.pbnst.pbnstByCpcYears);
|
||||
const pbnstBySidoYearsHeader = useDmStore((state) => state.pbnst.pbnstBySidoYearsHeader);
|
||||
const pbnstBySidoYears = useDmStore((state) => state.pbnst.pbnstBySidoYears);
|
||||
|
||||
// 출처 텍스트
|
||||
function SourceText() {
|
||||
return (
|
||||
<p className="mt-7 text-center text-[13px] text-neutral-500">
|
||||
자료: 하수도정보시스템 {selectYear} 하수도 통계
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
void getPbnstByLawYears();
|
||||
void getPbnstByUsgYears();
|
||||
void getPbnstByCpcYears();
|
||||
void getPbnstBySidoYears();
|
||||
}, [getPbnstByLawYears, getPbnstByUsgYears, getPbnstByCpcYears, getPbnstBySidoYears]);
|
||||
|
||||
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 | DmStatusUsgYearsType,
|
||||
data: DmStatusLawYearsType[] | DmStatusUsgYearsType[],
|
||||
headers: TableHeaderType[],
|
||||
unitSize: number = 1, // 단위 변경 1000 인 경우, 100,000 -> 100 으로 변경
|
||||
) => {
|
||||
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} ${[0, 2, 4].includes(index) ? "bg-[#EAF5F5]" : ""}`}
|
||||
>
|
||||
{(String(rowData["COL2"]).indexOf("CNT") > -1)
|
||||
? Number(value).toLocaleString("ko-KR")
|
||||
: ((String(rowData["COL2"]).indexOf("REUSERT") > -1)
|
||||
? formatUsage(value as string | number, 1, 1)
|
||||
: formatUsage(value as string | number, unitSize, 1))
|
||||
}
|
||||
</td>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const renderPbnstUsgCells = (
|
||||
rowIdx: number,
|
||||
row: DmStatusBildTpYearsType | DmStatusUsgYearsType,
|
||||
headers: TableHeaderType[]
|
||||
) => {
|
||||
const rowData = row as Record<string, string | number>;
|
||||
const isLastInGroup = rowIdx === 8 || rowIdx === 17;
|
||||
|
||||
const getType = (colNm:string) => {
|
||||
const last3 = colNm.slice(-3); // 끝 3자리
|
||||
const prefix = last3[0]; // S 또는 D
|
||||
|
||||
if (prefix === 'S') {
|
||||
const num = parseInt(last3.slice(1), 10); // 숫자
|
||||
if (num < 8) return 'red-item';
|
||||
if (num >= 8) return 'blue-item';
|
||||
}
|
||||
|
||||
return ''; // 조건 안 맞으면 빈값 (필요시 기본값)
|
||||
};
|
||||
|
||||
return headers.map((header, index) => {
|
||||
const value = rowData[header.id];
|
||||
const colNm = String(rowData["COL_NM"] ?? "");
|
||||
const type = getType(colNm);
|
||||
const isSubItem = type === "red-item" || type === "blue-item";
|
||||
|
||||
if (index === 0) {
|
||||
console.log(header.id, value);
|
||||
return (
|
||||
<td key={`${rowIdx}-${header.id}`} className={`${tableStyles.td} relative`}>
|
||||
{isSubItem ? (
|
||||
<>
|
||||
<div
|
||||
className={`absolute left-[1px] w-[16px] bg-white z-10 top-[-2px] ${
|
||||
isLastInGroup ? "bottom-[0px]" : "bottom-[-2px]"
|
||||
}`}
|
||||
/>
|
||||
<div
|
||||
className={`absolute left-[16px] w-[4px] z-20 ${
|
||||
type === "red-item" ? "bg-[#FF8B8B]" : "bg-[#4ECBFF]"
|
||||
} top-[-2px] ${
|
||||
isLastInGroup ? "bottom-[0px]" : "bottom-[-2px]"
|
||||
}`}
|
||||
/>
|
||||
<span className="text-[#4f4f4f] font-bold block w-full text-center relative z-30 translate-x-[8px]">
|
||||
{value}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="font-bold text-neutral-900 block w-full text-center">
|
||||
{value}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<td
|
||||
key={`${rowIdx}-${header.id}`}
|
||||
className={`${tableStyles.td} ${index === 0 ? "!font-bold !text-neutral-900" : ""} ${[0, 2, 4].includes(index) ? "bg-[#EAF5F5]" : ""}`}
|
||||
>
|
||||
{formatUsage(value as string | number, 1000, 1)}
|
||||
</td>
|
||||
);
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
const renderSidoUsgCells = (
|
||||
rowIdx: number,
|
||||
row: DmStatusSidoUsgType,
|
||||
headers: TableHeaderType[]
|
||||
) => {
|
||||
const rowData = row as Record<string, string | number>;
|
||||
|
||||
return headers.map((header, index) => {
|
||||
let value = rowData[header.id];
|
||||
value = index === 0 ? value : formatUsage(value as string | number, 1000, 1);
|
||||
value = value === "0.0"? "-" : value;
|
||||
|
||||
return (
|
||||
<td
|
||||
key={`${rowIdx}-${header.id}`}
|
||||
className={`${tableStyles.td} ${index === 0 ? "!font-bold !text-neutral-900" : ""} ${[1, 9].includes(index) ? "bg-[#EAF5F5]" : ""}`}
|
||||
>
|
||||
{value}
|
||||
</td>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const title = "하수처리수 재이용시설(현황)";
|
||||
|
||||
return (
|
||||
@@ -155,181 +371,15 @@ export default function SewageStatusSection() {
|
||||
>
|
||||
구분
|
||||
</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(pbnstYears, headerColors6)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{[
|
||||
{
|
||||
group: "전체",
|
||||
rows: [
|
||||
[
|
||||
"개소수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>",
|
||||
"671",
|
||||
"681",
|
||||
"698",
|
||||
"704",
|
||||
"714",
|
||||
"717",
|
||||
],
|
||||
[
|
||||
"하수처리량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
|
||||
"7,163.7",
|
||||
"7,140.4",
|
||||
"7,375.6",
|
||||
"7,335.8",
|
||||
"7,378.9",
|
||||
"7,537.2",
|
||||
],
|
||||
[
|
||||
"재이용량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
|
||||
"1,112.7",
|
||||
"1,148.7",
|
||||
"1,148.7",
|
||||
"1,127.0",
|
||||
"1,136.8",
|
||||
"1,137.5",
|
||||
],
|
||||
[
|
||||
"재이용률 <span class='text-[13px] font-normal text-[#767676]'>(%)</span>",
|
||||
"17.4",
|
||||
"16.5",
|
||||
"15.5",
|
||||
"14.1",
|
||||
"14.3",
|
||||
"14.4",
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "법적 대상",
|
||||
rows: [
|
||||
[
|
||||
"개소수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>",
|
||||
"68",
|
||||
"82",
|
||||
"94",
|
||||
"97",
|
||||
"101",
|
||||
"118",
|
||||
],
|
||||
[
|
||||
"하수처리량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
|
||||
"761.2",
|
||||
"839.0",
|
||||
"935.3",
|
||||
"1,158.7",
|
||||
"1,220.6",
|
||||
"1,473.6",
|
||||
],
|
||||
[
|
||||
"재이용량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
|
||||
"162.2",
|
||||
"190.6",
|
||||
"218.5",
|
||||
"244.6",
|
||||
"247.2",
|
||||
"324.9",
|
||||
],
|
||||
[
|
||||
"재이용률 <span class='text-[13px] font-normal text-[#767676]'>(%)</span>",
|
||||
"24.7",
|
||||
"25.4",
|
||||
"27.8",
|
||||
"25.7",
|
||||
"24.2",
|
||||
"24.1",
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "법적 미대상",
|
||||
rows: [
|
||||
[
|
||||
"개소수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>",
|
||||
"603",
|
||||
"599",
|
||||
"604",
|
||||
"607",
|
||||
"613",
|
||||
"599",
|
||||
],
|
||||
[
|
||||
"하수처리량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
|
||||
"6,402.5",
|
||||
"6,301.4",
|
||||
"6,440.3",
|
||||
"6,177.1",
|
||||
"6,158.3",
|
||||
"6,063.5",
|
||||
],
|
||||
[
|
||||
"재이용량 <span class='text-[13px] font-normal text-[#767676]'>(백만m³/년)</span>",
|
||||
"950.6",
|
||||
"958.1",
|
||||
"926.2",
|
||||
"882.4",
|
||||
"889.5",
|
||||
"812.7",
|
||||
],
|
||||
[
|
||||
"재이용률 <span class='text-[13px] font-normal text-[#767676]'>(%)</span>",
|
||||
"16.5",
|
||||
"15.3",
|
||||
"13.6",
|
||||
"12.2",
|
||||
"12.6",
|
||||
"12.5",
|
||||
],
|
||||
],
|
||||
},
|
||||
].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>
|
||||
))}
|
||||
{pbnstByLawYears.map((row, idx, arr) => (
|
||||
<tr key={idx}>
|
||||
{renderCells(idx, row, arr, pbnstByLawYearsHeader, 1000)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -341,12 +391,15 @@ export default function SewageStatusSection() {
|
||||
|
||||
<Hr className="my-11" />
|
||||
|
||||
{/* 2) 연도별 하수처리수 재이용 현황 */}
|
||||
{/* 2) 용도별 하수처리수 재이용 현황 */}
|
||||
<section id="status-treated-usage" className="scroll-mt-[120px]">
|
||||
<SectionTitle>연도별 하수처리수 재이용 현황</SectionTitle>
|
||||
<SectionTitle>용도별 하수처리수 재이용 현황</SectionTitle>
|
||||
|
||||
<div className="mt-8">
|
||||
<div className={tableStyles.container}>
|
||||
<div className="mb-2 text-right text-[13px] text-neutral-600">
|
||||
(단위: 백만m³/일)
|
||||
</div>
|
||||
<table className={tableStyles.table}>
|
||||
<colgroup>
|
||||
<col style={{ width: "180px" }} />
|
||||
@@ -362,91 +415,15 @@ export default function SewageStatusSection() {
|
||||
<th className={`${tableStyles.th} ${tableStyles.headerBg}`}>
|
||||
구분
|
||||
</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(pbnstYears, headerColors6)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{[
|
||||
{ label: "총 재이용량", type: "total", values: ["1,112.7", "1,148.7", "1,144.7", "1,127.0", "1,136.8", "1,137.5"] },
|
||||
{ label: "장내 재이용", type: "category", values: ["520.6", "519.8", "513.9", "520.3", "502.2", "490.0"] },
|
||||
{ label: "세척수", type: "red-item", values: ["177.9", "174.4", "169.4", "180.9", "196.8", "191.2"] },
|
||||
{ label: "냉각수", type: "red-item", values: ["45.5", "46.8", "50.4", "40.6", "38.3", "41.7"] },
|
||||
{ label: "청소수", type: "red-item", values: ["17.6", "21.2", "21.2", "21.7", "20.8", "20.5"] },
|
||||
{ label: "조경용수", type: "red-item", values: ["0.1", "0.1", "-", "-", "-", "-"] },
|
||||
{ label: "회생용수", type: "red-item", values: ["15.8", "16.7", "17.8", "15.7", "14.4", "14.0"] },
|
||||
{ label: "장내급수도", type: "red-item", values: ["2.4", "-", "-", "-", "-", "-"] },
|
||||
{ label: "장내기타용수", type: "red-item", values: ["261.3", "260.6", "255.0", "261.1", "231.8", "222.6"] },
|
||||
{ label: "장외 재이용", type: "category", values: ["592.1", "628.9", "630.8", "606.7", "634.6", "647.5"] },
|
||||
{ label: "청소·화장실용수", type: "blue-item", values: ["0.6", "0.4", "0.4", "0.4", "0.4", "0.4"] },
|
||||
{ label: "세척·살수용수", type: "blue-item", values: ["5.6", "9.9", "2.9", "2.1", "3.0", "3.6"] },
|
||||
{ label: "조경용수", type: "blue-item", values: ["10.3", "16.4", "5.9", "4.5", "8.9", "9.5"] },
|
||||
{ label: "친수용수", type: "blue-item", values: ["7.8", "3.1", "3.1", "3.0", "10.9", "10.5"] },
|
||||
{ label: "하천유지용수", type: "blue-item", values: ["480.5", "482.5", "496.2", "442.7", "471.7", "484.0"] },
|
||||
{ label: "농업용수", type: "blue-item", values: ["12.2", "11.9", "13.4", "10.7", "10.6", "11.4"] },
|
||||
{ label: "지하수 충전", type: "blue-item", values: ["0.0", "0.0", "0.0", "13.4", "0.0", "0.0"] },
|
||||
{ label: "공업용수", type: "blue-item", values: ["75.2", "104.6", "108.9", "129.9", "129.0", "128.1"] },
|
||||
].map((row, idx) => {
|
||||
const isSubItem = row.type === "red-item" || row.type === "blue-item";
|
||||
const isLastInGroup = idx === 8 || idx === 17;
|
||||
|
||||
return (
|
||||
<tr key={idx} className="bg-white">
|
||||
<td className={`${tableStyles.td} relative`}>
|
||||
{isSubItem ? (
|
||||
<>
|
||||
<div
|
||||
className={`absolute left-[1px] w-[16px] bg-white z-10 top-[-2px] ${
|
||||
isLastInGroup ? "bottom-[0px]" : "bottom-[-2px]"
|
||||
}`}
|
||||
/>
|
||||
<div
|
||||
className={`absolute left-[16px] w-[4px] z-20 ${
|
||||
row.type === "red-item" ? "bg-[#FF8B8B]" : "bg-[#4ECBFF]"
|
||||
} top-[-2px] ${
|
||||
isLastInGroup ? "bottom-[0px]" : "bottom-[-2px]"
|
||||
}`}
|
||||
/>
|
||||
<span className="text-[#4f4f4f] font-bold block w-full text-center relative z-30 translate-x-[8px]">
|
||||
{row.label}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="font-bold text-neutral-900 block w-full text-center">
|
||||
{row.label}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
|
||||
{row.values.map((val, i) => (
|
||||
<td
|
||||
key={i}
|
||||
className={`${tableStyles.td} ${
|
||||
[0, 2, 4].includes(i) ? "bg-[#EAF5F5]" : ""
|
||||
}`}
|
||||
>
|
||||
{val}
|
||||
</td>
|
||||
))}
|
||||
{pbnstByUsgYears.map((row, idx) => (
|
||||
<tr key={idx} className="bg-white">
|
||||
{renderPbnstUsgCells(idx, row, pbnstByUsgYearsHeader)}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -482,153 +459,14 @@ export default function SewageStatusSection() {
|
||||
>
|
||||
구분
|
||||
</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(pbnstYears, headerColors6)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{[
|
||||
{
|
||||
group: "전체",
|
||||
rows: [
|
||||
[
|
||||
"시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>",
|
||||
"671",
|
||||
"681",
|
||||
"698",
|
||||
"704",
|
||||
"714",
|
||||
"717",
|
||||
],
|
||||
[
|
||||
"시설용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
|
||||
"25,846",
|
||||
"26,067",
|
||||
"26,244",
|
||||
"26,492",
|
||||
"26,586",
|
||||
"26,766",
|
||||
],
|
||||
[
|
||||
"처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
|
||||
"1,112.7",
|
||||
"1,148.7",
|
||||
"1,144.7",
|
||||
"1,127.0",
|
||||
"1,136.8",
|
||||
"1,137.5",
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "법적 대상",
|
||||
rows: [
|
||||
[
|
||||
"시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>",
|
||||
"68",
|
||||
"82",
|
||||
"94",
|
||||
"97",
|
||||
"101",
|
||||
"118",
|
||||
],
|
||||
[
|
||||
"시설용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
|
||||
"3,088.9",
|
||||
"3,359.2",
|
||||
"3,612.6",
|
||||
"4,412.2",
|
||||
"4,692.3",
|
||||
"5,503.8",
|
||||
],
|
||||
[
|
||||
"처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
|
||||
"162.2",
|
||||
"190.6",
|
||||
"218.5",
|
||||
"244.6",
|
||||
"247.2",
|
||||
"324.9",
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "법적 미대상",
|
||||
rows: [
|
||||
[
|
||||
"시설수 <span class='text-[13px] font-normal text-[#767676]'>(개소)</span>",
|
||||
"603",
|
||||
"599",
|
||||
"604",
|
||||
"607",
|
||||
"613",
|
||||
"599",
|
||||
],
|
||||
[
|
||||
"시설용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
|
||||
"22,757",
|
||||
"22,708",
|
||||
"22,631",
|
||||
"22,080",
|
||||
"21,894",
|
||||
"21,262",
|
||||
],
|
||||
[
|
||||
"처리용량 <span class='text-[13px] font-normal text-[#767676]'>(만m³/일)</span>",
|
||||
"950.6",
|
||||
"958.1",
|
||||
"926.2",
|
||||
"882.4",
|
||||
"889.5",
|
||||
"812.7",
|
||||
],
|
||||
],
|
||||
},
|
||||
].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>
|
||||
{pbnstByCpcYears.map((row, idx, arr) => (
|
||||
<tr key={idx}>
|
||||
{renderCells(idx, row, arr, pbnstByCpcYearsHeader, 10000)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -669,60 +507,28 @@ export default function SewageStatusSection() {
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
rowSpan={3}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg}`}
|
||||
>
|
||||
시도
|
||||
<th rowSpan={3} className={`${tableStyles.th} ${tableStyles.headerBg}`}> 시도 </th>
|
||||
<th rowSpan={3} className={`${tableStyles.th} ${tableStyles.headerBg}`} >
|
||||
연간<br />하수<br />처리량
|
||||
</th>
|
||||
<th
|
||||
rowSpan={3}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg}`}
|
||||
>
|
||||
연간
|
||||
<br />
|
||||
하수
|
||||
<br />
|
||||
처리량
|
||||
</th>
|
||||
<th
|
||||
colSpan={7}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg} py-2`}
|
||||
>
|
||||
<th colSpan={7} className={`${tableStyles.th} ${tableStyles.headerBg} py-2`} >
|
||||
재이용현황
|
||||
</th>
|
||||
<th
|
||||
rowSpan={3}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg}`}
|
||||
>
|
||||
재이용률
|
||||
<br />
|
||||
(%)
|
||||
<th rowSpan={3} className={`${tableStyles.th} ${tableStyles.headerBg}`} >
|
||||
재이용률<br />(%)
|
||||
</th>
|
||||
<th
|
||||
rowSpan={3}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg}`}
|
||||
>
|
||||
<th rowSpan={3} className={`${tableStyles.th} ${tableStyles.headerBg}`} >
|
||||
비고
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg}`}
|
||||
>
|
||||
<th rowSpan={2} className={`${tableStyles.th} ${tableStyles.headerBg}`} >
|
||||
계
|
||||
</th>
|
||||
<th
|
||||
rowSpan={2}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg}`}
|
||||
>
|
||||
<th rowSpan={2} className={`${tableStyles.th} ${tableStyles.headerBg}`} >
|
||||
장내
|
||||
</th>
|
||||
<th
|
||||
colSpan={5}
|
||||
className={`${tableStyles.th} ${tableStyles.headerBg} py-1`}
|
||||
>
|
||||
<th colSpan={5} className={`${tableStyles.th} ${tableStyles.headerBg} py-1`} >
|
||||
장외
|
||||
</th>
|
||||
</tr>
|
||||
@@ -745,38 +551,10 @@ export default function SewageStatusSection() {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{[
|
||||
["합계", "7,537.2", "1,137.5", "490.0", "647.5", "484.0", "128.1", "11.4", "24.0", "15.1%", ""],
|
||||
["서울특별시", "1,567.0", "114.9", "59.3", "55.6", "55.1", "-", "-", "0.5", "7.3%", ""],
|
||||
["부산광역시", "491.5", "146.2", "120.7", "25.5", "25.3", "-", "-", "0.2", "29.7%", ""],
|
||||
["대구광역시", "432.7", "102.4", "38.2", "64.2", "64.1", "-", "-", "0.1", "23.7%", ""],
|
||||
["인천광역시", "302.3", "57.7", "11.6", "46.1", "29.2", "12.1", "0.5", "4.3", "19.1%", ""],
|
||||
["광주광역시", "211.1", "28.7", "6.5", "22.3", "22.2", "-", "-", "0.1", "13.6%", ""],
|
||||
["대전광역시", "244.6", "11.9", "11.9", "0.68", "0.0", "-", "-", "0.1", "4.9%", ""],
|
||||
["울산광역시", "235.1", "36.1", "6.1", "29.9", "29.7", "0.2", "-", "-", "15.3%", ""],
|
||||
["세종특별자치시", "38.5", "2.5", "2.0", "0.5", "0.4", "-", "0.2", "-", "6.6%", ""],
|
||||
["경기도", "1,926.8", "313.3", "122.2", "191.0", "153.0", "33.3", "0.4", "4.3", "16.3%", ""],
|
||||
["강원도", "230.4", "19.6", "15.4", "4.2", "2.1", "-", "-", "2.1", "8.5%", ""],
|
||||
["충청북도", "190.9", "15.6", "6.3", "9.2", "7.4", "0.6", "-", "1.2", "8.2%", ""],
|
||||
["충청남도", "241.5", "41.4", "9.8", "31.5", "17.7", "8.6", "4.5", "0.8", "17.1%", ""],
|
||||
["전라북도", "292.4", "42.7", "7.5", "35.1", "33.5", "0.2", "1.0", "0.5", "14.6%", ""],
|
||||
["전라남도", "254.0", "23.6", "12.3", "11.3", "8.7", "0.0", "1.0", "1.6", "9.3%", ""],
|
||||
["경상북도", "378.4", "129.1", "33.7", "95.3", "20.8", "72.5", "0.8", "1.3", "34.1%", ""],
|
||||
["경상남도", "411.3", "50.1", "25.0", "25.0", "14.7", "0.5", "3.0", "6.9", "12.2%", ""],
|
||||
["제주특별자치도", "88.6", "1.7", "1.5", "0.12", "-", "-", "0.1", "-", "1.9%", ""],
|
||||
].map((row, idx) => (
|
||||
<tr key={idx} className="bg-white">
|
||||
{row.map((val, i) => (
|
||||
<td
|
||||
key={i}
|
||||
className={`${tableStyles.td} ${
|
||||
i === 0 ? "!font-bold !text-neutral-900" : ""
|
||||
} ${[1, 3, 9].includes(i) ? "bg-[#EAF5F5]" : ""}`}
|
||||
>
|
||||
{val}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
{pbnstBySidoYears.map((row, idx) => (
|
||||
<tr key={idx} className="bg-white">
|
||||
{renderSidoUsgCells(idx, row, pbnstBySidoYearsHeader)}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -788,4 +566,4 @@ export default function SewageStatusSection() {
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ export const formatUsage = (
|
||||
unitSize: number = 1,
|
||||
decimalPlaces: number = 0
|
||||
) => {
|
||||
if (value === null || value === undefined || value === "") return "";
|
||||
const numeric =
|
||||
typeof value === "number" ? value : Number(String(value).replaceAll(",", ""));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { fetchType, getFetch } from "@/components/ui/api";
|
||||
import type {
|
||||
TableHeaderType, DmStatusBildTpYearsType, DmStatusUsgBildTpType, DmStatusUsgYearsType,
|
||||
DmStatusLawYearsType,
|
||||
DmStatusLawYearsType, DmStatusSidoUsgType,
|
||||
} from "./type";
|
||||
import { rainyByBildTpYearsHeader, rainyByUsgBildTpHeader, rainyByUsgYearsHeader } from "./type";
|
||||
import { rswtrByLawYearsHeader, rswtrByBildTpYearsHeader, rswtrByUsgYearsHeader } from "./type";
|
||||
@@ -47,10 +47,10 @@ export type DmStatusType = {
|
||||
pbnstByUsgYearsHeader: TableHeaderType[];
|
||||
pbnstByCpcYearsHeader: TableHeaderType[];
|
||||
pbnstBySidoYearsHeader: TableHeaderType[];
|
||||
pbnstByLawYears: DmStatusBildTpYearsType[];
|
||||
pbnstByUsgYears: DmStatusBildTpYearsType[];
|
||||
pbnstByCpcYears: DmStatusBildTpYearsType[];
|
||||
pbnstBySidoYears: DmStatusBildTpYearsType[];
|
||||
pbnstByLawYears: DmStatusLawYearsType[];
|
||||
pbnstByUsgYears: DmStatusUsgYearsType[];
|
||||
pbnstByCpcYears: DmStatusLawYearsType[];
|
||||
pbnstBySidoYears: DmStatusSidoUsgType[];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -201,11 +201,16 @@ export const DmStatusReducer = (set: any): DmStatusActions => {
|
||||
getPbnstByLawYears: async () => {
|
||||
const res = await getFetch(fetchType.WR,"/dmStatus/pbnstByLawYears");
|
||||
const pbnstByLawYears = Array.isArray(res?.data) ? res.data : [];
|
||||
const maxYear = Number(pbnstByLawYears[0]?.MAXYR);
|
||||
const pbnstYears = Number.isFinite(maxYear)
|
||||
? Array.from({ length: 6 }, (_, index) => String(maxYear - 5 + index))
|
||||
: dmStatusState.rswtr.rswtrYears;
|
||||
|
||||
set((state: DmStatusType) => ({
|
||||
...state,
|
||||
pbnst: {
|
||||
...state.pbnst,
|
||||
pbnstYears,
|
||||
pbnstByLawYears,
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -45,6 +45,7 @@ export type DmStatusUsgYearsType = {
|
||||
Y4: string | number;
|
||||
Y5: string | number;
|
||||
Y6: string | number;
|
||||
COL_NM?: string; // 컬럼명
|
||||
MAXYR?: string; // 최종 확정 연도
|
||||
};
|
||||
|
||||
@@ -60,15 +61,23 @@ export type DmStatusLawYearsType = {
|
||||
Y6: string | number;
|
||||
};
|
||||
|
||||
export type DmStatusSidoYearsType = {
|
||||
COL: string; // 컬럼 구분
|
||||
MAXYR?: string; // 최종 확정 연도
|
||||
Y1: string | number;
|
||||
Y2: string | number;
|
||||
Y3: string | number;
|
||||
Y4: string | number;
|
||||
Y5: string | number;
|
||||
Y6: string | number;
|
||||
export type DmStatusSidoUsgType = {
|
||||
ADST_CD: string; // 시도 코드
|
||||
SIDONM: string; // 시도명
|
||||
TPUT_TOTAL: string; // 연간하수처리량(천톤/년)
|
||||
USE_AMNT_TOTAL: number; // 재이용현황
|
||||
USE_AMNT_D01: number;
|
||||
USE_AMNT_D02: number;
|
||||
USE_AMNT_S11: number; // 청소·화장실용수
|
||||
USE_AMNT_S12: number; // 세척·살수용수
|
||||
USE_AMNT_S13: number; // 조경용수
|
||||
USE_AMNT_S14: number; // 친수용수
|
||||
USE_AMNT_S15: number; // 하천유지용수
|
||||
USE_AMNT_S16: number; // 농업용수
|
||||
USE_AMNT_S17: number; // 지하수충전
|
||||
USE_AMNT_S18: number; // 공업용수
|
||||
USE_AMNT_ETC: number; // 기타 (청소·화장실용수+세척·살수용수+조경용수+친수용수+지하수충전)
|
||||
REUSE_RT: number;
|
||||
};
|
||||
|
||||
|
||||
@@ -226,7 +235,8 @@ export const rswtrByUsgYearsHeader: TableHeaderType[] = [
|
||||
|
||||
// 연도별 하수처리수 재이용 현황
|
||||
export const pbnstByLawYearsHeader: 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 },
|
||||
@@ -237,7 +247,7 @@ export const pbnstByLawYearsHeader: TableHeaderType[] = [
|
||||
|
||||
// 용도별 하수처리수 재이용 현황
|
||||
export const pbnstByUsgYearsHeader: TableHeaderType[] = [
|
||||
{ id: "BILD_TP", title: "구분", row: 0, widthPercent: 15 },
|
||||
{ id: "USG_NM", 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 },
|
||||
@@ -248,7 +258,8 @@ export const pbnstByUsgYearsHeader: TableHeaderType[] = [
|
||||
|
||||
// 하수처리시설 설치 및 이용 현황
|
||||
export const pbnstByCpcYearsHeader: TableHeaderType[] = [
|
||||
{ id: "USE_NM", 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 },
|
||||
@@ -259,12 +270,16 @@ export const pbnstByCpcYearsHeader: TableHeaderType[] = [
|
||||
|
||||
// 시도별 하수처리수 재이용 현황
|
||||
export const pbnstBySidoYearsHeader: TableHeaderType[] = [
|
||||
{ id: "USE_NM", 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 },
|
||||
{ id: "Y4", title: "2022", row: 0, widthPercent: 7 },
|
||||
{ id: "Y5", title: "2023", row: 0, widthPercent: 10 },
|
||||
{ id: "Y6", title: "2024", row: 1, widthPercent: 5 },
|
||||
{ id: "SIDONM", title: "시도", row: 0, widthPercent: 15 },
|
||||
{ id: "TPUT_TOTAL", title: "연간하수처리량", row: 1, widthPercent: 5 },
|
||||
{ id: "USE_AMNT_TOTAL", title: "재이용현황계", row: 1, widthPercent: 5 },
|
||||
{ id: "USE_AMNT_D01", title: "재이용현황 장내", row: 1, widthPercent: 5 },
|
||||
{ id: "USE_AMNT_D02", title: "재이용현황 장외소계", row: 0, widthPercent: 7 },
|
||||
{ id: "USE_AMNT_S15", title: "장외 하천유지용수", row: 0, widthPercent: 10 },
|
||||
{ id: "USE_AMNT_S16", title: "장외 농업용수", row: 1, widthPercent: 5 },
|
||||
{ id: "USE_AMNT_S18", title: "장외 공업용수", row: 1, widthPercent: 5 },
|
||||
{ id: "USE_AMNT_ETC", title: "장외 기타용수", row: 1, widthPercent: 5 },
|
||||
{ id: "REUSE_RT", title: "재이용률", row: 1, widthPercent: 5 },
|
||||
{ id: "REMARK", title: "비고", row: 1, widthPercent: 5 },
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user