sanguu516
6 months ago
10 changed files with 545 additions and 0 deletions
@ -0,0 +1,113 @@ |
|||||||
|
import dayjs from 'dayjs'; |
||||||
|
import { useEffect, useState, useRef, useCallback } from 'react'; |
||||||
|
import { useSelector } from '@src/redux/store'; |
||||||
|
import { Spinner, Badge } from '@component/ui'; |
||||||
|
import { EMPTY_MESSAGE } from '@src/configs/msgConst'; |
||||||
|
|
||||||
|
export default function FlightApprovalsInfo(props) { |
||||||
|
const [results, setSearchResults] = useState([]); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (props.data) { |
||||||
|
setSearchResults(props.data); |
||||||
|
} |
||||||
|
}, []); |
||||||
|
useEffect(() => { |
||||||
|
if (props.filter) { |
||||||
|
const results = props.data.filter(item => |
||||||
|
item.Representative.toLowerCase().includes(props.filter.toLowerCase()) |
||||||
|
); |
||||||
|
setSearchResults(results); |
||||||
|
} |
||||||
|
}, [props.filter]); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='layer-content drone-list'> |
||||||
|
{!results ? ( |
||||||
|
<> |
||||||
|
<div className='no-dataTable'>{EMPTY_MESSAGE}</div> |
||||||
|
{loading && ( |
||||||
|
<div |
||||||
|
style={{ |
||||||
|
display: 'flex', |
||||||
|
justifyContent: 'center', |
||||||
|
flexDirection: 'column', |
||||||
|
alignItems: 'center' |
||||||
|
}} |
||||||
|
> |
||||||
|
<Spinner color='primary' /> |
||||||
|
<span>Loading...</span> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
</> |
||||||
|
) : ( |
||||||
|
<> |
||||||
|
return ( |
||||||
|
<div className='layer-ti'> |
||||||
|
<h4>비행승인 신청 결과 목록 </h4> |
||||||
|
<Badge color='light-primary' className='badge-glow'> |
||||||
|
총 {results.length}건 결과 |
||||||
|
</Badge> |
||||||
|
</div> |
||||||
|
{results.map(data => ( |
||||||
|
<div |
||||||
|
className={`layer-content-list ${ |
||||||
|
data.cntrlId === props.selected ? 'on' : '' |
||||||
|
}`}
|
||||||
|
onClick={() => { |
||||||
|
props.handlerDetail(data.cntrlId); |
||||||
|
}} |
||||||
|
key={Math.random()} |
||||||
|
> |
||||||
|
<dl> |
||||||
|
<dt> |
||||||
|
<div className='list-left-txt'>민원번호</div> |
||||||
|
<div className='list-right-txt'>{data.complaint}</div> |
||||||
|
</dt> |
||||||
|
<dt> |
||||||
|
<div className='list-left-txt'>위도/경도</div> |
||||||
|
<div className='list-right-txt'>{data.coord}</div> |
||||||
|
</dt> |
||||||
|
<dt> |
||||||
|
<div className='list-left-txt'>반경</div> |
||||||
|
<div className='list-right-txt'>{data.radius}m</div> |
||||||
|
</dt> |
||||||
|
<dt> |
||||||
|
<div className='list-left-txt'>고도</div> |
||||||
|
<div className='list-right-txt'>{data.elev}m</div> |
||||||
|
</dt> |
||||||
|
<dt> |
||||||
|
<div className='list-left-txt'>승인 결과</div> |
||||||
|
<div className='list-right-txt'>{data.approval}</div> |
||||||
|
</dt> |
||||||
|
<dt> |
||||||
|
<div className='list-left-txt'>사유</div> |
||||||
|
<div className='list-right-txt'>{data.reason}</div> |
||||||
|
</dt> |
||||||
|
<dt> |
||||||
|
<div className='list-left-txt'>담당 관할기관</div> |
||||||
|
<div className='list-right-txt'>{data.Representative}</div> |
||||||
|
</dt> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
))} |
||||||
|
) |
||||||
|
{false && ( |
||||||
|
<div |
||||||
|
style={{ |
||||||
|
display: 'flex', |
||||||
|
justifyContent: 'center', |
||||||
|
flexDirection: 'column', |
||||||
|
alignItems: 'center' |
||||||
|
}} |
||||||
|
> |
||||||
|
<Spinner color='primary' /> |
||||||
|
<span>Loading...</span> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
{/* <div ref={setTarget} /> */} |
||||||
|
</> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,253 @@ |
|||||||
|
import { |
||||||
|
useEffect, |
||||||
|
useState, |
||||||
|
lazy, |
||||||
|
useRef, |
||||||
|
useCallback, |
||||||
|
Suspense |
||||||
|
} from 'react'; |
||||||
|
import FlightApprovalsInfo from './FlightApprovalsInfo.js'; |
||||||
|
import FlightApprovalsReport from './FlightApprovalsReport.js'; |
||||||
|
import mapboxgl from 'mapbox-gl'; |
||||||
|
import { MAPBOX_TOKEN } from '../../configs/constants'; |
||||||
|
const FeatureAirZone = lazy(() => |
||||||
|
import('../map/mapbox/feature/FeatureAirZone.js') |
||||||
|
); |
||||||
|
import MapboxDraw from '@mapbox/mapbox-gl-draw'; |
||||||
|
import { |
||||||
|
CircleMode, |
||||||
|
DragCircleMode, |
||||||
|
DirectMode, |
||||||
|
SimpleSelectMode |
||||||
|
} from 'mapbox-gl-draw-circle'; |
||||||
|
import MapboxLanguage from '@mapbox/mapbox-gl-language'; |
||||||
|
import threebox from 'threebox-plugin'; |
||||||
|
|
||||||
|
export default function FlightApprovalsList() { |
||||||
|
const [data, setData] = useState([ |
||||||
|
{ |
||||||
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd4', |
||||||
|
complaint: '15000', |
||||||
|
radius: '100', |
||||||
|
coord: '37.33395/126.59298', |
||||||
|
elev: '100', |
||||||
|
approval: '승인', |
||||||
|
reason: '관제권 내 허용 고도(50m/80m)', |
||||||
|
Representative: '김포항공관리사무소', |
||||||
|
stArea: ' 인천광역시 부평구 청천동 372', |
||||||
|
cntrlStDt: '2023-11-22 13:14:12', |
||||||
|
cntrlEndDt: '2023-11-22 13:16:29' |
||||||
|
}, |
||||||
|
{ |
||||||
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd5', |
||||||
|
complaint: '15000', |
||||||
|
radius: '100', |
||||||
|
coord: '37.33395/126.59298', |
||||||
|
elev: '100', |
||||||
|
approval: '승인', |
||||||
|
reason: '관제권 내 허용 고도(50m/80m)', |
||||||
|
Representative: '김포항공관리사무소', |
||||||
|
stArea: ' 인천광역시 부평구 청천동 372', |
||||||
|
cntrlStDt: '2023-11-22 13:14:12', |
||||||
|
cntrlEndDt: '2023-11-22 13:16:29' |
||||||
|
}, |
||||||
|
{ |
||||||
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd6', |
||||||
|
complaint: '15000', |
||||||
|
radius: '100', |
||||||
|
elev: '100', |
||||||
|
coord: '37.33395/126.59298', |
||||||
|
approval: '승인', |
||||||
|
reason: '관제권 내 허용 고도(50m/80m)', |
||||||
|
Representative: '김포항공관리사무소', |
||||||
|
stArea: ' 인천광역시 부평구 청천동 372', |
||||||
|
cntrlStDt: '2023-11-22 13:14:12', |
||||||
|
cntrlEndDt: '2023-11-22 13:16:29' |
||||||
|
}, |
||||||
|
{ |
||||||
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd7', |
||||||
|
complaint: '15000', |
||||||
|
radius: '100', |
||||||
|
coord: '37.33395/126.59298', |
||||||
|
elev: '100', |
||||||
|
approval: '승인', |
||||||
|
reason: '관제권 내 허용 고도(50m/80m)', |
||||||
|
Representative: '김포항공관리사무소', |
||||||
|
stArea: ' 인천광역시 부평구 청천동 372', |
||||||
|
cntrlStDt: '2023-11-22 13:14:12', |
||||||
|
cntrlEndDt: '2023-11-22 13:16:29' |
||||||
|
}, |
||||||
|
{ |
||||||
|
cntrlId: '580d97c7-a7f8-4378-90bc-6dbc42d85bd8', |
||||||
|
complaint: '15000', |
||||||
|
radius: '100', |
||||||
|
coord: '37.33395/126.59298', |
||||||
|
elev: '100', |
||||||
|
approval: '승인', |
||||||
|
reason: '관제권 내 허용 고도(50m/80m)', |
||||||
|
Representative: '김포항공관리사무소', |
||||||
|
stArea: ' 인천광역시 부평구 청천동 372', |
||||||
|
cntrlStDt: '2023-11-22 13:14:12', |
||||||
|
cntrlEndDt: '2023-11-22 13:16:29' |
||||||
|
} |
||||||
|
]); |
||||||
|
const [selected, setSelected] = useState(null); |
||||||
|
const [isMapLoading, setIsMapLoading] = useState(false); |
||||||
|
// 비행구역 그리기
|
||||||
|
const [drawObj, setDrawObj] = useState(); |
||||||
|
|
||||||
|
const [filter, setFilter] = useState(''); |
||||||
|
// 지도
|
||||||
|
const [mapObject, setMapObject] = useState(); |
||||||
|
const handlerSearch = search => { |
||||||
|
setFilter(search); |
||||||
|
|
||||||
|
// setParams({ ...params, search1 });
|
||||||
|
// dispatch(
|
||||||
|
// getSmltList({
|
||||||
|
// searchParams: { ...params, search1 },
|
||||||
|
// page: 1
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
}; |
||||||
|
|
||||||
|
// 상세보기
|
||||||
|
const handlerDetail = id => { |
||||||
|
setSelected(id); |
||||||
|
}; |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
// handlerMapInit();
|
||||||
|
}, []); |
||||||
|
|
||||||
|
const handlerMapInit = () => { |
||||||
|
mapboxgl.accessToken = MAPBOX_TOKEN; |
||||||
|
const map = new mapboxgl.Map({ |
||||||
|
container: 'map', |
||||||
|
style: 'mapbox://styles/mapbox/streets-v12' |
||||||
|
}); |
||||||
|
|
||||||
|
// 비행구역 상세맵 draw 정보 셋팅
|
||||||
|
const draw = new MapboxDraw({ |
||||||
|
displayControlsDefault: false, |
||||||
|
userProperties: true, |
||||||
|
boxSelect: false, |
||||||
|
modes: { |
||||||
|
...MapboxDraw.modes, |
||||||
|
draw_circle: CircleMode, |
||||||
|
drag_circle: DragCircleMode, |
||||||
|
direct_select: DirectMode, |
||||||
|
simple_select: SimpleSelectMode |
||||||
|
}, |
||||||
|
styles: [ |
||||||
|
{ |
||||||
|
// polyline
|
||||||
|
id: 'gl-draw-line', |
||||||
|
type: 'line', |
||||||
|
filter: [ |
||||||
|
'all', |
||||||
|
['==', '$type', 'LineString'], |
||||||
|
['!=', 'mode', 'static'] |
||||||
|
], |
||||||
|
layout: { |
||||||
|
'line-cap': 'round', |
||||||
|
'line-join': 'round' |
||||||
|
}, |
||||||
|
paint: { |
||||||
|
'line-color': '#8a1c05', |
||||||
|
'line-dasharray': [0.2, 2], |
||||||
|
'line-width': 2 |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
// polygon fill
|
||||||
|
id: 'gl-draw-polygon-fill', |
||||||
|
type: 'fill', |
||||||
|
filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']], |
||||||
|
paint: { |
||||||
|
'fill-color': '#8a1c05', |
||||||
|
'fill-outline-color': '#8a1c05', |
||||||
|
'fill-opacity': 0.1 |
||||||
|
} |
||||||
|
}, |
||||||
|
// polygon outline
|
||||||
|
{ |
||||||
|
id: 'gl-draw-polygon-stroke-active', |
||||||
|
type: 'line', |
||||||
|
filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']], |
||||||
|
layout: { |
||||||
|
'line-cap': 'round', |
||||||
|
'line-join': 'round' |
||||||
|
}, |
||||||
|
paint: { |
||||||
|
'line-color': '#8a1c05', |
||||||
|
'line-dasharray': [0.2, 2], |
||||||
|
'line-width': 2 |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
// vertex point halos
|
||||||
|
id: 'gl-draw-polygon-and-line-vertex-halo-active', |
||||||
|
type: 'circle', |
||||||
|
filter: [ |
||||||
|
'all', |
||||||
|
['==', 'meta', 'vertex'], |
||||||
|
['==', '$type', 'Point'], |
||||||
|
['!=', 'mode', 'static'] |
||||||
|
], |
||||||
|
paint: { |
||||||
|
'circle-radius': 8, |
||||||
|
'circle-color': '#ffffff' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
// vertex points
|
||||||
|
id: 'gl-draw-polygon-and-line-vertex-active', |
||||||
|
type: 'circle', |
||||||
|
filter: [ |
||||||
|
'all', |
||||||
|
['==', 'meta', 'vertex'], |
||||||
|
['==', '$type', 'Point'], |
||||||
|
['!=', 'mode', 'static'] |
||||||
|
], |
||||||
|
paint: { |
||||||
|
'circle-radius': 6, |
||||||
|
'circle-color': '#8a1c05' |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
}); |
||||||
|
|
||||||
|
setDrawObj(draw); |
||||||
|
map.dragRotate.disable(); |
||||||
|
|
||||||
|
const language = new MapboxLanguage(); |
||||||
|
map.addControl(language); |
||||||
|
|
||||||
|
const tb = (window.tb = new threebox.Threebox( |
||||||
|
map, |
||||||
|
map.getCanvas().getContext('webgl'), |
||||||
|
{ |
||||||
|
enableSelectingObjects: true, |
||||||
|
enableTooltips: true |
||||||
|
} |
||||||
|
)); |
||||||
|
|
||||||
|
setMapObject(map); |
||||||
|
// dispatch(clientMapInit(map));
|
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className=''> |
||||||
|
<div className='layer-content'> |
||||||
|
<FlightApprovalsReport handlerSearch={handlerSearch} /> |
||||||
|
<FlightApprovalsInfo |
||||||
|
data={data} |
||||||
|
filter={filter} |
||||||
|
selected={selected} |
||||||
|
handlerDetail={handlerDetail} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
import { useState } from 'react'; |
||||||
|
import { Calendar, X } from 'react-feather'; |
||||||
|
import Flatpickr from 'react-flatpickr'; |
||||||
|
import { Button, Input, InputGroup } from '@component/ui'; |
||||||
|
|
||||||
|
export default function FlightApprovalsReport(props) { |
||||||
|
// 식별번호
|
||||||
|
const [filterId, setFilterId] = useState(''); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<div className='layer-ti'> |
||||||
|
<h4>비행승인 신청 결과 현황</h4> |
||||||
|
</div> |
||||||
|
<div className='layer-search layer-search-form'> |
||||||
|
<div></div> |
||||||
|
<div> |
||||||
|
<InputGroup> |
||||||
|
<Input |
||||||
|
type='text' |
||||||
|
placeholder='관할기관을 입력해주세요.' |
||||||
|
value={filterId} |
||||||
|
onChange={e => setFilterId(`${e.target.value}`)} |
||||||
|
/> |
||||||
|
</InputGroup> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<Button |
||||||
|
color='primary' |
||||||
|
onClick={() => props.handlerSearch(filterId)} |
||||||
|
size='sm' |
||||||
|
> |
||||||
|
검색 |
||||||
|
</Button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
import { useEffect, useState, lazy, Suspense } from 'react'; |
||||||
|
import { Card } from '@component/ui'; |
||||||
|
import { Map } from 'react-feather'; |
||||||
|
import FlightApprovalsList from '../../components/flight/FlightApprovalsList'; |
||||||
|
export default function FlightApprovalsContainer() { |
||||||
|
// 오른쪽 사이드 메뉴 표출 여부
|
||||||
|
const [openSetting, setOpenSetting] = useState(true); |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
{openSetting ? ( |
||||||
|
<div className='right-menu active'> |
||||||
|
<button |
||||||
|
className='right-layer-btn' |
||||||
|
onClick={() => setOpenSetting(false)} |
||||||
|
> |
||||||
|
<Map size={18} /> |
||||||
|
</button> |
||||||
|
<div className='right-layer active' style={{ width: '500px' }}> |
||||||
|
<FlightApprovalsList /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) : ( |
||||||
|
<div className='right-menu'> |
||||||
|
<button |
||||||
|
className='right-layer-btn' |
||||||
|
onClick={() => setOpenSetting(true)} |
||||||
|
> |
||||||
|
<Map size={18} /> |
||||||
|
</button> |
||||||
|
<div className='right-layer'></div> |
||||||
|
</div> |
||||||
|
)} |
||||||
|
<div className='main-data-box flight-data' style={{ width: '440px' }}> |
||||||
|
<Card> |
||||||
|
<div className='data-box-header'> |
||||||
|
<span className='box-ti'>관활기관 신청 결과 건수</span> |
||||||
|
</div> |
||||||
|
<div |
||||||
|
className='data-list-box' |
||||||
|
style={{ |
||||||
|
display: 'flex', |
||||||
|
gap: '10px', |
||||||
|
flexWrap: 'wrap' |
||||||
|
}} |
||||||
|
> |
||||||
|
<div className='data-list'> |
||||||
|
<span className=''>서울지방항공청 1건</span> |
||||||
|
</div> |
||||||
|
<div className='data-list'> |
||||||
|
<span className=''>김포공항관리사무소 3건</span> |
||||||
|
</div> |
||||||
|
<div className='data-list'> |
||||||
|
<span className=''>청주공항출장소 2건</span> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div |
||||||
|
style={{ |
||||||
|
display: 'flex', |
||||||
|
gap: '10px', |
||||||
|
justifyContent: 'start' |
||||||
|
}} |
||||||
|
> |
||||||
|
<div className='data-list'> |
||||||
|
<span className=''>부산지방공청 1건</span> |
||||||
|
</div> |
||||||
|
<div className='data-list'> |
||||||
|
<span className=''>제주지방항공청 1건</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
</> |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
export default [ |
||||||
|
{ |
||||||
|
id: 'flight_001', |
||||||
|
title: '비행기관 신청 결과 건수', |
||||||
|
navLink: '/flightApprovals' |
||||||
|
} |
||||||
|
]; |
@ -0,0 +1,13 @@ |
|||||||
|
import { lazy } from 'react'; |
||||||
|
|
||||||
|
const RouteFlight = [ |
||||||
|
{ |
||||||
|
path: '/analysis/history/list', |
||||||
|
component: lazy(() => import('../../views/flight/FlightView')), |
||||||
|
meta: { |
||||||
|
authRoute: true |
||||||
|
} |
||||||
|
} |
||||||
|
]; |
||||||
|
|
||||||
|
export default RouteFlight; |
@ -0,0 +1,19 @@ |
|||||||
|
import '@styles/react/libs/flatpickr/flatpickr.scss'; |
||||||
|
import '@styles/react/libs/tables/react-dataTable-component.scss'; |
||||||
|
import '../../assets/css/custom.css'; |
||||||
|
import FlightApprovalsContainer from '../../containers/flight/flightApprovalsContainer'; |
||||||
|
import { MapControl } from '../../components/map/MapControl'; |
||||||
|
|
||||||
|
export default function FlightView() { |
||||||
|
return ( |
||||||
|
<div className='pal-container'> |
||||||
|
{/* <Helmet> |
||||||
|
<title>관제시스템</title> |
||||||
|
</Helmet> */} |
||||||
|
<div className='map' style={{ width: '100vw' }}> |
||||||
|
<MapControl /> |
||||||
|
</div> |
||||||
|
<FlightApprovalsContainer />; |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
Loading…
Reference in new issue