diff --git a/apps/sn/app/map/SearchModal.tsx b/apps/sn/app/map/SearchModal.tsx index b817e5d2e..f901ace48 100644 --- a/apps/sn/app/map/SearchModal.tsx +++ b/apps/sn/app/map/SearchModal.tsx @@ -1,143 +1,141 @@ -import FeatureClickEventPopup from './featureClickEventPopup'; -import React, { useState } from 'react'; -import axios from 'axios'; -import { UiModal, UiTable } from '@common/business_components/ui'; -import { Button, Input, Label } from '@common/components'; -import { UiTable2 } from '@common/business_components/ui/table/index-2'; -import { UITab2 } from '@common/business_components/ui/tab/index-2'; -import { SelectBox2 } from '@common/business_components/ui/select/index-2'; -import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; -import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox'; - - +import FeatureClickEventPopup from "./featureClickEventPopup"; +import React, { useState } from "react"; +import axios from "axios"; +import { UiModal, UiTable } from "@common/business_components/ui"; +import { Button, Input, Label } from "@common/components"; +import { UiTable2 } from "@common/business_components/ui/table/index-2"; +import { UITab2 } from "@common/business_components/ui/tab/index-2"; +import { SelectBox2 } from "@common/business_components/ui/select/index-2"; +import { YearRangeSelectBox } from "@/components/ui/YearRangeSelectBox"; +import { SidoSigunguSelectBox } from "@/components/ui/SidoSigunguSelectBox"; const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`; // 탭 const TABS = [ - { val: 'basic', text: '기본정보' }, - { val: 'operation', text: '운영정보' }, - { val: 'report', text: '하수도정비기본계획보고서' }, + { val: "basic", text: "기본정보" }, + { val: "operation", text: "운영정보" }, + { val: "report", text: "하수도정비기본계획보고서" }, ]; // 기본정보 '구분' 선택 목록 const BASIC_TYPES = [ - { val: 'tb_ms_swage_ppl', text: '하수관로' }, - { val: 'tb_il_swage_prcs_fclt', text: '하수처리시설' }, - { val: 'tb_ms_swage_prcs_zone', text: '하수처리구역' }, - { val: 'tb_ms_swage_mh', text: '하수맨홀' }, - { val: 'tb_ms_swage_psmtn_1', text: '오수펌프' }, - { val: 'tb_ms_swage_psmtn_2', text: '빗물펌프' }, - { val: 'tb_ms_otfl', text: '우수토실' }, + { val: "tb_ms_swage_ppl", text: "하수관로" }, + { val: "tb_il_swage_prcs_fclt", text: "하수처리시설" }, + { val: "tb_ms_swage_prcs_zone", text: "하수처리구역" }, + { val: "tb_ms_swage_mh", text: "하수맨홀" }, + { val: "tb_ms_swage_psmtn_1", text: "오수펌프" }, + { val: "tb_ms_swage_psmtn_2", text: "빗물펌프" }, + { val: "tb_ms_otfl", text: "우수토실" }, ]; // 운영정보 '구분' 선택 목록 const WORK_TYPES = [ - { val: 'maintenance', text: '보수 및 갱신' }, - { val: 'cleaning', text: '청소 및 준설' }, - { val: 'inspection', text: '점검 및 진단' }, + { val: "maintenance", text: "보수 및 갱신" }, + { val: "cleaning", text: "청소 및 준설" }, + { val: "inspection", text: "점검 및 진단" }, ]; const YEARS = Array.from({ length: 100 }, (_, i) => `${2025 - i}`); // 테이블 헤더 리스트 // 하수관로 const swagePplTableHeadlist = [ - { id: 'pipeNumber', title: '관로번호' }, - { id: 'gisManageNumber', title: '관리번호(GIS)' }, - { id: 'managingInstitution', title: '관리기관' }, - { id: 'drawingNumber', title: '도엽번호' }, - { id: 'installationLocation', title: '설치위치' }, - { id: 'usage', title: '용도' }, - { id: 'pipeDiameter', title: '관경' }, - { id: 'pipeLength', title: '관로연장' }, - { id: 'pipeType', title: '관종' }, - { id: 'burialDepth', title: '매설심도' }, - { id: 'constructionYear', title: '개보수 년도' }, - { id: 'installationSubject', title: '설치 주체' }, - { id: 'area', title: '구역' }, - { id: 'division', title: '분구' }, - { id: 'alignmentType', title: '지선/간선 구분' }, - { id: 'flowType', title: '흐름 방식' }, - { id: 'boxCount', title: '박스 열수' }, - { id: 'height', title: '높이' }, - { id: 'width', title: '폭' }, - { id: 'startManholeNumber', title: '시점 맨홀번호' }, - { id: 'endManholeNumber', title: '종점 맨홀번호' }, - { id: 'startElevation', title: '시점관저고' }, - { id: 'endElevation', title: '종점관저고' }, -] + { id: "pipeNumber", title: "관로번호" }, + { id: "gisManageNumber", title: "관리번호(GIS)" }, + { id: "managingInstitution", title: "관리기관" }, + { id: "drawingNumber", title: "도엽번호" }, + { id: "installationLocation", title: "설치위치" }, + { id: "usage", title: "용도" }, + { id: "pipeDiameter", title: "관경" }, + { id: "pipeLength", title: "관로연장" }, + { id: "pipeType", title: "관종" }, + { id: "burialDepth", title: "매설심도" }, + { id: "constructionYear", title: "개보수 년도" }, + { id: "installationSubject", title: "설치 주체" }, + { id: "area", title: "구역" }, + { id: "division", title: "분구" }, + { id: "alignmentType", title: "지선/간선 구분" }, + { id: "flowType", title: "흐름 방식" }, + { id: "boxCount", title: "박스 열수" }, + { id: "height", title: "높이" }, + { id: "width", title: "폭" }, + { id: "startManholeNumber", title: "시점 맨홀번호" }, + { id: "endManholeNumber", title: "종점 맨홀번호" }, + { id: "startElevation", title: "시점관저고" }, + { id: "endElevation", title: "종점관저고" }, +]; // 하수처리구역 const swageZoneTableHeadlist = [ - { id: 'ctpvNm', title: '시도명' }, - { id: 'sggNm', title: '시군구명' }, - { id: 'swtrmtZoneNm', title: '하수처리구역명' }, - { id: 'swtrmtFcltCd', title: '하수처리시설번호' }, - { id: 'swtrmtFcltNm', title: '하수처리시설명' }, -] + { id: "ctpvNm", title: "시도명" }, + { id: "sggNm", title: "시군구명" }, + { id: "swtrmtZoneNm", title: "하수처리구역명" }, + { id: "swtrmtFcltCd", title: "하수처리시설번호" }, + { id: "swtrmtFcltNm", title: "하수처리시설명" }, +]; // 하수처리시설 const swageFcltTableHeadlist = [ - { id: 'swtrmtFcltCd', title: '하수처리시설코드' }, - { id: 'swtrmtFcltNm', title: '하수처리시설명' }, - { id: 'fcltCpct', title: '시설용량' }, - { id: 'rgnExpln', title: '지역설명' }, - { id: 'cmcnYmd', title: '준공일자' }, - { id: 'oprtngStrtYmd', title: '가동개시일자' }, - { id: 'clsgYmd', title: '폐쇄일자' }, - { id: 'laeNm', title: '지자체명' }, - { id: 'ctpvNm', title: '시도명' }, - { id: 'sggNm', title: '시군구명' }, - { id: 'sareaNm', title: '권역명' }, - { id: 'lrgeSareaNm', title: '대권역명' }, - { id: 'rvrNm', title: '하천명' }, - { id: 'addr', title: '주소' }, - { id: 'daddr', title: '상세주소' }, - { id: 'rdnmAddr', title: '도로명주소' }, - { id: 'dtlRdnmAddr', title: '상세도로명주소' }, - { id: 'dschgWtstNm', title: '방류수계명' }, - { id: 'pllnArea', title: '부지면적' }, - { id: 'mngRprtvBzentyNm', title: '관리대행업제명' }, - { id: 'swtrmtPpltnCnt', title: '하수처리인구수' }, - { id: 'prcsZoneAreaSum', title: '처리구역면적합계' }, - { id: 'geom', title: 'geometry' }, - { id: 'xcrd', title: 'X좌표' }, - { id: 'ycrd', title: 'Y좌표' }, - { id: 'rprsMsrcCn', title: '대표공법내용' }, - { id: 'sttyCrtrBod', title: '법정기준생물화학적산소요구량' }, - { id: 'sttyCrtrToc', title: '법정기준TOC' }, - { id: 'sttyCrtrSs', title: '법정기준SS' }, - { id: 'sttyCrtrTn', title: '법정기준총질소' }, - { id: 'sttyCrtrTph', title: '법정기준총인' }, - { id: 'sttyCrtrClbclCnt', title: '법정기준대장균수' }, - { id: 'bsnNm', title: '유역명' }, + { id: "swtrmtFcltCd", title: "하수처리시설코드" }, + { id: "swtrmtFcltNm", title: "하수처리시설명" }, + { id: "fcltCpct", title: "시설용량" }, + { id: "rgnExpln", title: "지역설명" }, + { id: "cmcnYmd", title: "준공일자" }, + { id: "oprtngStrtYmd", title: "가동개시일자" }, + { id: "clsgYmd", title: "폐쇄일자" }, + { id: "laeNm", title: "지자체명" }, + { id: "ctpvNm", title: "시도명" }, + { id: "sggNm", title: "시군구명" }, + { id: "sareaNm", title: "권역명" }, + { id: "lrgeSareaNm", title: "대권역명" }, + { id: "rvrNm", title: "하천명" }, + { id: "addr", title: "주소" }, + { id: "daddr", title: "상세주소" }, + { id: "rdnmAddr", title: "도로명주소" }, + { id: "dtlRdnmAddr", title: "상세도로명주소" }, + { id: "dschgWtstNm", title: "방류수계명" }, + { id: "pllnArea", title: "부지면적" }, + { id: "mngRprtvBzentyNm", title: "관리대행업제명" }, + { id: "swtrmtPpltnCnt", title: "하수처리인구수" }, + { id: "prcsZoneAreaSum", title: "처리구역면적합계" }, + { id: "geom", title: "geometry" }, + { id: "xcrd", title: "X좌표" }, + { id: "ycrd", title: "Y좌표" }, + { id: "rprsMsrcCn", title: "대표공법내용" }, + { id: "sttyCrtrBod", title: "법정기준생물화학적산소요구량" }, + { id: "sttyCrtrToc", title: "법정기준TOC" }, + { id: "sttyCrtrSs", title: "법정기준SS" }, + { id: "sttyCrtrTn", title: "법정기준총질소" }, + { id: "sttyCrtrTph", title: "법정기준총인" }, + { id: "sttyCrtrClbclCnt", title: "법정기준대장균수" }, + { id: "bsnNm", title: "유역명" }, ]; // 하수맨홀 (추후 작성 예정) const swageMhTableHeadlist = [ - { id: 'swtrmtFcltCd', title: '하수처리시설코드' }, + { id: "swtrmtFcltCd", title: "하수처리시설코드" }, ]; // 운영정보 const operationTableHeadlist = [ - { id: 'no', title: 'NO' }, - { id: 'manageNumber', title: '관리번호' }, - { id: 'diagnosisYear', title: '진단년도' }, - { id: 'null1', title: '...' }, - { id: 'null2', title: '...' }, - { id: 'installationLocation', title: '매설위치' }, + { id: "no", title: "NO" }, + { id: "manageNumber", title: "관리번호" }, + { id: "diagnosisYear", title: "진단년도" }, + { id: "null1", title: "..." }, + { id: "null2", title: "..." }, + { id: "installationLocation", title: "매설위치" }, ]; // 하수도정비 기본계획 보고서 const reportTableHeadlist = [ - { id: 'no', title: 'NO' }, - { id: 'approvalYear', title: '승인년도' }, - { id: 'sido', title: '시도' }, - { id: 'sigungu', title: '시군구' }, - { id: 'treatmentPlant', title: '하수처리장' }, - { id: 'treatmentZone', title: '하수처리구역' }, - { id: 'reportCount', title: '보고서(00건)' }, - { id: 'planMapCount', title: '하수도대장 평면도(00건)' }, - { id: 'regDate', title: '등록일자' }, + { id: "no", title: "NO" }, + { id: "approvalYear", title: "승인년도" }, + { id: "sido", title: "시도" }, + { id: "sigungu", title: "시군구" }, + { id: "treatmentPlant", title: "하수처리장" }, + { id: "treatmentZone", title: "하수처리구역" }, + { id: "reportCount", title: "보고서(00건)" }, + { id: "planMapCount", title: "하수도대장 평면도(00건)" }, + { id: "regDate", title: "등록일자" }, ]; const 처리구역List = [ - { val: '0', text: '선택' }, - { val: 'a', text: 'A' }, - { val: 'b', text: 'B' }, + { val: "0", text: "선택" }, + { val: "a", text: "A" }, + { val: "b", text: "B" }, ]; interface SearchModalProps { @@ -147,7 +145,12 @@ interface SearchModalProps { } // 날짜 조합 함수 -const getDateString = (year: string, month: string, day: string, defaultDate: string) => { +const getDateString = ( + year: string, + month: string, + day: string, + defaultDate: string, +) => { if (!year && !month && !day) return defaultDate; const y = year || defaultDate.slice(0, 4); const m = month || defaultDate.slice(4, 6); @@ -155,38 +158,41 @@ const getDateString = (year: string, month: string, day: string, defaultDate: st return `${y}${m}${d}`; }; -const SearchModal: React.FC = ({ open, onOpenChange, onFeatureSelect }) => { - const [activeTab, setActiveTab] = useState(TABS[0]?.val ?? 'basic'); - const [workType, setWorkType] = useState(WORK_TYPES[0]?.val ?? ''); +const SearchModal: React.FC = ({ + open, + onOpenChange, + onFeatureSelect, +}) => { + const [activeTab, setActiveTab] = useState(TABS[0]?.val ?? "basic"); + const [workType, setWorkType] = useState(WORK_TYPES[0]?.val ?? ""); const [showTable, setShowTable] = useState(false); const [tableData, setTableData] = useState([]); const [tableCount, setTableCount] = useState(0); const [curPage, setCurPage] = useState(1); - const [basicType, setBasicType] = useState(BASIC_TYPES[0]?.val ?? ''); + const [basicType, setBasicType] = useState(BASIC_TYPES[0]?.val ?? ""); const [시도, set시도] = useState(0); const [시군구, set시군구] = useState(0); - const [처리구역, set처리구역] = useState(''); + const [처리구역, set처리구역] = useState(""); // 날짜 상태 선언 - const [시작1, set시작1] = useState(''); - const [시작2, set시작2] = useState(''); - const [종료1, set종료1] = useState(''); - const [종료2, set종료2] = useState(''); - const [변수1, set변수1] = useState(''); - const [변수2, set변수2] = useState(''); - const [변수3, set변수3] = useState(''); - const [변수4, set변수4] = useState(''); + const [시작1, set시작1] = useState(""); + const [시작2, set시작2] = useState(""); + const [종료1, set종료1] = useState(""); + const [종료2, set종료2] = useState(""); + const [변수1, set변수1] = useState(""); + const [변수2, set변수2] = useState(""); + const [변수3, set변수3] = useState(""); + const [변수4, set변수4] = useState(""); // 시작, 종료, 경과년도 const [yearFilter, setYearFilter] = useState({ - 시작: '', - 종료: '', - 경과년도: '' + 시작: "", + 종료: "", + 경과년도: "", }); - const [가동개시_시작_월, set가동개시_시작_월] = useState(''); - const [가동개시_종료_월, set가동개시_종료_월] = useState(''); - const [가동개시_시작_일, set가동개시_시작_일] = useState(''); - const [가동개시_종료_일, set가동개시_종료_일] = useState(''); - + const [가동개시_시작_월, set가동개시_시작_월] = useState(""); + const [가동개시_종료_월, set가동개시_종료_월] = useState(""); + const [가동개시_시작_일, set가동개시_시작_일] = useState(""); + const [가동개시_종료_일, set가동개시_종료_일] = useState(""); // 상세 정보 조회를 위한 상태 추가 const [popupFeature, setPopupFeature] = useState(null); @@ -194,17 +200,23 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature // 오늘 날짜 구하기 const today = new Date(); const todayYear = today.getFullYear().toString(); - const todayMonth = (today.getMonth() + 1).toString().padStart(2, '0'); - const todayDate = today.getDate().toString().padStart(2, '0'); + const todayMonth = (today.getMonth() + 1).toString().padStart(2, "0"); + const todayDate = today.getDate().toString().padStart(2, "0"); // UiTable2에 넘길 headlist를 BASIC_TYPES 값에 따라 분기 처리 let dynamicHeadlist = swageZoneTableHeadlist; // default 값 - if (activeTab === 'operation') dynamicHeadlist = operationTableHeadlist; // 운영정보 - else if (activeTab === 'report') dynamicHeadlist = reportTableHeadlist; // 하수도정비기본계획보고서 - else if (basicType === 'tb_ms_swage_ppl') dynamicHeadlist = swagePplTableHeadlist; // 하수관로 - else if (basicType === 'tb_il_swage_prcs_fclt') dynamicHeadlist = swageFcltTableHeadlist; // 하수처리시설 - else if (basicType === 'tb_ms_swage_prcs_zone') dynamicHeadlist = swageZoneTableHeadlist; // 하수처리구역 - else if (basicType === 'tb_ms_swage_mh') dynamicHeadlist = swageMhTableHeadlist; // 하수맨홀 + if (activeTab === "operation") + dynamicHeadlist = operationTableHeadlist; // 운영정보 + else if (activeTab === "report") + dynamicHeadlist = reportTableHeadlist; // 하수도정비기본계획보고서 + else if (basicType === "tb_ms_swage_ppl") + dynamicHeadlist = swagePplTableHeadlist; // 하수관로 + else if (basicType === "tb_il_swage_prcs_fclt") + dynamicHeadlist = swageFcltTableHeadlist; // 하수처리시설 + else if (basicType === "tb_ms_swage_prcs_zone") + dynamicHeadlist = swageZoneTableHeadlist; // 하수처리구역 + else if (basicType === "tb_ms_swage_mh") + dynamicHeadlist = swageMhTableHeadlist; // 하수맨홀 // 조회 버튼 클릭 시 1페이지로 이동하도록 수정 const handleSearch = () => { @@ -225,25 +237,25 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature React.useEffect(() => { // filterParams 초기화 // setFilterParams({}); - set시작1(''); - set시작2(''); - set종료1(''); - set종료2(''); - set변수1(''); - set변수2(''); - set변수3(''); - set변수4(''); - set가동개시_시작_월(''); - set가동개시_종료_월(''); - set가동개시_시작_일(''); - set가동개시_종료_일(''); + set시작1(""); + set시작2(""); + set종료1(""); + set종료2(""); + set변수1(""); + set변수2(""); + set변수3(""); + set변수4(""); + set가동개시_시작_월(""); + set가동개시_종료_월(""); + set가동개시_시작_일(""); + set가동개시_종료_일(""); set시도(0); set시군구(0); - set처리구역(''); + set처리구역(""); setYearFilter({ - 시작: '', - 종료: '', - 경과년도: '' + 시작: "", + 종료: "", + 경과년도: "", }); setShowTable(false); setTableCount(0); @@ -260,7 +272,6 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature } }, [curPage]); - // 하수관로용 CQL 필터 생성 const pplCqlFilters = () => { const cqlFilters: string[] = []; @@ -270,9 +281,21 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature if (변수3) cqlFilters.push(`행정읍면동코드='${변수3}'`); if (변수4) cqlFilters.push(`경과년도='${변수4}'`); // 설치년도 범위 - const startDate = getDateString(yearFilter.시작, 가동개시_시작_월, 가동개시_시작_일, '19000101'); - const endDate = getDateString(yearFilter.종료, 가동개시_종료_월, 가동개시_종료_일, `${todayYear}${todayMonth}${todayDate}`); - cqlFilters.push(`설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`); + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + cqlFilters.push( + `설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`, + ); // 관경(mm) 범위 if (시작1 && 종료1) cqlFilters.push(`관경 BETWEEN ${시작1} AND ${종료1}`); else if (시작1) cqlFilters.push(`관경 >= ${시작1}`); @@ -288,11 +311,24 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const facilityCqlFilters = () => { const cqlFilters: string[] = []; // 가동개시일자 범위 - const startDate = getDateString(yearFilter.시작, 가동개시_시작_월, 가동개시_시작_일, '19000101'); - const endDate = getDateString(yearFilter.종료, 가동개시_종료_월, 가동개시_종료_일, `${todayYear}${todayMonth}${todayDate}`); - cqlFilters.push(`oprtng_strt_ymd >= '${startDate}' and oprtng_strt_ymd <= '${endDate}'`); + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + cqlFilters.push( + `oprtng_strt_ymd >= '${startDate}' and oprtng_strt_ymd <= '${endDate}'`, + ); // 시설용량 범위 - if (시작1 && 종료1) cqlFilters.push(`fclt_cpct BETWEEN ${시작1} AND ${종료1}`); + if (시작1 && 종료1) + cqlFilters.push(`fclt_cpct BETWEEN ${시작1} AND ${종료1}`); else if (시작1) cqlFilters.push(`fclt_cpct >= ${시작1}`); else if (종료1) cqlFilters.push(`fclt_cpct <= ${종료1}`); // 하수처리시설명 @@ -312,9 +348,21 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const mhCqlFilters = () => { const cqlFilters: string[] = []; // 설치년도 범위 - const startDate = getDateString(yearFilter.시작, 가동개시_시작_월, 가동개시_시작_일, '19000101'); - const endDate = getDateString(yearFilter.종료, 가동개시_종료_월, 가동개시_종료_일, `${todayYear}${todayMonth}${todayDate}`); - cqlFilters.push(`설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`); + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + cqlFilters.push( + `설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`, + ); if (변수1) cqlFilters.push(`경과년도='${변수1}'`); if (변수2) cqlFilters.push(`용도코드='${변수2}'`); // 구경(mm) 범위 @@ -328,16 +376,30 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const psmtnCqlFilters = () => { const cqlFilters: string[] = []; // 설치년도 범위 - const startDate = getDateString(yearFilter.시작, 가동개시_시작_월, 가동개시_시작_일, '19000101'); - const endDate = getDateString(yearFilter.종료, 가동개시_종료_월, 가동개시_종료_일, `${todayYear}${todayMonth}${todayDate}`); - cqlFilters.push(`설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`); + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + cqlFilters.push( + `설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`, + ); if (변수1) cqlFilters.push(`경과년도='${변수1}'`); // 일일처리용량 범위 - if (시작1 && 종료1) cqlFilters.push(`일일처리용량 BETWEEN ${시작1} AND ${종료1}`); + if (시작1 && 종료1) + cqlFilters.push(`일일처리용량 BETWEEN ${시작1} AND ${종료1}`); else if (시작1) cqlFilters.push(`일일처리용량 >= ${시작1}`); else if (종료1) cqlFilters.push(`일일처리용량 <= ${종료1}`); // 우수양수능력 범위 - if (시작2 && 종료2) cqlFilters.push(`우수양수능력 BETWEEN ${시작2} AND ${종료2}`); + if (시작2 && 종료2) + cqlFilters.push(`우수양수능력 BETWEEN ${시작2} AND ${종료2}`); else if (시작2) cqlFilters.push(`우수양수능력 >= ${시작2}`); else if (종료2) cqlFilters.push(`우수양수능력 <= ${종료2}`); @@ -347,13 +409,26 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const otflCqlFilters = () => { const cqlFilters: string[] = []; // 설치년도 범위 - const startDate = getDateString(yearFilter.시작, 가동개시_시작_월, 가동개시_시작_일, '19000101'); - const endDate = getDateString(yearFilter.종료, 가동개시_종료_월, 가동개시_종료_일, `${todayYear}${todayMonth}${todayDate}`); - cqlFilters.push(`설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`); + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + cqlFilters.push( + `설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`, + ); if (변수1) cqlFilters.push(`경과년도='${변수1}'`); if (변수2) cqlFilters.push(`하천명 ILIKE '%${변수1}%'`); // 계획방류량 범위 - if (시작1 && 종료1) cqlFilters.push(`계획방류량 BETWEEN ${시작1} AND ${종료1}`); + if (시작1 && 종료1) + cqlFilters.push(`계획방류량 BETWEEN ${시작1} AND ${종료1}`); else if (시작1) cqlFilters.push(`계획방류량 >= ${시작1}`); else if (종료1) cqlFilters.push(`계획방류량 <= ${종료1}`); @@ -363,9 +438,21 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const operationCqlFilters = () => { const cqlFilters: string[] = []; // 설치년도 범위 - const startDate = getDateString(yearFilter.시작, 가동개시_시작_월, 가동개시_시작_일, '19000101'); - const endDate = getDateString(yearFilter.종료, 가동개시_종료_월, 가동개시_종료_일, `${todayYear}${todayMonth}${todayDate}`); - cqlFilters.push(`설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`); + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + cqlFilters.push( + `설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`, + ); return cqlFilters; }; // 하수도정비기본계획보고서용 CQL 필터 생성 @@ -376,185 +463,220 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature if (시군구) cqlFilters.push(`sgg_cd='${시군구}'`); if (처리구역) cqlFilters.push(`처리구역='${처리구역}'`); if (변수1) cqlFilters.push(`처리구역코드='${변수1}'`); - const startDate = getDateString(yearFilter.시작, 가동개시_시작_월, 가동개시_시작_일, '19000101'); - const endDate = getDateString(yearFilter.종료, 가동개시_종료_월, 가동개시_종료_일, `${todayYear}${todayMonth}${todayDate}`); - cqlFilters.push(`설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`); + const startDate = getDateString( + yearFilter.시작, + 가동개시_시작_월, + 가동개시_시작_일, + "19000101", + ); + const endDate = getDateString( + yearFilter.종료, + 가동개시_종료_월, + 가동개시_종료_일, + `${todayYear}${todayMonth}${todayDate}`, + ); + cqlFilters.push( + `설치시작년도 >= '${startDate}' and 설치시작년도 <= '${endDate}'`, + ); return cqlFilters; }; - // 검색 API 호출 함수 const fetchFilteredData = () => { const queryParams = new URLSearchParams({ lyrTypeNm: basicType, page: `${curPage - 1}`, - size: '10', - sort: 'string', + size: "10", + sort: "string", }); // page와 size 사용해서 api 호출하는 걸로 바꾸기 let cqlFilters: string[] = []; - if (activeTab === 'basic') { - if (basicType === 'tb_ms_swage_prcs_zone') cqlFilters = zoneCqlFilters(); - else if (basicType === 'tb_il_swage_prcs_fclt') cqlFilters = facilityCqlFilters(); - else if (basicType === 'tb_ms_swage_ppl') cqlFilters = pplCqlFilters(); - } - else if (activeTab === 'operation') cqlFilters = zoneCqlFilters(); + if (activeTab === "basic") { + if (basicType === "tb_ms_swage_prcs_zone") cqlFilters = zoneCqlFilters(); + else if (basicType === "tb_il_swage_prcs_fclt") + cqlFilters = facilityCqlFilters(); + else if (basicType === "tb_ms_swage_ppl") cqlFilters = pplCqlFilters(); + } else if (activeTab === "operation") cqlFilters = zoneCqlFilters(); else cqlFilters = reportCqlFilters(); - // 탭 + 구분 별로 cqlFilter 추가 예정 - if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and ')); + if (cqlFilters.length > 0) + queryParams.append("cqlFiter", cqlFilters.join(" and ")); - console.log('API URL:', `${API_URL}/v1/fclts?${queryParams.toString()}`); - axios.get(`${API_URL}/v1/fclts?${queryParams.toString()}`) - .then(res => { - console.log('필터링된 API 결과(개수):', res.data.count); - console.log('필터링된 API 결과(데이터):', res.data.data); + console.log("API URL:", `${API_URL}/v1/fclts?${queryParams.toString()}`); + axios + .get(`${API_URL}/v1/fclts?${queryParams.toString()}`) + .then((res) => { + console.log("필터링된 API 결과(개수):", res.data.count); + console.log("필터링된 API 결과(데이터):", res.data.data); setTableData(res.data.data || []); setTableCount(res.data.count || []); setShowTable(true); }) - .catch(err => { - console.error('API ERROR:', err); + .catch((err) => { + console.error("API ERROR:", err); setTableData([]); }); }; - const renderBody = () => ( <> {/* 탭 영역 */} ({ value: tab.val, label: tab.text, onClick: () => setActiveTab(tab.val), }))} + tabList={TABS.map((tab) => ({ + value: tab.val, + label: tab.text, + onClick: () => setActiveTab(tab.val), + }))} > {/* 각각의 탭 영역 */} {/* 기본정보 탭 */} - {activeTab === 'basic' && ( -
+ {activeTab === "basic" && ( +
{/* 구분 */} -
+
setBasicType(String(value))} + onSelectValue={(value: string | number) => + setBasicType(String(value)) + } value={basicType} />
{/* 분기처리: 하수관로 */} - {basicType === 'tb_ms_swage_ppl' && ( + {basicType === "tb_ms_swage_ppl" && (
-
+
{/* 설치년도 */} setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + onChange={(range) => + setYearFilter({ + ...yearFilter, + 시작: range.start, + 종료: range.end, + }) + } startLabel="설치년도" endLabel="" /> {/* 경과년도 */} -
- +
+ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); setYearFilter({ ...yearFilter, 경과년도: val }); }} />
{/* 용도코드 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set변수1(val); }} /> {/* 재질코드 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set변수2(val); }} /> {/* 행정읍면동코드 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set변수3(val); }} />
-
+
{/* 관경 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set시작1(val); }} /> - ~ + ~ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set종료1(val); }} /> {/* 연장 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set시작2(val); }} /> - ~ + ~ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set종료2(val); }} /> @@ -562,44 +684,54 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature
)} {/* 분기처리: 하수처리시설 */} - {basicType === 'tb_il_swage_prcs_fclt' && ( + {basicType === "tb_il_swage_prcs_fclt" && (
{/* 가동개시일자 */} -
+
setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + onChange={(range) => + setYearFilter({ + ...yearFilter, + 시작: range.start, + 종료: range.end, + }) + } startLabel="가동개시일자" endLabel="" /> {/* 시설용량 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set시작1(val); }} /> - ~ + ~ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set종료1(val); }} /> {/* 하수처리시설명 */} - + { @@ -610,27 +742,31 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature
)} {/* 분기처리: 하수처리구역 */} - {basicType === 'tb_ms_swage_prcs_zone' && ( + {basicType === "tb_ms_swage_prcs_zone" && (
-
+
- + { set변수1(e.target.value); }} /> - + { @@ -641,61 +777,73 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature
)} {/* 분기처리: 하수맨홀 */} - {basicType === 'tb_ms_swage_mh' && ( + {basicType === "tb_ms_swage_mh" && (
-
+
{/* 설치년도 */} setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + onChange={(range) => + setYearFilter({ + ...yearFilter, + 시작: range.start, + 종료: range.end, + }) + } startLabel="설치년도" endLabel="" /> {/* 경과년도 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); setYearFilter({ ...yearFilter, 경과년도: val }); }} /> {/* 용도코드 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set변수1(val); }} /> {/* 하수맨홀 구경 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set시작1(val); }} /> - ~ + ~ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set종료1(val); }} /> @@ -703,74 +851,87 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature
)} {/* 분기처리: 하수펌프장 */} - {(basicType === 'tb_ms_swage_psmtn_1' || basicType === 'tb_ms_swage_psmtn_2') && ( + {(basicType === "tb_ms_swage_psmtn_1" || + basicType === "tb_ms_swage_psmtn_2") && (
-
+
{/* 설치년도 */} -
+
setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + onChange={(range) => + setYearFilter({ + ...yearFilter, + 시작: range.start, + 종료: range.end, + }) + } startLabel="설치년도" endLabel="" /> {/* 경과년도 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); setYearFilter({ ...yearFilter, 경과년도: val }); }} />
{/* 일일처리용량 - 오수맨홀 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set시작1(val); }} /> - ~ + ~ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set종료1(val); }} /> {/* 우수양수능력 - 우수맨홀 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set시작2(val); }} /> - ~ + ~ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set종료2(val); }} /> @@ -778,35 +939,45 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature
)} {/* 분기처리: 우수토실? 토구? */} - {basicType === 'tb_ms_otfl' && ( + {basicType === "tb_ms_otfl" && (
-
+
{/* 설치년도 */} -
+
setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + onChange={(range) => + setYearFilter({ + ...yearFilter, + 시작: range.start, + 종료: range.end, + }) + } startLabel="설치년도" endLabel="" /> {/* 경과년도 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); setYearFilter({ ...yearFilter, 경과년도: val }); }} />
{/* 하천명 */} - + { @@ -814,25 +985,27 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature }} /> {/* 계획방류량 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set시작1(val); }} /> - ~ + ~ { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set종료1(val); }} /> @@ -842,41 +1015,54 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature {/* 조회 버튼 중앙 정렬 */}
- +
)} {/* 운영정보 탭 */} - {activeTab === 'operation' && ( -
-
+ {activeTab === "operation" && ( +
+
({ val: w.val, text: w.text }))} - onSelectValue={val => setWorkType(String(val))} + selectArray={WORK_TYPES.map((w) => ({ + val: w.val, + text: w.text, + }))} + onSelectValue={(val) => setWorkType(String(val))} value={workType} /> {/* 설치년도 */} -
+
setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + onChange={(range) => + setYearFilter({ + ...yearFilter, + 시작: range.start, + 종료: range.end, + }) + } startLabel="설치년도" endLabel="" /> {/* 경과년도 */} - + { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); setYearFilter({ ...yearFilter, 경과년도: val }); }} /> @@ -884,15 +1070,17 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature
{/* 조회 버튼 중앙 정렬 */}
- +
)} {/* 하수도정비기본계획보고서 탭 */} - {activeTab === 'report' && ( -
+ {activeTab === "report" && ( +
{/* 시도, 시군구, 하수처리구역 한 줄 */} -
+
= ({ open, onOpenChange, onFeature onSigunguChange={set시군구} /> ({ val: opt.val, text: opt.text }))} - onSelectValue={val => set처리구역(String(val))} + selectArray={처리구역List.map((opt) => ({ + val: opt.val, + text: opt.text, + }))} + onSelectValue={(val) => set처리구역(String(val))} value={처리구역} /> { // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); + const val = e.target.value.replace(/[^0-9]/g, ""); set변수1(val); }} /> setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + onChange={(range) => + setYearFilter({ + ...yearFilter, + 시작: range.start, + 종료: range.end, + }) + } startLabel="승인년도" endLabel="" />
{/* 조회 버튼 중앙 정렬 */}
- +
)} - - {/* 📋 결과 리스트 */} - < div - className="border rounded-lg space-y-2 w-full h-[60vh] overflow-auto" - onWheel={e => { - // 세로 스크롤이 최상단/최하단에 도달했을 때 가로 스크롤이 막히는 현상을 해결 - const container = e.currentTarget; - const isShift = e.shiftKey; - if (!isShift) return; - - // 세로 스크롤 위치 - const atTop = container.scrollTop === 0; - const atBottom = Math.ceil(container.scrollTop + container.clientHeight) >= container.scrollHeight; - - // 세로 스크롤이 최상단/최하단에 도달한 경우에만 가로 스크롤 수동 처리 - if ((atTop && e.deltaY < 0) || (atBottom && e.deltaY > 0)) { - container.scrollLeft += e.deltaY; - e.preventDefault(); - } - }} - > - {/* 선택된 탭의 label */} - < div className="m-2 text-2xl font-bold mb-2" > - {TABS.find(tab => tab.val === activeTab)?.text} - {/* 조회 결과 라벨 및 건수 표시 */} - { +
+ {/* 테이블 영역 (가로/세로 스크롤 가능) */} +
+ { - // 조회 건수 변수 선언 const resultCount = tableData.length; - // 탭별 라벨 const label = - activeTab === 'basic' - ? BASIC_TYPES.find(type => type.val === basicType)?.text - : activeTab === 'operation' - ? WORK_TYPES.find(type => type.val === workType)?.text - : activeTab === 'report' - ? '하수도정비기본계획보고서' - : TABS.find(tab => tab.val === activeTab)?.text; + activeTab === "basic" + ? BASIC_TYPES.find((type) => type.val === basicType)?.text + : activeTab === "operation" + ? WORK_TYPES.find((type) => type.val === workType)?.text + : activeTab === "report" + ? "하수도정비기본계획보고서" + : TABS.find((tab) => tab.val === activeTab)?.text; return ( -
- ▶ {label} 조회 결과 - ({tableCount}건) -
+ <> + {label} 조회 결과 ({tableCount})건 + ); })() - } - -
+ } // 중복 방지 + tableData={tableData} + headlist={dynamicHeadlist} + pageSize={tableData.length < 10 ? tableData.length : 10} + total={tableCount} + children={undefined} + cellClick={handleCellClick} + onPageChange={setCurPage} + resetPageNo={false} + cur={curPage} + height="51vh" + />
+
); @@ -1010,10 +1184,10 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature z-[101] `} body={renderBody()} - headerTitle="검색" - // 필요시 footerContent 등 추가 + headerTitle="" + // 필요시 footerContent 등 추가 /> ); -} +}; export default React.memo(SearchModal); diff --git a/packages/common/business_components/src/ui/tab/index-2.tsx b/packages/common/business_components/src/ui/tab/index-2.tsx index c8f6e75dd..71c103835 100644 --- a/packages/common/business_components/src/ui/tab/index-2.tsx +++ b/packages/common/business_components/src/ui/tab/index-2.tsx @@ -18,8 +18,8 @@ const UITab2 = React.forwardRef< UITabProps >(({defaultValue, tabList, children}, ref)=>{ return ( - - + + {tabList.map((tab) => ( (-1); - const [curState, setCurState] = useState(cur ?? 1); + useEffect(() => { setCurState(cur ?? 1); }, [cur]); @@ -40,7 +54,7 @@ export function UiTable2({ tableData, headlist, pageSize, total, children, headN const handlePageChange = (page: number) => { setCurState(page); onPageChange(page); - } + }; const handleCellClick = (index: number, headId: string) => { if (cellClick) { @@ -50,58 +64,91 @@ export function UiTable2({ tableData, headlist, pageSize, total, children, headN }; const startIdx = (curState - 1) * pageSize; - const endIdx = startIdx + pageSize; return ( <> - {headName ? ( + {headName && (
-

{headName}

+
+

{headName}

+
- ) : null} -
-
+ )} + +
+ {/* ✅ 외부에서 조절 가능한 높이 적용 */} +
- {/* 스크롤 관련 div 제거 */} {children ? ( <>{children} ) : ( - {headlist?.map((head) => ( - ( + + text-center whitespace-nowrap overflow-hidden + text-ellipsis bg-white" + > {head.title} ))} )} - - {tableData.map((el: { [key: string]: string | number | boolean | object }, index) => ( - - {headlist?.map((head) => ( - handleCellClick(startIdx + index, head.id)} - key={head.id + index} - > - {typeof el[head.id] === 'number' ? String(el[head.id]).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : String(el[head.id] ?? '')} - - ))} + + + {tableData.length > 0 ? ( + tableData.map((el, index) => ( + + {headlist.map((head) => ( + handleCellClick(startIdx + index, head.id)} + > + {typeof el[head.id] === 'number' + ? String(el[head.id]).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + : String(el[head.id] ?? '')} + + ))} + + )) + ) : ( + + + {/* ✅ 높이 보장 + 가운데 정렬용 div */} +
+ 🔍 검색 결과가 없습니다. +
+
- ))} + )}
- {/* 페이지네이션을 sticky 하단에 고정 */} - {total > 0 && ( -
- + + {/* 페이지네이션 하단 고정 */} + { ( +
+
)}