From 908ec81fb7584a1c935042d2e5444b4922cadaf5 Mon Sep 17 00:00:00 2001 From: LGS Date: Tue, 17 Mar 2026 15:47:34 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=EC=B9=A8=EC=9E=85=EC=88=98=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=20=ED=8C=9D=EC=97=85=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/infilChart.tsx | 447 +++++++++--------- 1 file changed, 226 insertions(+), 221 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 9f481a2b9..094936638 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -1,268 +1,273 @@ 'use client' -import { CHART_FORM, type ChartConfig, MainChart, UiModal } from "@common/business_components"; + +import React, { useEffect, useMemo, useState } from 'react'; +import moment from 'moment'; + +import { + CHART_FORM, + type ChartConfig, + MainChart, + UiModal, +} from '@common/business_components'; import { SelectBox } from '@common/business_components/ui'; import { Button, Input, Label } from '@common/components'; -import React, { useEffect, useState } from 'react'; -import moment from "moment"; import type { TInftwtAnls } from './aplcnYms'; import * as fn from './aplcnYms'; -import { useInfilChartModalStore } from '../chartModalStore'; // 모달 상태 관리 스토어 +import { useInfilChartModalStore } from '../chartModalStore'; + type ModalOpenProp = { - pplMngNo?: string, // 관로관리번호 -} -type DataType = { label: string; val: number }; + pplMngNo?: string; // 관로관리번호 +}; -const InfilChart = ({ pplMngNo }: ModalOpenProp) => { - const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useInfilChartModalStore(); // 모달 상태 관리 스토어 - const [popupOpen, setPopupOpen] = React.useState(false); // 조회조건팝업 - const buttonRef = React.useRef(null); // 버튼 참조 - const [popupPosition, setPopupPosition] = useState<{ top: number; left: number }>({ top: 0, left: 0 }); // 팝업 위치 - const [selectedAplcnYm, setSelectedAplcnYm] = useState(""); +type DataType = { + label: string; + val: number; +}; + +const INITIAL_ANALYSIS_OPTIONS = [{ val: 0, text: '선택' }]; + +const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { + const { isOpen: isModalOpen, setIsOpen: setIsModalOpen } = useInfilChartModalStore(); + + const [selectedAplcnYm, setSelectedAplcnYm] = useState(''); const [inftwtAnlss, setInftwtAnlss] = useState([]); - const [inftwtAnlsInfos, setInftwtAnlsInfos] = useState<{ text: string; val: number; hidden?: boolean }[]>([{ val: 0, text: '선택' }]); // 침입수분석정보 options - const [inftwtAnls, setInftwtAnls] = useState(null); // 침입수분석정보 - const [selectedInftwtAnls, setSelectedInftwtAnls] = useState(0); // 침입수분석 정보 선택시 사용 + const [inftwtAnlsInfos, setInftwtAnlsInfos] = useState<{ text: string; val: number; hidden?: boolean }[]>( + INITIAL_ANALYSIS_OPTIONS, + ); + const [inftwtAnls, setInftwtAnls] = useState(null); + const [selectedInftwtAnls, setSelectedInftwtAnls] = useState(0); const [chartData, setChartData] = useState<{ chartData1: DataType[]; chartData2: DataType[] }>({ - chartData1: [], chartData2: [], + chartData1: [], + chartData2: [], }); - const [inftwtQty, setInftwtQty] = useState("0"); // 침입수량 - const aplcnYms = fn.useAplcnYms('inftwtAnlsRslt'); // 상수사용월 데이터 가져오기 + const [inftwtQty, setInftwtQty] = useState('0'); - pplMngNo = "L" + pplMngNo; // inp파일에 하수관로와 맨홀의 번호가 같으면 분석 오류가 발행하여 - const openPopup = () => { - if (buttonRef.current) { - const rect = buttonRef.current.getBoundingClientRect(); // 버튼 위치 계산 - setPopupPosition({ - top: rect.bottom + window.scrollY, // 버튼 아래쪽 - left: rect.left + window.scrollX, // 버튼 왼쪽 - }); - } - setPopupOpen(true); // 팝업 열기 - }; + const aplcnYms = fn.useAplcnYms('inftwtAnlsRslt'); + const normalizedPplMngNo = pplMngNo ? `L${pplMngNo}` : ''; const chartForm = CHART_FORM.LINE; const chartConfig = { - chartData1: { label: '순오수량', color: "red", }, - chartData2: { label: '실측하수량', color: "orange", } + chartData1: { label: '순오수량', color: 'red' }, + chartData2: { label: '실측하수량', color: 'orange' }, } as ChartConfig; + const hasChartData = useMemo(() => { + return chartData.chartData1.length > 0 || chartData.chartData2.length > 0; + }, [chartData]); + + const resetState = () => { + setSelectedAplcnYm(''); + setInftwtAnlss([]); + setInftwtAnlsInfos(INITIAL_ANALYSIS_OPTIONS); + setInftwtAnls(null); + setSelectedInftwtAnls(0); + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); + }; + useEffect(() => { - if (isModalOpen === false) { - setPopupOpen(true); // 모달이 닫힐 때 조회조건팝업은 열어두기 - setSelectedAplcnYm(""); // 상수사용월 초기화 - setInftwtAnlss([]); // 침입수분석 초기화 - setInftwtAnlsInfos([{ val: 0, text: '선택' }]); // 침입수분석정보 초기화 - setInftwtAnls(null); // 침입수분석정보 초기화 - setSelectedInftwtAnls(0); // 침입수분석 일련번호 초기화 - setChartData({ chartData1: [], chartData2: [], }); // 차트 데이터 초기화 - setInftwtQty("0"); // 침입수량 초기화 + if (!isModalOpen) { + resetState(); } }, [isModalOpen]); - // 상수사용월 변경 핸들러 const handleAplcnYmChange = async (val: string | number) => { const selectedValue = String(val); setSelectedAplcnYm(selectedValue); - - // 즉시 관련 상태 초기화 + setInftwtAnlss([]); setInftwtAnls(null); + setSelectedInftwtAnls(0); + setInftwtQty('0'); + setChartData({ chartData1: [], chartData2: [] }); - // 빈 값이면 초기화만 하고 종료 - if (!selectedValue || selectedValue === "0" || selectedValue === "") { - setInftwtAnlsInfos([{ val: 0, text: '선택' }]); + if (!selectedValue || selectedValue === '0') { + setInftwtAnlsInfos(INITIAL_ANALYSIS_OPTIONS); return; } - // API 호출 try { const data = await fn.selectInftwtAnls(selectedValue); - setInftwtAnlss(data ?? []); - setInftwtAnlsInfos(fn.getOptionsInftwtAnlsInfo(data)); + const list = data ?? []; + setInftwtAnlss(list); + setInftwtAnlsInfos(fn.getOptionsInftwtAnlsInfo(list)); } catch (error) { - console.error("selectInftwtAnls 에러:", error); + console.error('selectInftwtAnls 에러:', error); setInftwtAnlss([]); - setInftwtAnlsInfos([{ val: 0, text: '선택' }]); + setInftwtAnlsInfos(INITIAL_ANALYSIS_OPTIONS); } - setSelectedInftwtAnls(0); }; - // 분석정보 변경 핸들러 const handleInftwtAnlsSnChange = (val: string | number) => { const selectedValue = Number(val); - setSelectedInftwtAnls(selectedValue); - // 선택된 침입수분석 정보에 대한 처리 로직 + setSelectedInftwtAnls(selectedValue); + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); + if (selectedValue === 0) { setInftwtAnls(null); return; } - const selectedAnls = inftwtAnlss.find(anls => anls.inftwtAnlsSn === selectedValue); - if (selectedAnls) { - setInftwtAnls(selectedAnls); + const selectedAnls = inftwtAnlss.find((anls) => anls.inftwtAnlsSn === selectedValue) ?? null; + setInftwtAnls(selectedAnls); + }; + + const infilRsltChart = async () => { + if (!selectedAplcnYm || selectedInftwtAnls === 0 || !normalizedPplMngNo) { + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); + return; + } + + try { + const [inftwtAnlsRslt, oilq, qty] = await Promise.all([ + fn.selectInftwtAnlsRslt(selectedInftwtAnls, normalizedPplMngNo), + fn.selectOilq(selectedInftwtAnls, normalizedPplMngNo).catch((err) => { + console.error('selectOilq 에러:', err); + return []; + }), + fn.selectPplInftwtQty(selectedInftwtAnls, normalizedPplMngNo).catch((err) => { + console.error('selectPplInftwtQty 에러:', err); + return 0; + }), + ]); + + setChartData({ + chartData1: fn.getChartDataInftwtAnlsRslt(inftwtAnlsRslt ?? []), + chartData2: fn.getChartDataOilq(oilq ?? []), + }); + + const normalizedQty = Number(qty ?? 0); + setInftwtQty(normalizedQty.toLocaleString('ko-KR')); + } catch (error) { + console.error('infilRsltChart 에러:', error); + setChartData({ chartData1: [], chartData2: [] }); + setInftwtQty('0'); } }; - const closePopup = () => { // 팝업 닫기 - setPopupOpen(false); - } - const infilRsltChart = () => { // 그래프 & 팝업 닫기 - - fn.selectInftwtAnlsRslt(selectedInftwtAnls, pplMngNo).then((data) => {// 침입수분석 결과 조회 - const rsltData = fn.getChartDataInftwtAnlsRslt(data ?? []); - setChartData(prev => ({ - ...prev, - chartData1: rsltData // 침입수분석결과 - })); - }); - fn.selectOilq(selectedInftwtAnls, pplMngNo).then((data) => {// 유량 조회 - const rsltData = fn.getChartDataOilq(data ?? []); - setChartData(prev => ({ - ...prev, - chartData2: rsltData // 유량 - })); - }).catch((err) => { - console.error("selectOilq 에러:", err); - setChartData(prev => ({ - ...prev, - chartData2: [] // 유량 데이터 초기화 - })); - }); - fn.selectPplInftwtQty(selectedInftwtAnls, pplMngNo).then((data) => {// 침입수량 조회 - if (data > 0) { - setInftwtQty(data.toLocaleString('ko-KR')); - } - }); - setPopupOpen(false); - }; + const renderInfoInput = (label: string, value?: string | number | null) => ( +
+ + +
+ ); const renderBody = () => ( - <> -
침입수분석결과
- -
-
- - {/* 상수사용량 적용연월 */} -
- ● 상수사용량 적용연월 -
- - {(selectedAplcnYm) ? moment(selectedAplcnYm, "YYYYMM").format("YYYY-MM") : ""} - -
-
- {/* 침입수량 분석결과 */} -
- ● 침입수량 산정결과 -
- 침입수량 : - {inftwtQty} - m³/d -
-
-
- {/* 차트 */} -
- -
+
+
+
- {popupOpen && ( -
-
침입수분석 입력현황
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - + +
+
+

+ 침입수 분석 선택 조건 +

+ +
+
+
+ + +
+ +
+ + +
+ + {renderInfoInput('오수전환율:', inftwtAnls?.drtwSwtcRt ?? '')} + {renderInfoInput('시간패턴 파일명:', inftwtAnls?.atflHrPttnNm ?? '')} + {renderInfoInput('수용가-맨홀 매칭:', inftwtAnls?.atflMpngNm ?? '')} + {renderInfoInput('관망도 파일명:', inftwtAnls?.atflInpNm ?? '')} + {renderInfoInput('유량 파일명:', inftwtAnls?.atflOilqNm ?? '')}
-
- - +
-
)} - {/* */} - - ) + + +
+

침입수 분석 결과

+ +
+
+
+ ● + 상수사용량 적용연월 +
+
+ {selectedAplcnYm ? moment(selectedAplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} +
+
+ +
+
+ ● + 침입수량 산정결과 +
+
+ 침입수량 + {inftwtQty} + m³/d +
+
+
+ +
+ {hasChartData ? ( + + ) : ( +
+ 데이터가 없습니다. +
+ )} +
+
+
+
+ ); return ( { onOpenChange={setIsModalOpen} headerTitle="" bodyClass={` - min-h-[50vh] - w-[55vw] - max-w-none - max-h-none - overflow-visible - z-[50] - `} + w-[78vw] + max-w-none + min-h-[74vh] + max-h-none + overflow-visible + z-[50] + `} body={renderBody()} - noFooterYn='Y' + noFooterYn="Y" /> - ) -} + ); +}; -export default React.memo(InfilChart); \ No newline at end of file +export default React.memo(InfilChart); From 630c9492cdc380c885903408c592351cb6d66187 Mon Sep 17 00:00:00 2001 From: dongsilove Date: Tue, 17 Mar 2026 22:42:46 +0900 Subject: [PATCH 2/8] =?UTF-8?q?sn:=20=EC=B9=A8=EC=9E=85=EC=88=98=201?= =?UTF-8?q?=EC=B0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/infilChart.tsx | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 094936638..9b2401c28 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -150,10 +150,10 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { }; const renderInfoInput = (label: string, value?: string | number | null) => ( -
- +
+ {
); + const handleReset = () => { + resetState(); + } const renderBody = () => (
@@ -169,14 +172,14 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => {
-

+

침입수 분석 선택 조건

-
-
-

침입수 분석 결과

+

침입수 분석 결과

@@ -259,7 +262,7 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { yFieldText2="" /> ) : ( -
+
데이터가 없습니다.
)} From f993a4a13e922af92343a6659ab2bb86d2065369 Mon Sep 17 00:00:00 2001 From: dongsilove Date: Tue, 17 Mar 2026 22:53:00 +0900 Subject: [PATCH 3/8] =?UTF-8?q?sn:=20=ED=8F=B0=ED=8A=B8=20=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/popupComponent/chart/infilChart.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 9b2401c28..0f4d0bdb7 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -230,23 +230,23 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => {
- ● + {/* ● */} 상수사용량 적용연월
-
+
{selectedAplcnYm ? moment(selectedAplcnYm, 'YYYYMM').format('YYYY-MM') : '-'}
- ● + {/* ● */} 침입수량 산정결과
- 침입수량 - {inftwtQty} - m³/d + 침입수량 + {inftwtQty} + m³/d
From 13fad0c692906b7ee6c780bac6ba1769aa161643 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 09:38:43 +0900 Subject: [PATCH 4/8] =?UTF-8?q?sn:=20=EC=B9=A8=EC=9E=85=EC=88=982=EC=B0=A8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/popupComponent/chart/infilChart.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx index 0f4d0bdb7..4086f1966 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/infilChart.tsx @@ -151,9 +151,9 @@ const InfilChart = ({ pplMngNo = '' }: ModalOpenProp) => { const renderInfoInput = (label: string, value?: string | number | null) => (
- + {
-
-
-

- 강우유입수분석 결과 -

+

+ 강우유입수분석 결과 +

-
-
-
- 상수사용량 적용연월 -
-
- {aplcnYm ? moment(aplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} -
+
+ {/* 좌측 카드 */} +
+
+ 상수사용량 적용연월 +
+
+ {aplcnYm ? moment(aplcnYm, 'YYYYMM').format('YYYY-MM') : '-'} +
+
+ + {/* 우측 카드 */} +
+ {/* 좌측: 제목 (세로 가운데 정렬) */} +
+ + 강우유입수량 분석결과 + +
+ + {/* 우측: 지표 영역 */} +
+ +
+ 평균RDII +
+ {rdiiQty} + m³/d +
+
+ +
+ 적용 강우량 +
+ {rainTotal} + mm +
+
+ +
+ 강우량 대비 RDII +
+ {totalVolume} + m³/mm +
+
+
+
-
-
- 강우유입수량 분석결과 -
-
-
- 평균RDII -
- {rdiiQty} - m³/d -
+
+ {hasChartData ? ( + + ) : ( +
+ 데이터가 없습니다.
-
- 적용강우량 -
- {rainTotal} - mm -
-
-
- 강우량대비 RDII -
- {totalVolume} - m³/mm -
-
-
+ )}
-
- -
- {hasChartData ? ( - - ) : ( -
- 데이터가 없습니다. -
- )} -
From 165c7bcbbfa9a4a241f6cdc3c6c404b4f1a33aef Mon Sep 17 00:00:00 2001 From: LGS Date: Wed, 18 Mar 2026 14:13:08 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=EC=B9=A8=EC=9E=85=EC=88=98=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=EA=B2=B0=EA=B3=BC=20[=EA=B0=95=EC=9A=B0=EC=9C=A0?= =?UTF-8?q?=EC=9E=85=EC=88=98=EB=B6=84=EC=84=9D=EA=B2=B0=EA=B3=BC]=20?= =?UTF-8?q?=EB=B0=95=EC=8A=A4=20=E5=85=A7=203=EA=B0=9C=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=20=EB=8B=A8=EC=9C=84=20=EC=A0=95=EB=A0=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/rdiiChart.tsx | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx index 359b7978c..58d9f9a49 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -275,28 +275,39 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => { {/* 우측: 지표 영역 */}
- -
+
평균RDII -
- {rdiiQty} - m³/d +
+
+ + {rdiiQty} + + m³/d +
-
+
적용 강우량 -
- {rainTotal} - mm +
+
+ + {rainTotal} + + mm +
-
+
강우량 대비 RDII -
- {totalVolume} - m³/mm +
+
+ + {totalVolume} + + m³/mm +
From 53356228a7dc31236905bcd9b8a18ca346b7da94 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 15:24:32 +0900 Subject: [PATCH 8/8] =?UTF-8?q?sn:=20=EA=B0=95=EC=9A=B0=EC=9C=A0=EC=9E=85?= =?UTF-8?q?=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../popupComponent/chart/rdiiChart.tsx | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx index 58d9f9a49..07286bcbe 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -265,49 +265,49 @@ const RdiiChart = ({ pplMngNo = '' }: ModalOpenProp) => {
{/* 우측 카드 */} -
+
{/* 좌측: 제목 (세로 가운데 정렬) */} -
- - 강우유입수량 분석결과 - +
+
+ 강우유입수량 분석결과 +
{/* 우측: 지표 영역 */} -
-
- 평균RDII -
-
- - {rdiiQty} - - m³/d -
+
+
+
+ 평균RDII +
+
+ {rdiiQty} +
+
+ m³/d
-
- 적용 강우량 -
-
- - {rainTotal} - - mm -
+
+
+ 적용 강우량 +
+
+ {rainTotal} +
+
+ mm
-
- 강우량 대비 RDII -
-
- - {totalVolume} - - m³/mm -
+
+
+ 강우량 대비 RDII +
+
+ {totalVolume} +
+
+ m³/mm