From ac7e014fb547c2a4dde14c61a23dbbb4326037b7 Mon Sep 17 00:00:00 2001 From: sanguu516 Date: Tue, 9 Jul 2024 17:23:44 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B4=80=EC=A0=9C=EA=B3=BC=20=EC=9A=B4?= =?UTF-8?q?=ED=99=A9=EA=B3=BC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/account/login/AccountLogin.js | 2 +- ...ovalsTable.js => ControlApprovalsTable.js} | 2 +- .../flight/OperationApprovalsTable.js | 1149 +++++++++++++++++ src/containers/controlRightMenuContainer.js | 154 +++ .../flight/ControlApprovalsContainer.js | 655 ++++++++++ .../flight/OperationApprovalsContainer.js | 655 ++++++++++ src/containers/rightMenuContainer.js | 4 +- src/router/hoc/authenticationCheck.tsx | 8 +- src/router/index.tsx | 2 +- src/router/routes/RouteFlight.js | 13 +- src/router/routes/index.js | 21 +- src/views/controlMenuView.js | 13 + src/views/flight/FlightView.js | 1 - ...wFlightView.js => controlApprovalsView.js} | 6 +- src/views/flight/operationApprovalsView.js | 15 + 15 files changed, 2682 insertions(+), 18 deletions(-) rename src/components/flight/{NewFlightApprovalsTable.js => ControlApprovalsTable.js} (99%) create mode 100644 src/components/flight/OperationApprovalsTable.js create mode 100644 src/containers/controlRightMenuContainer.js create mode 100644 src/containers/flight/ControlApprovalsContainer.js create mode 100644 src/containers/flight/OperationApprovalsContainer.js create mode 100644 src/views/controlMenuView.js rename src/views/flight/{NewFlightView.js => controlApprovalsView.js} (61%) create mode 100644 src/views/flight/operationApprovalsView.js diff --git a/src/components/account/login/AccountLogin.js b/src/components/account/login/AccountLogin.js index 026f88e9..cb1d4530 100644 --- a/src/components/account/login/AccountLogin.js +++ b/src/components/account/login/AccountLogin.js @@ -69,7 +69,7 @@ export const AccountLogin = ({ history }) => { if (meta.requestStatus === 'fulfilled') { if (loginForm?.userId === 'GMPATC') { - history.push('/flight/Approvals/new'); + history.push('/operation/approvals'); } else { history.push('/control'); } diff --git a/src/components/flight/NewFlightApprovalsTable.js b/src/components/flight/ControlApprovalsTable.js similarity index 99% rename from src/components/flight/NewFlightApprovalsTable.js rename to src/components/flight/ControlApprovalsTable.js index 852dd703..6489e81b 100644 --- a/src/components/flight/NewFlightApprovalsTable.js +++ b/src/components/flight/ControlApprovalsTable.js @@ -13,7 +13,7 @@ import { } from '@src/redux/features/laanc/laancThunk'; import { ERROR_MESSAGE, ERROR_TITLE } from '@src/configs/msgConst'; -export default function NewFlightApprovalsTable(props) { +export default function ControlApprovalsTable(props) { const dispatch = useDispatch(); // 비행승인 목록 diff --git a/src/components/flight/OperationApprovalsTable.js b/src/components/flight/OperationApprovalsTable.js new file mode 100644 index 00000000..0bc7452a --- /dev/null +++ b/src/components/flight/OperationApprovalsTable.js @@ -0,0 +1,1149 @@ +import React, { useEffect, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { Button, Card } from '@component/ui'; +import { openModal } from '@src/redux/features/comn/message/messageSlice'; +import { FaAngleDown, FaAngleUp } from 'react-icons/fa'; +import { Form, Input, Table, Typography } from 'antd'; +import { HOST } from '../../configs/constants'; +import axios from 'axios'; +import { getAccessToken } from '../../utility/authService/jwtTokenUtil'; +import { + updateLaancAprv, + getLaancAprvList +} from '@src/redux/features/laanc/laancThunk'; +import { ERROR_MESSAGE, ERROR_TITLE } from '@src/configs/msgConst'; + +export default function OperationApprovalsTable(props) { + const dispatch = useDispatch(); + + // 비행승인 목록 + const { laancAprvList, laancElev, laancAprvLoading } = useSelector( + state => state.laancState + ); + + // 승인, 미승인, 비대상 건수 + const [approvalCdValue, setApprovalCdValue] = useState({ + S: 0, + F: 0, + C: 0, + U: 0 + }); + + // 확장된 행 키 + const [expandedRowKeys, setExpandedRowKeys] = useState([]); + + // 수정 키 + const [editingKey, setEditingKey] = useState(''); + + // select row key + const [selectedRowKey, setSelectedRowKey] = useState(''); + + const [form] = Form.useForm(); + + // 수정 키 확인 + const isEditing = record => record.key === editingKey; + + useEffect(() => { + let approvalCdValue = { S: 0, F: 0, C: 0, U: 0 }; + + laancAprvList.map(item => { + item.areaList.map(area => { + if (area.approvalCd === 'S') { + approvalCdValue.S += 1; + } else if (area.approvalCd === 'F') { + approvalCdValue.F += 1; + } else if (area.approvalCd === 'C') { + approvalCdValue.C += 1; + } else { + approvalCdValue.U += 1; + } + }); + }); + + setApprovalCdValue({ + F: approvalCdValue.F, + S: approvalCdValue.S, + C: approvalCdValue.C, + U: approvalCdValue.U + }); + + if (editingKey) { + setEditingKey(''); + } + }, [laancAprvList]); + + // 수정 이벤트 + const edit = record => { + form.setFieldsValue({ + planAreaSno: record.planAreaSno, + bufferZone: record.bufferZone, + fltElev: record.fltElev, + dtl: record.dtl, + era: record.era, + rm: record.rm, + ...record + }); + setEditingKey(record.key); + }; + + // 취소 이벤트 + const cancel = () => { + setEditingKey(''); + }; + + // 저장 이벤트 + const save = async (key, type) => { + try { + const row = await form.validateFields(); + const index = { ...row, planAreaSno: selectedRowKey }; + + const updateRes = await dispatch( + updateLaancAprv([ + { + planAreaSno: selectedRowKey, + bufferZone: row.bufferZone, + fltElev: row.fltElev, + dtl: row.dtl || '', + era: row.era || '', + rm: row.rm || '' + } + ]) + ); + + if (updateRes.meta.requestStatus === 'fulfilled') { + setEditingKey(''); + await dispatch( + getLaancAprvList({ + searchStDt: props.startDate, + searchEndDt: props.endDate + }) + ); + } else { + handlerErrorModal(ERROR_TITLE, ERROR_MESSAGE); + } + } catch (errInfo) { + handlerErrorModal(ERROR_TITLE, ERROR_MESSAGE); + } + }; + + // 데이터 + const columns = [ + { + title: ( + <> + 신청 +
+ 번호 + + ), + dataIndex: 'applyNo', + align: 'center', + width: '60px' + }, + { + title: ( + <> + 신청
월 + + ), + dataIndex: 'applyDtMonth', + width: '70px', + align: 'center', + render: text => `${text}월` + }, + { + title: ( + <> + 신청
일 + + ), + dataIndex: 'applyDtDay', + width: '70px', + align: 'center', + + render: text => `${text}일` + }, + { + title: ( + <> + 신청
+ 구역 수 + + ), + dataIndex: 'areaList', + align: 'center', + width: '85px', + render: areaList => <>총{areaList.length}건 + }, + { + title: <>신청자, + dataIndex: 'applyNm', + width: '90px', + align: 'center', + + render: text => (text ? text : '-') + }, + { + title: ( + <> + 행정
+ 구역 1 + + ), + dataIndex: 'areaList', + width: '90px', + align: 'center', + render: areaList => { + return areaList.length <= 1 && areaList[0].addr1 + ? areaList[0].addr1 + : '-'; + } + }, + { + title: ( + <> + 행정
+ 구역 2 + + ), + dataIndex: 'areaList', + width: '90px', + align: 'center', + render: areaList => { + return areaList.length <= 1 && areaList[0].addr2 + ? areaList[0].addr2 + : '-'; + } + }, + { + title: ( + <> + 상세
+ 주소 + + ), + dataIndex: 'areaList', + width: '100px', + align: 'center', + render: areaList => { + return areaList.length <= 1 && areaList[0].addr3 + ? areaList[0].addr3 + : '-'; + } + }, + { + title: ( + <> + 장애물
+ 제한 +
+ 표면 +
+ + ), + dataIndex: 'areaList', + width: '100px', + align: 'center', + render: areaList => { + return areaList.length <= 1 + ? areaList[0].fltElevMax === 120 + ? '원추' + : areaList[0].fltElevMax > 45 && areaList[0].fltElevMax < 100 + ? '수평' + : '-' + : '-'; + } + }, + { + title: ( + <> + 증심좌표
+ (위도,경도) + + ), + dataIndex: 'areaList', + align: 'center', + width: '85px', + render: areaList => { + return areaList.length <= 1 ? ( + <> + {areaList[0].lat.toFixed(5)}, +
+ {areaList[0].lon.toFixed(5)} + + ) : ( + '-' + ); + } + }, + { + title: ( + <> + 비행
+ 반경 +
+ (m이내) + + ), + dataIndex: 'bufferZone', + align: 'center', + width: '80px', + editable: true, + render: (text, record) => { + return text ? text : '-'; + } + }, + { + title: ( + <> + 신청
+ 고도 +
+ (m이하) + + ), + dataIndex: 'fltElev', + align: 'center', + width: '80px', + editable: true, + render: (text, record) => { + return text ? text : '-'; + } + }, + { + title: ( + <> + 최고비행 +
+ 해발고도 (m) + + ), + dataIndex: 'fltElevMax', + align: 'center', + width: '80px', + render: (text, record) => { + return text ? text : '-'; + } + }, + { + title: ( + <> + 세부
+ 사항 + + ), + dataIndex: 'dtl', + align: 'center', + editable: true, + width: '110px', + render: dtl => { + return dtl ? dtl : '-'; + } + }, + { + title: ( + <> + 비행
+ 목적 + + ), + dataIndex: 'areaList', + align: 'center', + width: '110px', + render: areaList => { + return areaList.length <= 1 && areaList[0].purpose + ? areaList[0].purpose + : '-'; + } + }, + { + title: ( + <> + 긴급 +
+ 구조 기관 + + ), + dataIndex: 'era', + align: 'center', + width: '110px', + editable: true, + render: era => { + return era ? era : '-'; + } + }, + { + title: <>비고, + dataIndex: 'rm', + align: 'center', + width: '110px', + editable: true, + render: rm => { + return rm ? rm : '-'; + } + }, + { + title: ( + <> + 검토
+ 결과 + + ), + dataIndex: 'areaList', + align: 'center', + width: '120px', + render: areaList => { + const approvalCounts = areaList.reduce( + (counts, item) => { + if (item.approvalCd === 'U') { + counts.unapproved += 1; + } else if (item.approvalCd === 'S') { + counts.approved += 1; + } else if (item.approvalCd === 'C') { + counts.conditionalapproval += 1; + } else { + counts.pending += 1; + } + return counts; + }, + { unapproved: 0, approved: 0, pending: 0, conditionalapproval: 0 } + ); + + return ( + <> + {areaList.length > 1 ? ( + <> + 승인: {approvalCounts.approved}건
+ 미승인: + {approvalCounts.pending}건 +
+ 조건부승인:{approvalCounts.conditionalapproval}건
+ 비대상: + {approvalCounts.unapproved}건 + + ) : ( + <> + {areaList[0].approvalCd === 'U' + ? '비대상' + : areaList[0].approvalCd === 'S' + ? '승인' + : areaList[0].approvalCd === 'C' + ? '조건부승인' + : '미승인'} + + )} + + ); + } + }, + { + title: <>더보기, + dataIndex: 'areaList', + align: 'center', + width: '130px', + render: (areaList, record) => + areaList.length > 1 ? ( + + ) : ( + <>- + ) + }, + { + title: '편집', + dataIndex: 'planAreaSno', + align: 'center', + width: '110px', + render: (_, record) => { + const editable = isEditing(record); + return record.areaList.length <= 1 ? ( + editable ? ( + + save(record.key, 'outer')} + style={{ + marginRight: 8 + }} + > + 저장 + + cancel()}>취소 + + ) : ( + + ) + ) : ( + <>- + ); + } + } + ]; + + // 확장된 테이블 데이터 + const expandedRowRender = record => { + const childColumns = [ + { + dataIndex: 'applyNo', + width: '60px', + align: 'center' + }, + { + dataIndex: 'applyDtMonth', + width: '70px', + align: 'center', + + render: text => `${text}월` + }, + { + dataIndex: 'applyDtDay', + width: '70px', + align: 'center', + render: text => `${text}일` + }, + { + dataIndex: 'zoneNo', + align: 'center', + width: '85px', + render: text => { + return <>구역{text}; + } + }, + { + dataIndex: 'applyNm', + align: 'center', + width: '90px', + render: text => { + return text ? text : '-'; + } + }, + { + dataIndex: 'addr1', + align: 'center', + width: '90px', + render: text => { + return text ? text : <>-; + } + }, + { + dataIndex: 'addr2', + align: 'center', + width: '90px', + render: text => { + return text ? text : <>-; + } + }, + { + dataIndex: 'addr3', + align: 'center', + width: '100px', + render: text => { + return text ? text : <>-; + } + }, + + { + dataIndex: 'fltElevMax', + align: 'center', + width: '100px', + render: text => { + return text + ? text === 120 + ? '원추' + : text > 45 && text < 100 + ? '수평' + : '-' + : '-'; + } + }, + + { + align: 'center', + width: '85px', + dataIndex: ['lat', 'lon'], + render: (text, record) => { + const lat = record.lat; + const lon = record.lon; + return ( + <> + {lat.toFixed(5)},
+ {lon.toFixed(5)} + + ); + } + }, + { + dataIndex: 'bufferZone', + align: 'center', + editable: true, + width: '80px' + }, + { + dataIndex: 'fltElev', + align: 'center', + editable: true, + width: '80px' + }, + { + dataIndex: 'fltElevMax', + align: 'center', + width: '80px', + render: text => { + return text ? text : <>-; + } + }, + { + dataIndex: 'dtl', + align: 'center', + editable: true, + width: '110px', + render: text => { + return text ? text : <>-; + } + }, + { + dataIndex: 'purpose', + align: 'center', + width: '110px', + render: text => { + return text ? text : <>-; + } + }, + { + dataIndex: 'era', + align: 'center', + editable: true, + width: '110px', + render: text => { + return text ? text : <>-; + } + }, + { + dataIndex: 'rm', + align: 'center', + editable: true, + width: '110px', + render: text => { + return text ? text : <>-; + } + }, + { + dataIndex: 'approvalCd', + align: 'center', + width: '120px', + render: text => ( + <> + {text === 'U' + ? '비대상' + : text === 'S' + ? '승인' + : text === 'C' + ? '조건부승인' + : '미승인'} + + ) + }, + { + dataIndex: '더보기', + align: 'center', + width: '130px', + render: text => { + return <>-; + } + }, + { + dataIndex: 'planAreaSno', + align: 'center', + width: '110px', + render: (_, record) => { + const editable = isEditing(record); + return editable ? ( + + save(record.key, 'inner')} + style={{ + marginRight: 8 + }} + > + 저장 + + cancel()}>취소 + + ) : ( + + ); + } + } + ]; + + const data = []; + record.areaList.map((item, index) => { + data.push({ + key: `${item.planAreaSno}-${index}`, + applyNo: item.applyNo, + applyDt: item.applyDt, + zoneNo: item.zoneNo, + lat: item.lat, + lon: item.lon, + applyDtDay: item.applyDtDay, + applyDtMonth: item.applyDtMonth, + bufferZone: item.bufferZone, + fltElev: item.fltElev, + rm: item.rm, + era: item.era, + fltElevMax: item.fltElevMax, + purpose: item.purpose, + applyNm: item.applyNm, + dtl: item.dtl, + approvalCd: item.approvalCd, + planAreaSno: item.planAreaSno, + addr1: item.addr1, + addr2: item.addr2, + addr3: item.addr3 + }); + }); + + return ( +
+ { + let className = ''; + if (record.approvalCd === 'S') { + className += 'flight-approval-row'; + } else if (record.approvalCd === 'F') { + className += 'flight-not-approval-row'; + } else if (record.approvalCd === 'C') { + className += 'flight-condition-approval-row editable-row'; + } else className; + + if (record.planAreaSno === props.selected) { + className += ' flight-approval-row-click'; + } + return className; + }} + size='small' + columns={childColumns.map(col => { + if (!col.editable) { + return col; + } + return { + ...col, + onCell: record => ({ + record, + inputType: + col.dataIndex === 'bufferZone' || col.dataIndex === 'fltElev' + ? 'number' + : 'text', + dataIndex: col.dataIndex, + title: col.title, + editing: isEditing(record) + }) + }; + })} + dataSource={data} + pagination={false} + components={{ + body: { + cell: EditableCell + } + }} + onRow={record => ({ + onClick: event => { + if (editingKey !== '') { + return; // edit 상태면 이벤트 실행 안 함 + } + setSelectedRowKey(record.planAreaSno); + + // 이벤트 버블링을 막기 위해 클릭된 요소가 'Edit' 버튼인지 확인 + if ( + event.target.tagName !== 'BUTTON' && + event.target.tagName !== 'A' && + !event.target.closest('.ant-input') && // input 요소를 감지 + !event.target.closest('.ant-input-number') // inputNumber 요소를 감지 + ) { + handleInRowClick(record); + } + } + })} + showHeader={false} + rowHoverable={false} + /> + + ); + }; + + // 테이블 데이터 + const mergedColumns = columns.map(col => { + if (!col.editable) { + return col; + } + return { + ...col, + onCell: record => ({ + record, + inputType: + col.dataIndex === 'bufferZone' || col.dataIndex === 'fltElev' + ? 'number' + : 'text', + dataIndex: col.dataIndex, + title: col.title, + editing: isEditing(record) + }) + }; + }); + + // 단순 메시지 표출 모달 + const handlerErrorModal = (header, body) => { + dispatch( + openModal({ + header: header, + body: body, + isHistoryBack: false, + isRefresh: true + }) + ); + }; + + // 모달 오픈 핸들러 + const handlerOpenModal = (approval, fltElev, fltElevMax) => { + if (approval === 'F') { + dispatch( + openModal({ + header: '미승인 사유', + body: `관제권 내 제한고도(신청고도${fltElev}m/허용고도${fltElevMax}m) 입니다.`, + type: 'error' + }) + ); + } else if (approval === 'S') { + dispatch( + openModal({ + header: '승인 사유', + body: `관제권 내 허용고도(신청고도${fltElev}m/허용고도${fltElevMax}m) 입니다.`, + type: 'success' + }) + ); + } else if (approval === 'C') { + dispatch( + openModal({ + header: '조건부 승인 사유', + body: `관제권 내 조건부 승인(신청고도${fltElev}m/허용고도${ + fltElevMax === undefined ? 150 : fltElevMax + }m) 입니다.`, + type: 'warning' + }) + ); + } else { + dispatch( + openModal({ + header: '비대상 사유', + body: `해당 구역은 비 대상(신청고도${fltElev}m/허용고도${ + fltElevMax === undefined ? 150 : fltElevMax + }m) 지역 입니다.`, + type: 'error' + }) + ); + } + }; + + // 날짜 포맷 변경 + const formatDate = dateString => { + const date = new Date(dateString); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year} 년 ${month} 월 ${day} 일`; + }; + + const handleExpand = key => { + const expanded = expandedRowKeys.includes(key); + const keys = expanded + ? expandedRowKeys.filter(k => k !== key) + : [...expandedRowKeys, key]; + setExpandedRowKeys(keys); + }; + + // 테이블 행 클릭 이벤트 + const handleRowClick = row => { + if (row.areaList.length > 1) return; + handlerOpenModal( + row.areaList[0].approvalCd, + row.areaList[0].fltElev, + row.areaList[0].fltElevMax + ); + props.handlerDetail(row.areaList[0]); + }; + + // 확장된 테이블 행 클릭 이벤트 + const handleInRowClick = row => { + handlerOpenModal(row.approvalCd, row.fltElev, row.fltElevMax); + props.handlerDetail(row); + }; + + const handleFileDownload = async type => { + try { + const fileDetails = { + pdf: { + url: `${HOST}api/bas/dos/plan/download/pdf?searchStDt=${ + props.startDate + }&searchEndDt=${props.endDate}&selectZone=${props.filterArea}${ + props.filterId ? '&approvalCd=${props.filterId}' : '' + }`, + name: '비행승인 관련 검토결과.pdf' + }, + excel: { + url: `${HOST}api/bas/dos/plan/download/excel?searchStDt=${ + props.startDate + }&searchEndDt=${props.endDate}&selectZone=${props.filterArea}${ + props.filterId ? '&approvalCd=${props.filterId}' : '' + }`, + name: '비행승인 검토.xlsx' + } + }; + + if (!fileDetails[type]) { + throw new Error('Invalid file type specified.'); + } + + const { url: fileUrl, name: fileName } = fileDetails[type]; + const accessToken = await getAccessToken(); + + const res = await axios({ + url: fileUrl, + method: 'GET', + responseType: 'blob', + headers: { + 'Content-Type': 'application/json', + Authorization: `${accessToken}` // Bearer 추가 + } + }); + + if (!res.headers) { + throw new Error('No response headers.'); + } + + const contentType = + res.headers['content-type'] || 'application/octet-stream'; + + const blob = new Blob([res.data], { type: contentType }); + const downloadUrl = window.URL.createObjectURL(blob); + + const link = document.createElement('a'); + link.href = downloadUrl; + link.style.display = 'none'; + link.download = fileName; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + window.URL.revokeObjectURL(downloadUrl); + } catch (error) { + console.error('File download failed:', error); + console.error(error.message); + } + }; + + return ( +
+
+
+

비행승인 신청 검토결과 목록

+
+
+
+
+ + {formatDate(props.startDate)} + {props.endDate && props.startDate !== props.endDate + ? '~' + formatDate(props.endDate) + ' ' + : null} + 총 + {approvalCdValue.S + + approvalCdValue.F + + approvalCdValue.U + + approvalCdValue.C} + 건 + +
+
+ + + +
+
+
+
+
    +
  • 승인 {approvalCdValue.S}건
  • +
  • 미승인 {approvalCdValue.F}건
  • +
  • + 조건부 승인 {approvalCdValue.C}건 +
  • +
  • 비대상 {approvalCdValue.U}건
  • +
+
+
+
+ +
+ {laancAprvList?.length > 0 ? ( +
+
({ + ...item, + key: `${item.planAreaSno}-${index}` + }))} + columns={mergedColumns} + rowClassName={record => { + let className = ''; + if (record.areaList.length <= 1) { + if (record?.areaList[0]?.approvalCd === 'S') { + className += 'flight-approval-row editable-row'; + } else if (record.areaList[0].approvalCd === 'F') { + className += 'flight-not-approval-row editable-row'; + } else if (record.areaList[0].approvalCd === 'C') { + className += + 'flight-condition-approval-row editable-row'; + } else className += 'editable-row'; + } + if ( + record.areaList.length <= 1 && + record.areaList[0].planAreaSno === props.selected + ) { + className += ' flight-approval-row-click'; + } + if (expandedRowKeys.includes(record.key)) { + className += ' expanded-row'; + } + if (record.areaList.length > 1) { + className += 'expanded-tr'; + } + return className; + }} + onRow={record => ({ + onClick: event => { + if (editingKey !== '') { + return; // edit 상태면 이벤트 실행 안 함 + } + setSelectedRowKey(record.planAreaSno); + // 이벤트 버블링을 막기 위해 클릭된 요소가 'Edit' 버튼인지 확인 + if ( + event.target.tagName !== 'BUTTON' && + event.target.tagName !== 'A' && + !event.target.closest('.ant-input') && // input 요소를 감지 + !event.target.closest('.ant-input-number') // inputNumber 요소를 감지 + ) { + handleRowClick(record); + } + } + })} + loading={laancAprvLoading} + expandable={{ + expandedRowRender, + expandedRowKeys: expandedRowKeys, + onExpand: (expanded, record) => handleExpand(record.key), + rowExpandable: record => record?.areaList?.length > 1 + }} + scroll={{ + x: 1500 + }} + rowHoverable={false} + expandIconColumnIndex={-1} + /> + + ) : ( +
+

비행승인 신청 건수가 없습니다.

+
+ )} + + + + + ); +} + +const EditableCell = ({ + editing, + dataIndex, + title, + inputType, + record, + index, + children, + ...restProps +}) => { + const inputNode = inputType === 'number' ? : ; + return ( + + ); +}; diff --git a/src/containers/controlRightMenuContainer.js b/src/containers/controlRightMenuContainer.js new file mode 100644 index 00000000..ac4027f6 --- /dev/null +++ b/src/containers/controlRightMenuContainer.js @@ -0,0 +1,154 @@ +import { useEffect, useState } from 'react'; +import dayjs from 'dayjs'; +import { useDispatch } from '@src/redux/store'; +import { getLaancAprvList } from '@src/redux/features/laanc/laancThunk'; +import ControlApprovalsTable from '@src/components/flight/ControlApprovalsTable'; +import NewFlightApprovalsReport from '@src/components/flight/NewFlightApprovalsReport'; + +function ControlRightMenuContainer() { + const [filter, setFilter] = useState(''); + const [startDate, setStartDate] = useState(dayjs().format('YYYY-MM-DD')); + const [endDate, setEndDate] = useState(); + const [selected, setSelected] = useState(null); + // 식별번호 + const [filterId, setFilterId] = useState(''); + + // 지역 + const [filterArea, setFilterArea] = useState(''); + + const dispatch = useDispatch(); + + useEffect(() => { + handlerOpnerPostMessage('initalState', null); + window.addEventListener('message', opnerMessage); + + return () => { + window.removeEventListener('message', opnerMessage); + }; + }, []); + + const opnerMessage = e => { + const { type } = e.data; + const { payload } = e.data; + + switch (type) { + case 'initalState': + setFilter(payload.filter); + setSelected(payload.selected); + setStartDate(payload.startDate); + setEndDate(payload.endDate); + + return; + // case 'handlerSearchRs': + // console.log(payload.filter); + // setFilter(payload.filter); + + // return; + default: + break; + } + }; + + const handlerOpnerPostMessage = (type, payload) => { + switch (type) { + case 'initalState': + window.opener.postMessage({ type, payload }); + return; + case 'search': + window.opener.postMessage({ type, payload }); + return; + case 'detail': + window.opener.postMessage({ type, payload }); + return; + case 'closedSync': + window.opener.postMessage({ type, payload }); + default: + break; + } + }; + + const handlerSearch = (search, searchDate, filterArea) => { + setStartDate(searchDate.startDate); + setEndDate(searchDate.endDate); + setFilter(search); + if ( + search != '' && + (search === '승인' || search === '미승인' || search === '비대상') + ) { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea, + approvalCd: search === '승인' ? 'S' : search === '미승인' ? 'F' : 'U' + }) + ); + } else if (search != '') { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea, + applyNo: search + }) + ); + } else { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea + }) + ); + } + localStorage.setItem( + 'popupState', + JSON.stringify({ + filter: search, + selected: filterArea, + startDate: searchDate.startDate, + endDate: searchDate.endDate + }) + ); + handlerOpnerPostMessage('search', { search, searchDate, filterArea }); + }; + + const handlerDetail = area => { + setSelected(area.planAreaSno); + handlerOpnerPostMessage('detail', { area }); + }; + + const handleBeforeUnload = () => { + handlerOpnerPostMessage('closedSync', ''); + }; + + return ( +
+
+
+ + +
+
+
+ ); +} + +export default ControlRightMenuContainer; diff --git a/src/containers/flight/ControlApprovalsContainer.js b/src/containers/flight/ControlApprovalsContainer.js new file mode 100644 index 00000000..a37fdd37 --- /dev/null +++ b/src/containers/flight/ControlApprovalsContainer.js @@ -0,0 +1,655 @@ +import { useEffect, useRef, useState, lazy, Suspense } from 'react'; +import { useDispatch, useSelector } from '@src/redux/store'; +import NewFlightApprovalsReport from '../../components/flight/NewFlightApprovalsReport'; +import { + InitFeature, + handlerFitBounds, + handlerGetCircleCoord, + flightlayerWayPoint, + flightlayerPolyline, + flightlayerPolygon, + flightlayerBuffer +} from '../../utility/MapUtils'; +import { useHistory } from 'react-router-dom'; +import useMapType from '@hooks/useMapType'; +import { clientSaveAreaCoordinateList } from '@src/redux/features/laanc/laancSlice'; +import { MapControl } from '../../components/map/MapControl'; +import { clientSetIsMapLoading } from '@src/redux/features/laanc/laancSlice'; +import { clientMapInit } from '@src/redux/features/control/map/mapSlice'; +import ControlApprovalsTable from '@src/components/flight/ControlApprovalsTable'; +import { getLaancAprvList } from '@src/redux/features/laanc/laancThunk'; +import dayjs from 'dayjs'; +import { setLogout } from '@src/redux/features/account/auth/authThunk'; +import logo from '../../assets/images/logo/kac_logo_ icon.svg'; +import { AiOutlinePoweroff } from 'react-icons/ai'; +import WebsocketClient from '../../components/websocket/WebsocketClient'; +import { + Card, + ButtonGroup, + Button, + Modal, + ModalHeader, + ModalBody, + ModalFooter, + Table +} from '@component/ui'; +import { FiUsers, FiFileText } from 'react-icons/fi'; + +export default function ControlApprovalsContainer({ mode }) { + const dispatch = useDispatch(); + const history = useHistory(); + + const [selected, setSelected] = useState(null); + const [isMapLoading, setIsMapLoading] = useState(false); + // 비행구역 그리기 + + const [filter, setFilter] = useState(''); + // 지도 + const [mapObject, setMapObject] = useState(); + const [mapType, setMapType] = useMapType(); + const { areaCoordList, isOpenModal } = useSelector(state => state.laancState); + + const [startDate, setStartDate] = useState(dayjs().format('YYYY-MM-DD')); + const [endDate, setEndDate] = useState(dayjs().format('YYYY-MM-DD')); + + // 식별번호 + const [filterId, setFilterId] = useState(''); + + // 지역 + const [filterArea, setFilterArea] = useState('전체'); + + // 시군구 + const [district, setDistrict] = useState('전체'); + // 미니맵 레이어 + const [previewLayer, setPreviewLayer] = useState(); + + const map = useSelector(state => state.mapState.map); + + // popup + const [isPopup, setIsPopup] = useState(false); + const [popup, setPopup] = useState(null); + const popupRef = useRef(null); + const rightMenuRef = useRef(null); + const savedRightMenuRef = useRef(null); + const [clientX, setClientX] = useState(0); + + const previewGeo2 = { + type: 'FeatureCollection', + features: [] + }; + + useEffect(() => { + const searchStDt = dayjs().format('YYYY-MM-DD'); + const searchEndDt = dayjs().format('YYYY-MM-DD'); + dispatch( + getLaancAprvList({ + searchStDt, + searchEndDt + }) + ); + }, []); + + useEffect(() => { + if (areaCoordList.length !== 0) { + handlerPreviewDraw(); + } + }, [areaCoordList]); + + useEffect(() => { + if (map) { + window._mapbox = map; + let mapInstance = mode === 'container' ? map : window.opener._mapbox; + setMapObject(mapInstance); + } + }, [map]); + + useEffect(() => { + const childMessage = e => { + if (e.data.type) { + const { type } = e.data; + const { payload } = e.data; + console.log(payload); + switch (type) { + case 'initalState': + popupRef.current.postMessage({ + type: 'initalState', + payload: { + filter, + selected, + startDate, + endDate + } + }); + + return; + case 'search': + const { search, searchDate, filterArea } = payload; + + handlerSearch(search, searchDate, filterArea); + return; + case 'detail': + const { area } = payload; + handlerDetail(area); + return; + case 'closedSync': + popupRef.current.close(); + // localStorage.removeItem('popupState'); + return; + default: + break; + } + } + }; + + let timer; + if (rightMenuRef.current) { + savedRightMenuRef.current = rightMenuRef.current.getBoundingClientRect(); + } + if (popup) { + timer = setInterval(() => { + if (popup.closed) { + setIsPopup(false); + clearInterval(timer); + } + + if (savedRightMenuRef.current) { + const popupX = popup.screenX; + + const parentX = window.screenX + savedRightMenuRef.current.left - 70; + + const parentWidth = savedRightMenuRef.current.width; + + if (popupX >= parentX && popupX <= parentX + parentWidth) { + popup.close(); + setIsPopup(false); + clearInterval(timer); + } + } + }, 500); // 1초마다 체크 + } + window.addEventListener('message', childMessage); + + return () => { + clearInterval(timer); + window.removeEventListener('message', childMessage); + }; + }, [popup]); + + useEffect(() => { + const handleBeforeUnload = e => { + localStorage.removeItem('persist:root'); + + if (popupRef.current) { + popupRef.current.close(); + } + }; + + window.addEventListener('beforeunload', handleBeforeUnload); + + return () => { + window.removeEventListener('beforeunload', handleBeforeUnload); + }; + }, []); + + const handleDragEnd = e => { + setIsPopup(true); + const el = document.querySelector('.flight-approval-layer'); + + const popupWidth = el.offsetWidth; // 팝업의 너비 + const popupHeight = el.offsetHeight; // 팝업의 너비 + + // const popupX = window.screenX + window.outerWidth - e.clientX; // 오른쪽 끝에 띄우기 + // const popupY = Math.round( + // window.screenY + window.outerHeight / 2 - popupHeight / 2 + // ); + // setClientX(window.screenX + window.outerWidth - e.clientX); + const popupX = + window.screenX + + (window.outerWidth - popupWidth) / 2 + + e.clientX - + window.innerWidth / 2; // 드래그 끝나는 지점 + const popupY = Math.round( + window.screenY + window.outerHeight / 2 - popupHeight / 2 + ); + const option = `width=${popupWidth},height=${popupHeight},left=${popupX},top=${popupY}`; + popupRef.current = window.open('/rightMenu', 'NewWindow', option); + // setPopupOption(option); + setPopup(popupRef.current); + }; + + const handlerSearch = (search, searchDate, filterArea) => { + setStartDate(searchDate.startDate); + setEndDate(searchDate.endDate); + + if ( + search != '' && + (search === '승인' || + search === '미승인' || + search === '비대상' || + search === '조건부승인') + ) { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea, + approvalCd: + search === '승인' + ? 'S' + : search === '미승인' + ? 'F' + : search === '조건부승인' + ? 'C' + : 'U' + }) + ); + } else if (search != '') { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea, + applyNo: search + }) + ); + } else { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea + }) + ); + } + // ); + setFilter(search); + if (popup) { + popupRef.current.postMessage({ + type: 'handlerSearchRs', + payload: { search } + }); + } + }; + + const handlerDetail = area => { + setSelected(area.planAreaSno); + + dispatch(clientSaveAreaCoordinateList([area])); + + handlerMapInit(); + }; + + const handlerMapInit = () => { + let mapInstance = mode === 'container' ? map : window.opener._mapbox; + + if (mapInstance.getSource('preview')) { + } else { + mapInstance.addSource('preview', { + type: 'geojson', + data: previewGeo2 + }); + mapInstance.addLayer(flightlayerWayPoint('preview')); + mapInstance.addLayer(flightlayerBuffer('preview')); + mapInstance.addLayer(flightlayerPolygon('preview')); + mapInstance.addLayer(flightlayerPolyline('preview')); + } + + dispatch(clientSetIsMapLoading(true)); + const preview = mapInstance.getSource('preview'); + + if (preview) setPreviewLayer(preview); + + setIsMapLoading(true); + + setMapObject(mapInstance); + + dispatch(clientMapInit(mapInstance)); + }; + + const handlerPreviewDraw = () => { + if (areaCoordList.length > 0) { + const areas = areaCoordList[0]; + + previewGeo2.features = []; + + let fitZoomPaths = []; + const radius = areas.bufferZone; + const circleCoords = handlerGetCircleCoord( + [areas.lon, areas.lat], + radius + ); + + const circle = InitFeature('Polygon', 'CIRCLE'); + circle.properties.center = [areas.lon, areas.lat]; + circle.geometry.coordinates = circleCoords; + + previewGeo2.features.push(circle); + + mapObject?.setCenter(circle.properties.center); + + fitZoomPaths = circleCoords[0]; + + handlerFitBounds(mapObject, fitZoomPaths, 400, 'CIRCLE', 'flight'); + + // mapObject.setPaintProperty('waypoint', 'circle-radius', 10); + mapObject?.getSource('preview').setData(previewGeo2); + } + }; + + const handlerLogout = async () => { + const { payload } = await dispatch(setLogout()); + + if (payload === 'SUCCESS') { + history.replace('/account/login'); + } + }; + + const [testModal, setTestModal] = useState(false); + + return ( + <> +
+
+ +
+
+ setTestModal(!testModal)} + className='modal-dialog-centered modal-lg' + > + setTestModal(!testModal)}> + 유효성 검사 상세보기 + + +
+
+ + 기체 정보 +
+
+
+ {editing ? ( + + {inputNode} + + ) : ( + children + )} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No유효성 검사제작 번호기체 용도기체 중량보험 가입
1 + 성공 + 163CGBEROA529Y영리25kg이하가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
+ + +
+
+ + 조종자 정보 +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No유효성 검사이름생년 월일자격 번호조종 자격
1 + 성공 + 홍*동1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
+
+
+ + + {' '} + + + +
+
+ +
+

지도유형

+
+ + + + + +
+
+
+

거리측정

+
+ + + + +
+
+
+
+
+ + +
+

+ + UTM +

+
    +
  • + +
  • +
  • + +
  • +
+
+ {!isPopup && ( +
+
+
+ + +
+
+
+ )} + + ); +} diff --git a/src/containers/flight/OperationApprovalsContainer.js b/src/containers/flight/OperationApprovalsContainer.js new file mode 100644 index 00000000..44895d85 --- /dev/null +++ b/src/containers/flight/OperationApprovalsContainer.js @@ -0,0 +1,655 @@ +import { useEffect, useRef, useState, lazy, Suspense } from 'react'; +import { useDispatch, useSelector } from '@src/redux/store'; +import NewFlightApprovalsReport from '../../components/flight/NewFlightApprovalsReport'; +import { + InitFeature, + handlerFitBounds, + handlerGetCircleCoord, + flightlayerWayPoint, + flightlayerPolyline, + flightlayerPolygon, + flightlayerBuffer +} from '../../utility/MapUtils'; +import { useHistory } from 'react-router-dom'; +import useMapType from '@hooks/useMapType'; +import { clientSaveAreaCoordinateList } from '@src/redux/features/laanc/laancSlice'; +import { MapControl } from '../../components/map/MapControl'; +import { clientSetIsMapLoading } from '@src/redux/features/laanc/laancSlice'; +import { clientMapInit } from '@src/redux/features/control/map/mapSlice'; +import OperationApprovalsTable from '@src/components/flight/OperationApprovalsTable'; +import { getLaancAprvList } from '@src/redux/features/laanc/laancThunk'; +import dayjs from 'dayjs'; +import { setLogout } from '@src/redux/features/account/auth/authThunk'; +import logo from '../../assets/images/logo/kac_logo_ icon.svg'; +import { AiOutlinePoweroff } from 'react-icons/ai'; +import WebsocketClient from '../../components/websocket/WebsocketClient'; +import { + Card, + ButtonGroup, + Button, + Modal, + ModalHeader, + ModalBody, + ModalFooter, + Table +} from '@component/ui'; +import { FiUsers, FiFileText } from 'react-icons/fi'; + +export default function OperationApprovalsContainer({ mode }) { + const dispatch = useDispatch(); + const history = useHistory(); + + const [selected, setSelected] = useState(null); + const [isMapLoading, setIsMapLoading] = useState(false); + // 비행구역 그리기 + + const [filter, setFilter] = useState(''); + // 지도 + const [mapObject, setMapObject] = useState(); + const [mapType, setMapType] = useMapType(); + const { areaCoordList, isOpenModal } = useSelector(state => state.laancState); + + const [startDate, setStartDate] = useState(dayjs().format('YYYY-MM-DD')); + const [endDate, setEndDate] = useState(dayjs().format('YYYY-MM-DD')); + + // 식별번호 + const [filterId, setFilterId] = useState(''); + + // 지역 + const [filterArea, setFilterArea] = useState('전체'); + + // 시군구 + const [district, setDistrict] = useState('전체'); + // 미니맵 레이어 + const [previewLayer, setPreviewLayer] = useState(); + + const map = useSelector(state => state.mapState.map); + + // popup + const [isPopup, setIsPopup] = useState(false); + const [popup, setPopup] = useState(null); + const popupRef = useRef(null); + const rightMenuRef = useRef(null); + const savedRightMenuRef = useRef(null); + const [clientX, setClientX] = useState(0); + + const previewGeo2 = { + type: 'FeatureCollection', + features: [] + }; + + useEffect(() => { + const searchStDt = dayjs().format('YYYY-MM-DD'); + const searchEndDt = dayjs().format('YYYY-MM-DD'); + dispatch( + getLaancAprvList({ + searchStDt, + searchEndDt + }) + ); + }, []); + + useEffect(() => { + if (areaCoordList.length !== 0) { + handlerPreviewDraw(); + } + }, [areaCoordList]); + + useEffect(() => { + if (map) { + window._mapbox = map; + let mapInstance = mode === 'container' ? map : window.opener._mapbox; + setMapObject(mapInstance); + } + }, [map]); + + useEffect(() => { + const childMessage = e => { + if (e.data.type) { + const { type } = e.data; + const { payload } = e.data; + console.log(payload); + switch (type) { + case 'initalState': + popupRef.current.postMessage({ + type: 'initalState', + payload: { + filter, + selected, + startDate, + endDate + } + }); + + return; + case 'search': + const { search, searchDate, filterArea } = payload; + + handlerSearch(search, searchDate, filterArea); + return; + case 'detail': + const { area } = payload; + handlerDetail(area); + return; + case 'closedSync': + popupRef.current.close(); + // localStorage.removeItem('popupState'); + return; + default: + break; + } + } + }; + + let timer; + if (rightMenuRef.current) { + savedRightMenuRef.current = rightMenuRef.current.getBoundingClientRect(); + } + if (popup) { + timer = setInterval(() => { + if (popup.closed) { + setIsPopup(false); + clearInterval(timer); + } + + if (savedRightMenuRef.current) { + const popupX = popup.screenX; + + const parentX = window.screenX + savedRightMenuRef.current.left - 70; + + const parentWidth = savedRightMenuRef.current.width; + + if (popupX >= parentX && popupX <= parentX + parentWidth) { + popup.close(); + setIsPopup(false); + clearInterval(timer); + } + } + }, 500); // 1초마다 체크 + } + window.addEventListener('message', childMessage); + + return () => { + clearInterval(timer); + window.removeEventListener('message', childMessage); + }; + }, [popup]); + + useEffect(() => { + const handleBeforeUnload = e => { + localStorage.removeItem('persist:root'); + + if (popupRef.current) { + popupRef.current.close(); + } + }; + + window.addEventListener('beforeunload', handleBeforeUnload); + + return () => { + window.removeEventListener('beforeunload', handleBeforeUnload); + }; + }, []); + + const handleDragEnd = e => { + setIsPopup(true); + const el = document.querySelector('.flight-approval-layer'); + + const popupWidth = el.offsetWidth; // 팝업의 너비 + const popupHeight = el.offsetHeight; // 팝업의 너비 + + // const popupX = window.screenX + window.outerWidth - e.clientX; // 오른쪽 끝에 띄우기 + // const popupY = Math.round( + // window.screenY + window.outerHeight / 2 - popupHeight / 2 + // ); + // setClientX(window.screenX + window.outerWidth - e.clientX); + const popupX = + window.screenX + + (window.outerWidth - popupWidth) / 2 + + e.clientX - + window.innerWidth / 2; // 드래그 끝나는 지점 + const popupY = Math.round( + window.screenY + window.outerHeight / 2 - popupHeight / 2 + ); + const option = `width=${popupWidth},height=${popupHeight},left=${popupX},top=${popupY}`; + popupRef.current = window.open('/rightMenu', 'NewWindow', option); + // setPopupOption(option); + setPopup(popupRef.current); + }; + + const handlerSearch = (search, searchDate, filterArea) => { + setStartDate(searchDate.startDate); + setEndDate(searchDate.endDate); + + if ( + search != '' && + (search === '승인' || + search === '미승인' || + search === '비대상' || + search === '조건부승인') + ) { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea, + approvalCd: + search === '승인' + ? 'S' + : search === '미승인' + ? 'F' + : search === '조건부승인' + ? 'C' + : 'U' + }) + ); + } else if (search != '') { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea, + applyNo: search + }) + ); + } else { + dispatch( + getLaancAprvList({ + searchStDt: searchDate.startDate, + searchEndDt: searchDate.endDate, + selectZone: filterArea + }) + ); + } + // ); + setFilter(search); + if (popup) { + popupRef.current.postMessage({ + type: 'handlerSearchRs', + payload: { search } + }); + } + }; + + const handlerDetail = area => { + setSelected(area.planAreaSno); + + dispatch(clientSaveAreaCoordinateList([area])); + + handlerMapInit(); + }; + + const handlerMapInit = () => { + let mapInstance = mode === 'container' ? map : window.opener._mapbox; + + if (mapInstance.getSource('preview')) { + } else { + mapInstance.addSource('preview', { + type: 'geojson', + data: previewGeo2 + }); + mapInstance.addLayer(flightlayerWayPoint('preview')); + mapInstance.addLayer(flightlayerBuffer('preview')); + mapInstance.addLayer(flightlayerPolygon('preview')); + mapInstance.addLayer(flightlayerPolyline('preview')); + } + + dispatch(clientSetIsMapLoading(true)); + const preview = mapInstance.getSource('preview'); + + if (preview) setPreviewLayer(preview); + + setIsMapLoading(true); + + setMapObject(mapInstance); + + dispatch(clientMapInit(mapInstance)); + }; + + const handlerPreviewDraw = () => { + if (areaCoordList.length > 0) { + const areas = areaCoordList[0]; + + previewGeo2.features = []; + + let fitZoomPaths = []; + const radius = areas.bufferZone; + const circleCoords = handlerGetCircleCoord( + [areas.lon, areas.lat], + radius + ); + + const circle = InitFeature('Polygon', 'CIRCLE'); + circle.properties.center = [areas.lon, areas.lat]; + circle.geometry.coordinates = circleCoords; + + previewGeo2.features.push(circle); + + mapObject?.setCenter(circle.properties.center); + + fitZoomPaths = circleCoords[0]; + + handlerFitBounds(mapObject, fitZoomPaths, 400, 'CIRCLE', 'flight'); + + // mapObject.setPaintProperty('waypoint', 'circle-radius', 10); + mapObject?.getSource('preview').setData(previewGeo2); + } + }; + + const handlerLogout = async () => { + const { payload } = await dispatch(setLogout()); + + if (payload === 'SUCCESS') { + history.replace('/account/login'); + } + }; + + const [testModal, setTestModal] = useState(false); + + return ( + <> +
+
+ +
+
+ setTestModal(!testModal)} + className='modal-dialog-centered modal-lg' + > + setTestModal(!testModal)}> + 유효성 검사 상세보기 + + +
+
+ + 기체 정보 +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No유효성 검사제작 번호기체 용도기체 중량보험 가입
1 + 성공 + 163CGBEROA529Y영리25kg이하가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
2 + 실패 + 163CGBEROA529Y영리25kg이하미 가입
+
+
+
+
+ + 조종자 정보 +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No유효성 검사이름생년 월일자격 번호조종 자격
1 + 성공 + 홍*동1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
2 + 실패 + 김*혜1995****91-****12
+
+
+
+ + {' '} + +
+
+
+
+ +
+

지도유형

+
+ + + + + +
+
+
+

거리측정

+
+ + + + +
+
+
+
+
+ +
+
+

+ + UTM +

+
    +
  • + +
  • +
  • + +
  • +
+
+ {!isPopup && ( +
+
+
+ + +
+
+
+ )} + + ); +} diff --git a/src/containers/rightMenuContainer.js b/src/containers/rightMenuContainer.js index ec63b7ac..d1176102 100644 --- a/src/containers/rightMenuContainer.js +++ b/src/containers/rightMenuContainer.js @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import dayjs from 'dayjs'; import { useDispatch } from '@src/redux/store'; import { getLaancAprvList } from '@src/redux/features/laanc/laancThunk'; -import NewFlightApprovalsTable from '@src/components/flight/NewFlightApprovalsTable'; +import OperationApprovalsTable from '@src/components/flight/OperationApprovalsTable'; import NewFlightApprovalsReport from '@src/components/flight/NewFlightApprovalsReport'; function RightMenuContainer() { @@ -136,7 +136,7 @@ function RightMenuContainer() { filterArea={filterArea} setFilterArea={setFilterArea} /> - diff --git a/src/router/routes/RouteFlight.js b/src/router/routes/RouteFlight.js index 5c0b1c44..702f5bb4 100644 --- a/src/router/routes/RouteFlight.js +++ b/src/router/routes/RouteFlight.js @@ -2,8 +2,17 @@ import { lazy } from 'react'; const RouteFlight = [ { - path: '/flight/approvals/new', - component: lazy(() => import('../../views/flight/NewFlightView')), + path: '/operation/approvals', + component: lazy(() => import('../../views/flight/operationApprovalsView')), + layout: 'BlankLayout', + + meta: { + authRoute: true + } + }, + { + path: '/control/approvals', + component: lazy(() => import('../../views/flight/controlApprovalsView')), layout: 'BlankLayout', meta: { diff --git a/src/router/routes/index.js b/src/router/routes/index.js index 1ca304f6..66e434cd 100644 --- a/src/router/routes/index.js +++ b/src/router/routes/index.js @@ -105,6 +105,14 @@ const Routes = [ authRoute: true } }, + { + path: '/control/rightMenu', + component: lazy(() => import('../../views/rightMenuView')), + layout: 'BlankLayout', + meta: { + authRoute: true + } + }, { path: '/history/record/sample1', component: lazy(() => @@ -231,13 +239,22 @@ const Routes = [ const GimpoControlRoutes = [ { - path: '/flight/approvals/new', - component: lazy(() => import('../../views/flight/NewFlightView')), + path: '/operation/approvals', + component: lazy(() => import('../../views/flight/operationApprovalsView')), layout: 'BlankLayout', meta: { authRoute: true } }, + { + path: '/control/approvals', + component: lazy(() => import('../../views/flight/controlApprovalsView')), + layout: 'BlankLayout', + meta: { + authRoute: true + } + }, + { path: '/rightMenu', component: lazy(() => import('../../views/rightMenuView')), diff --git a/src/views/controlMenuView.js b/src/views/controlMenuView.js new file mode 100644 index 00000000..2f658507 --- /dev/null +++ b/src/views/controlMenuView.js @@ -0,0 +1,13 @@ +import '@styles/react/libs/flatpickr/flatpickr.scss'; +import '@styles/react/libs/tables/react-dataTable-component.scss'; +import '../assets/css/custom.css'; +import ControlRightMenuContainer from '../containers/controlRightMenuContainer'; +import FlightApprovalsContainer from '../containers/flight/flightApprovalsContainer'; + +export default function rightMenuView() { + return ( +
+ +
+ ); +} diff --git a/src/views/flight/FlightView.js b/src/views/flight/FlightView.js index 03e876f1..bde5fba0 100644 --- a/src/views/flight/FlightView.js +++ b/src/views/flight/FlightView.js @@ -3,7 +3,6 @@ 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 ( diff --git a/src/views/flight/NewFlightView.js b/src/views/flight/controlApprovalsView.js similarity index 61% rename from src/views/flight/NewFlightView.js rename to src/views/flight/controlApprovalsView.js index f9821b4d..f9f70773 100644 --- a/src/views/flight/NewFlightView.js +++ b/src/views/flight/controlApprovalsView.js @@ -1,15 +1,15 @@ import '@styles/react/libs/flatpickr/flatpickr.scss'; import '@styles/react/libs/tables/react-dataTable-component.scss'; import '../../assets/css/custom.css'; -import NewFlightApprovalsContainer from '../../containers/flight/NewFlightApprovalsContainer'; +import ControlApprovalsContainer from '../../containers/flight/ControlApprovalsContainer'; -export default function NewFlightView() { +export default function OperationApprovalsView() { return (
{/* 관제시스템 */} - ; + ;
); } diff --git a/src/views/flight/operationApprovalsView.js b/src/views/flight/operationApprovalsView.js new file mode 100644 index 00000000..a966bef7 --- /dev/null +++ b/src/views/flight/operationApprovalsView.js @@ -0,0 +1,15 @@ +import '@styles/react/libs/flatpickr/flatpickr.scss'; +import '@styles/react/libs/tables/react-dataTable-component.scss'; +import '../../assets/css/custom.css'; +import OperationApprovalsContainer from '../../containers/flight/OperationApprovalsContainer'; + +export default function OperationApprovalsView() { + return ( +
+ {/* + 관제시스템 + */} + ; +
+ ); +}