From 1f219aafd673e26b089656b7d81894871acf5c94 Mon Sep 17 00:00:00 2001 From: hhjk00 Date: Mon, 13 Nov 2023 11:23:41 +0900 Subject: [PATCH 1/5] =?UTF-8?q?api=20url=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/statistics/actions/index.ts | 2 +- src/modules/statistics/apis/index.ts | 4 ++-- src/modules/statistics/models/index.ts | 2 +- src/modules/statistics/reducers/index.ts | 9 +++++---- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/modules/statistics/actions/index.ts b/src/modules/statistics/actions/index.ts index a25343b..54357b7 100644 --- a/src/modules/statistics/actions/index.ts +++ b/src/modules/statistics/actions/index.ts @@ -32,4 +32,4 @@ const actions = { FLIGHT_STCS_SEARCH }; -export type StcsAction = ActionType; +export type StatisticsAction = ActionType; diff --git a/src/modules/statistics/apis/index.ts b/src/modules/statistics/apis/index.ts index aa087fc..af20220 100644 --- a/src/modules/statistics/apis/index.ts +++ b/src/modules/statistics/apis/index.ts @@ -4,7 +4,7 @@ import { FlightSearchRq } from '../models'; export const stcsAPI = { flight: async () => { - return await axios.get('/api/main/dash/stcs/flight-static'); + return await axios.get('/api/main/statistics/flight-static'); }, flightSearch: async (data: FlightSearchRq) => { const { type } = data; @@ -19,6 +19,6 @@ export const stcsAPI = { arrayFormat: 'repeat' }); - return await axios.get(`api/main/dash/stcs/flight/${type}${queryString}`); + return await axios.get(`api/main/statistics/flight/${type}${queryString}`); } }; diff --git a/src/modules/statistics/models/index.ts b/src/modules/statistics/models/index.ts index 6ea0329..7a066ba 100644 --- a/src/modules/statistics/models/index.ts +++ b/src/modules/statistics/models/index.ts @@ -1,4 +1,4 @@ -export interface IStcsState { +export interface IStatisticsState { flight: Flight; flightSearch: FlightSearch; } diff --git a/src/modules/statistics/reducers/index.ts b/src/modules/statistics/reducers/index.ts index a9cd09f..ecad560 100644 --- a/src/modules/statistics/reducers/index.ts +++ b/src/modules/statistics/reducers/index.ts @@ -1,11 +1,12 @@ import { createReducer } from 'typesafe-actions'; import produce from 'immer'; import * as Actions from '../actions'; -import { IStcsState, initialState } from '../models'; +import { IStatisticsState, initialState } from '../models'; -export const statisticsReducer = createReducer( - initialState -) +export const statisticsReducer = createReducer< + IStatisticsState, + Actions.StatisticsAction +>(initialState) // 비행 통계 (비행시간, 비행거리, 비행횟수) .handleAction(Actions.FLIGHT_STCS.success, (state, action) => produce(state, draft => { From 83e7e1153f710780f5b4868d570de06c8c788063 Mon Sep 17 00:00:00 2001 From: hhjk00 Date: Mon, 13 Nov 2023 13:48:33 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=EB=B9=84=ED=96=89=20=EC=8B=A4=EC=A0=81=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/FlightPerformanceContainer.js | 485 ++++++++++++++++++ src/navigation/statistics/index.js | 6 + src/router/routes/RouteStatistics.js | 6 + src/views/statistics/FlightPerformanceView.js | 8 + 4 files changed, 505 insertions(+) create mode 100644 src/containers/statistics/FlightPerformanceContainer.js create mode 100644 src/views/statistics/FlightPerformanceView.js diff --git a/src/containers/statistics/FlightPerformanceContainer.js b/src/containers/statistics/FlightPerformanceContainer.js new file mode 100644 index 0000000..d05add2 --- /dev/null +++ b/src/containers/statistics/FlightPerformanceContainer.js @@ -0,0 +1,485 @@ +import { CustomMainLayout } from '../../components/layout/CustomMainLayout'; +import { + Button, + Col, + Row, + Card, + CardHeader, + CardTitle, + CardBody, + CustomInput +} from 'reactstrap'; +import { Search } from 'react-feather'; +import { FcAlarmClock, FcWorkflow, FcBarChart } from 'react-icons/fc'; +import { Bar, Doughnut } from 'react-chartjs-2'; +import { useCallback, useEffect, useState } from 'react'; +import { useDispatch } from 'react-redux'; +import * as StcsActions from '../../modules/statistics/actions'; + +export default function FlightPerformanceContainer({ + tooltipShadow, + gridLineColor, + labelColor +}) { + const dispatch = useDispatch(); + + const [searchType, setSearchType] = useState({ + category: '비행실적', + dateType: 'year', + year: new Date().getFullYear(), + month: new Date().getMonth() + 1, + day: new Date().getDate() + }); + const [dateLists, setDateLists] = useState({ + month: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + day: [] + }); + + const titleName = '비행 실적 통계'; + + useEffect(() => { + const { year, month } = searchType; + const lastDay = new Date(year, Number(month), 0).getDate(); + const dayList = Array.from({ length: lastDay }, (_, index) => index + 1); + + setDateLists({ ...dateLists, day: dayList }); + }, [searchType.month]); + + // 검색조건 handler + const handleChangeSearchType = useCallback( + (type, val) => { + setSearchType({ + ...searchType, + [type]: val + }); + }, + [searchType] + ); + + const options = { + elements: { + rectangle: { + borderWidth: 2, + borderSkipped: 'bottom' + } + }, + responsive: true, + maintainAspectRatio: false, + responsiveAnimationDuration: 500, + legend: { + display: false + }, + tooltips: { + // Updated default tooltip UI + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowBlur: 8, + shadowColor: tooltipShadow, + backgroundColor: '#fff', + titleFontColor: '#000', + bodyFontColor: '#000' + }, + scales: { + xAxes: [ + { + display: true, + gridLines: { + display: true, + color: gridLineColor, + zeroLineColor: gridLineColor + }, + scaleLabel: { + display: false + }, + ticks: { + fontColor: labelColor + } + } + ], + yAxes: [ + { + display: true, + gridLines: { + color: gridLineColor, + zeroLineColor: gridLineColor + }, + ticks: { + stepSize: 100, + min: 0, + max: 400, + fontColor: labelColor + } + } + ] + } + }, + data = { + labels: [ + '7/12', + '8/12', + '9/12', + '10/12', + '11/12', + '12/12', + '13/12', + '14/12', + '15/12', + '16/12', + '17/12' + ], + datasets: [ + { + data: [275, 90, 190, 205, 125, 85, 55, 87, 127, 150, 230, 280, 190], + backgroundColor: '#00bcd4', + borderColor: '#00bcd4', + barThickness: 15 + } + ] + }; + + const options2 = { + responsive: true, + maintainAspectRatio: true, + responsiveAnimationDuration: 500, + cutoutPercentage: 60, + legend: { + position: 'bottom', + labels: { + usePointStyle: true, + padding: 18, + boxWidth: 8, + fontColor: labelColor, + fontSize: 14, + fontWeight: 500, + fontFamily: ['Rubik', 'Montserrat', 'NotoSansKR'] + } + }, + tooltips: { + callbacks: { + label(tooltipItem, data) { + const label = data.datasets[0].labels[tooltipItem.index] || '', + value = data.datasets[0].data[tooltipItem.index]; + const output = ` ${label} : ${value} %`; + return output; + } + }, + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowBlur: 8, + shadowColor: tooltipShadow, + backgroundColor: '#fff', + titleFontColor: '#000', + bodyFontColor: '#000' + } + }, + data2 = { + labels: ['PA0001', 'PA0002', 'PA0003', 'PA0004', 'PA0005'], + datasets: [ + { + labels: ['PA0001', 'PA0002', 'PA0003', 'PA0004', 'PA0005'], + data: [10, 20, 30, 40, 80], + // 레드버전 + // backgroundColor: [ + // '#ffe8d1', + // '#ffb59e', + // '#f0826b', + // '#Bd4f38', + // '#8a1c05' + // ], + + backgroundColor: [ + '#ccffff', + '#99ffff', + '#66ffff', + '#33efff', + '#00bcd4' + ], + borderWidth: 0, + pointStyle: 'rectRounded' + } + ] + }; + + return ( + +
+
+ + +
+ + + + + + + + + +
+ + + + 비행 실적 + PA0001 + + + 8일 10시간 35분 12초 +
+ + 1일 35분 12초 + + + 35분 12초 +
+
+ + +
+ + + + + + + + + +
+ + + + 비행 계획 + PA0002 + + + 10,845m +
+ + 1,201m + + + 53m +
+
+ + +
+ + + + + + + + + +
+ + + + 비행 승인 + PA0002 + + + 1,024,845건 +
+ + 111,201건 + + + 153건 +
+
+ +
+
+
+ + +
+
+

검색조건

+
+ {/*
+ + + 검색 + +
*/} +
+ + +
+
+
+
+
검색조건
+
+
+ + + + handleChangeSearchType( + 'category', + e.target.value + ) + } + > + + + + + + +
+
+
+
+
+
+
+
+ +
+
+
+ + + + + {searchType.category} 통계 +
+ +
+ + handleChangeSearchType('dateType', e.target.value) + } + > + + + + + +
+ + {searchType.dateType === 'month' || + searchType.dateType === 'day' || + searchType.dateType === 'one-day' ? ( + <> +
+ + handleChangeSearchType('year', e.target.value) + } + > + + +
+ {searchType.dateType === 'day' || + searchType.dateType === 'one-day' ? ( +
+ + handleChangeSearchType( + 'month', + e.target.value + ) + } + > + {dateLists.month.map(i => ( + + ))} + +
+ ) : null} + {searchType.dateType === 'one-day' ? ( +
+ + handleChangeSearchType('day', e.target.value) + } + > + {dateLists.day.map(i => ( + + ))} + +
+ ) : null} + + ) : null} +
+ {/* + */} +
+
+ +
+ +
+
+
+ + + + + {searchType.category} TOP5 + + +
+ +
+ {/*
+
+
*/} +
+
+ +
+
+
+
+ ); +} diff --git a/src/navigation/statistics/index.js b/src/navigation/statistics/index.js index f46b83d..a42eb80 100644 --- a/src/navigation/statistics/index.js +++ b/src/navigation/statistics/index.js @@ -15,5 +15,11 @@ export default [ type: 'item', title: '비정상상황 통계', navLink: '/statistics/abnormal' + }, + { + id: 'statistics_001_03', + type: 'item', + title: '비행 실적', + navLink: '/statistics/performance' } ]; diff --git a/src/router/routes/RouteStatistics.js b/src/router/routes/RouteStatistics.js index 4447a7c..d0a4deb 100644 --- a/src/router/routes/RouteStatistics.js +++ b/src/router/routes/RouteStatistics.js @@ -10,6 +10,12 @@ const RouteStatistics = [ component: lazy(() => import('../../views/statistics/AbnormalSituationView') ) + }, + { + path: '/statistics/performance', + component: lazy(() => + import('../../views/statistics/FlightPerformanceView') + ) } ]; diff --git a/src/views/statistics/FlightPerformanceView.js b/src/views/statistics/FlightPerformanceView.js new file mode 100644 index 0000000..3d12853 --- /dev/null +++ b/src/views/statistics/FlightPerformanceView.js @@ -0,0 +1,8 @@ +import '../../assets/css/custom.css'; +import '@styles/react/libs/flatpickr/flatpickr.scss'; +import '@styles/react/libs/tables/react-dataTable-component.scss'; +import FlightPerformanceContainer from '../../containers/statistics/FlightPerformanceContainer'; + +export default function FlightPerformanceView() { + return ; +} From b174aedcfd884616f3db63ace0f1fdc7ff107775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=83=81=ED=98=84?= Date: Mon, 13 Nov 2023 16:19:47 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=EC=A1=B0=EC=A2=85=EC=82=AC=20=EC=A4=80?= =?UTF-8?q?=EC=88=98=EC=82=AC=ED=95=AD=20text=20=EC=99=BC=EC=AA=BD=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/laanc/step/LaancStep2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/laanc/step/LaancStep2.js b/src/components/laanc/step/LaancStep2.js index 2f27540..14f68de 100644 --- a/src/components/laanc/step/LaancStep2.js +++ b/src/components/laanc/step/LaancStep2.js @@ -358,7 +358,7 @@ export default function LaancStep2({ 조종자 준수사항 -
+
① 초경량비행장치 조종자는 법 제129조제1항에 따라 다음 각 호의 어느 하나에 해당하는 행위를 해서는 안된다.
다만, 무인비행장치의 조종자에 대해서는 제4호 및 제5호를 From 232034f37e389ed4c5f0481c6d8dbb2525cba574 Mon Sep 17 00:00:00 2001 From: hhjk00 Date: Mon, 13 Nov 2023 16:31:50 +0900 Subject: [PATCH 4/5] =?UTF-8?q?=EB=B9=84=ED=96=89=20=EC=8B=A4=EC=A0=81=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B2=BD=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...eContainer.js => FlightResultContainer.js} | 102 +++++++++++++----- src/navigation/statistics/index.js | 2 +- src/router/routes/RouteStatistics.js | 6 +- src/views/statistics/FlightPerformanceView.js | 8 -- src/views/statistics/FlightResultView.js | 8 ++ 5 files changed, 84 insertions(+), 42 deletions(-) rename src/containers/statistics/{FlightPerformanceContainer.js => FlightResultContainer.js} (87%) delete mode 100644 src/views/statistics/FlightPerformanceView.js create mode 100644 src/views/statistics/FlightResultView.js diff --git a/src/containers/statistics/FlightPerformanceContainer.js b/src/containers/statistics/FlightResultContainer.js similarity index 87% rename from src/containers/statistics/FlightPerformanceContainer.js rename to src/containers/statistics/FlightResultContainer.js index d05add2..fe66ab7 100644 --- a/src/containers/statistics/FlightPerformanceContainer.js +++ b/src/containers/statistics/FlightResultContainer.js @@ -12,19 +12,20 @@ import { import { Search } from 'react-feather'; import { FcAlarmClock, FcWorkflow, FcBarChart } from 'react-icons/fc'; import { Bar, Doughnut } from 'react-chartjs-2'; -import { useCallback, useEffect, useState } from 'react'; -import { useDispatch } from 'react-redux'; +import { useCallback, useEffect, useRef, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import * as StcsActions from '../../modules/statistics/actions'; -export default function FlightPerformanceContainer({ +export default function ResultContainer({ tooltipShadow, gridLineColor, labelColor }) { const dispatch = useDispatch(); + const { result, resultSearch } = useSelector(state => state.statisticsState); const [searchType, setSearchType] = useState({ - category: '비행실적', + category: 'FLT_RESULT', dateType: 'year', year: new Date().getFullYear(), month: new Date().getMonth() + 1, @@ -37,6 +38,11 @@ export default function FlightPerformanceContainer({ const titleName = '비행 실적 통계'; + useEffect(() => { + dispatch(StcsActions.RESULT_STCS.request()); + }, []); + + // 해당 월에 맞는 요일 표출 useEffect(() => { const { year, month } = searchType; const lastDay = new Date(year, Number(month), 0).getDate(); @@ -45,6 +51,25 @@ export default function FlightPerformanceContainer({ setDateLists({ ...dateLists, day: dayList }); }, [searchType.month]); + useEffect(() => { + const { category, dateType, year, month, day } = searchType; + + const dateMapping = { + month: year, + day: `${year}-${month}`, + 'one-day': `${year}-${month}-${day}` + }; + const date = dateMapping[dateType] || ''; + + dispatch( + StcsActions.RESULT_STCS_SEARCH.request({ + cate: category, + date, + type: dateType + }) + ); + }, [searchType]); + // 검색조건 handler const handleChangeSearchType = useCallback( (type, val) => { @@ -56,6 +81,35 @@ export default function FlightPerformanceContainer({ [searchType] ); + // 그래프 타이틀 handler + const handlerTitleName = category => { + const categoryMappings = { + TIME: '비행 실적', + DISTANCE: '비행 계획', + FLT_COUNT: '비행 승인' + }; + return categoryMappings[category]; + }; + + const handlerBarTicks = () => { + const data = resultSearch.topData.map(i => i.value); + const max = Math.max(...data); + const min = Math.min(...data); + const stepSize = handlerStepSize(max); + + return { max, min, stepSize }; + }; + + const handlerStepSize = max => { + if (max <= 1000) { + return 100; + } else if (max <= 5000) { + return 500; + } else { + return 1000; + } + }; + const options = { elements: { rectangle: { @@ -104,9 +158,7 @@ export default function FlightPerformanceContainer({ zeroLineColor: gridLineColor }, ticks: { - stepSize: 100, - min: 0, - max: 400, + ...handlerBarTicks(), fontColor: labelColor } } @@ -114,22 +166,10 @@ export default function FlightPerformanceContainer({ } }, data = { - labels: [ - '7/12', - '8/12', - '9/12', - '10/12', - '11/12', - '12/12', - '13/12', - '14/12', - '15/12', - '16/12', - '17/12' - ], + labels: resultSearch?.topData.map(i => i.name), datasets: [ { - data: [275, 90, 190, 205, 125, 85, 55, 87, 127, 150, 230, 280, 190], + data: resultSearch?.topData.map(i => i.value), backgroundColor: '#00bcd4', borderColor: '#00bcd4', barThickness: 15 @@ -173,11 +213,11 @@ export default function FlightPerformanceContainer({ } }, data2 = { - labels: ['PA0001', 'PA0002', 'PA0003', 'PA0004', 'PA0005'], + labels: resultSearch?.graphData.map(i => i.name), datasets: [ { - labels: ['PA0001', 'PA0002', 'PA0003', 'PA0004', 'PA0005'], - data: [10, 20, 30, 40, 80], + labels: resultSearch?.graphData.map(i => i.name), + data: resultSearch?.graphData.map(i => i.value), // 레드버전 // backgroundColor: [ // '#ffe8d1', @@ -331,13 +371,13 @@ export default function FlightPerformanceContainer({ ) } > - - - @@ -359,7 +399,9 @@ export default function FlightPerformanceContainer({ - {searchType.category} 통계 + + {handlerTitleName(searchType.category)} 통계 +
@@ -465,7 +507,9 @@ export default function FlightPerformanceContainer({ - {searchType.category} TOP5 + + {handlerTitleName(searchType.category)} TOP5 +
diff --git a/src/navigation/statistics/index.js b/src/navigation/statistics/index.js index a42eb80..bcfcce7 100644 --- a/src/navigation/statistics/index.js +++ b/src/navigation/statistics/index.js @@ -20,6 +20,6 @@ export default [ id: 'statistics_001_03', type: 'item', title: '비행 실적', - navLink: '/statistics/performance' + navLink: '/statistics/result' } ]; diff --git a/src/router/routes/RouteStatistics.js b/src/router/routes/RouteStatistics.js index d0a4deb..f3a4fcb 100644 --- a/src/router/routes/RouteStatistics.js +++ b/src/router/routes/RouteStatistics.js @@ -12,10 +12,8 @@ const RouteStatistics = [ ) }, { - path: '/statistics/performance', - component: lazy(() => - import('../../views/statistics/FlightPerformanceView') - ) + path: '/statistics/result', + component: lazy(() => import('../../views/statistics/FlightResultView')) } ]; diff --git a/src/views/statistics/FlightPerformanceView.js b/src/views/statistics/FlightPerformanceView.js deleted file mode 100644 index 3d12853..0000000 --- a/src/views/statistics/FlightPerformanceView.js +++ /dev/null @@ -1,8 +0,0 @@ -import '../../assets/css/custom.css'; -import '@styles/react/libs/flatpickr/flatpickr.scss'; -import '@styles/react/libs/tables/react-dataTable-component.scss'; -import FlightPerformanceContainer from '../../containers/statistics/FlightPerformanceContainer'; - -export default function FlightPerformanceView() { - return ; -} diff --git a/src/views/statistics/FlightResultView.js b/src/views/statistics/FlightResultView.js new file mode 100644 index 0000000..4e589a5 --- /dev/null +++ b/src/views/statistics/FlightResultView.js @@ -0,0 +1,8 @@ +import '../../assets/css/custom.css'; +import '@styles/react/libs/flatpickr/flatpickr.scss'; +import '@styles/react/libs/tables/react-dataTable-component.scss'; +import FlightResultContainer from '../../containers/statistics/FlightResultContainer'; + +export default function FlightResultView() { + return ; +} From 0672a547b1d31de359842f396af581a53a4fd492 Mon Sep 17 00:00:00 2001 From: hhjk00 Date: Mon, 13 Nov 2023 16:32:43 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=EB=B9=84=ED=96=89=20=EC=8B=A4=EC=A0=81=20a?= =?UTF-8?q?pi=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/statistics/actions/index.ts | 34 ++++++++++++-- src/modules/statistics/apis/index.ts | 26 ++++++++-- src/modules/statistics/models/index.ts | 49 +++++++++---------- src/modules/statistics/reducers/index.ts | 16 +++++++ src/modules/statistics/sagas/index.ts | 60 +++++++++++++++++++++++- 5 files changed, 149 insertions(+), 36 deletions(-) diff --git a/src/modules/statistics/actions/index.ts b/src/modules/statistics/actions/index.ts index 54357b7..50a2e4a 100644 --- a/src/modules/statistics/actions/index.ts +++ b/src/modules/statistics/actions/index.ts @@ -1,6 +1,6 @@ import { AxiosError } from 'axios'; import { createAsyncAction, ActionType } from 'typesafe-actions'; -import { Flight, FlightSearch, FlightSearchRq } from '../models'; +import { IStcsRs, IStcsSearchRq, IStcsSearchRs } from '../models'; // 비행 통계 (비행시간, 비행거리, 비행횟수) const FLIGHT_STCS_REQUEST = 'statistics/flight/FLIGHT_STCS_REQUEST'; @@ -15,21 +15,47 @@ const FLIGHT_STCS_SEARCH_SUCCESS = const FLIGHT_STCS_SEARCH_FAILURE = 'statistics/flight/FLIGHT_STCS_SEARCH_FAILURE'; +// 비행 실적 통계 (비행실적, 비행계획, 비행승인) +const RESULT_STCS_REQUEST = 'statistics/flight/RESULT_STCS_REQUEST'; +const RESULT_STCS_SUCCESS = 'statistics/flight/RESULT_STCS_SUCCESS'; +const RESULT_STCS_FAILURE = 'statistics/flight/RESULT_STCS_FAILURE'; + +// 비행 실적 통계 카테고리별 검색 +const RESULT_STCS_SEARCH_REQUEST = 'statistics/RESULT_STCS_SEARCH_REQUEST'; +const RESULT_STCS_SEARCH_SUCCESS = + 'statistics/flight/RESULT_STCS_SEARCH_SUCCESS'; +const RESULT_STCS_SEARCH_FAILURE = + 'statistics/flight/RESULT_STCS_SEARCH_FAILURE'; + export const FLIGHT_STCS = createAsyncAction( FLIGHT_STCS_REQUEST, FLIGHT_STCS_SUCCESS, FLIGHT_STCS_FAILURE -)(); +)(); export const FLIGHT_STCS_SEARCH = createAsyncAction( FLIGHT_STCS_SEARCH_REQUEST, FLIGHT_STCS_SEARCH_SUCCESS, FLIGHT_STCS_SEARCH_FAILURE -)(); +)(); + +export const RESULT_STCS = createAsyncAction( + RESULT_STCS_REQUEST, + RESULT_STCS_SUCCESS, + RESULT_STCS_FAILURE +)(); + +export const RESULT_STCS_SEARCH = createAsyncAction( + RESULT_STCS_SEARCH_REQUEST, + RESULT_STCS_SEARCH_SUCCESS, + RESULT_STCS_SEARCH_FAILURE +)(); const actions = { FLIGHT_STCS, - FLIGHT_STCS_SEARCH + FLIGHT_STCS_SEARCH, + RESULT_STCS, + RESULT_STCS_SEARCH }; export type StatisticsAction = ActionType; diff --git a/src/modules/statistics/apis/index.ts b/src/modules/statistics/apis/index.ts index af20220..5119879 100644 --- a/src/modules/statistics/apis/index.ts +++ b/src/modules/statistics/apis/index.ts @@ -1,12 +1,12 @@ import axios from '../../utils/customAxiosUtil'; import qs from 'qs'; -import { FlightSearchRq } from '../models'; +import { IStcsSearchRq } from '../models'; -export const stcsAPI = { +export const statisticsAPI = { flight: async () => { return await axios.get('/api/main/statistics/flight-static'); }, - flightSearch: async (data: FlightSearchRq) => { + flightSearch: async (data: IStcsSearchRq) => { const { type } = data; const params = {}; Object.keys(data).forEach(i => { @@ -20,5 +20,25 @@ export const stcsAPI = { }); return await axios.get(`api/main/statistics/flight/${type}${queryString}`); + }, + result: async () => { + return await axios.get('/api/main/statistics/flight/result-static'); + }, + resultSearch: async (data: IStcsSearchRq) => { + const { type } = data; + const params = {}; + Object.keys(data).forEach(i => { + if (data[i] && i !== 'type') { + params[`${i}`] = data[i]; + } + }); + const queryString = qs.stringify(params, { + addQueryPrefix: true, + arrayFormat: 'repeat' + }); + + return await axios.get( + `/api/main/statistics/flight/result/${type}${queryString}` + ); } }; diff --git a/src/modules/statistics/models/index.ts b/src/modules/statistics/models/index.ts index 7a066ba..5d90bb1 100644 --- a/src/modules/statistics/models/index.ts +++ b/src/modules/statistics/models/index.ts @@ -1,46 +1,41 @@ export interface IStatisticsState { - flight: Flight; - flightSearch: FlightSearch; + flight: IStcsRs[]; + flightSearch: IStcsSearchRs; + result: IStcsRs[]; + resultSearch: IStcsSearchRs; } -export interface Flight { - count: number; - data: { - name: string; - year: string; - month: string; - day: string; - }[]; +export interface IStcsRs { + name: string; + year: string; + month: string; + day: string; } -export interface FlightSearch { - count: number; - data: { - graphData: SearchData[]; - topData: SearchData[]; - }; +export interface IStcsSearchRs { + graphData: IStcsSearchData[]; + topData: IStcsSearchData[]; } -export interface SearchData { +export interface IStcsSearchData { name: string; value: number; } -export interface FlightSearchRq { +export interface IStcsSearchRq { cate: string; date: string; type: string; } export const initialState = { - flight: { - count: 0, - data: [] - }, + flight: [], flightSearch: { - count: 0, - data: { - graphData: [], - topData: [] - } + graphData: [], + topData: [] + }, + result: [], + resultSearch: { + graphData: [], + topData: [] } }; diff --git a/src/modules/statistics/reducers/index.ts b/src/modules/statistics/reducers/index.ts index ecad560..8db03e2 100644 --- a/src/modules/statistics/reducers/index.ts +++ b/src/modules/statistics/reducers/index.ts @@ -21,4 +21,20 @@ export const statisticsReducer = createReducer< const data = action.payload; draft.flightSearch = data || state.flightSearch; }) + ) + + // 비행 실적 통계 (비행실적, 비행계획, 비행승인) + .handleAction(Actions.RESULT_STCS.success, (state, action) => + produce(state, draft => { + const data = action.payload; + draft.result = data || state.result; + }) + ) + + // 비행 실적 통계 카테고리별 검색 + .handleAction(Actions.RESULT_STCS_SEARCH.success, (state, action) => + produce(state, draft => { + const data = action.payload; + draft.resultSearch = data || state.resultSearch; + }) ); diff --git a/src/modules/statistics/sagas/index.ts b/src/modules/statistics/sagas/index.ts index eb616a0..d03a88b 100644 --- a/src/modules/statistics/sagas/index.ts +++ b/src/modules/statistics/sagas/index.ts @@ -9,7 +9,7 @@ function* flightStcsSaga( ) { try { const payload = action.payload; - const res = yield call(Apis.stcsAPI.flight); + const res = yield call(Apis.statisticsAPI.flight); const { data, errorCode } = res; if (errorCode) { @@ -36,7 +36,7 @@ function* flightStcsSearchSaga( ) { try { const payload = action.payload; - const res = yield call(Apis.stcsAPI.flightSearch, payload); + const res = yield call(Apis.statisticsAPI.flightSearch, payload); const { data, errorCode } = res; if (errorCode) { @@ -58,7 +58,63 @@ function* flightStcsSearchSaga( } } +function* resultStcsSaga( + action: ActionType +) { + try { + const payload = action.payload; + const res = yield call(Apis.statisticsAPI.result); + const { data, errorCode } = res; + + if (errorCode) { + // 오류메시지 호출 + yield put( + MessageActions.IS_ERROR({ + errorCode: errorCode, + errorMessage: '처리중 오류가 발생하였습니다', + isHistoryBack: false, + isRefresh: false + }) + ); + + return; + } + yield put(Actions.RESULT_STCS.success(data)); + } catch (error) { + yield put(Actions.RESULT_STCS.failure(error)); + } +} + +function* resultStcsSearchSaga( + action: ActionType +) { + try { + const payload = action.payload; + const res = yield call(Apis.statisticsAPI.resultSearch, payload); + const { data, errorCode } = res; + + if (errorCode) { + // 오류메시지 호출 + yield put( + MessageActions.IS_ERROR({ + errorCode: errorCode, + errorMessage: '처리중 오류가 발생하였습니다', + isHistoryBack: false, + isRefresh: false + }) + ); + + return; + } + yield put(Actions.RESULT_STCS_SEARCH.success(data)); + } catch (error) { + yield put(Actions.RESULT_STCS_SEARCH.failure(error)); + } +} + export function* statisticsSaga() { yield takeEvery(Actions.FLIGHT_STCS.request, flightStcsSaga); yield takeEvery(Actions.FLIGHT_STCS_SEARCH.request, flightStcsSearchSaga); + yield takeEvery(Actions.RESULT_STCS.request, resultStcsSaga); + yield takeEvery(Actions.RESULT_STCS_SEARCH.request, resultStcsSearchSaga); }