feat: WR(물재이용) 가뭄지도 팝업 구현 을 위한 Gis 수정
This commit is contained in:
@@ -123,6 +123,8 @@ function Gis({
|
||||
orderedLayers = [],
|
||||
checkInterval = 3000,
|
||||
height: height = "h-[calc(100vh-5rem)]",
|
||||
onOpenPopup = (data) => { },
|
||||
droughtDates = { startYmd: '', endYmd: '' }
|
||||
}) {
|
||||
const mapRef = useRef();
|
||||
const [mapObject, setMapObject] = useState({});
|
||||
@@ -245,6 +247,17 @@ function Gis({
|
||||
//setEditLayerItems(prev => [...layerItems])
|
||||
}, [treeData]);
|
||||
|
||||
// droughtDates를 전역(GisApp)에 반영
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
if (droughtDates?.startYmd && droughtDates?.endYmd) {
|
||||
GisApp.DROUGHT_DATES = {
|
||||
startYmd: String(droughtDates.startYmd),
|
||||
endYmd: String(droughtDates.endYmd),
|
||||
};
|
||||
}
|
||||
}, [droughtDates?.startYmd, droughtDates?.endYmd]);
|
||||
|
||||
const getLayerItems = (layerCode) => {
|
||||
const layerItems = Object.entries(layerCode)
|
||||
.filter(([key, obj], idx) => obj?.updtPsblYn === "Y")
|
||||
|
||||
@@ -30,6 +30,8 @@ const GisApp = {};
|
||||
*/
|
||||
//레이어 정보
|
||||
GisApp.layerInfos = [];
|
||||
// 가뭄 레이어 날짜 전역 보관소 추가
|
||||
GisApp.DROUGHT_DATES = { startYmd: '', endYmd: '' };
|
||||
//기본정보
|
||||
GisApp.GEOSERVER_URL = '/geoserver/hasudo/ows';
|
||||
GisApp.SN_GEOSERVER_URL = '/sewerage-service/api/v1/map/geometry';
|
||||
|
||||
@@ -112,7 +112,7 @@ GisOlLayer.prototype = {
|
||||
let toProj = GisApp.TO_PROJ;
|
||||
let lyrTyNm = options.lyrTyNm;
|
||||
let typename = this.storageNm + lyrTyNm;
|
||||
let filter = options?.flterSql && options.flterSql && options.flterSql.trim() !== ''
|
||||
let filter = options?.flterSql && options.flterSql && options.flterSql.trim() !== '';
|
||||
|
||||
let params = {};
|
||||
params['TYPENAME'] = typename;
|
||||
@@ -122,6 +122,10 @@ GisOlLayer.prototype = {
|
||||
params['SRS'] = toProj;
|
||||
params['OUTPUTFORMAT'] = 'application/json';
|
||||
if (filter) params['CQL_FILTER'] = filter;
|
||||
else if (GisApp.DROUGHT_DATES) {
|
||||
params['START_YMD'] = GisApp.DROUGHT_DATES.startYmd;
|
||||
params['END_YMD'] = GisApp.DROUGHT_DATES.endYmd;
|
||||
}
|
||||
let strParams = new URLSearchParams(params).toString();
|
||||
|
||||
let source = new VectorSource({
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
"use client";
|
||||
import { SelectBox, type SelectDataType } from "../../../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<string, string> = {
|
||||
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<any>;
|
||||
facilityTypes: { text: string; val: string }[];
|
||||
}
|
||||
|
||||
export const ComboSearchBar = ({
|
||||
onFeatureSelect,
|
||||
gisMaps,
|
||||
facilityTypes,
|
||||
}: SearchBarProps) => {
|
||||
const [sidoValue, setSidoValue] = useState("0");
|
||||
const [sigunValue, setSigunValue] = useState("0");
|
||||
const [sidoData, setSidoData] = useState<SelectDataType[]>([
|
||||
{ text: "선택", val: "0" },
|
||||
]);
|
||||
const [sigunData, setSigunData] = useState<SelectDataType[]>([
|
||||
{ text: "선택", val: "0" },
|
||||
]);
|
||||
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([
|
||||
{ text: "선택", val: "0" },
|
||||
]);
|
||||
|
||||
const [facilityData, setFacilityData] = useState<SelectDataType[]>([
|
||||
{ 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 = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`;
|
||||
const res = await fetch(url).then(res => res.json());
|
||||
|
||||
const list = res.features.map((f: any) => ({
|
||||
text: f.properties.mctpv_korn_nm,
|
||||
val: f.properties.mctpv_cd,
|
||||
}));
|
||||
setSidoData([{ text: "선택", val: "0" }, ...list]);
|
||||
};
|
||||
|
||||
const fetchSigungu = async () => {
|
||||
const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`;
|
||||
const res = await fetch(url).then(res => res.json());
|
||||
|
||||
const list = res.features.map((f: any) => ({
|
||||
text: f.properties.sgg_korn_nm,
|
||||
val: f.properties.sgg_cd,
|
||||
}));
|
||||
setSigunData(list);
|
||||
};
|
||||
|
||||
//시설명 콤보박스 조회
|
||||
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();
|
||||
fetchSigungu();
|
||||
}, []);
|
||||
|
||||
//시군구 데이터 초기화
|
||||
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 (
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<div className="col-span-4">
|
||||
<div className="card card-border flex">
|
||||
<div className="col-span-10 flex flex-row">
|
||||
{facilityTypes.length > 1 && (
|
||||
<SelectBox
|
||||
labelClass="w-[120px]"
|
||||
className="mr-10 w-[190px]"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label="시설물유형"
|
||||
selectArray={[{ text: "선택", val: "0" }, ...facilityTypes]}
|
||||
onSelectValue={(val: any) =>
|
||||
onSelectValue(val.toString(), "facilityType")
|
||||
}
|
||||
value={facilityType}
|
||||
/>
|
||||
)}
|
||||
<SelectBox
|
||||
labelClass="w-[40px]"
|
||||
className="mr-5 w-[150px]"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label=""
|
||||
selectArray={sidoData}
|
||||
onSelectValue={(val: any) =>
|
||||
onSelectValue(val.toString(), "ctpvCd")
|
||||
}
|
||||
value={sidoValue}
|
||||
/>
|
||||
<SelectBox
|
||||
labelClass="w-[65px]"
|
||||
className="mr-5 w-[150px]"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label=""
|
||||
selectArray={filteredSigunData}
|
||||
onSelectValue={(val: any) =>
|
||||
onSelectValue(val.toString(), "sggCd")
|
||||
}
|
||||
value={sigunValue}
|
||||
/>
|
||||
<SelectBox
|
||||
labelClass="w-[60px]"
|
||||
className="mr-3 w-[180px]"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label="시설명"
|
||||
selectArray={facilityData}
|
||||
onSelectValue={(val: any) =>
|
||||
onSelectValue(val.toString(), "fcltCd")
|
||||
}
|
||||
value={facilityValue}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row space-x-2">
|
||||
<Button
|
||||
color="primary"
|
||||
className="mx-2 ml-5 mt-1"
|
||||
size={"sm"}
|
||||
onClick={handleSearch}
|
||||
>
|
||||
조회
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,302 @@
|
||||
"use client";
|
||||
import { SelectBox, type SelectDataType } from "../../../ui";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import GisApp from "../lib/gis.core";
|
||||
|
||||
const geoserverUrl =
|
||||
"/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&outputFormat=application/json";
|
||||
|
||||
const FACILITY_TYPE_URL_MAP: Record<string, string> = {
|
||||
tb_il_swage_prcs_fclt: geoserverUrl, //하수처리시설
|
||||
};
|
||||
|
||||
interface SearchBarProps {
|
||||
gisMaps: React.RefObject<any>;
|
||||
facilityTypes: { text: string; val: string }[];
|
||||
}
|
||||
|
||||
export const ProcSearchBar = ({ gisMaps, facilityTypes }: SearchBarProps) => {
|
||||
const [sidoValue, setSidoValue] = useState("0");
|
||||
const [sigunValue, setSigunValue] = useState("0");
|
||||
const [sidoData, setSidoData] = useState<SelectDataType[]>([
|
||||
{ text: "시도", val: "0" },
|
||||
]);
|
||||
const [sigunData, setSigunData] = useState<SelectDataType[]>([
|
||||
{ text: "시군구", val: "0" },
|
||||
]);
|
||||
const [filteredSigunData, setFilteredSigunData] = useState<SelectDataType[]>([
|
||||
{ text: "시군구", val: "0" },
|
||||
]);
|
||||
|
||||
const [facilityData, setFacilityData] = useState<SelectDataType[]>([
|
||||
{ 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 = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_ctpv&outputFormat=application/json&propertyName=mctpv_korn_nm,mctpv_cd`;
|
||||
const res = await fetch(url).then(res => res.json());
|
||||
|
||||
const list = res.features.map((f: any) => ({
|
||||
text: f.properties.mctpv_korn_nm,
|
||||
val: f.properties.mctpv_cd,
|
||||
}));
|
||||
setSidoData([{ text: "선택", val: "0" }, ...list]);
|
||||
};
|
||||
|
||||
const fetchSigungu = async () => {
|
||||
const url = `/geoserver/hasudo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hasudo:tb_ms_sgg&outputFormat=application/json&propertyName=sgg_cd,sgg_korn_nm`;
|
||||
const res = await fetch(url).then(res => res.json());
|
||||
|
||||
const list = res.features.map((f: any) => ({
|
||||
text: f.properties.sgg_korn_nm,
|
||||
val: f.properties.sgg_cd,
|
||||
}));
|
||||
setSigunData(list);
|
||||
};
|
||||
|
||||
//시설명 콤보박스 조회
|
||||
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();
|
||||
fetchSigungu();
|
||||
}, []);
|
||||
|
||||
//시군구 데이터 초기화
|
||||
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);
|
||||
|
||||
// 하수처리시설일 때 바로 handleFeatureFocus 호출
|
||||
if (val !== "0") {
|
||||
handleFeatureFocus({
|
||||
fid: val,
|
||||
layerNm: "tb_il_swage_prcs_fclt", // 레이어 이름
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
[initializeSigunData, sigunData, sigunValue, sidoData, sidoValue],
|
||||
);
|
||||
|
||||
const handleFeatureFocus = (data: any) => {
|
||||
const map = gisMaps.current;
|
||||
if (!map) {
|
||||
console.warn("지도가 초기화되지 않았습니다.");
|
||||
return;
|
||||
}
|
||||
// 항상 같은 select 객체 사용
|
||||
const select = GisApp.Module.select as any;
|
||||
if (!select) return;
|
||||
// 1. 기존 선택 초기화
|
||||
//select.resetSelectedFeature();
|
||||
// 2. data가 OpenLayers Feature 인스턴스인지 확인
|
||||
let foundFeature: any = null;
|
||||
let featureId = data.fid;
|
||||
map
|
||||
.getLayers()
|
||||
.getArray()
|
||||
.forEach((layer: any) => {
|
||||
const source = layer.getSource?.();
|
||||
if (source?.getFeatureById) {
|
||||
const feature = source.getFeatureById(String(featureId).trim());
|
||||
if (feature) foundFeature = feature;
|
||||
}
|
||||
});
|
||||
// 3. 피처 선택
|
||||
if (foundFeature) {
|
||||
const geometry = foundFeature.getGeometry();
|
||||
if (geometry) {
|
||||
const extent = geometry.getExtent();
|
||||
map.getView().fit(extent, {
|
||||
duration: 300,
|
||||
padding: [50, 50, 50, 50],
|
||||
maxZoom: 16,
|
||||
constrainResolution: true,
|
||||
nearest: true,
|
||||
});
|
||||
} else {
|
||||
console.warn("geometry를 찾을 수 없습니다:", data);
|
||||
}
|
||||
} else {
|
||||
console.warn("Feature를 찾을 수 없습니다:", data);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-4 gap-4">
|
||||
<div className="col-span-4">
|
||||
<div className="card card-border flex">
|
||||
<div className="col-span-10 flex flex-row">
|
||||
<SelectBox
|
||||
labelClass="w-[40px]"
|
||||
className="mr-10 w-[150px]"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label=""
|
||||
selectArray={sidoData}
|
||||
onSelectValue={(val: any) =>
|
||||
onSelectValue(val.toString(), "ctpvCd")
|
||||
}
|
||||
value={sidoValue}
|
||||
/>
|
||||
<SelectBox
|
||||
labelClass="w-[65px]"
|
||||
className="mr-10 w-[150px]"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label=""
|
||||
selectArray={filteredSigunData}
|
||||
onSelectValue={(val: any) =>
|
||||
onSelectValue(val.toString(), "sggCd")
|
||||
}
|
||||
value={sigunValue}
|
||||
/>
|
||||
<SelectBox
|
||||
labelClass="w-[60px]"
|
||||
className="mr-3 w-[180px]"
|
||||
selectClass="rounded-lg bg-white"
|
||||
label=""
|
||||
selectArray={facilityData}
|
||||
onSelectValue={(val: any) =>
|
||||
onSelectValue(val.toString(), "fcltCd")
|
||||
}
|
||||
value={facilityValue}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user