Browse Source

비행승인 페이지 작업중

master
sanguu516 6 months ago
parent
commit
fc38978ef1
  1. 3
      src/@core/layouts/components/menu/vertical-menu/index.js
  2. 11
      src/@core/layouts/components/navbar/NavbarUser.js
  3. 113
      src/components/flight/FlightApprovalsInfo.js
  4. 253
      src/components/flight/FlightApprovalsList.js
  5. 39
      src/components/flight/FlightApprovalsReport.js
  6. 76
      src/containers/flight/flightApprovalsContainer.js
  7. 7
      src/navigation/flight/index.js
  8. 13
      src/router/routes/RouteFlight.js
  9. 11
      src/router/routes/index.js
  10. 19
      src/views/flight/FlightView.js

3
src/@core/layouts/components/menu/vertical-menu/index.js

@ -11,6 +11,7 @@ import analysis from '@src/navigation/analysis';
import laanc from '@src/navigation/laanc';
import cstmrService from '@src/navigation/cstmrService';
import statistics from '@src/navigation/statistics';
import flightApprovals from '@src/navigation/flight';
// ** Third Party Components
import classnames from 'classnames';
@ -48,6 +49,8 @@ const Sidebar = props => {
return statistics;
case 'cstmrService':
return cstmrService;
case 'flightApprovals':
return flightApprovals;
case '/':
return [];
}

11
src/@core/layouts/components/navbar/NavbarUser.js

@ -93,6 +93,17 @@ const NavbarUser = props => {
LAANC 승인 관리
</NavLink>
</NavItem>
<NavItem>
<NavLink
onClick={() => window.open('/flightApprovals', '_blank')}
// active={active === '2'}
// onClick={() => {
// toggle('2')
// }}
>
비행승인 신청 결과
</NavLink>
</NavItem>
<NavItem>
<NavLink
onClick={() => window.open('/control', '_blank')}

113
src/components/flight/FlightApprovalsInfo.js

@ -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>
);
}

253
src/components/flight/FlightApprovalsList.js

@ -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>
);
}

39
src/components/flight/FlightApprovalsReport.js

@ -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>
);
}

76
src/containers/flight/flightApprovalsContainer.js

@ -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>
</>
);
}

7
src/navigation/flight/index.js

@ -0,0 +1,7 @@
export default [
{
id: 'flight_001',
title: '비행기관 신청 결과 건수',
navLink: '/flightApprovals'
}
];

13
src/router/routes/RouteFlight.js

@ -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;

11
src/router/routes/index.js

@ -7,6 +7,8 @@ import RouteWeather from './RouteWeather';
import RouteLaance from './RouteLaance';
import RouterCstmrService from './RouterCstmrService';
import RouteStatistics from './RouteStatistics';
import RouteFlight from './RouteFlight';
// ** Document title
const TemplateTitle = '%s - Dron Control System';
@ -23,6 +25,7 @@ const Routes = [
...RouteLaance,
...RouterCstmrService,
...RouteStatistics,
...RouteFlight,
{
path: '/home',
component: lazy(() => import('../../views/Home'))
@ -86,6 +89,14 @@ const Routes = [
authRoute: true
}
},
{
path: '/flightApprovals',
component: lazy(() => import('../../views/flight/FlightView')),
layout: 'BlankLayout',
meta: {
authRoute: true
}
},
{
path: '/history/record/sample1',
component: lazy(() =>

19
src/views/flight/FlightView.js

@ -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…
Cancel
Save