"use client"; import { SelectBox, type SelectDataType } from "@common/business_components/ui"; import { Button } from "@common/components/ui"; import { useCallback, useEffect, useState } from "react"; const geoserverUrl = "/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&outputFormat=application/json"; const FACILITY_TYPE_URL_MAP: Record = { tb_il_swage_prcs_fclt: geoserverUrl, //하수처리시설 tb_wr_bdst_ruse_fclt: "/reuse-service/reuseFc/pubDetailList/{year}/{sggCd}/1/1000", //재이용시설 post tb_wr_rnwtr_utztn_fclt: "/reuse-service/reuseFc/rainyInfoList/1/1000/{sggCd}", //빗물이용시설 get tb_wr_rswtr_fclt: "/reuse-service/reuseFc/waterreuseFc/1/1000/{sggCd}", //중수도시설 get tb_wr_htdfl_fclt: "/reuse-service/drain/facilityList/1/1000/{sggCd}", //온배수시설 get tb_wr_ruse_fclt_dmd_co: "/reuse-service/reuseFc/request/1/1000/{sggCd}", //수요처 get tb_wr_tmpr_dmd_co: "/reuse-service/reuseFc/request/temp/1/1000/{sidoNm} {sggNm}", //잠재수요처 get }; interface SearchBarProps { onFeatureSelect: (feature: any) => void; gisMaps: React.RefObject; facilityTypes: { text: string; val: string }[]; } export function SearchBar({ onFeatureSelect, gisMaps, facilityTypes, }: SearchBarProps) { const [sidoValue, setSidoValue] = useState("0"); const [sigunValue, setSigunValue] = useState("0"); const [sidoData, setSidoData] = useState([ { text: "선택", val: "0" }, ]); const [sigunData, setSigunData] = useState([ { text: "선택", val: "0" }, ]); const [filteredSigunData, setFilteredSigunData] = useState([ { text: "선택", val: "0" }, ]); const [facilityData, setFacilityData] = useState([ { text: "선택", val: "0" }, ]); const [facilityValue, setFacilityValue] = useState("0"); const [facilityType, setFacilityType] = useState( facilityTypes?.length === 1 && facilityTypes[0] ? facilityTypes[0].val : "0" ); //시도, 시군구 조회 const fetchSido = async () => { const url = `/cms-service/api/v1/code/cache/ADSTDSTRCD/Y`; const res = await fetch(url); const json = await res.json(); const sidoList = json .filter( (item: any) => typeof item.lwpoCd === "string" && item.lwpoCd.length === 2 ) .map((feature: any) => ({ val: feature.lwpoCd, text: feature.lwpoCdNm, })); setSidoData([{ text: "선택", val: "0" }, ...sidoList]); const sigunList = json .filter( (item: any) => typeof item.lwpoCd === "string" && item.lwpoCd.length !== 2 ) .map((feature: any) => ({ val: feature.lwpoCd, text: feature.lwpoCdNm, })); setSigunData(sigunList); }; //시설명 콤보박스 조회 const fetchFacilitiesBySggNm = async ( sggCd: string, sggNm: string, sidoNm: string, currentFacilityType?: string ) => { const type = currentFacilityType ?? facilityType; if (!type || type === "0") return; const baseUrlTemplate = FACILITY_TYPE_URL_MAP[type]; if (!baseUrlTemplate) return; const year = new Date().getFullYear().toString(); let url = baseUrlTemplate .replace("{year}", year) .replace("{sggCd}", sggCd) .replace("{sidoNm}", encodeURIComponent(sidoNm)) .replace("{sggNm}", encodeURIComponent(sggNm)); let list: SelectDataType[] = []; if ( type === "tb_il_swage_prcs_fclt" //하수처리시설 ) { const cqlFilter = `ctpv_nm='${encodeURIComponent(sidoNm)}' AND sgg_nm='${encodeURIComponent(sggNm)}'`; url = `${url}&typeName=hasudo:${type}&cql_filter=${cqlFilter}`; const res = await fetch(url); const json = await res.json(); list = json.features.map((f: any) => ({ text: f.properties.swtrmt_fclt_nm ?? "(이름없음)", val: f.id, })); } else if ( type === "tb_wr_bdst_ruse_fclt" // 재이용시설 ) { //재용에서 참조하는 하수처리시설 목록 const paramsRes = await fetch("/reuse-service/reuseFc/pubFc"); const paramsJson = await paramsRes.json(); const params = paramsJson.data; const res = await fetch(url, { method: "POST", headers: { accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify(params), }); const json = await res.json(); list = (json.data || []).map((item: any) => ({ text: item.ruseUtztnFcltNm ?? "(이름없음)", val: item.pbnstRuseFcltId, })); } else if ( type === "tb_wr_ruse_fclt_dmd_co" //수요처 ) { const res = await fetch(url); const json = await res.json(); list = (json.data || []).map((item: any) => ({ text: item.dmdCoNm ?? "(이름없음)", val: item.dmdInfoId, })); } else if ( type === "tb_wr_tmpr_dmd_co" //잠재수요처 ) { // GET 방식 const res = await fetch(url); const json = await res.json(); list = (json.data || []).map((item: any) => ({ text: item.dmdCoNm ?? "(이름없음)", val: item.fctryMngSn, })); } else { // GET 방식 const res = await fetch(url); const json = await res.json(); list = (json.data || []).map((item: any) => ({ text: item.bdstNm ?? "(이름없음)", val: item.bdstInfoSn, })); } setFacilityData([{ text: "선택", val: "0" }, ...list]); setFacilityValue("0"); }; //시도, 시군구 초기 데이터 조회 useEffect(() => { fetchSido(); }, []); //시군구 데이터 초기화 const initializeSigunData = useCallback( (sidoCd: string) => { if (sidoCd === "0") { setFilteredSigunData([{ text: "선택", val: "0" }]); setSigunValue("0"); return; } const prefix = sidoCd.substring(0, 2); const filtered = sigunData.filter((item) => item.val.startsWith(prefix)); setFilteredSigunData([{ text: "선택", val: "0" }, ...filtered]); setSigunValue("0"); }, [sigunData] ); //콤보박스 선택시 연관 콤보박스 처리 const onSelectValue = useCallback( (val: string, type: string) => { if (type === "ctpvCd") { setSidoValue(val); initializeSigunData(val); setFacilityData([{ text: "선택", val: "0" }]); setFacilityValue("0"); } else if (type === "sggCd") { setSigunValue(val); const sidoNm = sidoData.find((item) => item.val === sidoValue)?.text || ""; const sggNm = sigunData.find((item) => item.val === val)?.text || ""; const sggCd = sigunData.find((item) => item.val === val)?.val || ""; if (sggNm && sidoNm) fetchFacilitiesBySggNm(sggCd, sggNm, sidoNm, facilityType); } else if (type === "facilityType") { setFacilityType(val); setFacilityValue("0"); setFacilityData([{ text: "선택", val: "0" }]); const sidoNm = sidoData.find((item) => item.val === sidoValue)?.text || ""; const sggNm = sigunData.find((item) => item.val === sigunValue)?.text || ""; const sggCd = sigunData.find((item) => item.val === sigunValue)?.val || ""; if (sggNm && sidoNm) fetchFacilitiesBySggNm(sggCd, sggNm, sidoNm, val); } else if (type === "fcltCd") { setFacilityValue(val); } }, [initializeSigunData, sigunData, sigunValue, sidoData, sidoValue] ); //조회 버튼 클릭 const handleSearch = () => { if (!gisMaps.current || facilityValue === "0") return; const layers = gisMaps.current.getLayers().getArray(); for (const layer of layers) { const source = layer.getSource?.(); const feature = source?.getFeatureById?.(facilityValue); if (feature) { onFeatureSelect(feature); return; } } alert("해당 처리시설을 지도에서 찾을 수 없습니다."); }; return (
{facilityTypes.length > 1 && ( onSelectValue(val.toString(), "facilityType") } value={facilityType} /> )} onSelectValue(val.toString(), "ctpvCd")} value={sidoValue} /> onSelectValue(val.toString(), "sggCd")} value={sigunValue} /> onSelectValue(val.toString(), "fcltCd")} value={facilityValue} />
); }