diff --git a/apps/sn/.env.local b/apps/sn/.env.local index b755f2b4b..6c43ab12c 100644 --- a/apps/sn/.env.local +++ b/apps/sn/.env.local @@ -9,6 +9,6 @@ NEXT_PUBLIC_AUTH_USER_ID = token-id NEXT_PUBLIC_ACCESS_TOKEN = access-token NEXT_PUBLIC_REFRESH_TOKEN = refresh-token -#NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API -NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성 부장님 API +NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API +#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api # 최용성 부장님 API #NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api # 박이정 차장님 API diff --git a/apps/sn/app/(map-layout)/map/components/common/index.ts b/apps/sn/app/(map-layout)/map/components/common/index.ts index a17d2a0a8..feee420b3 100644 --- a/apps/sn/app/(map-layout)/map/components/common/index.ts +++ b/apps/sn/app/(map-layout)/map/components/common/index.ts @@ -20,16 +20,16 @@ type LayerContentMap = { // 레이어 선택시 변경되는 팝업 컨텐츠 동적으로 변경하도록 작업 const layerContentMap: LayerContentMap = { // TODO: gis데이터 추가되면 추가 작업 필요 - "하수처리시설": { component: SwtrmtFclt, }, - // 하수관로 개발용 - // "하수처리시설": { component: MsSwagePpl, }, + //"하수처리시설": { component: SwtrmtFclt, }, + "하수처리시설": { component: MsSwagePpl, }, "하수처리구역": {}, "우수토실": { component: Ssc, }, "중점우수토실": { component: Ssc, }, // 중점우수토실 여부 설정 "하수관로": { component: MsSwagePpl, }, "하수맨홀": { component: smh, }, - "빗물펌프": { component: StormWaterPump }, - "오수펌프": { component: sewagePump }, + "하수펌프장": { component: sewagePump }, + // "빗물펌프": { component: StormWaterPump }, + // "오수펌프": { component: sewagePump }, }; // 동적 컴포넌트 반환 함수 diff --git a/apps/sn/app/(map-layout)/map/components/common/table.ts b/apps/sn/app/(map-layout)/map/components/common/table.ts index d06973d37..54a75e27e 100644 --- a/apps/sn/app/(map-layout)/map/components/common/table.ts +++ b/apps/sn/app/(map-layout)/map/components/common/table.ts @@ -1,3 +1,33 @@ +// 하수관로 +export const MsSwagePplCol = [ + { id: 'avgGrdn', title: '평균구배' }, + { id: 'clarFvlc', title: '맑음유속' }, + { id: 'drtwMltvArea', title: '오수배수면적' }, + { id: 'exclnMltvArea', title: '우수배수면적' }, + { id: 'fcltMngNo', title: '시설관리번호' }, + // { id: 'fcltyShpCd', title: '시설물형태코드' }, + // { id: 'fid', title: 'FID' }, + // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, + { id: 'instMngNo', title: '기관관리번호' }, + { id: 'instlYmd', title: '설치일자' }, + { id: 'mapshtNo', title: '도엽번호' }, + // { id: 'mngInstCd', title: '관리기관코드' }, + // { id: 'mqltCd', title: '재질코드' }, + // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, + { id: 'pdmt', title: '관경' }, + { id: 'prlg', title: '연장' }, + { id: 'rnyssnFvlc', title: '우기유속' }, + { id: 'scendDpth', title: '종점깊이' }, + { id: 'scendMhlMngNo', title: '종점맨홀관리번호' }, + { id: 'tmptDpth', title: '시점깊이' }, + { id: 'tmptMhlMngNo', title: '시점맨홀관리번호' }, + { id: 'trflnCnt', title: '차선수' }, + // { id: 'usgCd', title: '용도코드' }, + { id: 'vrtcLen', title: '세로길이' }, + { id: 'wdthLen', title: '가로길이' }, + // { id: 'lyrTypeNm', title: '레이어타입명' }, +] + // 하수처리시설 export const SwtrmtFcltCol = [ { id: 'swtrmtFcltNm', title: '하수처리시설명' }, @@ -6,7 +36,7 @@ export const SwtrmtFcltCol = [ { id: 'cmcnYmd', title: '준공일자' }, { id: 'oprtngStrtYmd', title: '가동개시일자' }, { id: 'clsgYmd', title: '폐쇄일자' }, - { id: 'prcsMsrcCd', title: '처리공법코드' }, + // { id: 'prcsMsrcCd', title: '처리공법코드' }, // { id: 'laeCd', title: '지자체코드' }, { id: 'laeNm', title: '지자체명' }, { id: 'ctpvNm', title: '시도명' }, @@ -52,27 +82,49 @@ export const SwtrmtPrcsZoneCol = [ // 하수맨홀 export const MsSwageMhlCol = [ - { id: 'fid', title: 'FID' }, - { id: 'geom', title: 'geometry' }, - { id: 'ftreSmblCd', title: '지형지물부호코드' }, - { id: 'mngNo', title: '관리번호' }, + // { id: 'fid', title: 'FID' }, + // { id: 'geom', title: 'geometry' }, + // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, + { id: 'fcltMngNo', title: '시설관리번호' }, // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, { id: 'mapshtNo', title: '도엽번호' }, // { id: 'mngInstCd', title: '관리기관코드' }, { id: 'instlYmd', title: '설치일자' }, { id: 'lastDrdgnYmd', title: '최종준설일자' }, - { id: 'usgCd', title: '용도코드' }, + // { id: 'usgCd', title: '용도코드' }, // { id: 'fcltyShpCd', title: '시설물형태코드' }, - { id: 'mhlKndCd', title: '맨홀종류코드' }, + // { id: 'mhlKndCd', title: '맨홀종류코드' }, { id: 'swageMhDiam', title: '하수맨홀구경' }, { id: 'wdthLen', title: '가로길이' }, { id: 'vrtcLen', title: '세로길이' }, // { id: 'mqltCd', title: '재질코드' }, - { id: 'altdVl', title: '표고값' }, - { id: 'dpthlVl', title: '심도값' }, - { id: 'instMngNo', title: '기관관리번호' } + { id: 'altdVl', title: '표고' }, + { id: 'dpthlVl', title: '심도' }, + // { id: 'instMngNo', title: '기관관리번호' } ]; +// 하수펌프장 +export const SewagePump = [ + // { id: 'fid', title: 'FID' }, + // { id: 'geom', title: 'geometry' }, + // { id: 'ftreSmbolCd', title: '지형지물부호코드' }, + { id: 'fcltMngNo', title: '시설관리번호' }, + // { id: 'pbadmsEmdCd', title: '행정읍면동코드' }, + { id: 'mapshtNo', title: '도엽번호' }, + // { id: 'mngInstCd', title: '관리기관코드' }, + { id: 'instlYmd', title: '설치일자' }, + { id: 'swagePmstnNm', title: '하수펌프장명' }, + { id: 'pllnArea', title: '부지면적' }, + // { id: 'opngSttsCd', title: '개통상태코드' }, + // { id: 'usgCd', title: '용도코드' }, + { id: 'dailyPrcsCpct', title: '일일처리용량' }, + { id: 'maxImpndCpct', title: '최대저수용량' }, + { id: 'altdVl', title: '표고' }, + { id: 'wtlvVl', title: '수위' }, + { id: 'exclnWpmpAblt', title: '우수양수능력' }, + { id: 'instMngNo', title: '기관관리번호' }, +] + // 중점우수토실 측정지점 export const untrtSwgRainCol1 = [ { id: 'manage_no', title: '관리번호' }, diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx index 43f70de24..1f7774bce 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/MsSwagePpl.tsx @@ -1,11 +1,12 @@ +'use client' import { VerticalTable } from '@/components/ui/verticalTable'; import React, { useState } from 'react' import InputSection from '../InputSection'; import { handleInputChange } from '../common'; import { Button } from '@common/components/ui'; import InfilChart from './chart/infilChart'; +import RdiiChart from './chart/rdiiChart'; // 하수관로 -// TODO: RDII 버튼인가 그거 팝업 두개 구현 필요 const inputColumn = [ { id: "title", title: "설치주제", type: "select", options: ["BTL", "재정사업"] }, { id: "swtrmt_zone_cd", title: "처리구역", type: "select", options: ["구역1", "구역2"] }, @@ -15,17 +16,24 @@ const inputColumn = [ { id: "flow", title: "흐름방식", type: "select", options: ["자연유하", "압송"] }, { id: "place", title: "매설위치", type: "select", options: ["도로", "하상"] }, ]; -const SwtrmtFclt = ({ featureData }: { featureData: any }) => { +const MsSwagePpl = ({ featureData }: { featureData: any }) => { // SwtrmtFclt console.log("featureData", featureData); - const [isModalOpen, setIsModalOpen] = React.useState(false); + const [isModalInfil, setIsModalInfil] = React.useState(false); + const [isModalRdii, setIsModalRdii] = React.useState(false); const [btnTxt, setBtnTxt] = useState(""); - const openModal = (e: React.MouseEvent) => { + const openModalRdii = (e: React.MouseEvent) => { e.currentTarget.textContent && setBtnTxt(e.currentTarget.textContent) - setIsModalOpen(true); + setIsModalRdii(true); + } + const openModalInfil = (e: React.MouseEvent) => { + e.currentTarget.textContent && setBtnTxt(e.currentTarget.textContent) + setIsModalInfil(true); }; - const closeModal = () => { - setIsModalOpen(false); + const closeModalInfil = () => { + setIsModalInfil(false); }; + const closeModalRdii = () => { + setIsModalRdii(false);}; const [repairData, setRepairData] = useState([ { year: "2025", type: "개대체" }, { year: "2025", type: "보수" }, @@ -68,20 +76,21 @@ const SwtrmtFclt = ({ featureData }: { featureData: any }) => {
- + + ) } -export default SwtrmtFclt \ No newline at end of file +export default MsSwagePpl \ No newline at end of file diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/chart/aplcnYms.ts b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/aplcnYms.ts new file mode 100644 index 000000000..c9106fb16 --- /dev/null +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/aplcnYms.ts @@ -0,0 +1,209 @@ +import {useState, useEffect} from 'react'; +import { getData } from '@/components/lib/api'; +export type TInftwtAnls = { + inftwtAnlsSn:number; + aplcnYm: string; + enoCd: string; + ctpvCd: string; + sggCd: string; + swageTmplntCd: string; + swageTmplntNm: string; + swtrmtZoneCd: string; + swtrmtZoneNm: string; + atflCd: string; + atflId: string; + atflInpNm: string; + atflHrPttnNm: string; + atflMpngNm: string; + atflOilqNm: string; + atflNm: string; + drtwSwtcRt:number; + anlsInfo: string; + scsYn: string; +}; +export type TInftwtAnlsRslt = { + inftwtAnlsSn: number; + pplMngNo: string; + anlsTm: string; + predcOilq:number; +} +export type TRdiiAnls = { + rainInfwtAnlsSn:number; + aplcnYm: string; + enoCd: string; + ctpvCd: string; + sggCd: string; + swageTmplntCd: string; + swageTmplntNm: string; + swtrmtZoneCd: string; + swtrmtZoneNm: string; + atflCd: string; + atflId: string; + atflInpNm: string; + atflHrPttnNm: string; + atflMpngNm: string; + atflRainNm: string; + atflNm: string; + drtwSwtcRt:number; + anlsInfo: string; + scsYn: string; + srcNm: string; // 출처이름 +}; +export type TRdiiAnlsRslt = { + rainInfwtAnlsSn: number; + pplMngNo: string; + anlsTm: string; + predcOilq:number; +} +export type TOilqData = { + inftwtAnlsSn: number; // 침입수분석 일련번호 + pplMngNo: string; // 관로관리번호 + mtrngDt: string; // 계측일시 + oilq: number; // 유량 +} +const getOptionsAplcnYm = (yyyymms: string[]): { text: string; val: string }[] => { + let yyyymms1 = yyyymms.map(dateStr => { + const year = dateStr.slice(0, 4); + const month = dateStr.slice(4, 6); + return { + text: `${year}-${month}`, + val: dateStr + }; + }); + yyyymms1.unshift({ val: '0', text: '선택' }); + return yyyymms1; +}; +const selectAplcnYms = async(gubun:string) => { // 상수사용월 + try { + const queryString = ''; + const result = await getData(`v1/${gubun}/aplcnYm${queryString ? `?${queryString}` : ''}`); + if (result && result.length > 0) { + console.log("selectAplcnYms", result); + return getOptionsAplcnYm(result); + } + } catch (error) { + console.error(error); + } +}; +export const useAplcnYms = (gubun:string) => { + const [data, setData] = useState<{ text: string; val: string }[]>([]); + + useEffect(() => { + const fetch = async (gubun:string) => { + const result = await selectAplcnYms(gubun); + if (result) setData(result); + }; + fetch(gubun); + }, []); + + return data; +}; +export const getOptionsInftwtAnlsInfo = (anlsArr: TInftwtAnls[]): { text: string; val: number }[] => { + const options = anlsArr.map(anls => ({ + text: anls.anlsInfo, + val: anls.inftwtAnlsSn, + })); + options.unshift({ val: 0, text: '선택' }); + return options; +}; + +export const selectInftwtAnls = async(aplcnYm:String) => { // 침입수분석 + try { + const queryString = aplcnYm ? `aplcnYm=${aplcnYm}` : ''; + const result = await getData(`v1/inftwtAnls${queryString ? `?${queryString}` : ''}`); + if (result && result.numberOfElements > 0) { + console.log("selectInftwtAnls", result.content); + return result.content; + } + } catch (error) { + console.error(error); + } +}; +export const getChartDataInftwtAnlsRslt = (arr: TInftwtAnlsRslt[]): { label: string; val: number }[] => { + const options = arr.map(anlsRslt => ({ + label: anlsRslt.anlsTm, + val: anlsRslt.predcOilq, + })); + return options; +}; +export const selectInftwtAnlsRslt = async(inftwtAnlsSn:number, pplMngNo:string) => { // 침입수분석 결과 + try { + if ((inftwtAnlsSn === undefined || inftwtAnlsSn === 0) || !pplMngNo) { + console.warn("inftwtAnlsSn or pplMngNo is not provided"); + return []; + } + const result = await getData(`v1/inftwtAnlsRslt/ppl/${inftwtAnlsSn}/${pplMngNo}`); + if (result && result.numberOfElements > 0) { + console.log("selectInftwtAnlsRslt", result.content); + return result.content; + } + } catch (error) { + console.error(error); + } +}; +export const getChartDataOilq = (arr: TOilqData[]): { label: string; val: number }[] => { + const options = arr.map(anlsRslt => ({ + label: anlsRslt.mtrngDt, + val: anlsRslt.oilq, + })); + return options; +}; +export const selectOilq = async(inftwtAnlsSn:number, pplMngNo:string) => { // 유량 + try { + if ((inftwtAnlsSn === undefined || inftwtAnlsSn === 0) || !pplMngNo) { + console.warn("inftwtAnlsSn or pplMngNo is not provided"); + return []; + } + const result = await getData(`v1/inftwtAnlsRslt/oilqppl/${inftwtAnlsSn}/${pplMngNo}`); + if (result && result.numberOfElements > 0) { + console.log("selectOilq", result.content); + return result.content; + } + } catch (error) { + console.error(error); + } +}; + +export const getOptionsRdiiAnlsInfo = (anlsArr: TRdiiAnls[]): { text: string; val: number }[] => { + const options = anlsArr.map(anls => ({ + text: anls.anlsInfo, + val: anls.rainInfwtAnlsSn, + })); + options.unshift({ val: 0, text: '선택' }); + return options; +}; + +export const selectRdiiAnls = async(aplcnYm:String) => { // 침입수분석 + try { + const queryString = aplcnYm ? `aplcnYm=${aplcnYm}` : ''; + const result = await getData(`v1/rdiiAnls${queryString ? `?${queryString}` : ''}`); + if (result && result.numberOfElements > 0) { + console.log("selectRdiiAnls", result.content); + return result.content; + } + } catch (error) { + console.error(error); + } +}; +export const getChartDataRdiiAnlsRslt = (arr: TRdiiAnlsRslt[]): { label: string; val: number }[] => { + const options = arr.map(anlsRslt => ({ + label: anlsRslt.anlsTm, + val: anlsRslt.predcOilq, + })); + return options; +}; +export const selectRdiiAnlsRslt = async(rainInfwtAnlsSn:number, pplMngNo:string) => { // 침입수분석 결과 + try { + if ((rainInfwtAnlsSn === undefined || rainInfwtAnlsSn === 0) || !pplMngNo) { + console.warn("RdiiAnlsSn or pplMngNo is not provided"); + return []; + } + const result = await getData(`v1/rdiiAnlsRslt/ppl/${rainInfwtAnlsSn}/${pplMngNo}`); + if (result && result.numberOfElements > 0) { + console.log("selectRdiiAnlsRslt", result.content); + return result.content; + } + } catch (error) { + console.error(error); + } +}; 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 f82184db8..7385d84cc 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,17 +1,37 @@ -import React, { useState } from 'react' -import { type ChartConfig, MainChart, CHART_FORM } from "@common/business_components"; -import Modal from '@/components/ui/modal'; -import { Button } from '@common/components/ui'; +'use client' +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 type { TInftwtAnls } from './aplcnYms'; +import { useAplcnYms, getOptionsInftwtAnlsInfo, selectInftwtAnls } from './aplcnYms'; +import { getChartDataInftwtAnlsRslt, selectInftwtAnlsRslt, selectOilq, getChartDataOilq } from './aplcnYms'; type ModalOpenProp = { isModalOpen: boolean, setIsModalOpen: (open: boolean) => void, closeModal: () => void, btnTxt?: string, } + const InfilChart = ({ btnTxt, isModalOpen, setIsModalOpen, closeModal }: ModalOpenProp) => { - const [popupOpen, setPopupOpen] = React.useState(false); + const [popupOpen, setPopupOpen] = React.useState(true); const buttonRef = React.useRef(null); // 버튼 참조 const [popupPosition, setPopupPosition] = useState<{ top: number; left: number }>({ top: 0, left: 0 }); // 팝업 위치 + const [aplcnYm, setAplcnYm] = useState("0"); + const [inftwtAnlss, setInftwtAnlss] = useState([]); + const [inftwtAnlsInfos, setInftwtAnlsInfos] = useState([{ val: 0, text: '선택' }]); // 침입수분석정보 options + const [inftwtAnls, setInftwtAnls] = useState(null); // 침입수분석정보 + const [inftwtAnlsSn, setInftwtAnlsSn] = useState(0); // 침입수분석 정보 선택시 사용 + const [chartData, setChartData] = useState<{ chartData1: { label: string; val: number }[]; chartData2: { label: string; val: number }[] }>({ + chartData1: [{ label: "1", val: 20 }, + { label: "3", val: 40 }, + { label: "5", val: 60 },], + chartData2: [{ label: "1", val: 15 }, + { label: "3", val: 35 }, + { label: "5", val: 55 },], + }); + const aplcnYms = useAplcnYms('inftwtAnlsRslt'); // 상수사용월 데이터 가져오기 const openPopup = () => { if (buttonRef.current) { const rect = buttonRef.current.getBoundingClientRect(); // 버튼 위치 계산 @@ -22,36 +42,89 @@ const InfilChart = ({ btnTxt, isModalOpen, setIsModalOpen, closeModal }: ModalOp } setPopupOpen(true); // 팝업 열기 }; - console.log("btnTxt", btnTxt); - const closePopup = () => { setPopupOpen(false); }; // 팝업 닫기 + //console.log("btnTxt", btnTxt); + const chartForm = CHART_FORM.LINE; - const chartData = { - chartData1: [ - { label: "1", val: 20 }, - { label: "3", val: 40 }, - { label: "5", val: 60 }, - ], - chartData2: [ - { label: "1", val: 15 }, - { label: "3", val: 35 }, - { label: "5", val: 55 }, - ], - } - const chartConfig = Object.values(chartData).flat().reduce((config, element) => { - config[element.label] = { - label: element.label, - color: "hsl(var(--chart-1))", - }; - return config; - }, {} as Record) satisfies ChartConfig; - const getCurrentDate = () => { - const today = new Date(); - const year = today.getFullYear(); - const month = String(today.getMonth() + 1).padStart(2, "0"); // 월은 0부터 시작하므로 +1 - return `${year}-${month}`; + const chartConfig = { + chartData1: { label: '침입수예측유량', color: "red", }, + chartData2: { label: '실측유량', color: "orange", } + } as ChartConfig; + + useEffect(() => { + if (isModalOpen === false) { + setPopupOpen(true); // 모달이 닫힐 때 팝업은 + setAplcnYm(""); // 상수사용월 초기화 + setInftwtAnlss([]); // 침입수분석 초기화 + setInftwtAnlsInfos([{ val: 0, text: '선택' }]); // 침입수분석정보 초기화 + setInftwtAnls(null); // 침입수분석정보 초기화 + setInftwtAnlsSn(0); // 침입수분석 일련번호 초기화 + setChartData({ + chartData1: [{ label: "1", val: 20 }, + { label: "3", val: 40 }, + { label: "5", val: 60 },], + chartData2: [{ label: "1", val: 15 }, + { label: "3", val: 35 }, + { label: "5", val: 55 },], + }); // 차트 데이터 초기화 + } + }, [isModalOpen]); + + // 상수사용월 변경시 분석 정보 리스트 가져오기 + useEffect(() => { + // aplcnYm이 비어있거나 "0"이면 API 호출하지 않음 + if (!aplcnYm || aplcnYm === "0" || aplcnYm === "") { + setInftwtAnlsSn(0); // 초기화 + setInftwtAnlsInfos([{ val: 0, text: '선택' }]); + return; + } + + selectInftwtAnls(aplcnYm) + .then((data) => { + setInftwtAnlss(data ?? []); + setInftwtAnlsInfos(getOptionsInftwtAnlsInfo(data)); + setInftwtAnlsSn(0); // 초기화 + }) + .catch((error) => { + console.error("selectInftwtAnls 에러:", error); + setInftwtAnlss([]); + setInftwtAnlsInfos([{ val: 0, text: '선택' }]); + }); + + }, [aplcnYm]); + + // 값 표시 + useEffect(() => { + // 선택된 침입수분석 정보에 대한 처리 로직 + if (inftwtAnlsSn === 0) return; + const selectedAnls = inftwtAnlss.find(anls => anls.inftwtAnlsSn === inftwtAnlsSn); + if (selectedAnls) { + setInftwtAnls(selectedAnls); + } + }, [inftwtAnlsSn]); + + const closePopup = () => { // 팝업 닫기 + selectInftwtAnlsRslt(inftwtAnlsSn, "L13101003").then((data) => {// 침입수분석 결과 조회 + const rsltData = getChartDataInftwtAnlsRslt(data ?? []); + setChartData(prev => ({ + ...prev, + chartData1: rsltData // 침입수분석결과 + })); + }); + selectOilq(inftwtAnlsSn,"L13101003").then((data) => {// 유량 조회 + const rsltData = getChartDataOilq(data ?? []); + setChartData(prev => ({ + ...prev, + chartData2: rsltData // 유량 + })); + }); + setPopupOpen(false); }; - return ( - + + + + const renderBody = () => ( + <> + {/* */} {/* 분석 입력현황 조회 */}
@@ -75,65 +148,111 @@ const InfilChart = ({ btnTxt, isModalOpen, setIsModalOpen, closeModal }: ModalOp
{popupOpen && (
-
분석 입력현황
-
-
상수사용량 정보:
-
- +
침입수분석 입력현황
+
+
+ + { + setAplcnYm(String(val)); + }} + />
-
오수 전환율:
-
- +
+ + { + setInftwtAnlsSn(Number(val)); + }} + />
-
수용가-맨홀 매칭:
-
- +
+ +
-
관망도 자료:
-
- +
+ + +
+
+ + +
+
+ + +
+
+ +
- {btnTxt === 'RDII' ? <>
강우 자료:
-
- -
-
RTX 계수 출처:
-
- -
- : null}
-
-
- )} - +
)} + {/* */} + + ) + + return ( + ) } 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 new file mode 100644 index 000000000..3b13a3df7 --- /dev/null +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/chart/rdiiChart.tsx @@ -0,0 +1,258 @@ +'use client' +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 type { TRdiiAnls, TRdiiAnlsRslt, TOilqData } from './aplcnYms'; +import { getChartDataRdiiAnlsRslt, selectRdiiAnlsRslt } from './aplcnYms'; +import { getOptionsRdiiAnlsInfo, selectRdiiAnls, useAplcnYms } from './aplcnYms'; +type ModalOpenProp = { + isModalOpen: boolean, + setIsModalOpen: (open: boolean) => void, + closeModal: () => void, + btnTxt?: string, +} + +const RdiiChart = ({ btnTxt, isModalOpen, setIsModalOpen, closeModal }: ModalOpenProp) => { + const [popupOpen, setPopupOpen] = React.useState(true); + const buttonRef = React.useRef(null); // 버튼 참조 + const [popupPosition, setPopupPosition] = useState<{ top: number; left: number }>({ top: 0, left: 0 }); // 팝업 위치 + const [aplcnYm, setAplcnYm] = useState(""); + const [rdiiAnlss, setRdiiAnlss] = useState([]); + const [rdiiAnlsInfos, setRdiiAnlsInfos] = useState([{ val: 0, text: '선택' }]); // 강우유입수분석정보 options + const [rdiiAnls, setRdiiAnls] = useState(null); // 강우유입수분석정보 + const [rainInfwtAnlsSn, setRainInfwtAnlsSn] = useState(0); // 강우유입수분석 정보 선택시 사용 + const [chartData, setChartData] = useState<{ chartData1: { label: string; val: number }[]; chartData2: { label: string; val: number }[] }>({ + chartData1: [{ label: "1", val: 20 }, + { label: "3", val: 40 }, + { label: "5", val: 60 },], + chartData2: [{ label: "1", val: 15 }, + { label: "3", val: 35 }, + { label: "5", val: 55 },], + }); + + const aplcnYms = useAplcnYms('rdiiAnlsRslt'); // 상수사용월 데이터 가져오기 + const openPopup = () => { + if (buttonRef.current) { + const rect = buttonRef.current.getBoundingClientRect(); // 버튼 위치 계산 + setPopupPosition({ + top: rect.bottom + window.scrollY, // 버튼 아래쪽 + left: rect.left + window.scrollX, // 버튼 왼쪽 + }); + } + setPopupOpen(true); // 팝업 열기 + }; + //console.log("btnTxt", btnTxt); + + const chartForm = CHART_FORM.LINE; + const chartConfig = { + chartData1: { label: '강우유입수예측유량', color: "red", }, + chartData2: { label: '실측유량', color: "orange", } + } as ChartConfig; + + useEffect(() => { + if (isModalOpen === false) { + setPopupOpen(true); // 모달이 닫힐 때 팝업은 + setAplcnYm(""); // 상수사용월 초기화 + setRdiiAnlss([]); // 강우유입수분석 초기화 + setRdiiAnlsInfos([{ val: 0, text: '선택' }]); // 강우유입수분석정보 초기화 + setRdiiAnls(null); // 강우유입수분석정보 초기화 + setRainInfwtAnlsSn(0); // 강우유입수분석 일련번호 초기화 + setChartData({ + chartData1: [{ label: "1", val: 20 }, + { label: "3", val: 40 }, + { label: "5", val: 60 },], + chartData2: [{ label: "1", val: 15 }, + { label: "3", val: 35 }, + { label: "5", val: 55 },], + }); // 차트 데이터 초기화 + } + }, [isModalOpen]); + + // 상수사용월 변경시 분석 정보 리스트 가져오기 + useEffect(() => { + // aplcnYm이 비어있거나 "0"이면 API 호출하지 않음 + if (!aplcnYm || aplcnYm === "0" || aplcnYm === "") { + setRainInfwtAnlsSn(0); // 초기화 + setRdiiAnlsInfos([]); + return; + } + + selectRdiiAnls(aplcnYm) + .then((data) => { + setRdiiAnlss(data ?? []); + setRdiiAnlsInfos(getOptionsRdiiAnlsInfo(data)); + setRainInfwtAnlsSn(0); // 초기화 + }) + .catch((error) => { + console.error("selectrdiiAnls 에러:", error); + setRdiiAnlss([]); + setRdiiAnlsInfos([]); + }); + }, [aplcnYm]); + + // 값 표시 + useEffect(() => { + // 선택된 강우유입수분석 정보에 대한 처리 로직 + if (rainInfwtAnlsSn === 0) return; + const selectedAnls = rdiiAnlss.find(anls => anls.rainInfwtAnlsSn === rainInfwtAnlsSn); + if (selectedAnls) { + setRdiiAnls(selectedAnls); + } + }, [rainInfwtAnlsSn]); + + const closePopup = () => { // 팝업 닫기 + selectRdiiAnlsRslt(rainInfwtAnlsSn, "L13101003").then((data) => {// 강우유입수분석 결과 조회 + const rsltData = getChartDataRdiiAnlsRslt(data ?? []); + setChartData(prev => ({ + ...prev, + chartData1: rsltData // 강우유입수분석결과 + })); + }); + // selectOilq(rdiiAnlsSn,"L13101003").then((data) => {// 유량 조회 + // const rsltData = getChartDataOilq(data ?? []); + // setChartData(prev => ({ + // ...prev, + // chartData2: rsltData // 유량 + // })); + // }); + setPopupOpen(false); + }; + + + + const renderBody = () => ( + <> + {/* 분석 입력현황 조회 */} +
+
+ + + {/* 강우유입수량 분석결과 */} +
+ 강우유입수량 분석결과 +
+ 120 + m³/d +
+
+
+ {/* 차트 */} +
+ +
+
+ {popupOpen && ( +
+
강우유입수분석 입력현황
+
+
+ + { + setAplcnYm(String(val)); + }} + /> +
+
+ + { + setRainInfwtAnlsSn(Number(val)); + }} + /> +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
)} + {/* */} + + ) + + return ( + + ) +} + +export default RdiiChart \ No newline at end of file diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx index 3867e16f9..97ae09a10 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/sewagePump.tsx @@ -5,13 +5,15 @@ const inputColumn = [ { id: "mltv_dtdv_nm", title: "배수분구", type: "input" }, { id: "freq", title: "설계빈도", type: "input" }, ] -// 오수펌프 -const sewagePump = ({ featureData }: { featureData: any }) => { +// 하수펌프장 +const sewagePump = () => { return ( -
-
+ <> + + ) } diff --git a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx index 79f90a32a..68a23de87 100644 --- a/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx +++ b/apps/sn/app/(map-layout)/map/featureClickEventPopup.tsx @@ -6,7 +6,7 @@ import { useGisContext } from "@common/business_components/ui/map/Gis"; import { Button } from "@common/components/ui"; import { useEffect, useRef, useState } from "react"; import { getLayerContentComponent } from "./components/common"; -import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2 } from "./components/common/table"; +import { SwtrmtFcltCol, SwtrmtPrcsZoneCol, untrtSwgRainCol1, untrtSwgRainCol2, MsSwagePplCol, SewagePump, MsSwageMhlCol } from "./components/common/table"; // TODO: const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, featureData: any }) => { const { gisMap } = useGisContext() as unknown as { checkedLayerIds: React.MutableRefObject; treeData: { lyrSn: number }[] | null; gisCore: any; gisMap: any; }; @@ -37,13 +37,26 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, featureLayer = layer; // 피처가 속한 레이어 찾기 } }); + console.log("featureLayer.get('lyrTyNm');", featureLayer.get('lyrTyNm')); // SearchModal 클릭 이벤트와 Gis 클릭 이벤트 구분하기 if (featureLayer.get('lyrNm') === null) { if (featureData.lyrTypeNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설'; else if (featureData.lyrTypeNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역'; else if (featureData.lyrTypeNm === 'om_dt_untrt_swg_rain') result = '중점우수토실'; + else if (featureData.lyrTypeNm === 'tb_ms_swage_ppl') result = '하수관로'; + else if (featureData.lyrTypeNm === 'tb_ms_swage_pmstn') result = '하수펌프장'; + else if (featureData.lyrTypeNm === 'tb_ms_swage_mhl') result = '하수맨홀'; + } + else { + const lyrTyNm = featureLayer.get('lyrTyNm'); + if (lyrTyNm === 'tb_il_swage_prcs_fclt') result = '하수처리시설'; + else if (lyrTyNm === 'tb_ms_swage_prcs_zone') result = '하수처리구역'; + else if (lyrTyNm === 'om_dt_untrt_swg_rain') result = '중점우수토실'; + else if (lyrTyNm === 'tb_ms_swage_ppl') result = '하수관로'; + else if (lyrTyNm === 'tb_ms_swage_pmstn') result = '하수펌프장'; + else if (lyrTyNm === 'tb_ms_swage_mhl') result = '하수맨홀'; + else result = featureLayer.get('lyrNm'); } - else result = featureLayer.get('lyrNm'); return result; // return featureLayer.get('lyrNm'); // 레이어 이름 출력 @@ -86,15 +99,21 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, setButtonChk(true) break; case '하수관로': + setHeadlist(MsSwagePplCol) setButtonChk(true) break; - case '오수펌프': - setButtonChk(true) - break; - case '빗물펌프': + // case '오수펌프': + // setButtonChk(true) + // break; + // case '빗물펌프': + // setButtonChk(true) + // break; + case '하수펌프장': + setHeadlist(SewagePump) setButtonChk(true) break; case '하수맨홀': + setHeadlist(MsSwageMhlCol) setButtonChk(true) break; default: diff --git a/apps/sn/app/components/lib/utils/date.ts b/apps/sn/app/components/lib/utils/date.ts index 9319d7013..fe717301f 100644 --- a/apps/sn/app/components/lib/utils/date.ts +++ b/apps/sn/app/components/lib/utils/date.ts @@ -11,3 +11,15 @@ export const yearOptions = Array.from({ length: 10 }, (_, i) => { const year = new Date().getFullYear() - i; return { text: `${year}년`, val: year.toString() }; }); + +// ["202506", "202505", "202502", "202405"] 을 SelectBox의 옵션으로 변환 +export const convertToTextValArray = (yyyymms: string[]): { text: string; val: string }[] => { + return yyyymms.map(dateStr => { + const year = dateStr.slice(0, 4); + const month = dateStr.slice(4, 6); + return { + text: `${year}-${month}`, + val: dateStr + }; + }); +}; \ No newline at end of file diff --git a/package.json b/package.json index 818c7999d..1af128b94 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "packages/*" ], "scripts": { - "build": "turbo run build --filter=!wr", + "build": "turbo run build --filter=!wr --filter=!cs", "build:common": "turbo run build --filter=@common/*", "dev": "turbo run dev", "dev:cs": "turbo run dev --filter=cs",