diff --git a/apps/sn/app/(map-layout)/layout.tsx b/apps/sn/app/(map-layout)/layout.tsx index 4337ee048..e7ab407c3 100644 --- a/apps/sn/app/(map-layout)/layout.tsx +++ b/apps/sn/app/(map-layout)/layout.tsx @@ -19,13 +19,10 @@ export default function MapLayout({ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); - const { fetchCtpvData, fetchSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); + const { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); - - // 시도, 시군구 호출 useEffect(() => { - fetchCtpvData(); - fetchSggData(); + fetchCtpvSggData(); fetchBIZ_SE_CD(); fetchBIZ_TY_CD(); }, []); diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx index 801164eb8..0ab04eea5 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/Ssc.tsx @@ -6,6 +6,7 @@ import { untrtSwgRainCol3, untrtSwgRainCol4, untrtSwgRainCol5 } from '../common/ import { VerticalTable } from '@/components/ui/verticalTable'; import { getData } from "@/components/lib/api"; import { formatDisplayData } from '@/components/lib/utils/formatDisplayValue'; +import { Label } from '@radix-ui/react-label'; const inputColumn = [ { id: "prrtymngYn", title: "중점여부", type: "select", options: ["우수토실", "중점우수토실"] }, @@ -180,49 +181,52 @@ const Ssc = ({ featureData, isMainSsc, chmbrXcnts, chmbrYdnts, onSaveClick }: { const renderModalBody = () => (
- {/* 강우정보 테이블 */} - +
+ + {/* 강우정보 테이블 */} + - {/* 측정정보 테이블 */} - - {/* 커스텀 헤더 */} - - 수량 - 수질 - - - 측정시작일시 - 측정종료일시 - 측정간격(분) - 측정기기설치위치 - 유량계 종류 및 모델명 - 채수시작일시 - 채수종료일시 - 채수횟수 - - + {/* 측정정보 테이블 */} + + {/* 커스텀 헤더 */} + + 수량 + 수질 + + + 측정시작일시 + 측정종료일시 + 측정간격(분) + 측정기기설치위치 + 유량계 종류 및 모델명 + 채수시작일시 + 채수종료일시 + 채수횟수 + + +
{/* 수량/수질측정 정보 테이블 */} void; - // onOpenChange?: (open: boolean) => void; - // onFeatureSelect?: (row: any) => void; - // setTableData?: (data: any[]) => void; - // setTableCount?: (count: number) => void; setBasicType: (type: string) => void; setCity: (city: number) => void; setCtpvName: (name: string) => void; @@ -52,7 +45,6 @@ interface BasicTabProps { } const BasicTab: React.FC = ({ - // open, basicType, city, sgg, @@ -64,10 +56,6 @@ const BasicTab: React.FC = ({ var2, yearFilter, handleSearch, - // onOpenChange, - // onFeatureSelect, - // setTableData, - // setTableCount, setBasicType, setCity, setCtpvName, diff --git a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx index dfd71a39d..c52a4ddab 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/operationTab.tsx @@ -55,15 +55,11 @@ export const operationInspectionTableHeadlist = [ ]; interface OperationTabProps { - open: boolean; workType: string; var1: string; var2: string; yearFilter: { start: string; end: string; }; handleSearch: () => void; - // onOpenChange: (open: boolean) => void; - // setTableData: (data: any[]) => void; - // setTableCount: (count: number) => void; setWorkType: (type: string) => void; setYearFilter: (filter: { start: string; end: string }) => void; setVar1: (value: string) => void; @@ -71,15 +67,11 @@ interface OperationTabProps { } const OperationTab: React.FC = ({ - open, workType, var1, var2, yearFilter, handleSearch, - // onOpenChange, - // setTableData, - // setTableCount, setWorkType, setVar1, setVar2, @@ -98,7 +90,7 @@ const OperationTab: React.FC = ({
({ diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx index 53fd312dc..8779f0fa5 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsFclt.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { YearRangeSelectBox } from '@/components/ui/YearRangeSelectBox'; import { Button, Input, Label } from '@common/components'; -import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox'; +import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox'; interface SwagePrcsFcltProps { @@ -47,7 +47,7 @@ const SwagePrcsFclt: React.FC = ({ return (
- { diff --git a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx index abeec54b9..8cb304d2a 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/swagePrcsZone.tsx @@ -1,6 +1,6 @@ // 하수처리구역 -import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox'; +import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox'; import { Button, Input, Label } from '@common/components'; import React from 'react'; @@ -31,10 +31,10 @@ const swagePrcsZone: React.FC = ({ return (
- { + onSidoChange={(sidoId: number) => { setCity(sidoId); setSgg(0); }} diff --git a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx index 9eab30712..c83d56232 100644 --- a/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx +++ b/apps/sn/app/(with-base-layout)/ii/BaseLayout.tsx @@ -1,12 +1,9 @@ 'use client' -import { getData } from '@/components/lib/api' -import { GovSidoSigunguSearchForm } from '@/components/ui/govSidoSigunguSearchForm' import { DateMonthPicker, Form, SelectBox } from '@common/business_components/ui' import ListDiv from '@common/business_components/ui/list_div' import { Button, Label } from '@common/components/ui' -import { useEffect, useState, type ReactNode } from 'react' -import LoadingOverlay from '@/components/ui/LoadingBar' -import { SidoSigunguSelectBox } from '@/components/ui/SidoSigunguSelectBox' +import { useState, type ReactNode } from 'react' +import { CtpvSggPrcsFcltSelectBox } from '@/components/ui/ctpvSggPrcsFcltSelectBox' type TitleName = { mainTitle: string @@ -44,10 +41,8 @@ type BaseLayout = { sggCd: number; sggName?: string; sigungu?: ApiSelectOption - selectedSwageTreatmentPlant?: string | number; - onSwageTreatmentPlantChange?: (value: string | number) => void; - selectedSwageProcessingZone?: string | number; - onSwageProcessingZoneChange?: (value: string | number) => void; + selectedSwagePrcsFclt?: string | number; + onSwagePrcsFcltChange?: (value: string | number) => void; aplcnYmFrom?: string setAplcnYmFrom?: (aplcnYmFrom: string) => void; aplcnYmTo?: string @@ -55,7 +50,7 @@ type BaseLayout = { setCtpvCd: (ctpv: number) => void; setSggCd: (sgg: number) => void; setSggName?: (sggName: string) => void; - isLoading?: boolean; + setIsLoading?: (isLoading: boolean) => void; onExcelDownload?: () => void; onDeleteFile?: () => void; onAnalysis?: () => void; @@ -75,8 +70,8 @@ const BaseLayout = ({ sggCd, sggName, sigungu, - selectedSwageTreatmentPlant, - onSwageTreatmentPlantChange, + selectedSwagePrcsFclt, + onSwagePrcsFcltChange, aplcnYmFrom, setAplcnYmFrom, aplcnYmTo, @@ -84,7 +79,7 @@ const BaseLayout = ({ setCtpvCd, setSggCd, setSggName, - isLoading, + setIsLoading, onExcelDownload, onDeleteFile, onAnalysis, @@ -93,57 +88,6 @@ const BaseLayout = ({ const defaultOption: ApiSelectOption = { val: '0', text: '전체' }; const [treatmentFacilityOptions, setTreatmentFacilityOptions] = useState([]); - const [isLoadingAreaData, setIsLoadingAreaData] = useState(isLoading || false); - - useEffect(() => { - onSwageTreatmentPlantChange?.(0); - - const fetchData = async () => { - if (!sggName) { - console.log("BaseLayout: Skipping fetchData because sigungu.val is:", sigungu?.val); - setTreatmentFacilityOptions([defaultOption]); - setIsLoadingAreaData(false); - return; - } - - setIsLoadingAreaData(true); - try { - - const queryParamsFacility = new URLSearchParams({ - lyrTypeNm: 'tb_il_swage_prcs_fclt', - page: '0', - size: '100000', // 요청하신 URL에 맞게 50으로 변경 가능 - sort: 'string', - }); - const cqlFiltersFacility: string[] = []; - if (sggName) cqlFiltersFacility.push(`sgg_nm ILIKE '%${sggName}%'`); - if (cqlFiltersFacility.length > 0) queryParamsFacility.append('cqlFiter', cqlFiltersFacility.join(' and ')); - - console.log("BaseLayout API URL for Facilities:", `v1/fclts?${queryParamsFacility.toString()}`); - - const facilityRes = await getData(`v1/fclts?${queryParamsFacility.toString()}`); - - console.log('facilityRes.data', facilityRes.data); - - const facilities = (facilityRes.data || []) - .map((item: any) => ({ - text: item.swtrmtFcltNm, - val: item.fid - })) - .sort((a: ApiSelectOption, b: ApiSelectOption) => a.text.localeCompare(b.text, 'ko')); - setTreatmentFacilityOptions([defaultOption, ...facilities]); - console.log("BaseLayout Fetched Treatment Facilities:", [defaultOption, ...facilities]); - - } catch (error) { - console.error("BaseLayout: 지역/시설 데이터 조회 중 오류 발생:", error); - setTreatmentFacilityOptions([defaultOption]); - } finally { - setIsLoadingAreaData(false); - } - }; - - fetchData(); - }, [sggName]); // sgg 상태가 변경될 때마다 실행 // 파일 다운로드 const isChckFile = () => { @@ -165,7 +109,6 @@ const BaseLayout = ({ return (
- {/* searchBox.title이 있으면 h3 태그로 제목을 표시합니다. */} {selectBox?.title && ( @@ -211,25 +154,18 @@ const BaseLayout = ({ /> )} - { + onSidoChange={(sidoId: number) => { setCtpvCd(sidoId); setSggCd(0); }} onSigunguChange={setSggCd} setSggName={setSggName} - /> - - onSwageTreatmentPlantChange?.(val)} - selectContentClass="z-[101]" + selectedSwagePrcsFclt={selectedSwagePrcsFclt} + onSwagePrcsFcltChange={onSwagePrcsFcltChange} + setIsLoading={setIsLoading} /> {selectBox?.searchChk && (
diff --git a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx index e2a51676e..7bb508e50 100644 --- a/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/irsetting/page.tsx @@ -340,12 +340,12 @@ const IrSetting = () => { ctpvCd={ctpvCd} sggCd={sggCd} sggName={sggName} - selectedSwageTreatmentPlant={select1} - onSwageTreatmentPlantChange={setSelect1} + selectedSwagePrcsFclt={select1} + onSwagePrcsFcltChange={setSelect1} setCtpvCd={setCtpvCd} setSggCd={setSggCd} setSggName={setSggName} - isLoading={isLoadingResult} + setIsLoading={setIsLoadingResult} onAnalysis={handleAnalysisClick} > {[
diff --git a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx index 491d2ae9d..a8b0a2b84 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdii/page.tsx @@ -396,12 +396,12 @@ export default function RTKForm() { ctpvCd={ctpvCd} sggCd={sggCd} sggName={sggName} - selectedSwageTreatmentPlant={select1} - onSwageTreatmentPlantChange={setSelect1} + selectedSwagePrcsFclt={select1} + onSwagePrcsFcltChange={setSelect1} setCtpvCd={setCtpvCd} setSggCd={setSggCd} setSggName={setSggName} - isLoading={isLoadingResult} + setIsLoading={setIsLoadingResult} onAnalysis={handleAnalysisClick} > {[
diff --git a/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx b/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx index d705728c5..66b8095db 100644 --- a/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/rdiiResult/page.tsx @@ -284,8 +284,8 @@ const Result = () => { ctpvCd={ctpvCd} sggCd={sggCd} sggName={sggName} - selectedSwageTreatmentPlant={form.watch("swageTmplntCd")} - onSwageTreatmentPlantChange={(val) => form.setValue("swageTmplntCd", String(val))} + selectedSwagePrcsFclt={form.watch("swageTmplntCd")} + onSwagePrcsFcltChange={(val) => form.setValue("swageTmplntCd", String(val))} aplcnYmFrom={form.watch("aplcnYmFrom")} setAplcnYmFrom={(val: string) => { form.setValue("aplcnYmFrom", val) }} aplcnYmTo={form.watch("aplcnYmTo")} @@ -293,7 +293,7 @@ const Result = () => { setCtpvCd={setCtpvCd} setSggCd={setSggCd} setSggName={setSggName} - isLoading={isLoadingResult} + setIsLoading={setIsLoadingResult} // Excel 다운로드 핸들러 추가 onExcelDownload={handleExcelDownload} onDeleteFile={handleFileDelete} diff --git a/apps/sn/app/(with-base-layout)/ii/result/page.tsx b/apps/sn/app/(with-base-layout)/ii/result/page.tsx index c27110223..7c7e4721a 100644 --- a/apps/sn/app/(with-base-layout)/ii/result/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/result/page.tsx @@ -282,8 +282,8 @@ const Result = () => { ctpvCd={ctpvCd} sggCd={sggCd} sggName={sggName} - selectedSwageTreatmentPlant={form.watch("swageTmplntCd")} - onSwageTreatmentPlantChange={(val) => form.setValue("swageTmplntCd", String(val))} + selectedSwagePrcsFclt={form.watch("swageTmplntCd")} + onSwagePrcsFcltChange={(val) => form.setValue("swageTmplntCd", String(val))} aplcnYmFrom={form.watch("aplcnYmFrom")} setAplcnYmFrom={(val: string) => { form.setValue("aplcnYmFrom", val) }} aplcnYmTo={form.watch("aplcnYmTo")} @@ -291,7 +291,7 @@ const Result = () => { setCtpvCd={setCtpvCd} setSggCd={setSggCd} setSggName={setSggName} - isLoading={isLoadingResult} // 로딩 상태 전달 + setIsLoading={setIsLoadingResult} // Excel 다운로드 핸들러 추가 onExcelDownload={handleExcelDownload} onDeleteFile={handleFileDelete} diff --git a/apps/sn/app/(with-base-layout)/layout.tsx b/apps/sn/app/(with-base-layout)/layout.tsx index 8c72ecb0c..f8e046717 100644 --- a/apps/sn/app/(with-base-layout)/layout.tsx +++ b/apps/sn/app/(with-base-layout)/layout.tsx @@ -20,11 +20,10 @@ export default function WithBaseLayout({ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); - const { fetchCtpvData, fetchSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); + const { fetchCtpvSggData, fetchBIZ_SE_CD, fetchBIZ_TY_CD } = useStore(); useEffect(() => { - fetchCtpvData(); - fetchSggData(); + fetchCtpvSggData(); fetchBIZ_SE_CD(); fetchBIZ_TY_CD(); }, []); diff --git a/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx b/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx deleted file mode 100644 index fc9962e75..000000000 --- a/apps/sn/app/components/ui/SidoSigunguSelectBox.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import React, { useState, useMemo, useEffect } from "react"; -import { SelectBox } from '@common/business_components/ui' -import { Label } from '@common/components'; -import useStore from '../../store/useStore'; - - -interface SidoSigunguSelectBoxProps { - sido: number; - sigungu: number; - onSidoChange: (id: number) => void; - setCtpvName?: (name: string) => void; - onSigunguChange: (id: number) => void; - setSggName?: (name: string) => void; - className?: string; -} - -export function SidoSigunguSelectBox({ - sido, - sigungu, - onSidoChange, - setCtpvName, - onSigunguChange, - setSggName, - className = "", -}: SidoSigunguSelectBoxProps) { - - const { ctpv, sgg} = useStore(); - - useEffect(() => { - (async () => { - onSidoChange(0); - onSigunguChange(0); - if (setCtpvName && setSggName) { - setCtpvName(""); - setSggName(""); - } - })(); - }, []); - - - return ( -
- - ({ val: opt.id, text: opt.name })) - ] - } - value={sido} - onSelectValue={val => { - onSidoChange(Number(val)); - if (setCtpvName) setCtpvName(ctpv.find(opt => Number(opt.id) === Number(val))?.name || ""); - }} - selectContentClass="z-[101]" - /> - - String(opt.id).slice(0, 2) === String(sido)) - .map(opt => ({ val: opt.id, text: opt.name })) - ] - } - value={sigungu} - onSelectValue={val => { - onSigunguChange(Number(val)) - if (setSggName) setSggName(sgg.find(opt => Number(opt.id) === Number(val))?.name || ""); - }} - selectContentClass="z-[101]" - /> -
- ); -} \ No newline at end of file diff --git a/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx b/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx new file mode 100644 index 000000000..8e6f9d4eb --- /dev/null +++ b/apps/sn/app/components/ui/ctpvSggPrcsFcltSelectBox.tsx @@ -0,0 +1,161 @@ +import React, { useState, useMemo, useEffect } from "react"; +import { SelectBox } from '@common/business_components/ui' +import { Label } from '@common/components'; +import useStore from '../../store/useStore'; +import { getData } from '@/components/lib/api/index'; + + +interface ApiSelectOption { + text: string; + val: string; +} +interface CtpvSggPrcsFcltSelectBoxProps { + sido: number; + sigungu: number; + sggName?: string; + onSidoChange: (id: number) => void; + onSigunguChange: (id: number) => void; + setCtpvName?: (name: string) => void; + setSggName?: (name: string) => void; + className?: string; + selectedSwagePrcsFclt?: string | number; + onSwagePrcsFcltChange?: (value: string | number) => void; + setIsLoading?: (isLoading: boolean) => void; +} + +const defaultOption: ApiSelectOption = { val: '0', text: '전체' }; + +export function CtpvSggPrcsFcltSelectBox({ + sido, + sigungu, + sggName, + onSidoChange, + setCtpvName, + onSigunguChange, + setSggName, + className = "", + selectedSwagePrcsFclt, + onSwagePrcsFcltChange, + setIsLoading, +}: CtpvSggPrcsFcltSelectBoxProps) { + + const [prcsFcltOptions, setPrcsFcltOptions] = useState([]); + const { ctpv, sgg } = useStore(); + + useEffect(() => { + (async () => { + onSidoChange(0); + onSigunguChange(0); + if (setCtpvName && setSggName) { + setCtpvName(""); + setSggName(""); + } + })(); + }, []); + + // useEffect(() => { + // onSwagePrcsFcltChange?.('0'); + + // const fetchData = async () => { + // if (!sggName) { + // console.log("BaseLayout: Skipping fetchData because sigungu.val is:", sggName); + // setPrcsFcltOptions([defaultOption]); + // if (setIsLoading) setIsLoading(false); + // return; + // } + + // if (setIsLoading) setIsLoading(true); + // try { + + // const queryParamsFacility = new URLSearchParams({ + // lyrTypeNm: 'tb_il_swage_prcs_fclt', + // page: '0', + // size: '100000', // 요청하신 URL에 맞게 50으로 변경 가능 + // sort: 'string', + // }); + // const cqlFiltersFacility: string[] = []; + // if (sggName) cqlFiltersFacility.push(`sgg_nm ILIKE '%${sggName}%'`); + // if (cqlFiltersFacility.length > 0) queryParamsFacility.append('cqlFiter', cqlFiltersFacility.join(' and ')); + + // console.log("BaseLayout API URL for Facilities:", `v1/fclts?${queryParamsFacility.toString()}`); + + // const facilityRes = await getData(`v1/fclts?${queryParamsFacility.toString()}`); + + // console.log('facilityRes.data', facilityRes.data); + + // const facilities = (facilityRes.data || []) + // .map((item: any) => ({ + // text: item.swtrmtFcltNm, + // val: item.fid + // })) + // .sort((a: ApiSelectOption, b: ApiSelectOption) => a.text.localeCompare(b.text, 'ko')); + // setPrcsFcltOptions(facilities); + // console.log("BaseLayout Fetched Treatment Facilities:", prcsFcltOptions); + + // } catch (error) { + // console.error("BaseLayout: 지역/시설 데이터 조회 중 오류 발생:", error); + // setPrcsFcltOptions([]); + // } finally { + // if (setIsLoading) setIsLoading(false); + // } + // }; + + // fetchData(); + // }, [sggName]); + + + return ( +
+ + ({ val: opt.id, text: opt.name })) + ] + } + value={sido} + onSelectValue={val => { + onSidoChange(Number(val)); + if (setCtpvName) setCtpvName(ctpv.find(opt => Number(opt.id) === Number(val))?.name || ""); + }} + selectContentClass="z-[101]" + /> + + String(opt.id).slice(0, 2) === String(sido)) + .map(opt => ({ val: opt.id, text: opt.name })) + ] + } + value={sigungu} + onSelectValue={val => { + onSigunguChange(Number(val)) + if (setSggName) setSggName(sgg.find(opt => Number(opt.id) === Number(val))?.name || ""); + }} + selectContentClass="z-[101]" + /> + {selectedSwagePrcsFclt && onSwagePrcsFcltChange && ( + <> + + onSwagePrcsFcltChange?.(val)} + selectContentClass="z-[101]" + /> + + )} +
+ ); +} \ No newline at end of file