|
|
|
@ -1,11 +1,5 @@
|
|
|
|
|
import { |
|
|
|
|
useEffect, |
|
|
|
|
useState, |
|
|
|
|
lazy, |
|
|
|
|
useRef, |
|
|
|
|
useCallback, |
|
|
|
|
Suspense |
|
|
|
|
} from 'react'; |
|
|
|
|
import { useEffect, useRef, useState, lazy, Suspense } from 'react'; |
|
|
|
|
import { useDispatch, useSelector } from '@src/redux/store'; |
|
|
|
|
import { Card } from '@component/ui'; |
|
|
|
|
import { Map } from 'react-feather'; |
|
|
|
|
import FlightApprovalsInfo from '../../components/flight/FlightApprovalsInfo'; |
|
|
|
@ -21,12 +15,30 @@ import MapboxLanguage from '@mapbox/mapbox-gl-language';
|
|
|
|
|
import threebox from 'threebox-plugin'; |
|
|
|
|
import mapboxgl from 'mapbox-gl'; |
|
|
|
|
import { MAPBOX_TOKEN } from '../../configs/constants'; |
|
|
|
|
import { getLaancDetail } from '@src/redux/features/laanc/laancThunk'; |
|
|
|
|
import { |
|
|
|
|
InitFeature, |
|
|
|
|
handlerCreatePoint, |
|
|
|
|
handlerFitBounds, |
|
|
|
|
handlerGetCircleCoord, |
|
|
|
|
layerBuffer, |
|
|
|
|
layerPolygon, |
|
|
|
|
layerPolyline, |
|
|
|
|
layerWayPoint, |
|
|
|
|
handlerCreateAirSpace |
|
|
|
|
} from '../../utility/MapUtils'; |
|
|
|
|
import { MapControl } from '../../components/map/MapControl'; |
|
|
|
|
import { clientSetIsMapLoading } from '@src/redux/features/laanc/laancSlice'; |
|
|
|
|
// redux
|
|
|
|
|
import { clientMapInit } from '@src/redux/features/control/map/mapSlice'; |
|
|
|
|
export default function FlightApprovalsContainer() { |
|
|
|
|
const dispatch = useDispatch(); |
|
|
|
|
|
|
|
|
|
// 오른쪽 사이드 메뉴 표출 여부
|
|
|
|
|
const [openSetting, setOpenSetting] = useState(true); |
|
|
|
|
const [data, setData] = useState([ |
|
|
|
|
{ |
|
|
|
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd4', |
|
|
|
|
planSno: '321', |
|
|
|
|
complaint: '15000', |
|
|
|
|
radius: '100', |
|
|
|
|
coord: '37.33395/126.59298', |
|
|
|
@ -39,7 +51,7 @@ export default function FlightApprovalsContainer() {
|
|
|
|
|
cntrlEndDt: '2023-11-22 13:16:29' |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd5', |
|
|
|
|
planSno: '322', |
|
|
|
|
complaint: '15000', |
|
|
|
|
radius: '100', |
|
|
|
|
coord: '37.33395/126.59298', |
|
|
|
@ -52,7 +64,7 @@ export default function FlightApprovalsContainer() {
|
|
|
|
|
cntrlEndDt: '2023-11-22 13:16:29' |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd6', |
|
|
|
|
planSno: '333', |
|
|
|
|
complaint: '15000', |
|
|
|
|
radius: '100', |
|
|
|
|
elev: '100', |
|
|
|
@ -65,7 +77,7 @@ export default function FlightApprovalsContainer() {
|
|
|
|
|
cntrlEndDt: '2023-11-22 13:16:29' |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd7', |
|
|
|
|
planSno: '344', |
|
|
|
|
complaint: '15000', |
|
|
|
|
radius: '100', |
|
|
|
|
coord: '37.33395/126.59298', |
|
|
|
@ -78,7 +90,7 @@ export default function FlightApprovalsContainer() {
|
|
|
|
|
cntrlEndDt: '2023-11-22 13:16:29' |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd8', |
|
|
|
|
planSno: '345', |
|
|
|
|
complaint: '15000', |
|
|
|
|
radius: '100', |
|
|
|
|
coord: '37.33395/126.59298', |
|
|
|
@ -99,6 +111,23 @@ export default function FlightApprovalsContainer() {
|
|
|
|
|
const [filter, setFilter] = useState(''); |
|
|
|
|
// 지도
|
|
|
|
|
const [mapObject, setMapObject] = useState(); |
|
|
|
|
|
|
|
|
|
const [areaCoordList, setAreaCoordList] = useState([]); |
|
|
|
|
|
|
|
|
|
const map = useSelector(state => state.mapState.map); |
|
|
|
|
const previewGeo = { |
|
|
|
|
type: 'FeatureCollection', |
|
|
|
|
features: [] |
|
|
|
|
}; |
|
|
|
|
useEffect(() => { |
|
|
|
|
if (areaCoordList.length != 0) { |
|
|
|
|
const area = areaCoordList[0]; |
|
|
|
|
if (area.areaType && area.areaType !== '') { |
|
|
|
|
handlerPreviewDraw(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, [areaCoordList]); |
|
|
|
|
|
|
|
|
|
const handlerSearch = search => { |
|
|
|
|
setFilter(search); |
|
|
|
|
|
|
|
|
@ -112,20 +141,20 @@ export default function FlightApprovalsContainer() {
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// 상세보기
|
|
|
|
|
const handlerDetail = id => { |
|
|
|
|
const handlerDetail = async id => { |
|
|
|
|
setSelected(id); |
|
|
|
|
const res = await dispatch(getLaancDetail(id)); |
|
|
|
|
setAreaCoordList(res.payload.areaList); |
|
|
|
|
handlerMapInit(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
// handlerMapInit();
|
|
|
|
|
}, []); |
|
|
|
|
if (map) { |
|
|
|
|
setMapObject(map); |
|
|
|
|
} |
|
|
|
|
}, [map]); |
|
|
|
|
|
|
|
|
|
const handlerMapInit = () => { |
|
|
|
|
mapboxgl.accessToken = MAPBOX_TOKEN; |
|
|
|
|
const map = new mapboxgl.Map({ |
|
|
|
|
container: 'map', |
|
|
|
|
style: 'mapbox://styles/mapbox/streets-v12' |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// 비행구역 상세맵 draw 정보 셋팅
|
|
|
|
|
const draw = new MapboxDraw({ |
|
|
|
@ -217,38 +246,92 @@ export default function FlightApprovalsContainer() {
|
|
|
|
|
} |
|
|
|
|
] |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
setDrawObj(draw); |
|
|
|
|
map.dragRotate.disable(); |
|
|
|
|
|
|
|
|
|
const language = new MapboxLanguage(); |
|
|
|
|
map.addControl(language); |
|
|
|
|
// dispatch(clientMapInit(map));
|
|
|
|
|
// 김포 3d 공역
|
|
|
|
|
|
|
|
|
|
const tb = (window.tb = new threebox.Threebox( |
|
|
|
|
map, |
|
|
|
|
map.getCanvas().getContext('webgl'), |
|
|
|
|
{ |
|
|
|
|
enableSelectingObjects: true, |
|
|
|
|
enableTooltips: true |
|
|
|
|
} |
|
|
|
|
)); |
|
|
|
|
dispatch(clientSetIsMapLoading(true)); |
|
|
|
|
|
|
|
|
|
setIsMapLoading(true); |
|
|
|
|
setMapObject(map); |
|
|
|
|
// dispatch(clientMapInit(map));
|
|
|
|
|
dispatch(clientMapInit(map)); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const handlerPreviewDraw = () => { |
|
|
|
|
if (areaCoordList) { |
|
|
|
|
const areas = areaCoordList[0]; |
|
|
|
|
const paths = []; |
|
|
|
|
areas.coordList.forEach(coord => paths.push([coord.lon, coord.lat])); |
|
|
|
|
|
|
|
|
|
let fitZoomPaths = []; |
|
|
|
|
|
|
|
|
|
if (areas.areaType) { |
|
|
|
|
if (areas.areaType === 'CIRCLE') { |
|
|
|
|
const radius = areas.bufferZone; |
|
|
|
|
const circleCoords = handlerGetCircleCoord(paths[0], radius); |
|
|
|
|
|
|
|
|
|
const circle = InitFeature('Polygon', 'CIRCLE'); |
|
|
|
|
circle.properties.center = paths[0]; |
|
|
|
|
circle.geometry.coordinates = circleCoords; |
|
|
|
|
|
|
|
|
|
mapObject.setCenter(circle.properties.center); |
|
|
|
|
|
|
|
|
|
fitZoomPaths = circleCoords[0]; |
|
|
|
|
} else { |
|
|
|
|
const lineString = InitFeature('LineString', 'LINE'); |
|
|
|
|
const bufferPolyline = InitFeature('LineString', 'buffer'); |
|
|
|
|
const polygon = InitFeature('Polygon', 'POLYGON'); |
|
|
|
|
const point = []; |
|
|
|
|
if (areas.areaType === 'LINE') { |
|
|
|
|
lineString.geometry.coordinates = paths; |
|
|
|
|
|
|
|
|
|
//버퍼 생성
|
|
|
|
|
if (areas.bufferCoordList) { |
|
|
|
|
const bufferPaths = []; |
|
|
|
|
|
|
|
|
|
areas.bufferCoordList.forEach(bfCoord => |
|
|
|
|
bufferPaths.push([bfCoord.lon, bfCoord.lat]) |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
bufferPolyline.geometry.coordinates = bufferPaths; |
|
|
|
|
} |
|
|
|
|
} else if (areas.areaType === 'POLYGON') { |
|
|
|
|
polygon.geometry.coordinates = [paths]; |
|
|
|
|
} |
|
|
|
|
// 포인트 생성
|
|
|
|
|
paths.forEach((p, i) => { |
|
|
|
|
const wayPoint = handlerCreatePoint(p, i, areas.areaType); |
|
|
|
|
point.push(wayPoint); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
//지도 줌 좌표 설정
|
|
|
|
|
fitZoomPaths = paths.concat(); |
|
|
|
|
} |
|
|
|
|
console.log('>>>', mapObject); |
|
|
|
|
|
|
|
|
|
handlerFitBounds(map, fitZoomPaths, 50, areas.areaType); |
|
|
|
|
|
|
|
|
|
map.setPaintProperty('waypoint', 'circle-radius', 10); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<div className='map' style={{ width: '100vw' }}> |
|
|
|
|
<MapControl /> |
|
|
|
|
</div> |
|
|
|
|
{openSetting ? ( |
|
|
|
|
<div className='right-menu active'> |
|
|
|
|
<button |
|
|
|
|
className='right-layer-btn' |
|
|
|
|
style={{ right: '500px' }} |
|
|
|
|
onClick={() => setOpenSetting(false)} |
|
|
|
|
> |
|
|
|
|
<Map size={18} /> |
|
|
|
|
</button> |
|
|
|
|
<div className='right-layer active' style={{ width: '500px' }}> |
|
|
|
|
<div className='right-layer active'> |
|
|
|
|
<div className='layer-content'> |
|
|
|
|
<FlightApprovalsReport handlerSearch={handlerSearch} /> |
|
|
|
|
<FlightApprovalsInfo |
|
|
|
|