박상현 11 months ago
parent
commit
680966b8d8
  1. 12
      src/components/laanc/map/LaancAreaMap.js
  2. 61
      src/components/laanc/step/LaancStep1.js
  3. 123
      src/components/laanc/step/LaancStep2.js
  4. 4
      src/containers/laanc/LaancContainer.js
  5. 98
      src/containers/laanc/LaancPlanContainer.js
  6. 48
      src/modules/laanc/actions/laancActions.ts
  7. 13
      src/modules/laanc/apis/laancApi.ts
  8. 39
      src/modules/laanc/models/laancModels.ts
  9. 22
      src/modules/laanc/reducers/laancReducers.ts
  10. 40
      src/modules/laanc/sagas/laancSagas.ts

12
src/components/laanc/map/LaancAreaMap.js

@ -340,7 +340,17 @@ export default function LaancAreaMap({
}
return (
<div>
<div
onClick={() => {
const allObj = drawObj
.getAll()
.features.filter(o => o.properties.id !== 'BUFFER');
drawObj.changeMode('direct_select', {
featureId: allObj[i].id
});
}}
>
<h6 className='ti'>비행구역 {i + 1}</h6>
<div className='coords-box-scroll'>
{coord?.map((co, idx) => {

61
src/components/laanc/step/LaancStep1.js

@ -38,7 +38,10 @@ export default function LaancStep1({
const { user } = useSelector(state => state.authState);
const { areaCoordList } = useSelector(state => state.flightState);
const { laancSun } = useSelector(state => state.laancState);
const { laancSun, laancElev, laancArea } = useSelector(
state => state.laancState
);
const { inAirArea } = useSelector(state => state.flightState);
const fltElevRef = useRef(null);
const bufferZoneRef = useRef(null);
const schFltStDtRef = useRef(null);
@ -50,7 +53,6 @@ export default function LaancStep1({
const [popoverCommercial, setPopoverCommercial] = useState(false);
const [popoverSchFltStDt, setPopoverSchFltStDt] = useState(false);
const [popoverSchFltEndDt, setPopoverSchFltEndDt] = useState(false);
const [isErrorModal, setIsErrorModal] = useState({
isOpen: false,
title: '',
@ -183,6 +185,47 @@ export default function LaancStep1({
url: 'https://drone.onestop.go.kr/introduce/systemintro3 '
});
}
if (
!laancArea.duplicated &&
parseInt(value.replace('/^0+/', 'm', ''), 10) < 150
) {
setIsErrorModal({
isOpen: true,
title: '고도 재설정 알림',
desc: (
<>
관제권 비행금지 공역을 제외한 지역에서는 주간에 150m미만의
<br />
고도에서는 비행승인없이 비행가능합니다.
</>
)
});
}
if (
laancArea.duplicated &&
parseInt(value.replace('/^0+/', 'm', ''), 10) >= laancElev &&
parseInt(value.replace('/^0+/', 'm', ''), 10) < 150
) {
setIsErrorModal({
isOpen: true,
title: '검토 결과 사전안내',
desc: (
<>
유효성 검사에 실패하여 승인 대상입니다.
<br />
제출하신 비행계획서의 고도는 {laancElev}m이하에서만 비행이
가능합니다.
<br />
고도 설정을 다시 확인해주시기 바랍니다.
</>
)
});
handleChange({
type: 'area',
name: 'fltElev',
value: 0
});
}
case 'fltMethod':
if (value === '군집비행') {
handleChange({
@ -190,17 +233,10 @@ export default function LaancStep1({
name: 'fltMethod',
value: ''
});
setIsLaancModal({
setIsErrorModal({
isOpen: true,
title: '군집 비행 목적',
desc: (
<>
군집 비행의 경우 담당자와 협의가 필요합니다. <br />
아래 링크를 통해 담당자와 협의 부탁드립니다.
</>
),
type: '처리부서안내 바로가기',
url: 'https://drone.onestop.go.kr/introduce/systemintro3 '
title: '비행 구역 설정',
desc: '비행 구역 설정을 먼저 설정 해 주세요'
});
}
}
@ -545,6 +581,7 @@ export default function LaancStep1({
onBlur={e => handleBlur(e.target.value, 'fltElev')}
onChange={e => {
const { name, value } = e.target;
handleChange({
type: 'area',
name,

123
src/components/laanc/step/LaancStep2.js

@ -85,8 +85,7 @@ export default function LaancStep2({
agreeYn: 'Y',
termsSno: termsList[0]?.termsSno
}
],
validatedRs: laancApply
]
});
};
//laanc 문구 정의 함수
@ -156,40 +155,19 @@ export default function LaancStep2({
</Alert>
</Col>
<Col className='list-input' md='6'>
<Alert
color={
data.arcrftList[0].idntfNum != 'PA0002'
? 'success'
: 'warning'
}
>
<Alert color={'success'}>
<div className='alert-body'>
{data.arcrftList[0].idntfNum != 'PA0002' ? (
<CheckCircle size={15} />
) : (
<AlertCircle size={15} />
)}
<CheckCircle size={15} />
<span className='ms-1'> 기체보험가입 정보</span>
</div>
</Alert>
</Col>
{/* validation은 on 클래스로 제어 */}
<Col className='validation on' md='12'>
{data.arcrftList[0].idntfNum === 'PA0002' ? (
<p>
<AlertTriangle />
기체가 보험에 가입되어 있지 않거나 유효기간이 만료되었습니다.
{/* <AlertTriangle />
조종자자격증이 유효하지 않습니다.
<br /> */}
</p>
) : null}
{data.arcrftList[0].idntfNum != 'PA0002' ? (
<p style={{ color: '#28c76f' }}>
<CheckCircle />
유효성 검사가 정상적으로 완료되었습니다.
</p>
) : null}
<p style={{ color: '#28c76f' }}>
<CheckCircle />
유효성 검사가 정상적으로 완료되었습니다.
</p>
</Col>
</Row>
</div>
@ -206,57 +184,16 @@ export default function LaancStep2({
</div>
<div className='mt-1'>
{/* 사전 결과 승인 대상일때 color=success */}
<Alert
color={
(laancApply?.valid &&
data.arcrftList[0].idntfNum != 'PA0002') ||
data.aprvlYn === 'Y'
? 'success'
: 'warning'
}
>
<Alert color={'success'}>
<div className='alert-body'>
{(laancApply?.valid &&
data.arcrftList[0].idntfNum != 'PA0002') ||
data.aprvlYn === 'Y' ? (
<>
<CheckCircle size={15} />
<span className='ms-1'> 검토 결과 승인 대상입니다.</span>
<span className='cancel-txt'>
제출하신 비행계획은 자동승인 대상 입니다.
<br />
<br />
자동승인을 위해 다음 스텝으로 진행하시기 바랍니다.
</span>
</>
) : (
<>
{data.arcrftList[0].idntfNum === 'PA0002' ? (
<>
<AlertCircle size={15} />
<span className='ms-1'>
{' '}
검토 결과 승인 대상입니다.
</span>
<span className='cancel-txt'>
유효성 검사에 실패하였습니다.
<br />
<br />
아래 이전 버튼을 눌러 스텝1에서 기체번호를
확인해주시기 바랍니다.
</span>
</>
) : (
laancReason(
laancApply?.flight,
laancApply?.arcrftDuplicated,
laancApply?.planAreaDuplicatd,
laancApply?.pilotQlfc,
laancApply?.arcrftInsurance
)
)}
</>
)}
<CheckCircle size={15} />
<span className='ms-1'> 검토 결과 승인 대상입니다.</span>
<span className='cancel-txt'>
제출하신 비행계획은 자동승인 대상 입니다.
<br />
<br />
자동승인을 위해 다음 스텝으로 진행하시기 바랍니다.
</span>
</div>
</Alert>
{/* <Alert color='success'>
@ -281,7 +218,7 @@ export default function LaancStep2({
name='memberName'
size='sm'
placeholder=''
value={user.memberName}
value={user?.memberName}
disabled
/>
</FormGroup>
@ -418,17 +355,15 @@ export default function LaancStep2({
className='terms-box'
dangerouslySetInnerHTML={{ __html: termsList[0]?.termsCn }}
></div>
{!laancIsCheck ? (
<CustomInput
inline
type='checkbox'
className='terms-check'
id='exampleCustomCheckbox'
label='조종자 준수사항 미 준수 시 처벌에 동의합니다.'
checked={isterms}
onChange={() => setIsterms(!isterms)}
/>
) : null}
<CustomInput
inline
type='checkbox'
className='terms-check'
id='exampleCustomCheckbox'
label='조종자 준수사항 미 준수 시 처벌에 동의합니다.'
checked={isterms}
onChange={() => setIsterms(!isterms)}
/>
</>
) : null}
</Col>
@ -450,11 +385,7 @@ export default function LaancStep2({
<span></span>
</li>
</ul>
<Button
disabled={!isterms || laancIsCheck}
outline
onClick={() => handlerCreate()}
>
<Button disabled={!isterms} outline onClick={() => handlerCreate()}>
다음
</Button>
</ModalFooter>

4
src/containers/laanc/LaancContainer.js

@ -5,6 +5,7 @@ import moment from 'moment';
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
import { CustomMainLayout } from '../../components/layout/CustomMainLayout';
import * as LaancAction from '../../modules/laanc/actions/laancActions';
import * as AreaAction from '../../modules/basis/flight/actions/basisFlightAction';
import { drawTypeChangeAction } from '../../modules/control/map/actions/controlMapActions';
import {
JOIN_LIST,
@ -91,6 +92,9 @@ export default function LaancContainer() {
const handleApply = () => {
dispatch(drawTypeChangeAction(''));
dispatch(LaancAction.LAANC_APPROVAL_INIT());
dispatch(LaancAction.LAANC_ALTITUDE_INIT());
dispatch(LaancAction.LAANC_AREA_INIT());
dispatch(AreaAction.AREA_DETAIL_INIT());
setDisabledAnimation(true);
setCurrentParm(true);
};

98
src/containers/laanc/LaancPlanContainer.js

@ -24,10 +24,11 @@ export default function LaancPlanContainer({
const { areaCoordList } = useSelector(state => state.flightState);
const { user } = useSelector(state => state.authState);
const { laancApply } = useSelector(state => state.laancState);
const { laancApply, laancArea, laancElev } = useSelector(
state => state.laancState
);
const [isBuffer, setIsBuffer] = useState(false);
const { inAirArea } = useSelector(state => state.flightState);
const [step, setStep] = useState(1);
const [detailData, setDetailData] = useState(initFlightBas.initDetail);
@ -41,11 +42,13 @@ export default function LaancPlanContainer({
});
useEffect(() => {
setDetailData({
...detailData,
cstmrSno: user.cstmrSno,
memberName: user.memberName
});
if (user) {
setDetailData({
...detailData,
cstmrSno: user.cstmrSno,
memberName: user.memberName
});
}
return () => {
dispatch(drawTypeChangeAction(''));
};
@ -59,27 +62,10 @@ export default function LaancPlanContainer({
}, [finalDetailData]);
// laanc 승인 api 200 시 step 이동
useEffect(() => {
if (laancApply) {
const { valid, evaluatedTargetArea, flight } = laancApply;
// 사전결과 미승인 대상
if (!valid && !evaluatedTargetArea && flight) {
setIsErrorModal({
isOpen: true,
title: '검토 결과 사전안내',
desc: (
<>
검토 결과 승인 대상입니다.
<p>
제줄하신 비행계획서는 별도의 승인이 필요없습니다.
<br />
조종자 준수사항에 유의하여 비행하시기 바랍니다.
</p>
</>
)
});
return;
} else if (!valid) {
const handlerLaanc = () => {
// 사전결과 미승인 대상
if (laancArea && laancElev) {
if (detailData.arcrftList[0].idntfNum === 'PA0002') {
setIsErrorModal({
isOpen: true,
title: '검토 결과 사전안내',
@ -87,48 +73,57 @@ export default function LaancPlanContainer({
<>
유효성 검사에 실패하여 승인 대상입니다.
<p>
제출하신 비행계획서의 고도는 120m이하에서만 비행이 가능합니다.
기체가 보험에 가입되어 있지 않거나 유효기간이 만료되었습니다.
<br />
고도 설정을 다시 확인해주시기 바랍니다.
기체 번호를 다시 확인해주시기 바랍니다.
</p>
</>
)
});
return;
} else if (detailData.arcrftList[0].idntfNum === 'PA0002') {
} else if (
!laancArea.duplicated &&
detailData.fltType != 'COMMERCIAL' &&
detailData.arcrftList[0].arcrftWghtCd != '11'
) {
setIsErrorModal({
isOpen: true,
title: '검토 결과 사전안내',
desc: (
<>
유효성 검사에 실패하여 승인 대상입니다.
검토 결과 승인 대상입니다.
<p>
기체가 보험에 가입되어 있지 않거나 유효기간이 만료되었습니다.
제줄하신 비행계획서는 별도의 승인이 필요없습니다.
<br />
기체 번호를 다시 확인해주시기 바랍니다.
조종자 준수사항에 유의하여 비행하시기 바랍니다.
</p>
</>
)
});
return;
} else if (
parseInt(detailData.areaList[0].fltElev) <= laancElev &&
parseInt(detailData.areaList[0].fltElev) < 150
) {
setStep(2);
}
if (!valid && evaluatedTargetArea && !flight) {
setIsErrorModal({
isOpen: true,
title: '검토 결과 사전안내',
desc: (
<>
유효성 검사에 실패하여 승인 대상입니다.
<p>자세한 사항은 비행승인 검토결과를 확인해주시기 바랍니다.</p>
</>
)
});
return;
}
setStep(2);
}
}, [laancApply]);
// if (!valid && evaluatedTargetArea && !flight) {
// setIsErrorModal({
// isOpen: true,
// title: '검토 결과 사전안내',
// desc: (
// <>
// 유효성 검사에 실패하여 미 승인 대상입니다.
// <p>자세한 사항은 비행승인 검토결과를 확인해주시기 바랍니다.</p>
// </>
// )
// });
// return;
// }
};
// 버퍼 변경될 때 관제권 포함유무 체크
useEffect(() => {
@ -368,6 +363,7 @@ export default function LaancPlanContainer({
return false;
} else {
handlerLaanc();
// 비행 방식 직접 입력칸 활성화 후 작성 시 조건문
if (detailData.areaList[0].selffltMethod) {
setFinalDetailData({
@ -380,7 +376,7 @@ export default function LaancPlanContainer({
]
});
} else {
dispatch(LaancAction.LAANC_FLIGHT_Approval.request(detailData));
// dispatch(LaancAction.LAANC_FLIGHT_Approval.request(detailData));
}
}
};

48
src/modules/laanc/actions/laancActions.ts

@ -10,7 +10,10 @@ import {
LaancSunRq,
LaancAprvRq,
LaancAprvData,
LaancDetailData
LaancDetailData,
FlightPlanAreaData,
VaildElevData,
VaildAreaData
} from '../models/laancModels';
// laanc 비행계획서 승인
@ -38,9 +41,25 @@ const LAANC_DETAIL_REQUEST = 'laanc/detail/REQUEST';
const LAANC_DETAIL_SUCCESS = 'laanc/detail/SUCCESS';
const LAANC_DETAIL_FAILURE = 'laanc/detail/FAILURE';
//laanc 허용 고도
const LAANC_ALTITUDE_REQUEST = 'laanc/altitude/REQUEST';
const LAANC_ALTITUDE_SUCCESS = 'laanc/altitude/SUCCESS';
const LAANC_ALTITUDE_FAILURE = 'laanc/altitude/FAILURE';
// 비행 관제 구역 체크
const LAANC_VALID_AREA_REQUEST = 'laanc/valid/area/REQUEST';
const LAANC_VALID_AREA_SUCCESS = 'laanc/valid/area/SUCCESS';
const LAANC_VALID_AREA_FAILURE = 'laanc/valid/area/FAILURE';
// laanc 초기화
const INIT_LAANC = 'laanc/init';
// 허뎓 고도 초기화
const INIT_ALTITUDE = 'laanc/init/altitude';
// 관제권 초기화
const INIT_AREA = 'laanc/init/area';
// laanc 비행계획서 승인
export const LAANC_FLIGHT_Approval = createAsyncAction(
LAANC_FLIGHT_APPROVAL_REQUEST,
@ -48,8 +67,15 @@ export const LAANC_FLIGHT_Approval = createAsyncAction(
LAANC_FLIGHT_APPROVAL_FAILURE
)<FlightPlanData, LaancApproval, AxiosError>();
// laanc 초기화
export const LAANC_APPROVAL_INIT = createAction(INIT_LAANC)();
// 허용고도 초기화
export const LAANC_ALTITUDE_INIT = createAction(INIT_ALTITUDE)();
// 관제권 초기화
export const LAANC_AREA_INIT = createAction(INIT_AREA)();
// laanc 비행계획서 생성
export const LAANC_FLIGHT_CREATE = createAsyncAction(
LAANC_FLIGHT_CREATE_REQUEST,
@ -78,12 +104,30 @@ export const LAANC_DETAIL = createAsyncAction(
LAANC_DETAIL_FAILURE
)<string, LaancDetailData, AxiosError>();
// laanc 허용 고도
export const LAANC_ALTITUDE = createAsyncAction(
LAANC_ALTITUDE_REQUEST,
LAANC_ALTITUDE_SUCCESS,
LAANC_ALTITUDE_FAILURE
)<FlightPlanAreaData, VaildElevData[], AxiosError>();
//비행 관제 구역 체크
export const LAANC_VALID_AREA = createAsyncAction(
LAANC_VALID_AREA_REQUEST,
LAANC_VALID_AREA_SUCCESS,
LAANC_VALID_AREA_FAILURE
)<FlightPlanAreaData, VaildAreaData[], AxiosError>();
const actions = {
LAANC_FLIGHT_Approval,
LAANC_FLIGHT_CREATE,
LAANC_APPROVAL_INIT,
LAANC_SUN_DATA,
LAANC_APRV_LIST,
LAANC_DETAIL
LAANC_DETAIL,
LAANC_ALTITUDE,
LAANC_VALID_AREA,
LAANC_ALTITUDE_INIT,
LAANC_AREA_INIT
};
export type LaancAction = ActionType<typeof actions>;

13
src/modules/laanc/apis/laancApi.ts

@ -36,5 +36,18 @@ export const laancApi = {
getDetail: async (data: string) => {
const res = await axios.get(`api/bas/laanc/aprv/detail/${data}`);
return res.data;
},
//laanc 허용 고도
postValidElev: async (data: FlightPlanAreaData) => {
const res = await axios.post(`api/bas/laanc/valid/elev`, data);
return res;
},
// 비행 관제 구역 체크
postValidArea: async (data: FlightPlanAreaData) => {
const res = await axios.post(
`api/bas/laanc/valid/duplicated/airspace`,
data
);
return res;
}
};

39
src/modules/laanc/models/laancModels.ts

@ -7,6 +7,8 @@ export interface laancState {
laancSun: LaancSunData[] | undefined;
laancSearchData: LaancAprvData[] | undefined;
laancDetail: LaancDetailData | undefined;
laancElev: VaildElevData | undefined;
laancArea: VaildAreaData | undefined;
}
// laanc계획서 초기값
@ -368,6 +370,8 @@ export const laancControlData = {
laancSun: undefined,
laancSearchData: undefined,
laancDetail: undefined,
laancElev: undefined,
laancArea: undefined,
detail: {
planSno: 0,
groupId: '',
@ -751,3 +755,38 @@ export interface LaancDetailData {
elev: string;
arcrftWght: string;
}
export interface VaildElevData {
data: number;
}
// 비행 관제 구역 체크
export interface VaildAreaData {
rq: {
planAreaSno: number;
planSno: number;
areaType: string;
bufferZone: number;
fltElev: string;
docState: string;
coordList: [
{
planAreaCoordSno: number;
planAreaSno: number;
lat: number;
lon: number;
docState: string;
}
];
bufferCoordList: [
{
planAreaCoordSno: number;
planAreaSno: number;
lat: number;
lon: number;
docState: string;
}
];
};
duplicated: false;
}

22
src/modules/laanc/reducers/laancReducers.ts

@ -50,6 +50,28 @@ export const laancReducer = createReducer<laancState, Actions.LaancAction>(
const data = action.payload;
draft.laancDetail = data;
})
)
.handleAction(Actions.LAANC_ALTITUDE.success, (state, action) =>
produce(state, draft => {
const data = action.payload;
draft.laancElev = data[0];
})
)
.handleAction(Actions.LAANC_VALID_AREA.success, (state, action) =>
produce(state, draft => {
const data = action.payload;
draft.laancArea = data[0];
})
)
.handleAction(Actions.LAANC_ALTITUDE_INIT, (state, action) =>
produce(state, draft => {
draft.laancElev = undefined;
})
)
.handleAction(Actions.LAANC_AREA_INIT, (state, action) =>
produce(state, draft => {
draft.laancArea = undefined;
})
);
export default laancReducer;

40
src/modules/laanc/sagas/laancSagas.ts

@ -131,10 +131,50 @@ function* getDetailSaga(
);
}
}
// laanc 허용 고도
function* postValidElevSaga(
action: ActionType<typeof Actions.LAANC_ALTITUDE.request>
) {
try {
const deail = action.payload;
const res = yield call(Apis.laancApi.postValidElev, deail);
yield put(Actions.LAANC_ALTITUDE.success(res.data));
} catch (error) {
yield put(
MessageActions.IS_ERROR({
errorCode: ERROR_MESSAGE.code,
errorMessage: ERROR_MESSAGE.message,
isHistoryBack: false,
isRefresh: false
})
);
}
}
//비행 관제 구역 체크
function* postValidAreaSaga(
action: ActionType<typeof Actions.LAANC_VALID_AREA.request>
) {
try {
const deail = action.payload;
const res = yield call(Apis.laancApi.postValidArea, deail);
yield put(Actions.LAANC_VALID_AREA.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, postApprovalsata);
yield takeEvery(Actions.LAANC_FLIGHT_CREATE.request, postCreatesata);
yield takeEvery(Actions.LAANC_SUN_DATA.request, getSunDataSaga);
yield takeEvery(Actions.LAANC_APRV_LIST.request, getAprvListSaga);
yield takeEvery(Actions.LAANC_DETAIL.request, getDetailSaga);
yield takeEvery(Actions.LAANC_ALTITUDE.request, postValidElevSaga);
yield takeEvery(Actions.LAANC_VALID_AREA.request, postValidAreaSaga);
}

Loading…
Cancel
Save