@@ -796,7 +1211,7 @@ export default function LaancStep1({
type='select'
id='arcrftTypeCd'
name='arcrftTypeCd'
- value={data.arcrftList[0].arcrftTypeCd}
+ value={detailData.arcrftList[0].arcrftTypeCd}
bsSize='sm'
onChange={e => {
const { name, value } = e.target;
@@ -824,7 +1239,7 @@ export default function LaancStep1({
type='text'
id='idntfNum'
name='idntfNum'
- value={data.arcrftList[0].idntfNum}
+ value={detailData.arcrftList[0].idntfNum}
bsSize='sm'
onChange={e => {
const { name, value } = e.target;
@@ -858,7 +1273,7 @@ export default function LaancStep1({
centeredModal={centeredModal}
setCenteredModal={setCenteredModal}
handleChange={handleChange}
- data={data}
+ detailData={detailData}
page={1}
/>
@@ -908,6 +1323,19 @@ export default function LaancStep1({
다음
+ setIsPopUp(!isPopUp)}
+ className='modal-dialog-centered modal-lg notam-modal'
+ style={{ height: '25vh', width: '25vw' }}
+ >
+
+
diff --git a/src/components/laanc/step/LaancStep2.js b/src/components/laanc/step/LaancStep2.js
index 14f68de2..e6880e54 100644
--- a/src/components/laanc/step/LaancStep2.js
+++ b/src/components/laanc/step/LaancStep2.js
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import '@styles/react/libs/flatpickr/flatpickr.scss';
-import { AlertCircle, CheckCircle } from 'react-feather';
+import { CheckCircle } from 'react-feather';
import FlightArea from '../map/FlightArea';
import {
Row,
@@ -48,6 +48,7 @@ export default function LaancStep2({
const { laancPdf } = useSelector(state => state.laancState);
const dispatch = useDispatch();
+ // 약관 동의 데이터
useEffect(() => {
dispatch(
TermsActions.termsList.request({
@@ -58,12 +59,14 @@ export default function LaancStep2({
);
}, []);
+ // 비행 승인 요청
useEffect(() => {
if (flightData && Object.keys(flightData).length > 0) {
dispatch(LaancAction.LAANC_FLIGHT_CREATE.request(flightData));
}
}, [flightData]);
+ // 비행 승인 요청 성공
useEffect(() => {
if (laancPdf && flightData && Object.keys(flightData).length > 0) {
handlerStep(3);
diff --git a/src/containers/laanc/LaancContainer.js b/src/containers/laanc/LaancContainer.js
index 3655d5e1..58604613 100644
--- a/src/containers/laanc/LaancContainer.js
+++ b/src/containers/laanc/LaancContainer.js
@@ -17,18 +17,27 @@ export default function LaancContainer() {
const [currentParm, setCurrentParm] = useState(false);
const [disabledAnimation, setDisabledAnimation] = useState(false);
-
+ const [isSearch, setIsSearch] = useState(false);
const queryParams = new URLSearchParams(location.search);
const mapParam = queryParams.get('map');
+ // URL 쿼리 파라미터 중 'map' 값을 가져옵니다.
useEffect(() => {
- // URL 쿼리 파라미터 중 'map' 값을 가져옵니다.
+ // Redux Store 초기화
dispatch(drawTypeChangeAction(''));
dispatch(LaancAction.LAANC_APPROVAL_INIT());
dispatch(AreaAction.AREA_DETAIL_INIT());
setDisabledAnimation(mapParam != 'true' ? false : true);
}, [location]);
+ // Laanc 신청 이후 자동 검색
+ useEffect(() => {
+ if (disabledAnimation) {
+ setIsSearch(false);
+ } else setIsSearch(true);
+ }, [disabledAnimation]);
+
+ // LAANC 신청하기 버튼 클릭 헨들러
const handleApply = () => {
dispatch(drawTypeChangeAction(''));
dispatch(LaancAction.LAANC_APPROVAL_INIT());
@@ -64,7 +73,7 @@ export default function LaancContainer() {
) : null}
-
+
);
diff --git a/src/containers/laanc/LaancPlanContainer.js b/src/containers/laanc/LaancPlanContainer.js
index 958d2cd7..3941ea62 100644
--- a/src/containers/laanc/LaancPlanContainer.js
+++ b/src/containers/laanc/LaancPlanContainer.js
@@ -2,20 +2,13 @@ import { useEffect, useState } from 'react';
import LaancStep1 from '../../components/laanc/step/LaancStep1'; // laanc step 1
import LaancStep2 from '../../components/laanc/step/LaancStep2'; // laanc step 2
import LaancStep3 from '../../components/laanc/step/LaacnStep3'; // laanc step 3
-import moment from 'moment';
import { ErrorModal } from '../../components/modal/ErrorModal';
import { LaancModal } from '../../components/laanc/LaancModal';
import { initFlightBas } from '../../modules/laanc/models/laancModels';
import { Modal } from 'reactstrap';
-import {
- AREA_DETAIL_INIT,
- FLIGHT_PLAN_AREA_BUFFER_LIST
-} from '../../modules/basis/flight/actions/basisFlightAction';
+import { AREA_DETAIL_INIT } from '../../modules/basis/flight/actions/basisFlightAction';
import { useDispatch, useSelector } from 'react-redux';
import { drawTypeChangeAction } from '../../modules/control/map/actions/controlMapActions';
-import * as LaancAction from '../../modules/laanc/actions/laancActions';
-import * as AreaAction from '../../modules/basis/flight/actions/basisFlightAction';
-import axios from '../../modules/utils/customAxiosUtil';
export default function LaancPlanContainer({
currentParm,
@@ -24,9 +17,7 @@ export default function LaancPlanContainer({
}) {
const dispatch = useDispatch();
- const { areaCoordList } = useSelector(state => state.flightState);
const { user } = useSelector(state => state.authState);
- const { laancArea, laancElev } = useSelector(state => state.laancState);
const [step, setStep] = useState(1);
const [detailData, setDetailData] = useState(initFlightBas.initDetail);
@@ -44,6 +35,7 @@ export default function LaancPlanContainer({
url: ''
});
+ // 로그인 회원 정보 세팅
useEffect(() => {
if (user) {
setDetailData({
@@ -57,434 +49,12 @@ export default function LaancPlanContainer({
};
}, []);
- // 적용 버튼 Reducer 업데이트 될때마다 검사 로직
- useEffect(() => {
- if (detailData.areaList[0].fltElev != 0) {
- const maxElev = 150;
- const controlledAltitudeExceededWarning =
- laancArea?.duplicated &&
- parseInt(
- detailData.areaList[0].fltElev.replace('/^0+/', 'm', ''),
- 10
- ) >= laancElev[0] &&
- parseInt(detailData.areaList[0].fltElev.replace('/^0+/', 'm', ''), 10) <
- maxElev;
-
- if (controlledAltitudeExceededWarning) {
- setIsErrorModal({
- isOpen: true,
- title: '검토 결과 사전안내',
- desc: (
- <>
- 유효성 검사에 실패하여 미 승인 대상입니다.
-
- 제출하신 비행계획서의 고도는 {laancElev[0]}m이하에서만 비행이
- 가능합니다.
-
- 고도 설정을 다시 확인해주시기 바랍니다.
- >
- )
- });
- handleChange({
- type: 'area',
- name: 'fltElev',
- value: 0
- });
- }
- }
- }, [[laancElev]]);
-
- // laanc 승인 api 200 시 step 이동
- const handlerLaanc = async () => {
- if (laancArea && laancElev[0]) {
- // laanc 필요 없이 날 수 있음
- const laancNotRequired =
- !laancArea.duplicated &&
- detailData.fltType != 'COMMERCIAL' &&
- detailData.arcrftList[0].arcrftWghtCd != '11';
- const maxElev = 150;
-
- if (laancNotRequired) {
- setIsErrorModal({
- isOpen: true,
- title: '검토 결과 사전안내',
- desc: (
- <>
- 검토 결과 미 승인 대상입니다.
-
- 제줄하신 비행계획서는 별도의 승인이 필요없습니다.
-
- 조종자 준수사항에 유의하여 비행하시기 바랍니다.
-
- >
- )
- });
- return;
- } else if (detailData.areaList[0].fltMethod === '군집비행') {
- handleChange({
- type: 'area',
- name: 'fltMethod',
- value: ''
- });
- setIsLaancModal({
- isOpen: true,
- title: '군집 비행 목적',
- desc: (
- <>
- 군집 비행의 경우 담당자와 협의가 필요합니다.
- 아래 링크를 통해 담당자와 협의 부탁드립니다.
- >
- ),
- type: '처리부서안내 바로가기',
- url: 'https://drone.onestop.go.kr/introduce/systemintro3 '
- });
- } else if (
- parseInt(detailData.areaList[0].fltElev) <= laancElev[0] &&
- parseInt(detailData.areaList[0].fltElev) < maxElev
- ) {
- try {
- // 성공적으로 응답 받았을 때 처리할 내용 추가
- const tsData = await axios.post(`api/bas/laanc/valid/ts/pilot`, [
- detailData.arcrftList[0].idntfNum
- ]);
- if (!tsData.data.valid) {
- setIsErrorModal({
- isOpen: true,
- title: '검토 결과 사전안내',
- desc: (
- <>
- 유효성 검사에 실패하여 미 승인 대상입니다.
-
- 기체가 보험에 가입되어 있지 않거나 유효기간이
- 만료되었습니다.
-
- 기체 번호를 다시 확인해주시기 바랍니다.
-
- >
- )
- });
- return;
- } else {
- setStep(2);
- }
- } catch (error) {
- setIsErrorModal({
- isOpen: true,
- title: '오류',
- desc: <>처리중 오류가 발생하였습니다>
- });
- }
- }
- }
- };
-
// step 핸들러
const handlerStep = step => {
setStep(step);
};
- // 날씨 핸들러
- const handlerWeather = () => {
- setFormModal(!formModal);
- };
-
- // 비행계획서 작성 핸들러
- const handleChange = ({ name, value, type, index, pIndex }) => {
- const arrName = `${type}List`;
-
- switch (type) {
- case 'coord':
- setDetailData(prevState => {
- return {
- ...prevState,
- areaList: [
- {
- ...prevState.areaList[0],
-
- coordList: value
- }
- ]
- };
- });
- break;
- case 'area':
- if (name === 'fltMethod' && value != '직접입력') {
- setDetailData(prevState => {
- const arr = [...prevState[arrName]];
- const updateData = {
- ...prevState[arrName][0],
- [name]: value,
- fltMothoeRm: ''
- };
- arr[0] = updateData;
- return {
- ...prevState,
- [arrName]: arr
- };
- });
- } else if (
- detailData.areaList[0].areaType === 'LINE' ||
- name === 'bufferZone'
- ) {
- setDetailData(prevState => {
- const arr = [...prevState[arrName]];
- const prevBufferZone = prevState[arrName][0].bufferZone;
- const updateData = {
- ...prevState[arrName][0],
- [name]: value,
- concatBufferZone: prevBufferZone
- };
- arr[0] = updateData;
- return {
- ...prevState,
- [arrName]: arr
- };
- });
- } else {
- setDetailData(prevState => {
- const arr = [...prevState[arrName]];
- const updateData = {
- ...prevState[arrName][0],
- [name]: value
- };
- arr[0] = updateData;
- return {
- ...prevState,
- [arrName]: arr
- };
- });
- }
- break;
- case 'pilot':
- case 'arcrft':
- {
- setDetailData(prevState => {
- const arr = [...prevState[arrName]];
- const updateData = {
- ...prevState[arrName][0],
- [name]: value
- };
- arr[0] = updateData;
- return {
- ...prevState,
- [arrName]: arr
- };
- });
- }
- break;
- case 'plan':
- default:
- setDetailData(prevState => ({
- ...prevState,
- [name]: value
- }));
- break;
- }
- };
-
- // 스텝 1 다음 버튼 이벤트
- const handlerNext = () => {
- // 시작일자
- const schFltStDt = moment(detailData.schFltStDt, 'YYYY-MM-DD HH:mm:ss');
- // 종료일자
- const schFltEndDt = moment(detailData.schFltEndDt, 'YYYY-MM-DD HH:mm:ss');
-
- const currentDate = moment(); // 현재 날짜와 시간을 가져옵니다.
-
- const validateAircraftWeightCode =
- !detailData.arcrftList[0].arcrftTypeCd &&
- (detailData.commercial === 'COMMERCIAL' ||
- detailData.arcrftList[0].arcrftWghtCd == '9' ||
- detailData.arcrftList[0].arcrftWghtCd == '10' ||
- detailData.arcrftList[0].arcrftWghtCd == '11');
-
- const validateidntfNumCode =
- !detailData.arcrftList[0].idntfNum &&
- (detailData.commercial === 'COMMERCIAL' ||
- detailData.arcrftList[0].arcrftWghtCd == '9' ||
- detailData.arcrftList[0].arcrftWghtCd == '10' ||
- detailData.arcrftList[0].arcrftWghtCd == '11');
-
- if (!detailData.fltType) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '비행 종류(상업/비상업)를 선택해주세요.'
- });
- return false;
- } else if (
- !schFltStDt.isAfter(currentDate) ||
- !schFltEndDt.isAfter(currentDate)
- ) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '비행 일자가 이미 지난 일자입니다.'
- });
- return false;
- } else if (schFltStDt.isAfter(schFltEndDt)) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '비행일자를 확인해주세요.'
- });
- return false;
- } else if (schFltStDt.format('A h:mm') === 'PM 11:00') {
- setIsErrorModal({
- isOpen: true,
- title: '특별 비행',
- desc: (
- <>
- 야간 비행은 특별 비행에 해당됩니다.
-
- 특별 비행의 경우 드론원스톱을 통해서 신청해주시기 바랍니다.
- >
- )
- });
- return false;
- } else if (schFltStDt.format('A h:mm') === 'PM 5:00') {
- setIsErrorModal({
- isOpen: true,
- title: '비행구역 및 비행일자 중복',
- desc: (
- <>
- 설정하신 비행구역 및 비행시간에 이미 승인완료된 신청건이 있습니다.
-
다시 설정 부탁드립니다.
- >
- )
- });
- return false;
- } else if (!detailData.fltPurpose) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '비행목적을 선택해 주세요.'
- });
-
- return false;
- } else if (
- !detailData.areaList[0].fltElev ||
- detailData.areaList[0].fltElev === 0
- ) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '고도를 입력해 주세요.'
- });
-
- return false;
- } else if (!detailData.areaList[0].bufferZone) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '반경을 입력해 주세요.'
- });
-
- return false;
- } else if (
- detailData.areaList[0].concatBufferZone !=
- detailData.areaList[0].bufferZone &&
- detailData.areaList[0].areaType === 'LINE'
- ) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: <>적용 버튼을 누르지 않고 값을 변경 할 수 없습니다.>
- });
- // handleChange({
- // type: 'area',
- // name: 'bufferZone',
- // value: detailData.areaList[0].concatBufferZone
- // });
- } else if (!detailData.areaList[0].fltMethod) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '비행방식를 입력해 주세요.'
- });
-
- return false;
- } else if (
- detailData.areaList[0].fltMethod === '00' &&
- !detailData.areaList[0].fltMothoeRm
- ) {
- // 비행 방식 직접 입력칸 활성화 후 작성 시 조건문
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '비행방식을 입력해 주세요.'
- });
- return false;
- } else if (validateAircraftWeightCode) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '기체 종류를 입력해 주세요.'
- });
-
- return false;
- } else if (validateidntfNumCode) {
- setIsErrorModal({
- isOpen: true,
- title: '필수값 입력 오류',
- desc: '기체 신고 번호를 입력해 주세요.'
- });
- return false;
- } else {
- handlerLaanc();
- }
- };
-
- const handlerBufferApply = async () => {
- if (areaCoordList) {
- if (areaCoordList[0].coordList.length > 0) {
- // dispatch(LaancAction.LAANC_ALTITUDE.request(detailData.areaList));
- dispatch(LaancAction.LAANC_VALID_AREA.request(detailData.areaList));
-
- const array = [];
- const copy = { ...areaCoordList[0] };
- copy.bufferZone = detailData.areaList[0].bufferZone;
- array.push(copy);
-
- dispatch(FLIGHT_PLAN_AREA_BUFFER_LIST.request(array));
-
- try {
- const elev = await axios.post(
- `api/bas/laanc/valid/elev`,
- detailData.areaList
- );
-
- if (elev.data[0] === 0) {
- // dispatch(AREA_DETAIL_INIT());
- // dispatch(AreaAction.AREA_DETAIL_INIT());
- // dispatch(drawTypeChangeAction(''));
- // dispatch(LaancAction.LAANC_APPROVAL_INIT());
- setIsErrorModal({
- title: '비행 불가 지역',
- desc: (
- <>
- 설정하신 비행구역 중 허용고도가 0m인 구역이 있습니다.
-
- 버퍼존을 다시 확인해주시기 바랍니다.
- >
- ),
- isOpen: true
- });
- }
- dispatch(LaancAction.LAANC_ALTITUDE.success(elev.data));
- } catch (error) {
- {
- setIsErrorModal({
- isOpen: true,
- title: '오류',
- desc: '처리중 오류가 발생하였습니다'
- });
- }
- }
- }
- }
- };
-
+ // Laanc 승인 요청 취소 버튼 헨들러
const handlerLaancClose = () => {
setStep(1);
setDisabledAnimation(!disabledAnimation);
@@ -504,17 +74,13 @@ export default function LaancPlanContainer({
{step === 1 && (
<>
>
)}
@@ -541,6 +107,7 @@ export default function LaancPlanContainer({
/>
)}
+
diff --git a/src/modules/laanc/actions/laancActions.ts b/src/modules/laanc/actions/laancActions.ts
index d5680b9b..6ced9c7d 100644
--- a/src/modules/laanc/actions/laancActions.ts
+++ b/src/modules/laanc/actions/laancActions.ts
@@ -14,7 +14,8 @@ import {
FlightPlanAreaData,
VaildElevData,
VaildAreaData,
- LaancTsData
+ LaancTsData,
+ LaancTsQrData
} from '../models/laancModels';
// laanc 비행계획서 승인
@@ -57,11 +58,17 @@ const LAANC_VALID_TS_REQUEST = 'laanc/valid/ts/REQUEST';
const LAANC_VALID_TS_SUCCESS = 'laanc/valid/ts/SUCCESS';
const LAANC_VALID_TS_FAILURE = 'laanc/valid/ts/FAILURE';
+// laanc ts qr
+const LAANC_TS_QR_REQUEST = 'laanc/ts/qr/REQUEST';
+const LAANC_TS_QR_SUCCESS = 'laanc/ts/qr/SUCCESS';
+const LAANC_TS_QR_FAILURE = 'laanc/ts/qr/FAILURE';
+
// laanc 초기화
const INIT_LAANC = 'laanc/init';
// laanc approval detail 초기화
const INIT_APPROVAL_DETAIL = 'laanc/init/approval/detail';
+
// 허뎓 고도 초기화
// const INIT_ALTITUDE = 'laanc/init/altitude';
@@ -142,6 +149,13 @@ export const LAANC_VALID_TS = createAsyncAction(
LAANC_VALID_TS_FAILURE
)();
+// laanc ts qr
+export const LAANC_TS_QR = createAsyncAction(
+ LAANC_TS_QR_REQUEST,
+ LAANC_TS_QR_SUCCESS,
+ LAANC_TS_QR_FAILURE
+)();
+
const actions = {
LAANC_FLIGHT_Approval,
LAANC_FLIGHT_CREATE,
@@ -152,6 +166,7 @@ const actions = {
LAANC_ALTITUDE,
LAANC_VALID_AREA,
LAANC_VALID_TS,
+ LAANC_TS_QR,
LAANC_APPROVAL_DETAIL_INIT
};
export type LaancAction = ActionType;
diff --git a/src/modules/laanc/apis/laancApi.ts b/src/modules/laanc/apis/laancApi.ts
index 0e0e028d..2e1b5020 100644
--- a/src/modules/laanc/apis/laancApi.ts
+++ b/src/modules/laanc/apis/laancApi.ts
@@ -54,5 +54,10 @@ export const laancApi = {
postValidTs: async (data: string) => {
const res = await axios.post(`api/bas/laanc/valid/ts/pilot/${data}`);
return res;
+ },
+ // laanc ts qr
+ getTsQr: async (data: string) => {
+ const res = await axios.get(`api/bas/laanc/ts/qr/${data}`);
+ return res.data;
}
};
diff --git a/src/modules/laanc/models/laancModels.ts b/src/modules/laanc/models/laancModels.ts
index 98d6a89c..693ef285 100644
--- a/src/modules/laanc/models/laancModels.ts
+++ b/src/modules/laanc/models/laancModels.ts
@@ -10,6 +10,7 @@ export interface laancState {
laancElev: number[] | undefined;
laancArea: VaildAreaData | undefined;
laancTs: LaancTsData | undefined;
+ laancQrData: LaancTsQrData | undefined;
}
// laanc계획서 초기값
@@ -377,6 +378,7 @@ export const laancControlData = {
laancElev: undefined,
laancArea: undefined,
laancTs: undefined,
+ laancQrData: undefined,
detail: {
planSno: 0,
groupId: '',
@@ -817,3 +819,12 @@ export interface LaancTsData {
];
valid: boolean;
}
+
+// laanc Ts QR
+export interface LaancTsQrData {
+ rspCode: string;
+ rspMessage: string;
+ arcrftinsuranceyn: string;
+ arcrftdeclaration: string;
+ corpregyn: string;
+}
diff --git a/src/modules/laanc/reducers/laancReducers.ts b/src/modules/laanc/reducers/laancReducers.ts
index 8a7e5364..cba4abdc 100644
--- a/src/modules/laanc/reducers/laancReducers.ts
+++ b/src/modules/laanc/reducers/laancReducers.ts
@@ -83,6 +83,12 @@ export const laancReducer = createReducer(
const data = action.payload;
draft.laancTs = data;
})
+ )
+ .handleAction(Actions.LAANC_TS_QR.success, (state, action) =>
+ produce(state, draft => {
+ const data = action.payload;
+ draft.laancQrData = data;
+ })
);
// .handleAction(Actions.LAANC_ALTITUDE_INIT, (state, action) =>
// produce(state, draft => {
diff --git a/src/modules/laanc/sagas/laancSagas.ts b/src/modules/laanc/sagas/laancSagas.ts
index e9dc4b30..f5d516ec 100644
--- a/src/modules/laanc/sagas/laancSagas.ts
+++ b/src/modules/laanc/sagas/laancSagas.ts
@@ -171,6 +171,23 @@ function* postValidTsSaga(
);
}
}
+// laanc ts qr
+function* getTsQrSaga(action: ActionType) {
+ try {
+ const detail = action.payload;
+ const res = yield call(Apis.laancApi.getTsQr, detail);
+ // yield put(Actions.LAANC_TS_QR.success(res.data));
+ } catch (error) {
+ yield put(
+ MessageActions.IS_ERROR({
+ errorCode: ERROR_MESSAGE.code,
+ errorMessage: ERROR_MESSAGE.message,
+ isHistoryBack: false,
+ isRefresh: false
+ })
+ );
+ }
+}
export function* laancSaga() {
yield takeEvery(Actions.LAANC_FLIGHT_Approval.request, postApprovalSaga);
yield debounce(500, Actions.LAANC_FLIGHT_CREATE.request, postCreateSaga);