지대한
2 years ago
18 changed files with 606 additions and 58 deletions
@ -0,0 +1,59 @@ |
|||||||
|
import React from 'react'; |
||||||
|
import {Button, Card, Col, Row} from 'reactstrap'; |
||||||
|
import {GridDatabase} from '../../../crud/grid/GridDatatable'; |
||||||
|
|
||||||
|
|
||||||
|
const FlightPlanAprvGrid = ({data, columns, handleChangeSelected, handleClickAprv}) => { |
||||||
|
|
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='pal-card-box'> |
||||||
|
<Row> |
||||||
|
<Col> |
||||||
|
<div |
||||||
|
className='cont-ti d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||||
|
<div> |
||||||
|
<h4>비행계획서 신청 목록</h4> |
||||||
|
<span className='search-case'>검색결과 총 {!!data ? data.length : 0}건</span> |
||||||
|
</div> |
||||||
|
<div className='d-flex align-items-center'> |
||||||
|
<Button.Ripple |
||||||
|
color='primary' |
||||||
|
size='sm' |
||||||
|
onClick={handleClickAprv('aprv')} |
||||||
|
> |
||||||
|
승인 |
||||||
|
</Button.Ripple> |
||||||
|
<Button.Ripple |
||||||
|
color='primary' |
||||||
|
size='sm' |
||||||
|
style={{marginLeft: 10}} |
||||||
|
onClick={handleClickAprv('notAprov')} |
||||||
|
> |
||||||
|
미승인 |
||||||
|
</Button.Ripple> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className='invoice-list-wrapper'> |
||||||
|
<Card> |
||||||
|
<div className='invoice-list-dataTable'> |
||||||
|
<GridDatabase |
||||||
|
title={'비행이력'} |
||||||
|
data={data} |
||||||
|
columns={columns} |
||||||
|
count={!!data ? data.length : 0} |
||||||
|
// pagination={props.pagination}
|
||||||
|
selectableRows |
||||||
|
onSelectedRowsChange={handleChangeSelected} |
||||||
|
/> |
||||||
|
{/* 검색된 데이터가 없습니다. */} |
||||||
|
</div> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default FlightPlanAprvGrid; |
@ -0,0 +1,67 @@ |
|||||||
|
import React, {} from 'react'; |
||||||
|
import { GridDatabase } from "../../../crud/grid/GridDatatable"; |
||||||
|
import { |
||||||
|
Card, |
||||||
|
Button |
||||||
|
} from 'reactstrap'; |
||||||
|
|
||||||
|
|
||||||
|
const FlightPlanAprvGroupGrid = ({ data, count, selectGroup, handlerGroupCancel, handleGroupSelect }) => { |
||||||
|
|
||||||
|
const columns = [ |
||||||
|
{id: 'groupNm', name: '그룹 명', minWidth: '102px', cell: row => (<div>{row.groupNm}</div>)}, |
||||||
|
{id: 'groupId', name: '그룹 코드', minWidth: '102px', sortable: true, cell: row => (<div>{row.groupId}</div>)}, |
||||||
|
{sortable: true, cell: row => { |
||||||
|
return selectGroup?.groupId === row?.groupId ? ( |
||||||
|
<Button.Ripple |
||||||
|
color='danger' |
||||||
|
className='badge badge-danger' |
||||||
|
onClick={() => handlerGroupCancel()} |
||||||
|
> |
||||||
|
선택취소 |
||||||
|
</Button.Ripple> |
||||||
|
) : ( |
||||||
|
<Button.Ripple |
||||||
|
color='primary' |
||||||
|
className='badge badge-primary' |
||||||
|
onClick={() => { |
||||||
|
handleGroupSelect({ |
||||||
|
groupId: row?.groupId, |
||||||
|
groupNm: row?.groupNm, |
||||||
|
groupAuthCd: row?.groupAuthCd |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
> |
||||||
|
상세보기 |
||||||
|
</Button.Ripple> |
||||||
|
) |
||||||
|
}} |
||||||
|
]; |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<div className='cont-ti d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||||
|
<div> |
||||||
|
<h4>나의 그룹 목록</h4> |
||||||
|
<span className='search-case'>검색결과 총 {count}건</span> |
||||||
|
</div> |
||||||
|
<div className='d-flex align-items-center'></div> |
||||||
|
</div> |
||||||
|
<div className='invoice-list-wrapper'> |
||||||
|
<Card> |
||||||
|
<div className='invoice-list-dataTable'> |
||||||
|
<GridDatabase |
||||||
|
data={data} |
||||||
|
count={count} |
||||||
|
columns={columns} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
</> |
||||||
|
) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
export default FlightPlanAprvGroupGrid; |
@ -0,0 +1,175 @@ |
|||||||
|
import React, {useState} from 'react'; |
||||||
|
import {Button, Card, CardBody, Col, CustomInput, Row} from 'reactstrap'; |
||||||
|
import {Search} from 'react-feather'; |
||||||
|
import Flatpickr from 'react-flatpickr'; |
||||||
|
import moment from 'moment'; |
||||||
|
|
||||||
|
|
||||||
|
const FlightPlanAprvSearch = ({searchData, handleChangeSearchData, handleSearch}) => { |
||||||
|
|
||||||
|
const {schFltStDt, schFltEndDt, aprvlYn} = searchData; |
||||||
|
const initCheckState = { |
||||||
|
'all': aprvlYn == 'A', |
||||||
|
'yes': (aprvlYn == 'Y' || aprvlYn == 'A'), |
||||||
|
'no': (aprvlYn == 'N' || aprvlYn == 'A'), |
||||||
|
} |
||||||
|
const [checkState, setCheckState] = useState(initCheckState); |
||||||
|
const handleClickSearch = (e) => { |
||||||
|
handleSearch(searchData); |
||||||
|
} |
||||||
|
const handleChangeInput = (dates, value, config) => { |
||||||
|
if (dates.length === 2) { |
||||||
|
const schFltStDt = moment(dates[0]).format('YYYY-MM-DD HH:mm:ss'); |
||||||
|
const schFltEndDt = moment(dates[1]).set({'h': 23, 'm': 59, 's': 59}).format('YYYY-MM-DD HH:mm:ss'); |
||||||
|
handleChangeSearchData({schFltStDt, schFltEndDt}) |
||||||
|
} |
||||||
|
} |
||||||
|
const handleChangeCheckbox = (e) => { |
||||||
|
const {name, value, checked} = e.target; |
||||||
|
let val; |
||||||
|
switch (value) { |
||||||
|
case 'A': |
||||||
|
val = checked ? 'A' : ''; |
||||||
|
handleChangeSearchData({[name]: val}) |
||||||
|
setCheckState({ |
||||||
|
'all': checked, |
||||||
|
'yes': checked, |
||||||
|
'no': checked |
||||||
|
}) |
||||||
|
break; |
||||||
|
case 'Y': |
||||||
|
if (checked && checkState.no) val = 'A' |
||||||
|
else if (checked && !checkState.no) val = 'Y' |
||||||
|
else if (!checked && checkState.no) val = 'N' |
||||||
|
else if (!checked && !checkState.no) val = '' |
||||||
|
handleChangeSearchData({[name]: val}) |
||||||
|
setCheckState(prevState => ({ |
||||||
|
'all': prevState.no && checked, |
||||||
|
'yes': checked, |
||||||
|
'no': prevState.no |
||||||
|
})) |
||||||
|
break; |
||||||
|
case 'N': |
||||||
|
if (checked && checkState.yes) val = 'A' |
||||||
|
else if (checked && !checkState.yes) val = 'N' |
||||||
|
else if (!checked && checkState.yes) val = 'Y' |
||||||
|
else if (!checked && !checkState.yes) val = '' |
||||||
|
handleChangeSearchData({[name]: val}) |
||||||
|
setCheckState(prevState => ({ |
||||||
|
'all': prevState.yes && checked, |
||||||
|
'yes': prevState.yes, |
||||||
|
'no': checked |
||||||
|
})) |
||||||
|
break; |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return ( |
||||||
|
<div className='pal-card-box'> |
||||||
|
<Row> |
||||||
|
<Col> |
||||||
|
<div |
||||||
|
className='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' |
||||||
|
onClick={handleClickSearch} |
||||||
|
> |
||||||
|
<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' xl='4' md='6' sm='12'> |
||||||
|
<div className='d-flex align-items-center calendar-flat'> |
||||||
|
<Flatpickr |
||||||
|
id='searchDate' |
||||||
|
value={[ |
||||||
|
schFltStDt, |
||||||
|
schFltEndDt |
||||||
|
]} |
||||||
|
options={{ |
||||||
|
mode: 'range', |
||||||
|
// defaultDate: [
|
||||||
|
// props.params.stDate,
|
||||||
|
// props.params.endDate
|
||||||
|
// ]
|
||||||
|
}} |
||||||
|
onChange={handleChangeInput} |
||||||
|
className='form-control flat-picker bg-transparent border-0 shadow-none' |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</dt> |
||||||
|
|
||||||
|
<dt> |
||||||
|
<div className='search-box'> |
||||||
|
<div className='search-list-ti'>승인여부</div> |
||||||
|
<div className='search-list'> |
||||||
|
<div className='search-list-cont'> |
||||||
|
<CustomInput |
||||||
|
inline |
||||||
|
type='checkbox' |
||||||
|
id='exampleCustomCheckbox' |
||||||
|
label='전체' |
||||||
|
name="aprvlYn" |
||||||
|
value="A" |
||||||
|
// checked={true}
|
||||||
|
checked={checkState.all} |
||||||
|
onChange={handleChangeCheckbox} |
||||||
|
/> |
||||||
|
<CustomInput |
||||||
|
inline |
||||||
|
type='checkbox' |
||||||
|
id='exampleCustomCheckbox2' |
||||||
|
label='승인' |
||||||
|
name="aprvlYn" |
||||||
|
value="Y" |
||||||
|
checked={checkState.yes} |
||||||
|
onChange={handleChangeCheckbox} |
||||||
|
/> |
||||||
|
<CustomInput |
||||||
|
inline |
||||||
|
type='checkbox' |
||||||
|
id='exampleCustomCheckbox3' |
||||||
|
label='미승인' |
||||||
|
name="aprvlYn" |
||||||
|
value="N" |
||||||
|
checked={checkState.no} |
||||||
|
onChange={handleChangeCheckbox} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</dt> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
</CardBody> |
||||||
|
</Card> |
||||||
|
|
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default FlightPlanAprvSearch; |
@ -0,0 +1,97 @@ |
|||||||
|
import React, {useEffect, useState} from 'react'; |
||||||
|
import {Col, Row} from 'reactstrap'; |
||||||
|
import {CustomMainLayout} from '../../../../components/layout/CustomMainLayout'; |
||||||
|
import moment from 'moment/moment'; |
||||||
|
import FlightPlanAprvSearch from '../../../../components/basis/flight/aprv/FlightPlanAprvSearch'; |
||||||
|
import FlightPlanAprvGrid from '../../../../components/basis/flight/aprv/FlightPlanAprvGrid'; |
||||||
|
import {useDispatch, useSelector} from 'react-redux'; |
||||||
|
import * as FlightAction from '../../../../modules/basis/flight/actions/basisFlightAction'; |
||||||
|
|
||||||
|
const initSearchData = { |
||||||
|
schFltStDt: moment().set({'date': 1, 'h': 0, 'm': 0, 's': 0}).format('YYYY-MM-DD HH:mm:ss'), |
||||||
|
schFltEndDt: moment().set({'h': 23, 'm': 59, 's': 59}).format('YYYY-MM-DD HH:mm:ss'), |
||||||
|
aprvlYn: 'N', |
||||||
|
cstmrSno: 0, |
||||||
|
}; |
||||||
|
|
||||||
|
const columns = [ |
||||||
|
{id: 'planSno', name: '번호', cell: (row, i) => (<div>{i + 1}</div>)}, |
||||||
|
{id: 'fltPurpose', name: '비행목적', cell: row => (<div>{row.fltPurpose}</div>)}, |
||||||
|
{ |
||||||
|
id: 'fltMethod', name: '비행방식', cell: row => { |
||||||
|
const displayName = row.areaList && row.areaList.length > 0 && row.areaList[0].fltMethod || '-'; |
||||||
|
return <div>{displayName}</div> |
||||||
|
} |
||||||
|
}, |
||||||
|
{id: 'schFltStDt', name: '출발일', cell: row => (<div>{row.schFltStDt}</div>)}, |
||||||
|
{id: 'aprvlYn', name: '승인여부', cell: row => (<div>{row.aprvlYn}</div>)} |
||||||
|
]; |
||||||
|
|
||||||
|
const FlightPlanAprvContainer = () => { |
||||||
|
const dispatch = useDispatch(); |
||||||
|
const [searchData, setSearchData] = useState(initSearchData); |
||||||
|
const [selPlanSnoList, setSelPlanSnoList] = useState([]); |
||||||
|
const {aprvList, aprvProc} = useSelector(state => state.flightState); |
||||||
|
|
||||||
|
// 최초 비행계획서 목록 조회
|
||||||
|
useEffect(() => { |
||||||
|
handleSearch(searchData); |
||||||
|
}, []) |
||||||
|
useEffect(() => { |
||||||
|
if (aprvProc && aprvProc.result > 0) { |
||||||
|
handleSearch(searchData); |
||||||
|
} |
||||||
|
}, [aprvProc]) |
||||||
|
|
||||||
|
|
||||||
|
const handleSearch = (data) => { |
||||||
|
dispatch(FlightAction.FLIGHT_APRV_LIST.request(data)); |
||||||
|
} |
||||||
|
const handleChangeSearchData = (values) => { |
||||||
|
setSearchData(prevState => ({ |
||||||
|
...prevState, |
||||||
|
...values |
||||||
|
})) |
||||||
|
} |
||||||
|
const handleChangeSelected = ({selectedRows}) => { |
||||||
|
setSelPlanSnoList(selectedRows.map(item => item.planSno)) |
||||||
|
} |
||||||
|
const handleClickAprv = (type) => (e) => { |
||||||
|
// notAprov, aprv
|
||||||
|
console.log(type, selPlanSnoList, e) |
||||||
|
if (!selPlanSnoList || selPlanSnoList.length < 1) { |
||||||
|
alert('비행계획서를 선택해주세요.'); |
||||||
|
return; |
||||||
|
} |
||||||
|
; |
||||||
|
const sendData = { |
||||||
|
planSnoList: [...selPlanSnoList], |
||||||
|
aprvlYn: type === 'aprv' ? 'Y' : 'N' |
||||||
|
} |
||||||
|
dispatch(FlightAction.FLIGHT_APRV_PROC.request(sendData)); |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<CustomMainLayout title={"비행계획서 승인"}> |
||||||
|
<div className='pal-card-box'> |
||||||
|
<Row> |
||||||
|
<Col sm='12'> |
||||||
|
<FlightPlanAprvSearch |
||||||
|
searchData={searchData} |
||||||
|
handleChangeSearchData={handleChangeSearchData} |
||||||
|
handleSearch={handleSearch} |
||||||
|
/> |
||||||
|
<FlightPlanAprvGrid |
||||||
|
data={aprvList} |
||||||
|
columns={columns} |
||||||
|
handleChangeSelected={handleChangeSelected} |
||||||
|
handleClickAprv={handleClickAprv} |
||||||
|
/> |
||||||
|
</Col> |
||||||
|
</Row> |
||||||
|
</div> |
||||||
|
</CustomMainLayout> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default FlightPlanAprvContainer; |
@ -0,0 +1,9 @@ |
|||||||
|
import '@styles/react/libs/flatpickr/flatpickr.scss'; |
||||||
|
import '@styles/react/libs/tables/react-dataTable-component.scss'; |
||||||
|
import '../../../../assets/css/custom.css'; |
||||||
|
import React from 'react'; |
||||||
|
import FlightPlanAprvContainer from '../../../../containers/basis/flight/aprv/FlightPlanAprvContainer'; |
||||||
|
|
||||||
|
const FlightPlanAprv = (props) => <FlightPlanAprvContainer/>; |
||||||
|
|
||||||
|
export default FlightPlanAprv; |
Loading…
Reference in new issue