Browse Source

메인 대시보드(비행계획, 비행건수, 비정상상황)완료

pull/2/head
김장현 10 months ago
parent
commit
ba0559f055
  1. 203
      src/components/dashboard/DashboardGroupList.js
  2. 148
      src/components/dashboard/DashboardStcsArea.js
  3. 175
      src/components/dashboard/DashboardStcsDay.js
  4. 99
      src/components/dashboard/DroneFlightSchedule.js
  5. 86
      src/containers/main/dash/MainDashContainer.js
  6. 19
      src/modules/main/dash/actions/mainDashAction.ts
  7. 13
      src/modules/main/dash/apis/mainDashApi.ts
  8. 45
      src/modules/main/dash/models/mainDashModel.ts
  9. 7
      src/modules/main/dash/reducers/mainDashReducer.ts
  10. 53
      src/modules/main/dash/sagas/mainDashSaga.ts

203
src/components/dashboard/DashboardGroupList.js

@ -1,34 +1,193 @@
import { Plus } from 'react-feather'; import { Plus } from 'react-feather';
import { Card, CardBody, CardHeader, CardTitle, Table } from 'reactstrap'; import { Card, CardBody, CardHeader, CardTitle } from 'reactstrap';
import { GridDatabase } from '../../components/crud/grid/GridDatatable';
import { EDateType } from '../../modules/main/dash/models/mainDashModel.ts';
import { IoIosArrowRoundDown, IoIosArrowRoundUp } from 'react-icons/io';
export const DashboardGroupList = props => { const titles = {
dailyFlightPlan: '일일 비행계획 현황',
dailyFlightCount: '일일 비행건수 현황',
dailyFlightWarn: '일일 비정상상황 현황'
};
const columns = {
dailyFlightPlan: [
{
id: 'dateType',
name: '구분',
minWidth: '50px',
center: true,
cell: (row, i) => <div>{EDateType[`${row.dateType}`]}</div>
},
{
id: 'plan',
name: '제출',
minWidth: '50px',
center: true,
cell: (row, i) => <div>{row.plan}</div>
},
{
id: 'aprvn',
name: '승인',
minWidth: '50px',
center: true,
cell: row => {
return <div>{row.aprvn}</div>;
}
},
{
id: 'count',
name: '합계',
minWidth: '50px',
center: true,
cell: row => {
return <div>{row.count}</div>;
}
},
{
id: 'note',
name: '비고',
left: true,
cell: row => {
return (
<div>
{row.note >= 0 ? (
<IoIosArrowRoundUp color='red' />
) : (
<IoIosArrowRoundDown color='blue' />
)}
{Math.sqrt(Math.pow(Math.floor(row.note), 2))}%
</div>
);
}
}
],
dailyFlightCount: [
{
id: 'dateType',
name: '구분',
minWidth: '50px',
center: true,
cell: (row, i) => <div>{EDateType[`${row.dateType}`]}</div>
},
{
id: 'flightPlan',
name: '계획',
minWidth: '50px',
center: true,
cell: (row, i) => <div>{row.flightPlan}</div>
},
{
id: 'completeFlight',
name: '비행완료',
center: true,
cell: row => {
return <div>{row.completeFlight}</div>;
}
},
{
id: 'notFlight',
name: '미비행',
center: true,
cell: row => {
return <div>{row.notFlight}</div>;
}
},
{
id: 'note',
name: '비고',
left: true,
cell: row => {
return (
<div>
{row.note >= 0 ? (
<IoIosArrowRoundUp color='red' />
) : (
<IoIosArrowRoundDown color='blue' />
)}
{Math.sqrt(Math.pow(Math.floor(row.note), 2))}%
</div>
);
}
}
],
dailyFlightWarn: [
{
id: 'dateType',
name: '구분',
minWidth: '80px',
center: true,
cell: row => <div>{EDateType[`${row.dateType}`]}</div>
},
{
id: 'plan',
name: '비행경로이탈',
minWidth: '120px',
center: true,
cell: (row, i) => <div>{row.plan}</div>
},
{
id: 'altitude',
name: '비정상 고도',
minWidth: '105px',
center: true,
cell: row => {
return <div>{row.altitude}</div>;
}
},
{
id: 'crash',
name: '충돌위험',
minWidth: '95px',
center: true,
cell: row => {
return <div>{row.crash}</div>;
}
},
{
id: 'count',
name: '합계',
minWidth: '80px',
center: true,
cell: row => {
return <div>{row.count}</div>;
}
},
{
id: 'note',
name: '비고',
left: true,
cell: row => {
return (
<div>
{row.note >= 0 ? (
<IoIosArrowRoundUp color='red' />
) : (
<IoIosArrowRoundDown color='blue' />
)}
{Math.sqrt(Math.pow(Math.floor(row.note), 2))}%
</div>
);
}
}
]
};
export const DashboardGroupList = ({ title, pageMove, data }) => {
return ( return (
<Card> <Card>
<CardHeader className=''> <CardHeader className=''>
<CardTitle tag='h4'>그룹 정보</CardTitle> <CardTitle tag='h4'>{titles[title]}</CardTitle>
<button onClick={e => props.pageMove()}> <button onClick={e => pageMove()}>
<Plus /> <Plus />
</button> </button>
</CardHeader> </CardHeader>
<CardBody> <CardBody>
<Table striped responsive className='pal-table'> <GridDatabase
<thead> data={data}
<tr> count={data.length}
<th>그룹 </th> columns={columns[title]}
<th>생성일시</th> />
</tr>
</thead>
<tbody>
{props.data?.map((item, index) => {
return (
<tr key={index}>
<td>{item.groupNm}</td>
<td>{item.createDt}</td>
</tr>
);
})}
</tbody>
</Table>
</CardBody> </CardBody>
</Card> </Card>
); );

148
src/components/dashboard/DashboardStcsArea.js

@ -1,32 +1,53 @@
import { ko } from 'date-fns/esm/locale'; import { ko } from 'date-fns/esm/locale';
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Plus } from 'react-feather';
import { Doughnut } from 'react-chartjs-2'; import { Doughnut } from 'react-chartjs-2';
import DatePicker from 'react-datepicker'; import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css'; import 'react-datepicker/dist/react-datepicker.css';
import { Calendar } from 'react-feather'; import { Calendar } from 'react-feather';
import { Card, CardBody, CardHeader, CardTitle } from 'reactstrap'; import { Card, CardBody, CardHeader, CardTitle } from 'reactstrap';
import { useSkin } from '../../utility/hooks/useSkin';
const tooltipShadow = 'rgba(0, 0, 0, 0.25)';
const warningLightColor = '#FDAC34';
const successColorShade = '#28dac6';
const primaryColorShade = '#836AF9';
const yellowColor = '#ffe800';
const blueColor = '#2c9aff';
const options = {
responsive: true,
maintainAspectRatio: false,
responsiveAnimationDuration: 500,
cutoutPercentage: 60,
legend: { display: false },
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;
// }
},
// Updated default tooltip UI
shadowOffsetX: 1,
shadowOffsetY: 1,
shadowBlur: 8,
shadowColor: tooltipShadow,
backgroundColor: '#fff',
titleFontColor: '#000',
bodyFontColor: '#000'
}
};
const titles = {
droneStatus: '드론 현황',
flightsRegion: 'TOP5 지역 별 비행횟수 통계'
};
export const DashboardStcsArea = props => { export const DashboardStcsArea = props => {
const [chartData, setChartData] = useState({}); const [chartData, setChartData] = useState({});
const [skin, setSkin] = useSkin(),
labelColor = skin === 'dark' ? '#b4b7bd' : '#6e6b7b',
tooltipShadow = 'rgba(0, 0, 0, 0.25)',
gridLineColor = 'rgba(200, 200, 200, 0.2)',
lineChartPrimary = '#666ee8',
lineChartDanger = '#ff4961',
warningColorShade = '#ffe802',
warningLightColor = '#FDAC34',
successColorShade = '#28dac6',
primaryColorShade = '#836AF9',
infoColorShade = '#299AFF',
yellowColor = '#ffe800',
greyColor = '#4F5D70',
blueColor = '#2c9aff',
blueLightColor = '#84D0FF',
greyLightColor = '#EDF1F4';
const arrColors = [ const arrColors = [
successColorShade, successColorShade,
warningLightColor, warningLightColor,
@ -43,32 +64,6 @@ export const DashboardStcsArea = props => {
'blueColor' 'blueColor'
]; ];
const options = {
responsive: true,
maintainAspectRatio: false,
responsiveAnimationDuration: 500,
cutoutPercentage: 60,
legend: { display: false },
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;
// }
},
// Updated default tooltip UI
shadowOffsetX: 1,
shadowOffsetY: 1,
shadowBlur: 8,
shadowColor: tooltipShadow,
backgroundColor: '#fff',
titleFontColor: '#000',
bodyFontColor: '#000'
}
};
const chartDataInit = () => { const chartDataInit = () => {
let arrArea = []; let arrArea = [];
let arrValue = []; let arrValue = [];
@ -98,7 +93,7 @@ export const DashboardStcsArea = props => {
return ( return (
<Card> <Card>
<CardHeader className='d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row flex-column'> <CardHeader className='d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row flex-column'>
<CardTitle tag='h4'>TOP5 지역 비행횟수 통계</CardTitle> <CardTitle tag='h4'>{titles[`${props.title}`]}</CardTitle>
{/* <div className='d-flex align-items-center'> {/* <div className='d-flex align-items-center'>
<Calendar size={14} /> <Calendar size={14} />
<Flatpickr <Flatpickr
@ -110,25 +105,54 @@ export const DashboardStcsArea = props => {
className='form-control flat-picker bg-transparent border-0 shadow-none' className='form-control flat-picker bg-transparent border-0 shadow-none'
/> />
</div> */} </div> */}
<div className='datepicker-border-sm'> {props.title === 'flightsRegion' && (
<div className='datepicker-custom'> <>
<Calendar size={14} /> <div className='datepicker-border-sm'>
<DatePicker <div className='datepicker-custom'>
locale={ko} <Calendar size={14} />
selected={props.startDate} <DatePicker
onChange={date => props.setStartDate(date)} locale={ko}
dateFormat='yyy / MMMM' selected={props.startDate}
showMonthYearPicker onChange={date => props.setStartDate(date)}
showFullMonthYearPicker dateFormat='yyy / MMMM'
showFourColumnMonthYearPicker showMonthYearPicker
className='form-control bg-transparent border-0 shadow-none' showFullMonthYearPicker
/> showFourColumnMonthYearPicker
</div> className='form-control bg-transparent border-0 shadow-none'
</div> />
</div>
</div>
<button onClick={e => {}}>
<Plus />
</button>
</>
)}
</CardHeader> </CardHeader>
<CardBody> <CardBody>
<div style={{ height: '275px' }}> <div style={{ height: '275px' }}>
<Doughnut data={chartData} options={options} height={275} /> <Doughnut
data={chartData}
options={options}
height={275}
plugins={{
afterDraw: function (chart) {
let ctx = chart.chart.ctx;
let width = chart.chart.width;
let height = chart.chart.height;
chart.clear();
ctx.save();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(
'표시할 데이터가 없습니다.',
width / 2,
height / 2
);
ctx.restore();
}
}}
/>
</div> </div>
<div className='doughnut-chart-list'> <div className='doughnut-chart-list'>
{props.data?.map((item, index) => { {props.data?.map((item, index) => {

175
src/components/dashboard/DashboardStcsDay.js

@ -1,95 +1,83 @@
import 'react-datepicker/dist/react-datepicker.css';
import { ko } from 'date-fns/esm/locale'; import { ko } from 'date-fns/esm/locale';
import React, { useEffect, useState } from 'react'; import { Plus } from 'react-feather';
import { useEffect, useState } from 'react';
import { Bar } from 'react-chartjs-2'; import { Bar } from 'react-chartjs-2';
import DatePicker from 'react-datepicker'; import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { Calendar } from 'react-feather'; import { Calendar } from 'react-feather';
import { Card, CardBody, CardHeader, CardTitle } from 'reactstrap'; import { Card, CardBody, CardHeader, CardTitle } from 'reactstrap';
import { useSkin } from '../../utility/hooks/useSkin';
export const DashboardStcsDay = props => { const tooltipShadow = 'rgba(0, 0, 0, 0.25)';
const [chartData, setChartData] = useState({}); const gridLineColor = 'rgba(200, 200, 200, 0.2)';
const successColorShade = '#28dac6';
const [skin, setSkin] = useSkin(), const options = {
labelColor = skin === 'dark' ? '#b4b7bd' : '#6e6b7b', elements: {
tooltipShadow = 'rgba(0, 0, 0, 0.25)', rectangle: {
gridLineColor = 'rgba(200, 200, 200, 0.2)', borderWidth: 2,
lineChartPrimary = '#666ee8', borderSkipped: 'bottom'
lineChartDanger = '#ff4961', }
warningColorShade = '#ffe802', },
warningLightColor = '#FDAC34', responsive: true,
successColorShade = '#28dac6', maintainAspectRatio: false,
primaryColorShade = '#836AF9', responsiveAnimationDuration: 500,
infoColorShade = '#299AFF', legend: {
yellowColor = '#ffe800', display: false
greyColor = '#4F5D70', },
blueColor = '#2c9aff',
blueLightColor = '#84D0FF',
greyLightColor = '#EDF1F4';
const options = { tooltips: {
elements: { // Updated default tooltip UI
rectangle: { shadowOffsetX: 1,
borderWidth: 2, shadowOffsetY: 1,
borderSkipped: 'bottom' shadowBlur: 8,
} shadowColor: tooltipShadow,
}, backgroundColor: '#fff',
responsive: true, titleFontColor: '#000',
maintainAspectRatio: false, bodyFontColor: '#000'
responsiveAnimationDuration: 500, },
legend: { scales: {
display: false xAxes: [
}, {
tooltips: { display: true,
// Updated default tooltip UI gridLines: {
shadowOffsetX: 1,
shadowOffsetY: 1,
shadowBlur: 8,
shadowColor: tooltipShadow,
backgroundColor: '#fff',
titleFontColor: '#000',
bodyFontColor: '#000'
},
scales: {
xAxes: [
{
display: true, display: true,
gridLines: { color: gridLineColor,
display: true, zeroLineColor: gridLineColor
color: gridLineColor, },
zeroLineColor: gridLineColor scaleLabel: {
}, display: false
scaleLabel: { },
display: false ticks: {
}, fontColor: '#6e6b7b'
ticks: {
fontColor: labelColor
}
} }
], }
yAxes: [ ],
{ yAxes: [
display: true, {
gridLines: { display: true,
color: gridLineColor, gridLines: {
zeroLineColor: gridLineColor color: gridLineColor,
}, zeroLineColor: gridLineColor
ticks: { },
stepSize: 1, ticks: {
// min: 0, stepSize: 1,
// max: 400, // min: 0,
fontColor: labelColor // max: 400,
} fontColor: '#6e6b7bs'
} }
] }
} ]
}; }
};
export const DashboardStcsDay = ({ startDate, setStartDate, data }) => {
const [chartData, setChartData] = useState({});
const chartDataInit = () => { const chartDataInit = () => {
let arrDay = []; let arrDay = [];
let arrValue = []; let arrValue = [];
props.data?.map(item => { data?.map(item => {
arrDay.push(item.typeCd); arrDay.push(item.typeCd);
arrValue.push(item.count); arrValue.push(item.count);
}); });
@ -110,7 +98,7 @@ export const DashboardStcsDay = props => {
useEffect(() => { useEffect(() => {
chartDataInit(); chartDataInit();
}, [props.data]); }, [data]);
return ( return (
<Card> <Card>
@ -121,8 +109,8 @@ export const DashboardStcsDay = props => {
<Calendar size={14} /> <Calendar size={14} />
<DatePicker <DatePicker
locale={ko} locale={ko}
selected={props.startDate} selected={startDate}
onChange={date => props.setStartDate(date)} onChange={date => setStartDate(date)}
dateFormat='yyy / MMMM' dateFormat='yyy / MMMM'
showMonthYearPicker showMonthYearPicker
showFullMonthYearPicker showFullMonthYearPicker
@ -131,10 +119,37 @@ export const DashboardStcsDay = props => {
/> />
</div> </div>
</div> </div>
<button onClick={e => {}}>
<Plus />
</button>
</CardHeader> </CardHeader>
<CardBody> <CardBody>
<div style={{ height: '400px' }}> <div style={{ height: '400px' }}>
<Bar data={chartData} options={options} height={400} /> <Bar
data={chartData}
options={options}
height={400}
plugins={{
afterDraw: function (chart) {
if (data.length <= 0) {
let ctx = chart.chart.ctx;
let width = chart.chart.width;
let height = chart.chart.height;
chart.clear();
ctx.save();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(
'표시할 데이터가 없습니다.',
width / 2,
height / 2
);
ctx.restore();
}
}
}}
/>
</div> </div>
</CardBody> </CardBody>
</Card> </Card>

99
src/components/dashboard/DroneFlightSchedule.js

@ -0,0 +1,99 @@
import { Plus } from 'react-feather';
import { Card, CardBody, CardHeader, CardTitle, Input, Col } from 'reactstrap';
import { GridDatabase } from '../../components/crud/grid/GridDatatable';
const columns = [
{
id: 'a',
name: '그룹 몇',
minWidth: '50px',
center: true,
cell: (row, i) => <div>{row.a}</div>
},
{
id: 'b',
name: '조종자',
minWidth: '50px',
center: true,
cell: (row, i) => <div>{row.b}</div>
},
{
id: 'c',
name: '기체 신고 번호',
minWidth: '50px',
center: true,
cell: row => {
return <div>{row.c}</div>;
}
},
{
id: 'd',
name: '비행 시작 시간',
minWidth: '50px',
center: true,
cell: row => {
return <div>{row.d}</div>;
}
},
{
id: 'e',
name: '비행 종료 시간',
left: true,
cell: row => {
return <div>{row.e}</div>;
}
},
{
id: 'e',
name: '총 예상 비행시간',
left: true,
cell: row => {
return <div>{row.f}</div>;
}
},
{
id: 'e',
name: '상태',
left: true,
cell: row => {
return <div>{row.g}</div>;
}
}
];
const dummyData = [
{
a: '공항공사',
b: '홍길동',
c: 'PA123456',
d: '2023-11-11 10:00',
e: '2023-11-11 11:00',
f: '01:00',
g: '비행완료'
}
];
export default function DroneFlightSchedule({ pageMove, data }) {
return (
<Card>
<CardHeader className=''>
<CardTitle tag='h4'>드론 비행운항 목록</CardTitle>
<Col className='list-input' xs='2'>
<Input type='select'>
<option>그룹선택</option>
</Input>
<button onClick={e => {}}>
<Plus />
</button>
</Col>
</CardHeader>
<CardBody>
<GridDatabase
data={dummyData}
count={dummyData.length}
columns={columns}
/>
</CardBody>
</Card>
);
}

86
src/containers/main/dash/MainDashContainer.js

@ -1,28 +1,32 @@
import moment from 'moment'; import { useEffect, useState, useCallback } from 'react';
import { useEffect, useState } from 'react';
import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import moment from 'moment';
import { Col, Row } from 'reactstrap'; import { Col, Row } from 'reactstrap';
import { DashboardDronList } from '../../../components/dashboard/DashboardDronList'; import DroneFlightSchedule from '../../../components/dashboard/DroneFlightSchedule';
import { DashboardGroupList } from '../../../components/dashboard/DashboardGroupList'; import { DashboardGroupList } from '../../../components/dashboard/DashboardGroupList';
import { DashboardMenu } from '../../../components/dashboard/DashboardMenu';
import { DashboardStcsArea } from '../../../components/dashboard/DashboardStcsArea'; import { DashboardStcsArea } from '../../../components/dashboard/DashboardStcsArea';
import { DashboardStcsDay } from '../../../components/dashboard/DashboardStcsDay'; import { DashboardStcsDay } from '../../../components/dashboard/DashboardStcsDay';
import * as Actions from '../../../modules/main/dash/actions/mainDashAction'; import * as Actions from '../../../modules/main/dash/actions/mainDashAction';
import '@styles/react/libs/flatpickr/flatpickr.scss';
import '@styles/react/libs/tables/react-dataTable-component.scss';
import '../../../assets/css/custom.css';
export const MainDashContainer = () => { export const MainDashContainer = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { stcsDayList, stcsAreaList, groupList, dronList } = useSelector( /*
state => state.mainDashState stcsDayList : 비행횟수
stcsAreaList: TOP 5 지역 비행횟수
*/
const [dashboardData] = useSelector(
state => [state.mainDashState.dashboardData],
shallowEqual
); );
const history = useHistory();
const { user } = useSelector(state => state.authState, shallowEqual); const { user } = useSelector(state => state.authState, shallowEqual);
const [dayStartDate, setDayStartDate] = useState(new Date()); const [dayStartDate, setDayStartDate] = useState(new Date());
const [areaStartDate, setAreaStartDate] = useState(new Date()); const [areaStartDate, setAreaStartDate] = useState(new Date());
const history = useHistory();
const handlerStcsDaySearch = date => { const handlerStcsDaySearch = date => {
dispatch( dispatch(
@ -56,10 +60,13 @@ export const MainDashContainer = () => {
); );
}; };
const handlerStcsDayParam = date => { const handlerStcsDayParam = useCallback(
setDayStartDate(date); date => {
handlerStcsDaySearch(date); setDayStartDate(date);
}; handlerStcsDaySearch(date);
},
[dayStartDate]
);
const handlerStcsAreaParam = date => { const handlerStcsAreaParam = date => {
setAreaStartDate(date); setAreaStartDate(date);
@ -70,43 +77,48 @@ export const MainDashContainer = () => {
history.push('/basis/dron/index'); history.push('/basis/dron/index');
}; };
const handlerGroupDetail = () => { const handlerGroupDetail = useCallback(val => {
history.push('/basis/group/index'); history.push('/basis/group/index');
}; }, []);
const movePage = url => { const movePage = url => {
history.push(url); history.push(url);
}; };
useEffect(() => { useEffect(() => {
handlerStcsDaySearch(dayStartDate); dispatch(
handlerStcsAreaSearch(areaStartDate); Actions.DASHBOARD_DATA.request({
handlerGroupSearch(); stcsDay: moment(dayStartDate).format('YYYY-MM')
handlerDronSearch(); })
);
// handlerStcsDaySearch(dayStartDate);
// handlerStcsAreaSearch(areaStartDate);
// handlerGroupSearch();
// handlerDronSearch();
}, []); }, []);
useEffect(() => {}, [stcsDayList]);
return ( return (
<div className='main-dashboard'> <div className='main-dashboard'>
{/* <DashboardMenu movePage={movePage} /> */}
<div className='dashboard-section'> <div className='dashboard-section'>
<Row> <Row>
<Col md={4}> <Col md={4}>
<DashboardGroupList <DashboardGroupList
data={groupList}
pageMove={handlerGroupDetail} pageMove={handlerGroupDetail}
title='dailyFlightPlan'
data={dashboardData?.dailyFlightPlan || []}
/> />
</Col> </Col>
<Col md={4}> <Col md={4}>
<DashboardGroupList <DashboardGroupList
data={groupList}
pageMove={handlerGroupDetail} pageMove={handlerGroupDetail}
title='dailyFlightCount'
data={dashboardData?.dailyFlightCount || []}
/> />
</Col> </Col>
<Col md={4}> <Col md={4}>
<DashboardGroupList <DashboardGroupList
data={groupList}
pageMove={handlerGroupDetail} pageMove={handlerGroupDetail}
title='dailyFlightWarn'
data={dashboardData?.dailyFlightWarn || []}
/> />
</Col> </Col>
</Row> </Row>
@ -114,18 +126,18 @@ export const MainDashContainer = () => {
<div className='dashboard-section'> <div className='dashboard-section'>
<Row> <Row>
<Col lg={8} md={12} className='dashboard-chart'> <Col lg={8} md={12} className='dashboard-chart'>
<DashboardStcsDay <DroneFlightSchedule pageMove={handlerGroupDetail} data={[]} />
startDate={dayStartDate}
setStartDate={handlerStcsDayParam}
data={stcsDayList}
/>
</Col> </Col>
<Col lg={4} md={12} className='dashboard-chart'> <Col lg={4} md={12} className='dashboard-chart'>
{
// 드론 현황
}
<DashboardStcsArea <DashboardStcsArea
startDate={areaStartDate} startDate={areaStartDate}
setStartDate={handlerStcsAreaParam} setStartDate={handlerStcsAreaParam}
data={stcsAreaList} // data={stcsAreaList}
title='droneStatus'
/> />
</Col> </Col>
</Row> </Row>
@ -136,15 +148,19 @@ export const MainDashContainer = () => {
<DashboardStcsDay <DashboardStcsDay
startDate={dayStartDate} startDate={dayStartDate}
setStartDate={handlerStcsDayParam} setStartDate={handlerStcsDayParam}
data={stcsDayList} data={dashboardData?.stcsDayList || []}
/> />
</Col> </Col>
<Col lg={4} md={12} className='dashboard-chart'> <Col lg={4} md={12} className='dashboard-chart'>
{
// top5 지역 별 바행횟수
}
<DashboardStcsArea <DashboardStcsArea
startDate={areaStartDate} startDate={areaStartDate}
setStartDate={handlerStcsAreaParam} setStartDate={handlerStcsAreaParam}
data={stcsAreaList} // data={stcsAreaList}
title='flightsRegion'
/> />
</Col> </Col>
</Row> </Row>

19
src/modules/main/dash/actions/mainDashAction.ts

@ -4,7 +4,9 @@ import {
DronListData, DronListData,
GroupListData, GroupListData,
StcsAreaData, StcsAreaData,
StcsDayData StcsDayData,
IDashBoardData,
IDashBoardRq
} from '../models/mainDashModel'; } from '../models/mainDashModel';
const STCS_DAY_REQUEST = 'main/dash/STCS_DAY_REQUEST'; const STCS_DAY_REQUEST = 'main/dash/STCS_DAY_REQUEST';
@ -23,11 +25,15 @@ const DRON_LIST_REQUEST = 'main/dash/DRON_LIST_REQUEST';
const DRON_LIST_SUCCESS = 'main/dash/DRON_LIST_SUCCESS'; const DRON_LIST_SUCCESS = 'main/dash/DRON_LIST_SUCCESS';
const DRON_LIST_FAILURE = 'main/dash/DRON_LIST_FAILURE'; const DRON_LIST_FAILURE = 'main/dash/DRON_LIST_FAILURE';
const DASHBOARD_DATA_REQUEST = 'main/dashboard/DATA_REQUEST';
const DASHBOARD_DATA_SUCCESS = 'main/dashboard/DATA_SUCCESS';
const DASHBOARD_DATA_FAILURE = 'main/dashboard/DATA_FAILURE';
export const STCS_DAY = createAsyncAction( export const STCS_DAY = createAsyncAction(
STCS_DAY_REQUEST, STCS_DAY_REQUEST,
STCS_DAY_SUCCESS, STCS_DAY_SUCCESS,
STCS_DAY_FAILURE STCS_DAY_FAILURE
)<string, { data: StcsDayData[] }, AxiosError>(); )<{ yyyymm: string }, { data: StcsDayData[] }, AxiosError>();
export const STCS_AREA = createAsyncAction( export const STCS_AREA = createAsyncAction(
STCS_AREA_REQUEST, STCS_AREA_REQUEST,
@ -47,11 +53,18 @@ export const DRON_LIST = createAsyncAction(
DRON_LIST_FAILURE DRON_LIST_FAILURE
)<number, { data: DronListData[] }, AxiosError>(); )<number, { data: DronListData[] }, AxiosError>();
export const DASHBOARD_DATA = createAsyncAction(
DASHBOARD_DATA_REQUEST,
DASHBOARD_DATA_SUCCESS,
DASHBOARD_DATA_FAILURE
)<IDashBoardRq, IDashBoardData, AxiosError>();
const actions = { const actions = {
STCS_DAY, STCS_DAY,
STCS_AREA, STCS_AREA,
GROUP_LIST, GROUP_LIST,
DRON_LIST DRON_LIST,
DASHBOARD_DATA
}; };
export type MainDashAction = ActionType<typeof actions>; export type MainDashAction = ActionType<typeof actions>;

13
src/modules/main/dash/apis/mainDashApi.ts

@ -1,12 +1,14 @@
import qs from 'qs'; import qs from 'qs';
import axios from '../../../utils/customAxiosUtil'; import axios from '../../../utils/customAxiosUtil';
import { IDashBoardRq } from '../models/mainDashModel';
export const mainDashAPI = { export const mainDashAPI = {
stcsDay: async (data: string) => { stcsDay: async (data: { yyyymm: string }) => {
const queryString = qs.stringify(data, { const queryString = qs.stringify(data, {
addQueryPrefix: true, addQueryPrefix: true,
arrayFormat: 'repeat' arrayFormat: 'repeat'
}); });
console.log(data);
return await axios.get(`api/main/dash/stcs/day${queryString}`); return await axios.get(`api/main/dash/stcs/day${queryString}`);
}, },
stcsArea: async (data: string) => { stcsArea: async (data: string) => {
@ -31,5 +33,14 @@ export const mainDashAPI = {
arrayFormat: 'repeat' arrayFormat: 'repeat'
}); });
return await axios.get(`api/main/dash/arcrft/list${queryString}`); return await axios.get(`api/main/dash/arcrft/list${queryString}`);
},
dailyFlightWarn: async () => {
return await axios.get('api/main/dash/current/flight-warn');
},
dailyFlightPlan: async () => {
return await axios.get('api/main/dash/current/flight-plan');
},
dailyFlightCount: async () => {
return await axios.get('api/main/dash/stcs/dailyflight');
} }
}; };

45
src/modules/main/dash/models/mainDashModel.ts

@ -3,6 +3,37 @@ export interface MainDashState {
stcsAreaList: StcsAreaData[] | undefined; stcsAreaList: StcsAreaData[] | undefined;
groupList: GroupListData[] | undefined; groupList: GroupListData[] | undefined;
dronList: DronListData[] | undefined; dronList: DronListData[] | undefined;
dashboardData: IDashBoardData | undefined;
}
export enum EDateType {
yesterday = '전일',
today = '금일',
tomorrow = '명일'
}
export interface IDailyFlightPlan {
dateType: string;
plan: number;
aprvn: number;
count: number;
note: number;
}
export interface IDailyFlightWarn {
dateType: string;
plan: number;
altitude: number;
crash: number;
count: number;
note: number;
}
export interface IDailyFlightCount {
dateType: string;
flightPlan: number;
completeFlight: number;
notFlight: number;
note: number;
} }
export interface StcsDayData { export interface StcsDayData {
@ -29,11 +60,23 @@ export interface DronListData {
groupNm: string; groupNm: string;
} }
export interface IDashBoardData {
stcsDayList: StcsDayData[];
dailyFlightWarn: IDailyFlightWarn[];
dailyFlightCount: IDailyFlightCount[];
dailyFlightPlan: IDailyFlightPlan[];
}
export interface IDashBoardRq {
stcsDay: string;
}
export const initMainDash = { export const initMainDash = {
stcsDayList: undefined, stcsDayList: undefined,
stcsAreaList: undefined, stcsAreaList: undefined,
groupList: undefined, groupList: undefined,
dronList: undefined dronList: undefined,
dashboardData: undefined
}; };
// laanc 승인 목록 검색 // laanc 승인 목록 검색

7
src/modules/main/dash/reducers/mainDashReducer.ts

@ -25,10 +25,15 @@ export const mainDahReducer = createReducer<
draft.groupList = data; draft.groupList = data;
}) })
) )
.handleAction(Actions.DRON_LIST.success, (state, action) => .handleAction(Actions.DRON_LIST.success, (state, action) =>
produce(state, draft => { produce(state, draft => {
const { data } = action.payload; const { data } = action.payload;
draft.dronList = data; draft.dronList = data;
}) })
)
.handleAction(Actions.DASHBOARD_DATA.success, (state, action) =>
produce(state, draft => {
const data = action.payload;
draft.dashboardData = { ...data };
})
); );

53
src/modules/main/dash/sagas/mainDashSaga.ts

@ -1,4 +1,4 @@
import { call, put, takeEvery } from '@redux-saga/core/effects'; import { call, put, takeEvery, all } from '@redux-saga/core/effects';
import { ActionType } from 'typesafe-actions'; import { ActionType } from 'typesafe-actions';
import * as MessageActions from '../../../comn/message/actions/comnMessageAction'; import * as MessageActions from '../../../comn/message/actions/comnMessageAction';
import * as Actions from '../actions/mainDashAction'; import * as Actions from '../actions/mainDashAction';
@ -7,6 +7,7 @@ import * as Apis from '../apis/mainDashApi';
function* listStcsDay(action: ActionType<typeof Actions.STCS_DAY.request>) { function* listStcsDay(action: ActionType<typeof Actions.STCS_DAY.request>) {
try { try {
const params = action.payload; const params = action.payload;
const res = yield call(Apis.mainDashAPI.stcsDay, params); const res = yield call(Apis.mainDashAPI.stcsDay, params);
const { data, count, errorCode, errorMessage } = res; const { data, count, errorCode, errorMessage } = res;
if (errorCode) { if (errorCode) {
@ -116,9 +117,59 @@ function* listDron(action: ActionType<typeof Actions.DRON_LIST.request>) {
} }
} }
function* dashboardData(
action: ActionType<typeof Actions.DASHBOARD_DATA.request>
) {
try {
const params = action.payload;
/*
stcsDayList:
dailyFlightPlan: 일일
dailyFlightCount: 일일
dailyFlighWarn: 일일
*/
const { stcsDayList, dailyFlighWarn, dailyFlightPlan, dailyFlightCount } =
yield all({
stcsDayList: call(Apis.mainDashAPI.stcsDay, { yyyymm: params.stcsDay }),
dailyFlighWarn: call(Apis.mainDashAPI.dailyFlightWarn),
dailyFlightPlan: call(Apis.mainDashAPI.dailyFlightPlan),
dailyFlightCount: call(Apis.mainDashAPI.dailyFlightCount)
});
// if (errorCode) {
// // 오류메시지 호출
// yield put(
// MessageActions.IS_ERROR({
// errorCode: errorCode,
// errorMessage: '처리중 오류가 발생하였습니다',
// isHistoryBack: false,
// isRefresh: false
// })
// );
// return;
// }
yield put(
Actions.DASHBOARD_DATA.success({
stcsDayList: stcsDayList.data,
dailyFlightWarn: dailyFlighWarn.data.slice(
0,
dailyFlightPlan.data.length - 1
),
dailyFlightCount: dailyFlightCount.data,
dailyFlightPlan: dailyFlightPlan.data
})
);
} catch (error) {
yield put(Actions.DASHBOARD_DATA.failure(error));
}
}
export function* mainDashSaga() { export function* mainDashSaga() {
yield takeEvery(Actions.STCS_DAY.request, listStcsDay); yield takeEvery(Actions.STCS_DAY.request, listStcsDay);
yield takeEvery(Actions.STCS_AREA.request, listStcsArea); yield takeEvery(Actions.STCS_AREA.request, listStcsArea);
yield takeEvery(Actions.GROUP_LIST.request, listGroup); yield takeEvery(Actions.GROUP_LIST.request, listGroup);
yield takeEvery(Actions.DRON_LIST.request, listDron); yield takeEvery(Actions.DRON_LIST.request, listDron);
yield takeEvery(Actions.DASHBOARD_DATA.request, dashboardData);
} }

Loading…
Cancel
Save