From d11343726f6a1860f8218cce50b6de38d26552d5 Mon Sep 17 00:00:00 2001 From: swcho Date: Fri, 16 May 2025 16:46:06 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=97=B0=EB=8F=84=20=EB=B2=94=EC=9C=84?= =?UTF-8?q?=20=EC=84=A0=ED=83=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EB=B0=8F=20SearchModal=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/components/ui/YearRangeSelectBox.tsx | 42 +++ apps/sn/app/map/SearchModal.tsx | 242 ++++++------------ apps/sn/app/map/featureClickEventPopup.tsx | 2 +- .../src/ui/table/index-2.tsx | 3 +- 4 files changed, 127 insertions(+), 162 deletions(-) diff --git a/apps/sn/app/components/ui/YearRangeSelectBox.tsx b/apps/sn/app/components/ui/YearRangeSelectBox.tsx index 5e9aa0b3e..312c03e58 100644 --- a/apps/sn/app/components/ui/YearRangeSelectBox.tsx +++ b/apps/sn/app/components/ui/YearRangeSelectBox.tsx @@ -13,6 +13,48 @@ interface YearRangeSelectBoxProps { selectClass?: string; } +// 시작년도 selectArray 생성 함수 +export function getStartYearArray({ + minYear = 1900, + maxYear = new Date().getFullYear(), + placeholder = "년", + endYear, +}: { + minYear?: number; + maxYear?: number; + placeholder?: string; + endYear?: string; +} = {}) { + const years = Array.from({ length: maxYear - minYear + 1 }, (_, i) => + (maxYear - i).toString() + ).filter(y => !endYear || parseInt(y) <= parseInt(endYear)); + return [ + { val: "0", text: placeholder }, + ...years.map(y => ({ val: y, text: y })), + ]; +} + +// 종료년도 selectArray 생성 함수 +export function getEndYearArray({ + minYear = 1900, + maxYear = new Date().getFullYear(), + placeholder = "년", + startYear, +}: { + minYear?: number; + maxYear?: number; + placeholder?: string; + startYear?: string; +} = {}) { + const years = Array.from({ length: maxYear - minYear + 1 }, (_, i) => + (maxYear - i).toString() + ).filter(y => !startYear || parseInt(y) >= parseInt(startYear)); + return [ + { val: "9999", text: placeholder }, + ...years.map(y => ({ val: y, text: y })), + ]; +} + export function YearRangeSelectBox({ start, end, diff --git a/apps/sn/app/map/SearchModal.tsx b/apps/sn/app/map/SearchModal.tsx index 6dc74eccc..b817e5d2e 100644 --- a/apps/sn/app/map/SearchModal.tsx +++ b/apps/sn/app/map/SearchModal.tsx @@ -38,7 +38,7 @@ const WORK_TYPES = [ const YEARS = Array.from({ length: 100 }, (_, i) => `${2025 - i}`); // 테이블 헤더 리스트 -// 하수관로 (추후 작성 예정) +// 하수관로 const swagePplTableHeadlist = [ { id: 'pipeNumber', title: '관로번호' }, { id: 'gisManageNumber', title: '관리번호(GIS)' }, @@ -66,11 +66,8 @@ const swagePplTableHeadlist = [ ] // 하수처리구역 const swageZoneTableHeadlist = [ - // { id: 'ctpvCd', title: '시도코드' }, { id: 'ctpvNm', title: '시도명' }, - // { id: 'sggCd', title: '시군구코드' }, { id: 'sggNm', title: '시군구명' }, - // { id: 'swtrmtZoneSn', title: '하수처리구역번호' }, { id: 'swtrmtZoneNm', title: '하수처리구역명' }, { id: 'swtrmtFcltCd', title: '하수처리시설번호' }, { id: 'swtrmtFcltNm', title: '하수처리시설명' }, @@ -162,14 +159,13 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const [activeTab, setActiveTab] = useState(TABS[0]?.val ?? 'basic'); const [workType, setWorkType] = useState(WORK_TYPES[0]?.val ?? ''); const [showTable, setShowTable] = useState(false); - const [curPage, setCurPage] = useState(0); + const [tableData, setTableData] = useState([]); + const [tableCount, setTableCount] = useState(0); + const [curPage, setCurPage] = useState(1); const [basicType, setBasicType] = useState(BASIC_TYPES[0]?.val ?? ''); - const [하수처리구역명, set하수처리구역명] = useState(''); - const [하수처리시설명, set하수처리시설명] = useState(''); const [시도, set시도] = useState(0); const [시군구, set시군구] = useState(0); const [처리구역, set처리구역] = useState(''); - const [tableData, setTableData] = useState([]); // 날짜 상태 선언 const [시작1, set시작1] = useState(''); const [시작2, set시작2] = useState(''); @@ -179,10 +175,6 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const [변수2, set변수2] = useState(''); const [변수3, set변수3] = useState(''); const [변수4, set변수4] = useState(''); - // 하수관로 변수 - const [하수관로용도코드, set하수관로용도코드] = useState(''); - const [하수관로재질코드, set하수관로재질코드] = useState(''); - const [행정읍면동코드, set행정읍면동코드] = useState(''); // 시작, 종료, 경과년도 const [yearFilter, setYearFilter] = useState({ 시작: '', @@ -206,7 +198,7 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature const todayDate = today.getDate().toString().padStart(2, '0'); // UiTable2에 넘길 headlist를 BASIC_TYPES 값에 따라 분기 처리 - let dynamicHeadlist = swageZoneTableHeadlist; + let dynamicHeadlist = swageZoneTableHeadlist; // default 값 if (activeTab === 'operation') dynamicHeadlist = operationTableHeadlist; // 운영정보 else if (activeTab === 'report') dynamicHeadlist = reportTableHeadlist; // 하수도정비기본계획보고서 else if (basicType === 'tb_ms_swage_ppl') dynamicHeadlist = swagePplTableHeadlist; // 하수관로 @@ -221,27 +213,14 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature setShowTable(true); }; - // 선택된 필터 값을 저장할 상태 추가 - // const [filterParams, setFilterParams] = useState({}); - // cellClick 함수 타입 지정 const handleCellClick = (index?: number, headId?: string) => { - // 원하는 동작 구현 - console.log('Cell clicked:', index, headId); if (typeof index === "number") { - console.log('Selected row data:', tableData[index]); - onFeatureSelect(tableData[index]); + onFeatureSelect(tableData[index % 10]); // 10은 page size 하드 코딩한 숫자 onOpenChange(false); // SearchModal 닫기 } }; - const modalMinWidth = 'min-w-[900px]'; - const modalMaxWidth = 'max-w-6xl'; - - // 모달 높이 동적 계산 - const contentRef = React.useRef(null); - const [dynamicHeight, setDynamicHeight] = useState(undefined); - // 구분(basicType)이 바뀔 때마다 queryParams, filterParams 초기화 React.useEffect(() => { // filterParams 초기화 @@ -258,8 +237,6 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature set가동개시_종료_월(''); set가동개시_시작_일(''); set가동개시_종료_일(''); - set하수처리구역명(''); - set하수처리시설명(''); set시도(0); set시군구(0); set처리구역(''); @@ -269,57 +246,20 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature 경과년도: '' }); setShowTable(false); + setTableCount(0); setTableData([]); // queryParams는 fetchFilteredData 내에서 매번 새로 생성되므로 별도 상태 초기화는 필요 없음 }, [activeTab, basicType]); - + // 페이지 변경 시마다 데이터 fetch React.useEffect(() => { - if (contentRef.current) { - setDynamicHeight(contentRef.current.scrollHeight + 60); // 여유 padding + // showTable이 true일 때만 fetch (최초 렌더 방지) + if (showTable) { + fetchFilteredData(); // 실제 API 사용 시 + // fetchDummyData(); // 더미 데이터 사용 시 } - }, [activeTab, showTable, curPage, tableData.length]); + }, [curPage]); - // 시작년도 selectArray 생성 함수 - function getStartYearArray({ - minYear = 1900, - maxYear = new Date().getFullYear(), - placeholder = '년', - endYear, - }: { - minYear?: number; - maxYear?: number; - placeholder?: string; - endYear?: string; - } = {}) { - const years = Array.from({ length: maxYear - minYear + 1 }, (_, i) => - (maxYear - i).toString() - ).filter(y => !endYear || parseInt(y) <= parseInt(endYear)); - return [ - { val: '0', text: placeholder }, - ...years.map(y => ({ val: y, text: y })), - ]; - } - // 종료년도 selectArray 생성 함수 - function getEndYearArray({ - minYear = 1900, - maxYear = new Date().getFullYear(), - placeholder = '년', - startYear, - }: { - minYear?: number; - maxYear?: number; - placeholder?: string; - startYear?: string; - } = {}) { - const years = Array.from({ length: maxYear - minYear + 1 }, (_, i) => - (maxYear - i).toString() - ).filter(y => !startYear || parseInt(y) >= parseInt(startYear)); - return [ - { val: '9999', text: placeholder }, - ...years.map(y => ({ val: y, text: y })), - ]; - } // 하수관로용 CQL 필터 생성 const pplCqlFilters = () => { @@ -446,10 +386,12 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature // 검색 API 호출 함수 const fetchFilteredData = () => { const queryParams = new URLSearchParams({ - lyrTypeNm: basicType + lyrTypeNm: basicType, + page: `${curPage - 1}`, + size: '10', + sort: 'string', }); // page와 size 사용해서 api 호출하는 걸로 바꾸기 - const size = 10; let cqlFilters: string[] = []; if (activeTab === 'basic') { @@ -465,12 +407,13 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature if (cqlFilters.length > 0) queryParams.append('cqlFiter', cqlFilters.join(' and ')); - console.log('API URL:', `${API_URL}/v1/map/features?${queryParams.toString()}`); - axios.get(`${API_URL}/v1/map/features?${queryParams.toString()}`) + 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.length); - console.log('필터링된 API 결과:', res.data); - setTableData(res.data || []); + console.log('필터링된 API 결과(개수):', res.data.count); + console.log('필터링된 API 결과(데이터):', res.data.data); + setTableData(res.data.data || []); + setTableCount(res.data.count || []); setShowTable(true); }) .catch(err => { @@ -507,8 +450,8 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature {/* 분기처리: 하수관로 */} {basicType === 'tb_ms_swage_ppl' && (
- {/* 설치년도 */}
+ {/* 설치년도 */} = ({ open, onOpenChange, onFeature
{ @@ -531,6 +474,42 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature }} />
+ {/* 용도코드 */} + + { + // 숫자만 입력 허용 + const val = e.target.value.replace(/[^0-9]/g, ''); + set변수1(val); + }} + /> + {/* 재질코드 */} + + { + // 숫자만 입력 허용 + const val = e.target.value.replace(/[^0-9]/g, ''); + set변수2(val); + }} + /> + {/* 행정읍면동코드 */} + + { + // 숫자만 입력 허용 + const val = e.target.value.replace(/[^0-9]/g, ''); + set변수3(val); + }} + />
{/* 관경 */} @@ -580,44 +559,6 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature }} />
-
- {/* 용도코드 */} - - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); - set변수1(val); - }} - /> - {/* 재질코드 */} - - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); - set변수2(val); - }} - /> - {/* 행정읍면동코드 */} - - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); - set변수3(val); - }} - /> -
)} {/* 분기처리: 하수처리시설 */} @@ -704,29 +645,25 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature
{/* 설치년도 */} -
- setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} - startLabel="설치년도" - endLabel="" - /> - {/* 경과년도 */} - - { - // 숫자만 입력 허용 - const val = e.target.value.replace(/[^0-9]/g, ''); - setYearFilter({ ...yearFilter, 경과년도: val }); - }} - /> -
-
-
+ setYearFilter({ ...yearFilter, 시작: range.start, 종료: range.end })} + startLabel="설치년도" + endLabel="" + /> + {/* 경과년도 */} + + { + // 숫자만 입력 허용 + const val = e.target.value.replace(/[^0-9]/g, ''); + setYearFilter({ ...yearFilter, 경과년도: val }); + }} + /> {/* 용도코드 */} = ({ open, onOpenChange, onFeature }} />
-
-
{/* 일일처리용량 - 오수맨홀 */} = ({ open, onOpenChange, onFeature }} />
- -
{/* 하천명 */} = ({ open, onOpenChange, onFeature // 탭별 라벨 const label = activeTab === 'basic' - ? BASIC_TYPES.find(type => type.val === basicType)?.val + ? BASIC_TYPES.find(type => type.val === basicType)?.text : activeTab === 'operation' ? WORK_TYPES.find(type => type.val === workType)?.text : activeTab === 'report' @@ -1042,7 +975,7 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature return (
▶ {label} 조회 결과 - ({resultCount.toLocaleString()}건) + ({tableCount}건)
); })() @@ -1052,22 +985,13 @@ const SearchModal: React.FC = ({ open, onOpenChange, onFeature tableData={tableData} headlist={dynamicHeadlist} pageSize={tableData.length < 10 ? tableData.length : 10} - total={tableData.length} + total={tableCount} children={undefined} cellClick={handleCellClick} onPageChange={setCurPage} resetPageNo={false} cur={curPage} /> - {/* FeatureClickEventPopup 표시 */} - { - popupFeature && ( - setPopupFeature(null)} - /> - ) - }
diff --git a/apps/sn/app/map/featureClickEventPopup.tsx b/apps/sn/app/map/featureClickEventPopup.tsx index 223bebaa3..a7b55dc32 100644 --- a/apps/sn/app/map/featureClickEventPopup.tsx +++ b/apps/sn/app/map/featureClickEventPopup.tsx @@ -31,7 +31,7 @@ const FeatureClickEventPopup = ({ onClose, featureData }: { onClose: () => void, featureLayer = layer; // 피처가 속한 레이어 찾기 } }); - // SearchMoal 클릭 이벤트와 Gis 클릭 이벤트 구분하기 + // 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 = '하수처리구역'; diff --git a/packages/common/business_components/src/ui/table/index-2.tsx b/packages/common/business_components/src/ui/table/index-2.tsx index f4f4163f8..58ae1bbd0 100644 --- a/packages/common/business_components/src/ui/table/index-2.tsx +++ b/packages/common/business_components/src/ui/table/index-2.tsx @@ -51,7 +51,6 @@ export function UiTable2({ tableData, headlist, pageSize, total, children, headN const startIdx = (curState - 1) * pageSize; const endIdx = startIdx + pageSize; - const pageData = tableData.slice(startIdx, endIdx); return ( <> @@ -81,7 +80,7 @@ export function UiTable2({ tableData, headlist, pageSize, total, children, headN )} - {pageData.map((el: { [key: string]: string | number | boolean | object }, index) => ( + {tableData.map((el: { [key: string]: string | number | boolean | object }, index) => ( {headlist?.map((head) => (