153 lines
4.5 KiB
TypeScript
153 lines
4.5 KiB
TypeScript
"use client";
|
|
|
|
import Gis from "@common/business_components/ui/map/Gis";
|
|
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { SearchBar } from "./searchBar/searchBar";
|
|
|
|
interface FeatureData {
|
|
fid?: string;
|
|
ftrIdn?: string;
|
|
id?: string;
|
|
getGeometry?: () => { getExtent: () => number[] };
|
|
setStyle?: () => void;
|
|
}
|
|
|
|
interface MapInstance {
|
|
getLayers: () => {
|
|
getArray: () => Array<{
|
|
getSource?: () => { getFeatureById?: (id: string) => FeatureData | null };
|
|
}>;
|
|
};
|
|
getView: () => { fit: (extent: number[], options: object) => void };
|
|
}
|
|
|
|
const Map = () => {
|
|
const [treeData, setTreeData] = useState([]); // 초기값을 객체 또는 null로 설정
|
|
const gisMaps = useRef<MapInstance | null>(null);
|
|
const [isOpen, setIsOpen] = useState(false); // 팝업 열기/닫기 상태
|
|
const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); // SearchModal 열림 상태
|
|
const [featureData, setFeatureData] = useState<FeatureData | null>(null); // 선택된 피쳐 데이터
|
|
|
|
const fetchData = async () => {
|
|
try {
|
|
const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}/v1/map`;
|
|
const reqUrl = `${API_URL}/lyrStngs/FO_NETWORK`;
|
|
const response = await fetch(reqUrl, {
|
|
method: "GET",
|
|
headers: {
|
|
accept: "application/json",
|
|
},
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP 오류! 상태: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json(); // 여기서 json 파싱
|
|
setTreeData(data); // 데이터 설정
|
|
} catch (error) {
|
|
console.error("데이터 불러오기 실패:", error);
|
|
}
|
|
};
|
|
|
|
// 컴포넌트 마운트 시 1회 실행
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, []);
|
|
|
|
// SearchModal, GisContent 등에서 호출
|
|
const onFeatureSelect = (data: FeatureData) => {
|
|
const map = gisMaps.current;
|
|
if (!map) {
|
|
console.warn("지도가 초기화되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
// 항상 같은 select 객체 사용
|
|
const select = GisApp.Module.select as unknown as
|
|
| {
|
|
resetSelectedFeature: () => void;
|
|
selectFeature: (feature: FeatureData, selected: boolean) => void;
|
|
}
|
|
| undefined;
|
|
if (!select) return;
|
|
|
|
// 1. 기존 선택 초기화
|
|
select.resetSelectedFeature();
|
|
|
|
// 2. data가 OpenLayers Feature 인스턴스인지 확인
|
|
let foundFeature: FeatureData | null = null;
|
|
if (
|
|
data &&
|
|
typeof data.getGeometry === "function" &&
|
|
typeof data.setStyle === "function"
|
|
) {
|
|
// 이미 Feature 인스턴스라면 그대로 사용
|
|
foundFeature = data;
|
|
} else {
|
|
// 아니면 featureId로 맵에서 Feature 인스턴스를 찾아서 사용
|
|
const featureId = data.fid || data.ftrIdn || data.id;
|
|
map
|
|
.getLayers()
|
|
.getArray()
|
|
.forEach((layer) => {
|
|
const source = layer.getSource?.();
|
|
if (source?.getFeatureById) {
|
|
const feature = source.getFeatureById(String(featureId).trim());
|
|
if (feature) foundFeature = feature;
|
|
}
|
|
});
|
|
}
|
|
|
|
// 3. 피처 선택
|
|
if (foundFeature && foundFeature.getGeometry) {
|
|
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,
|
|
});
|
|
}
|
|
select.selectFeature(foundFeature, true);
|
|
} else {
|
|
console.warn("OpenLayers Feature를 찾을 수 없습니다:", data);
|
|
}
|
|
|
|
setFeatureData(data);
|
|
setIsOpen(true);
|
|
setIsSearchModalOpen(false);
|
|
};
|
|
|
|
return (
|
|
<div className="bg-container">
|
|
<Gis
|
|
treeData={treeData}
|
|
isSearch={false}
|
|
gisMaps={gisMaps}
|
|
isMiniMap={false}
|
|
searchView={undefined}
|
|
detailView={undefined}
|
|
onFeatureSelect={onFeatureSelect}
|
|
setIsOpen={setIsOpen}
|
|
setFeatureData={setFeatureData}
|
|
featureData={featureData}
|
|
setIsSearchModalOpen={setIsSearchModalOpen}
|
|
isOpen={isOpen}
|
|
isSearchModalOpen={isSearchModalOpen}
|
|
onCheckedLayersChange={undefined}
|
|
imgVisble={false}
|
|
searchBar={() => <SearchBar onFeatureSelect={onFeatureSelect} gisMaps={gisMaps} />}
|
|
waterDepth={undefined}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Map;
|