hhjk00
10 months ago
4 changed files with 505 additions and 0 deletions
@ -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 ( |
||||
<CustomMainLayout title={titleName}> |
||||
<div className='pal-card-box statistics'> |
||||
<div> |
||||
<Row> |
||||
<Col md='4'> |
||||
<div> |
||||
<table className='statistics-table'> |
||||
<tr> |
||||
<th rowSpan='2'> |
||||
<span> |
||||
<FcAlarmClock /> |
||||
</span> |
||||
<span>비행 실적</span> |
||||
<span>PA0001</span> |
||||
</th> |
||||
<td colSpan='3'> |
||||
<span className='date'>년</span> |
||||
<span className='date-data'>8일 10시간 35분 12초</span> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<span className='date'>월</span> |
||||
<span className='date-data'>1일 35분 12초</span> |
||||
</td> |
||||
<td> |
||||
<span className='date'>일</span> |
||||
<span className='date-data'>35분 12초</span> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</div> |
||||
</Col> |
||||
<Col md='4'> |
||||
<div> |
||||
<table className='statistics-table'> |
||||
<tr> |
||||
<th rowSpan='2'> |
||||
<span> |
||||
<FcWorkflow /> |
||||
</span> |
||||
<span>비행 계획</span> |
||||
<span>PA0002</span> |
||||
</th> |
||||
<td colSpan='3'> |
||||
<span className='date'>년</span> |
||||
<span className='date-data'>10,845m</span> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<span className='date'>월</span> |
||||
<span className='date-data'>1,201m</span> |
||||
</td> |
||||
<td> |
||||
<span className='date'>일</span> |
||||
<span className='date-data'>53m</span> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</div> |
||||
</Col> |
||||
<Col md='4'> |
||||
<div> |
||||
<table className='statistics-table'> |
||||
<tr> |
||||
<th rowSpan='2'> |
||||
<span> |
||||
<FcBarChart /> |
||||
</span> |
||||
<span>비행 승인</span> |
||||
<span>PA0002</span> |
||||
</th> |
||||
<td colSpan='3'> |
||||
<span className='date'>년</span> |
||||
<span className='date-data'>1,024,845건</span> |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td> |
||||
<span className='date'>월</span> |
||||
<span className='date-data'>111,201건</span> |
||||
</td> |
||||
<td> |
||||
<span className='date'>일</span> |
||||
<span className='date-data'>153건</span> |
||||
</td> |
||||
</tr> |
||||
</table> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<div> |
||||
<Row> |
||||
<Col> |
||||
<div className='mt-2 cont-ti d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>검색조건</h4> |
||||
</div> |
||||
{/* <div className='d-flex align-items-center'> |
||||
<Button.Ripple color='primary' size='sm'> |
||||
<Search size={16} /> |
||||
검색 |
||||
</Button.Ripple> |
||||
</div> */} |
||||
</div> |
||||
<Card> |
||||
<CardBody className='pal-card-body'> |
||||
<div className='search-cont'> |
||||
<dl> |
||||
<dt> |
||||
<div className='search-box'> |
||||
<div className='search-list-ti'>검색조건</div> |
||||
<div className='search-list'> |
||||
<div className='search-list-cont'> |
||||
<Row> |
||||
<Col className='list-input' md='4' sm='12'> |
||||
<CustomInput |
||||
inline |
||||
type='select' |
||||
id='' |
||||
bsSize='sm' |
||||
onChange={e => |
||||
handleChangeSearchType( |
||||
'category', |
||||
e.target.value |
||||
) |
||||
} |
||||
> |
||||
<option value={'비행 실적'}> |
||||
비행 실적 |
||||
</option> |
||||
<option value={'비행 계획'}> |
||||
비행 계획 |
||||
</option> |
||||
<option value={'비행 승인'}> |
||||
비행 승인 |
||||
</option> |
||||
</CustomInput> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<div> |
||||
<Row className='mt-2'> |
||||
<Col md='8' className='chart-wrap'> |
||||
<Card> |
||||
<CardHeader className='d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row flex-column'> |
||||
<CardTitle tag='h4'>{searchType.category} 통계</CardTitle> |
||||
<div className='select-date-wrap'> |
||||
<Row> |
||||
<div className='select-date'> |
||||
<CustomInput |
||||
inline |
||||
type='select' |
||||
id='' |
||||
bsSize='sm' |
||||
value={searchType.type} |
||||
onChange={e => |
||||
handleChangeSearchType('dateType', e.target.value) |
||||
} |
||||
> |
||||
<option value='year'>년</option> |
||||
<option value='month'>월</option> |
||||
<option value='day'>일</option> |
||||
<option value='one-day'>시간</option> |
||||
</CustomInput> |
||||
</div> |
||||
|
||||
{searchType.dateType === 'month' || |
||||
searchType.dateType === 'day' || |
||||
searchType.dateType === 'one-day' ? ( |
||||
<> |
||||
<div className='select-date'> |
||||
<CustomInput |
||||
inline |
||||
type='select' |
||||
id='' |
||||
bsSize='sm' |
||||
value={searchType.year} |
||||
onChange={e => |
||||
handleChangeSearchType('year', e.target.value) |
||||
} |
||||
> |
||||
<option>2023</option> |
||||
</CustomInput> |
||||
</div> |
||||
{searchType.dateType === 'day' || |
||||
searchType.dateType === 'one-day' ? ( |
||||
<div className='select-date'> |
||||
<CustomInput |
||||
inline |
||||
type='select' |
||||
id='' |
||||
bsSize='sm' |
||||
value={searchType.month} |
||||
onChange={e => |
||||
handleChangeSearchType( |
||||
'month', |
||||
e.target.value |
||||
) |
||||
} |
||||
> |
||||
{dateLists.month.map(i => ( |
||||
<option value={i} key={i}> |
||||
{i} |
||||
</option> |
||||
))} |
||||
</CustomInput> |
||||
</div> |
||||
) : null} |
||||
{searchType.dateType === 'one-day' ? ( |
||||
<div className='select-date'> |
||||
<CustomInput |
||||
inline |
||||
type='select' |
||||
id='' |
||||
bsSize='sm' |
||||
value={searchType.day} |
||||
onChange={e => |
||||
handleChangeSearchType('day', e.target.value) |
||||
} |
||||
> |
||||
{dateLists.day.map(i => ( |
||||
<option value={i} key={i}> |
||||
{i} |
||||
</option> |
||||
))} |
||||
</CustomInput> |
||||
</div> |
||||
) : null} |
||||
</> |
||||
) : null} |
||||
</Row> |
||||
{/* <Calendar size={14} /> |
||||
<Flatpickr |
||||
options={{ |
||||
mode: 'range', |
||||
defaultDate: ['2019-05-01', '2019-05-10'] |
||||
}} |
||||
className='form-control flat-picker bg-transparent border-0 shadow-none' |
||||
/> */} |
||||
</div> |
||||
</CardHeader> |
||||
<CardBody> |
||||
<div style={{ height: '400px' }}> |
||||
<Bar data={data} options={options} height={400} /> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
<Col md='4' className='chart-wrap'> |
||||
<Card> |
||||
<CardHeader className='d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row flex-column'> |
||||
<CardTitle tag='h4'>{searchType.category} TOP5</CardTitle> |
||||
</CardHeader> |
||||
<CardBody> |
||||
<div style={{ height: '275px' }}> |
||||
<Doughnut data={data2} options={options2} height={275} /> |
||||
</div> |
||||
{/* <div className='d-flex justify-content-between mt-3 mb-1'> |
||||
<div className='d-flex align-items-center'></div> |
||||
</div> */} |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</CustomMainLayout> |
||||
); |
||||
} |
@ -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 <FlightPerformanceContainer />; |
||||
} |
Loading…
Reference in new issue