Compare commits
7 Commits
master
...
feature/fl
Author | SHA1 | Date |
---|---|---|
junh_eee(이준희) | ca450f2a18 | 2 years ago |
junh_eee(이준희) | 710186424f | 2 years ago |
junh_eee(이준희) | 7f9b30ccc2 | 2 years ago |
junh_eee(이준희) | 365dceb484 | 2 years ago |
junh_eee(이준희) | 36c0aa7550 | 2 years ago |
junh_eee(이준희) | 039340c59c | 2 years ago |
junh_eee(이준희) | 642fcdb857 | 2 years ago |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 4.2 KiB |
@ -1,6 +1,6 @@
|
||||
// ** Router Import
|
||||
import Router from './router/Router'; |
||||
if (process.env.NODE_ENV === 'production') console.log = function () {}; |
||||
const App = props => <Router />; |
||||
import Router from './router/Router' |
||||
|
||||
export default App; |
||||
const App = props => <Router /> |
||||
|
||||
export default App |
||||
|
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 459 KiB |
@ -1,512 +0,0 @@
|
||||
import { useState, useEffect } from 'react'; |
||||
import { useSelector, useDispatch } from 'react-redux'; |
||||
import { |
||||
InputGroup, |
||||
InputGroupAddon, |
||||
InputGroupText, |
||||
Col, |
||||
TabPane, |
||||
FormGroup, |
||||
Input, |
||||
Button, |
||||
Modal, |
||||
ModalHeader, |
||||
ModalBody, |
||||
ModalFooter |
||||
} from 'reactstrap'; |
||||
import { User, Lock } from 'react-feather'; |
||||
import '../../../assets/css/custom.css'; |
||||
import { findAPI } from '../../../modules/account/find/apis/findApi'; |
||||
import { accountApi } from '../../../modules/account/register/apis/accountApi'; |
||||
import { updatePwAction } from '../../../modules/account/find/actions/findAction'; |
||||
|
||||
export const AccountFindPassword = props => { |
||||
const dispatch = useDispatch(); |
||||
const [activeTab, setActiveTab] = useState('2'); |
||||
|
||||
// ** Function to toggle tabs
|
||||
const toggle = tab => setActiveTab(tab); |
||||
//modal
|
||||
const [confirmModal, setConfirmModal] = useState(false); |
||||
const [saveModal, setSaveModal] = useState(false); |
||||
const [modal, setModal] = useState({ |
||||
isOpen: false, |
||||
title: '', |
||||
desc: '', |
||||
color: '' |
||||
}); |
||||
|
||||
//state값
|
||||
const { idResult, userId, pwResult, udResult } = useSelector( |
||||
state => state.findState |
||||
); |
||||
|
||||
//param으로 넘기기 위한 값
|
||||
const [inputId, setInputId] = useState(''); |
||||
const [inputHpno, setInputHpno] = useState(''); |
||||
const [inputCrtfy, setInputCrtfy] = useState(''); |
||||
const [inputNewPw, setInputNewPw] = useState(''); |
||||
const [inputNewPwCk, setInputNewPwCk] = useState(''); |
||||
|
||||
//3분 시간 및 인증
|
||||
const [minutes_Counter, setMinutes_Counter] = useState('03'); |
||||
const [seconds_Counter, setSeconds_Counter] = useState('00'); |
||||
const [timer, setTimer] = useState(null); |
||||
const [isRunning, setIsRunning] = useState(false); |
||||
const [sendCount, setSendCount] = useState(0); |
||||
const [isCrtfy, setIsCrtfy] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
setIsRunning(true); |
||||
if (isRunning) clearInterval(timer); |
||||
return () => { |
||||
clearInterval(timer); |
||||
setIsRunning(false); |
||||
}; |
||||
}, []); |
||||
|
||||
const handlerSend = async () => { |
||||
if (!inputId) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '아이디를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (!inputHpno) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '휴대폰 번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (sendCount >= 3) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '인증번호가 발송은 3회까지만 가능합니다.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
if (inputHpno.length < 11) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '올바른 번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
const res = await findAPI.sendForPw({ userId: inputId, hpno: inputHpno }); |
||||
if (res?.data.code === -1) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '가입되지 않은 회원정보입니다. 다시 확인해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
} else if (res?.data.code === 0) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '인증번호가 발송되었습니다.', |
||||
color: 'modal-primary' |
||||
}); |
||||
timeStart(); |
||||
} |
||||
}; |
||||
|
||||
const timeStart = () => { |
||||
if (isRunning) { |
||||
clearInterval(timer); |
||||
} |
||||
|
||||
setIsRunning(true); |
||||
setIsCrtfy(false); |
||||
|
||||
setSendCount(sendCount + 1); |
||||
timerStart(180); |
||||
}; |
||||
|
||||
const timerStart = count => { |
||||
let minutes, seconds; |
||||
|
||||
const timer = setInterval(() => { |
||||
setIsRunning(true); |
||||
minutes = parseInt(count / 60, 10); |
||||
seconds = parseInt(count % 60, 10); |
||||
minutes = minutes < 10 ? '0' + minutes : minutes; |
||||
seconds = seconds < 10 ? '0' + seconds : seconds; |
||||
setMinutes_Counter(minutes); |
||||
setSeconds_Counter(seconds); |
||||
|
||||
//타이머 끝
|
||||
if (--count < 0) { |
||||
clearInterval(timer); |
||||
setIsRunning(false); |
||||
// setValue('crtfyNo', '');
|
||||
// setCrtfyNo('');
|
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 만료', |
||||
desc: '인증번호가 만료되었습니다.', |
||||
color: 'modal-danger' |
||||
}); |
||||
} |
||||
}, 1000); |
||||
|
||||
setTimer(timer); |
||||
|
||||
return () => { |
||||
clearInterval(timer); |
||||
}; |
||||
}; |
||||
|
||||
const handlerConfirm = async () => { |
||||
if (!inputId) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '아이디를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (!inputHpno) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '휴대폰 번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (!inputCrtfy) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '인증번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
const res = await accountApi.crtfyhpConfirm(inputHpno, inputCrtfy); |
||||
if (!res.data.result) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '인증번호가 잘못되었습니다.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} else { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '인증되었습니다.', |
||||
color: 'modal-primary' |
||||
}); |
||||
setIsCrtfy(true); |
||||
setIsRunning(false); |
||||
} |
||||
}; |
||||
|
||||
const handlerUpdatePw = async () => { |
||||
if (!inputNewPw || !inputNewPwCk) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '비밀번호 변경', |
||||
desc: '비밀번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
const reg = |
||||
/^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@$!%*#?&])[A-Za-z0-9@$!%*#?&]{8,20}$/; |
||||
if (!reg.test(inputNewPw) || !reg.test(inputNewPwCk)) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '비밀번호 변경', |
||||
desc: '8자 이상, 20자 미만 영문자/숫자/특수문자(@$!%*#?&) 조합하여 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (inputNewPw !== inputNewPwCk) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '비밀번호 변경', |
||||
desc: '비밀번호가 일치하지 않습니다.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (inputNewPw === inputNewPwCk && inputNewPw && inputNewPwCk) { |
||||
dispatch( |
||||
updatePwAction.request({ |
||||
userId: inputId, |
||||
hpno: inputHpno, |
||||
newPw: inputNewPw |
||||
}) |
||||
); |
||||
setSaveModal(!saveModal); |
||||
} |
||||
}; |
||||
|
||||
let id = ''; |
||||
let hpno = ''; |
||||
let crtfyhp = ''; |
||||
let newpw = ''; |
||||
let newpwck = ''; |
||||
const handlerChange = e => { |
||||
const { name, value } = e.target; |
||||
|
||||
if (name == 'userId') { |
||||
id = value; |
||||
setInputId(id); |
||||
} else if (name == 'hpno') { |
||||
const regex = /^[0-9]{0,11}$/; |
||||
if (regex.test(value)) { |
||||
hpno = value; |
||||
setInputHpno(hpno); |
||||
} |
||||
} else if (name == 'crtfyhpNo') { |
||||
const regex = /^[0-9]{0,6}$/; |
||||
if (regex.test(value)) { |
||||
crtfyhp = value; |
||||
setInputCrtfy(crtfyhp); |
||||
} |
||||
} else if (name == 'newPw') { |
||||
const regex = /^[A-Za-z0-9@$!%*#?&]{0,20}$/; |
||||
if (regex.test(value)) { |
||||
newpw = value; |
||||
setInputNewPw(newpw); |
||||
} |
||||
} else if (name == 'newPwCk') { |
||||
const regex = /^[A-Za-z0-9@$!%*#?&]{0,20}$/; |
||||
if (regex.test(value)) { |
||||
newpwck = value; |
||||
setInputNewPwCk(newpwck); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
// const handlerClose = () => {
|
||||
// setModal({ ...modal, isOpen: !modal.isOpen });
|
||||
// setConfirmModal({ ...confirmModal, isOpen: !confirmModal.isOpen});
|
||||
// props.handlerClose();
|
||||
// }
|
||||
|
||||
return ( |
||||
<> |
||||
<TabPane tabId='2'> |
||||
<FormGroup className='form-label-group position-relative has-icon-left'> |
||||
<InputGroup className=''> |
||||
<InputGroupAddon addonType='prepend'> |
||||
<InputGroupText> |
||||
<User size={14} /> |
||||
</InputGroupText> |
||||
</InputGroupAddon> |
||||
<Input |
||||
type='text' |
||||
id='userId' |
||||
name='userId' |
||||
placeholder='아이디' |
||||
value={inputId} |
||||
onChange={handlerChange} |
||||
/> |
||||
</InputGroup> |
||||
</FormGroup> |
||||
<FormGroup> |
||||
<div className='input-btn'> |
||||
<Col md='3' xs='12'> |
||||
<Input type='select' placeholder='+(국가번호)'> |
||||
{/* <option>+82</option> */} |
||||
<option value={'+82'}>대한민국(+82)</option> |
||||
<option value={'+81'}>일본(+81)</option> |
||||
<option value={'+86'}>중국(+86)</option> |
||||
</Input> |
||||
</Col> |
||||
<Col md='6' xs='12'> |
||||
<Input |
||||
type='number' |
||||
id='hpno' |
||||
name='hpno' |
||||
placeholder='01012345678' |
||||
value={inputHpno} |
||||
onChange={handlerChange} |
||||
/> |
||||
</Col> |
||||
<Col md='3' xs='12'> |
||||
<Button color='primary' type='button' onClick={handlerSend}> |
||||
인증번호 발송 |
||||
</Button> |
||||
</Col> |
||||
</div> |
||||
</FormGroup> |
||||
<FormGroup> |
||||
<div className='input-btn time-span'> |
||||
<Col md='9' xs='12' className='timeInput'> |
||||
<Input |
||||
type='number' |
||||
id='crtfyhpNo' |
||||
name='crtfyhpNo' |
||||
placeholder='인증번호 입력' |
||||
value={inputCrtfy} |
||||
onChange={handlerChange} |
||||
{...(sendCount > 0 ? {} : { disabled: true })} |
||||
/> |
||||
{/* <span className='time'>남은시간 : 3:00</span> */} |
||||
<span className={!isRunning || isCrtfy ? 'time d-none' : 'time'}> |
||||
남은시간 {minutes_Counter}:{seconds_Counter} |
||||
</span> |
||||
</Col> |
||||
<Col md='3' xs='12'> |
||||
<Button |
||||
color='primary' |
||||
type='button' |
||||
onClick={handlerConfirm} |
||||
{...(isRunning ? {} : { disabled: true })} |
||||
> |
||||
인증번호 확인 |
||||
</Button> |
||||
</Col> |
||||
</div> |
||||
</FormGroup> |
||||
<FormGroup> |
||||
<div className='full-btn-2n vertically-centered-modal'> |
||||
{/* <div className='full-btn-2n vertically-centered-confirmModal'> */} |
||||
<Button |
||||
color='secondary' |
||||
type='button' |
||||
onClick={props.handlerClose} |
||||
> |
||||
취소 |
||||
</Button> |
||||
<Button |
||||
color='primary' |
||||
type='button' |
||||
onClick={() => setConfirmModal(!confirmModal)} |
||||
{...(isCrtfy ? {} : { disabled: true })} |
||||
> |
||||
확인 |
||||
</Button> |
||||
|
||||
<Modal |
||||
isOpen={confirmModal} |
||||
toggle={() => setConfirmModal(!confirmModal)} |
||||
className='modal-dialog-centered user-search-modal' |
||||
> |
||||
<ModalHeader toggle={() => setConfirmModal(!confirmModal)}> |
||||
비밀번호 확인 |
||||
</ModalHeader> |
||||
<ModalBody> |
||||
<span className='etc-txt'> |
||||
새로운 비밀번호로 변경해 주세요. |
||||
</span> |
||||
<FormGroup className='form-label-group position-relative has-icon-left'> |
||||
<InputGroup> |
||||
<InputGroupAddon addonType='prepend'> |
||||
<InputGroupText> |
||||
<Lock size={14} /> |
||||
</InputGroupText> |
||||
</InputGroupAddon> |
||||
<Input |
||||
type='password' |
||||
id='newPw' |
||||
name='newPw' |
||||
placeholder='새로운 비밀번호' |
||||
value={inputNewPw} |
||||
onChange={handlerChange} |
||||
/> |
||||
</InputGroup> |
||||
</FormGroup> |
||||
<FormGroup className='form-label-group position-relative has-icon-left mb-0'> |
||||
<InputGroup> |
||||
<InputGroupAddon addonType='prepend'> |
||||
<InputGroupText> |
||||
<Lock size={14} /> |
||||
</InputGroupText> |
||||
</InputGroupAddon> |
||||
<Input |
||||
type='password' |
||||
id='newPwCk' |
||||
name='newPwCk' |
||||
placeholder='새로운 비밀번호 확인' |
||||
value={inputNewPwCk} |
||||
onChange={handlerChange} |
||||
/> |
||||
</InputGroup> |
||||
</FormGroup> |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color='primary' type='button' onClick={handlerUpdatePw}> |
||||
저장 |
||||
</Button> |
||||
|
||||
<div className='vertically-centered-modal'> |
||||
<Modal |
||||
isOpen={saveModal} |
||||
toggle={() => setSaveModal(!saveModal)} |
||||
modalClassName='modal-primary' |
||||
className='modal-dialog-centered' |
||||
> |
||||
<ModalHeader toggle={() => setSaveModal(!saveModal)}> |
||||
비밀번호 변경 |
||||
</ModalHeader> |
||||
<ModalBody> |
||||
변경이 완료되었습니다. 다시 로그인해 주세요. |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color='primary' onClick={props.handlerClose}> |
||||
로그인 |
||||
</Button>{' '} |
||||
</ModalFooter> |
||||
</Modal> |
||||
</div> |
||||
</ModalFooter> |
||||
</Modal> |
||||
</div> |
||||
</FormGroup> |
||||
|
||||
<div className='vertically-centered-modal'> |
||||
<Modal |
||||
isOpen={modal.isOpen} |
||||
toggle={() => setModal({ ...modal, isOpen: !modal.isOpen })} |
||||
modalClassName={modal.color} |
||||
className='modal-dialog-centered' |
||||
> |
||||
<ModalHeader |
||||
toggle={() => setModal({ ...modal, isOpen: !modal.isOpen })} |
||||
> |
||||
{modal.title} |
||||
</ModalHeader> |
||||
<ModalBody>{modal.desc}</ModalBody> |
||||
<ModalFooter> |
||||
<Button |
||||
color='danger' |
||||
onClick={() => setModal({ ...modal, isOpen: !modal.isOpen })} |
||||
> |
||||
확인 |
||||
</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
</div> |
||||
</TabPane> |
||||
</> |
||||
); |
||||
}; |
@ -1,88 +0,0 @@
|
||||
import { useState } from "react"; |
||||
import { Form, InputGroup, InputGroupAddon, InputGroupText, Card, CardBody, Row, Col, Nav, NavItem, NavLink, TabContent, TabPane, Alert, FormGroup, Input, Label, Button, |
||||
Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap' |
||||
import classnames from 'classnames'; |
||||
import { |
||||
User, |
||||
Info, |
||||
Share, |
||||
X, |
||||
Lock, |
||||
Edit, |
||||
Trash2, |
||||
Image, |
||||
UserCheck, |
||||
Clipboard, |
||||
Settings, |
||||
AlertTriangle |
||||
} from 'react-feather'; |
||||
import { AccountFindUserId } from "./AccountFindUserId"; |
||||
import { AccountFindPassword } from "./AccountFindPassword"; |
||||
import { AccountFindUserIdContainer } from "../../../containers/account/find/AccountFindUserIdContainer"; |
||||
import { AccountFindPasswordContainer } from "../../../containers/account/find/AccountFindPasswordContainer"; |
||||
import { useHistory } from 'react-router-dom' |
||||
|
||||
export const AccountFindTab = props => { |
||||
const [activeTab, setActiveTab] = useState('2'); |
||||
const history = useHistory(); |
||||
|
||||
const toggle = tab => setActiveTab(tab) |
||||
|
||||
// const toggle = tab => {
|
||||
// if (activeTab !== tab) setActiveTab(tab);
|
||||
// };
|
||||
|
||||
const handlerClose = () => { |
||||
history.push(`/account/login`) |
||||
} |
||||
|
||||
return( |
||||
<> |
||||
<div className='card-body-tab-menu'> |
||||
<Nav pills> |
||||
<NavItem> |
||||
{/* <NavLink active={activeTab === '1'} onClick={() => toggle('1')}> */} |
||||
<NavLink |
||||
className={classnames({ active: activeTab === '1' })} |
||||
onClick={() => { |
||||
toggle('1'); |
||||
}} |
||||
> |
||||
<User size={14} /> |
||||
<span className='align-middle d-none d-sm-block'>아이디 찾기</span> |
||||
</NavLink> |
||||
</NavItem> |
||||
<NavItem> |
||||
{/* <NavLink active={activeTab === '2'} onClick={() => toggle('2')}> */} |
||||
<NavLink |
||||
className={classnames({active: activeTab === '2'})} |
||||
onClick={() => { |
||||
toggle('2'); |
||||
}} |
||||
> |
||||
<Lock size={14} /> |
||||
<span className='align-middle d-none d-sm-block'>비밀번호 찾기</span> |
||||
</NavLink> |
||||
</NavItem> |
||||
</Nav> |
||||
</div> |
||||
<Row className='app-user-edit'> |
||||
<Col sm='12'> |
||||
<Card> |
||||
<CardBody className='card-body-tab-cont'> |
||||
<TabContent activeTab={activeTab}> |
||||
<AccountFindUserIdContainer |
||||
handlerClose={handlerClose} |
||||
/> |
||||
<AccountFindPasswordContainer
|
||||
handlerClose={handlerClose} |
||||
/> |
||||
</TabContent> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
</> |
||||
) |
||||
|
||||
} |
@ -1,420 +0,0 @@
|
||||
import { useState, useEffect, useMemo } from 'react'; |
||||
import { useDispatch, useSelector } from 'react-redux'; |
||||
|
||||
import { |
||||
Form, |
||||
InputGroup, |
||||
InputGroupAddon, |
||||
InputGroupText, |
||||
Col, |
||||
TabPane, |
||||
FormGroup, |
||||
Input, |
||||
Button, |
||||
Modal, |
||||
ModalHeader, |
||||
ModalBody, |
||||
ModalFooter, |
||||
FormFeedback |
||||
} from 'reactstrap'; |
||||
import { User } from 'react-feather'; |
||||
|
||||
import '../../../assets/css/custom.css'; |
||||
import { |
||||
findUserIdAction, |
||||
sendForIdAction |
||||
} from '../../../modules/account/find/actions/findAction'; |
||||
import { accountApi } from '../../../modules/account/register/apis/accountApi'; |
||||
import { findAPI } from '../../../modules/account/find/apis/findApi'; |
||||
|
||||
export const AccountFindUserId = props => { |
||||
const dispatch = useDispatch(); |
||||
const [activeTab, setActiveTab] = useState('2'); |
||||
|
||||
// ** Function to toggle tabs
|
||||
const toggle = tab => setActiveTab(tab); |
||||
|
||||
//modal
|
||||
const [confirmModal, setConfirmModal] = useState(false); |
||||
const [modal, setModal] = useState({ |
||||
isOpen: false, |
||||
title: '', |
||||
desc: '', |
||||
color: '' |
||||
}); |
||||
|
||||
//state값
|
||||
const { idResult, userId, pwResult, udResult } = useSelector( |
||||
state => state.findState |
||||
); |
||||
|
||||
//param으로 넘기기 위한 값
|
||||
const [inputName, setInputName] = useState(''); |
||||
const [inputHpno, setInputHpno] = useState(''); |
||||
const [inputCrtfy, setInputCrtfy] = useState(''); |
||||
|
||||
//3분 시간 및 인증
|
||||
const [minutes_Counter, setMinutes_Counter] = useState('03'); |
||||
const [seconds_Counter, setSeconds_Counter] = useState('00'); |
||||
const [timer, setTimer] = useState(null); |
||||
const [isRunning, setIsRunning] = useState(false); |
||||
const [sendCount, setSendCount] = useState(0); |
||||
const [isCrtfy, setIsCrtfy] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
setIsRunning(true); |
||||
if (isRunning) clearInterval(timer); |
||||
return () => { |
||||
clearInterval(timer); |
||||
setIsRunning(false); |
||||
}; |
||||
}, []); |
||||
|
||||
const handlerSend = async () => { |
||||
if (!inputName) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '이름을 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (!inputHpno) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '휴대폰 번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (sendCount >= 3) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '인증번호가 발송은 3회까지만 가능합니다.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
if (inputHpno.length < 11) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '올바른 번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
const res = await findAPI.sendForId({ |
||||
memberName: inputName, |
||||
hpno: inputHpno |
||||
}); |
||||
if (res?.data.code === -1) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '가입되지 않은 회원정보입니다. 다시 확인해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
} else if (res?.data.code === 0) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 발송', |
||||
desc: '인증번호가 발송되었습니다.', |
||||
color: 'modal-primary' |
||||
}); |
||||
timeStart(); |
||||
} |
||||
}; |
||||
|
||||
const timeStart = () => { |
||||
if (isRunning) { |
||||
clearInterval(timer); |
||||
} |
||||
|
||||
setIsRunning(true); |
||||
setIsCrtfy(false); |
||||
|
||||
setSendCount(sendCount + 1); |
||||
timerStart(180); |
||||
}; |
||||
|
||||
const timerStart = count => { |
||||
let minutes, seconds; |
||||
|
||||
const timer = setInterval(() => { |
||||
setIsRunning(true); |
||||
minutes = parseInt(count / 60, 10); |
||||
seconds = parseInt(count % 60, 10); |
||||
minutes = minutes < 10 ? '0' + minutes : minutes; |
||||
seconds = seconds < 10 ? '0' + seconds : seconds; |
||||
setMinutes_Counter(minutes); |
||||
setSeconds_Counter(seconds); |
||||
|
||||
//타이머 끝
|
||||
if (--count < 0) { |
||||
clearInterval(timer); |
||||
setIsRunning(false); |
||||
// setValue('crtfyNo', '');
|
||||
// setCrtfyNo('');
|
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 만료', |
||||
desc: '인증번호가 만료되었습니다.', |
||||
color: 'modal-danger' |
||||
}); |
||||
} |
||||
}, 1000); |
||||
|
||||
setTimer(timer); |
||||
|
||||
return () => { |
||||
clearInterval(timer); |
||||
}; |
||||
}; |
||||
|
||||
const handlerConfirm = async () => { |
||||
if (!inputHpno) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '휴대폰 번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (!inputName) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '이름을 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
if (!inputCrtfy) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '인증번호를 입력해 주세요.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
const res = await accountApi.crtfyhpConfirm(inputHpno, inputCrtfy); |
||||
if (!res.data.result) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '인증번호가 잘못되었습니다.', |
||||
color: 'modal-danger' |
||||
}); |
||||
return; |
||||
} else { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '인증번호 인증', |
||||
desc: '인증되었습니다.', |
||||
color: 'modal-primary' |
||||
}); |
||||
setIsCrtfy(true); |
||||
setIsRunning(false); |
||||
} |
||||
}; |
||||
|
||||
let memberName = ''; |
||||
let hpno = ''; |
||||
let crtfyhp = ''; |
||||
const handlerChange = e => { |
||||
const { name, value } = e.target; |
||||
|
||||
if (name == 'memberName') { |
||||
const regex = /^[ㄱ-ㅎ|ㅏ-ㅣ|가-힣|a-z]{0,10}$/; |
||||
if (regex.test(value)) { |
||||
memberName = value; |
||||
setInputName(memberName); |
||||
} |
||||
} else if (name == 'hpno') { |
||||
const regex = /^[0-9]{0,11}$/; |
||||
if (regex.test(value)) { |
||||
hpno = value; |
||||
setInputHpno(hpno); |
||||
} |
||||
} else if (name == 'crtfyhpNo') { |
||||
const regex = /^[0-9]{0,6}$/; |
||||
if (regex.test(value)) { |
||||
crtfyhp = value; |
||||
setInputCrtfy(crtfyhp); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
//모든 인증 완료 후 확인버튼
|
||||
const handlerFindId = () => { |
||||
dispatch( |
||||
findUserIdAction.request({ memberName: inputName, hpno: inputHpno }) |
||||
); |
||||
setConfirmModal(!confirmModal); |
||||
}; |
||||
|
||||
return ( |
||||
<> |
||||
<TabPane tabId='1'> |
||||
<FormGroup className='form-label-group position-relative has-icon-left'> |
||||
<InputGroup className=''> |
||||
<InputGroupAddon addonType='prepend'> |
||||
<InputGroupText> |
||||
<User size={14} /> |
||||
</InputGroupText> |
||||
</InputGroupAddon> |
||||
<Input |
||||
type='text' |
||||
id='memberName' |
||||
name='memberName' |
||||
placeholder='이름' |
||||
value={inputName} |
||||
onChange={handlerChange} |
||||
/> |
||||
</InputGroup> |
||||
</FormGroup> |
||||
<FormGroup> |
||||
<div className='input-btn'> |
||||
<Col md='3' xs='12'> |
||||
<Input |
||||
type='select' |
||||
id='cntryCd' |
||||
name='cntryCd' |
||||
placeholder='+(국가번호)' |
||||
> |
||||
{/* <option>+82</option> */} |
||||
<option value={'+82'}>대한민국(+82)</option> |
||||
<option value={'+81'}>일본(+81)</option> |
||||
<option value={'+86'}>중국(+86)</option> |
||||
</Input> |
||||
</Col> |
||||
<Col md='6' xs='12'> |
||||
<Input |
||||
type='number' |
||||
id='hpno' |
||||
name='hpno' |
||||
placeholder='01012345678' |
||||
value={inputHpno} |
||||
onChange={handlerChange} |
||||
/> |
||||
</Col> |
||||
<Col md='3' xs='12'> |
||||
<Button color='primary' type='button' onClick={handlerSend}> |
||||
인증번호 발송 |
||||
</Button> |
||||
</Col> |
||||
</div> |
||||
</FormGroup> |
||||
|
||||
<FormGroup> |
||||
<div className='input-btn'> |
||||
<Col md='9' xs='12' className='timeInput'> |
||||
<Input |
||||
type='number' |
||||
id='crtfyhpNo' |
||||
name='crtfyhpNo' |
||||
placeholder='인증번호 입력' |
||||
value={inputCrtfy} |
||||
onChange={handlerChange} |
||||
{...(sendCount > 0 ? {} : { disabled: true })} |
||||
/> |
||||
<span className={!isRunning || isCrtfy ? 'time d-none' : 'time'}> |
||||
남은시간 {minutes_Counter}:{seconds_Counter} |
||||
</span> |
||||
</Col> |
||||
<Col md='3' xs='12'> |
||||
<Button |
||||
color='primary' |
||||
type='button' |
||||
onClick={handlerConfirm} |
||||
{...(isRunning ? {} : { disabled: true })} |
||||
> |
||||
인증번호 확인 |
||||
</Button> |
||||
</Col> |
||||
</div> |
||||
</FormGroup> |
||||
<FormGroup> |
||||
<div className='full-btn-2n vertically-centered-confirmModal'> |
||||
<Button |
||||
color='secondary' |
||||
type='button' |
||||
onClick={props.handlerClose} |
||||
> |
||||
취소 |
||||
</Button> |
||||
<Button |
||||
color='primary' |
||||
type='button' |
||||
onClick={handlerFindId} |
||||
{...(isCrtfy ? {} : { disabled: true })} |
||||
> |
||||
확인 |
||||
</Button> |
||||
|
||||
<Modal |
||||
isOpen={confirmModal} |
||||
toggle={() => setConfirmModal(!confirmModal)} |
||||
modalClassName='modal-primary' |
||||
className='modal-dialog-centered' |
||||
> |
||||
<ModalHeader toggle={() => setConfirmModal(!confirmModal)}> |
||||
아이디 확인 |
||||
</ModalHeader> |
||||
<ModalBody> |
||||
회원님의 아이디는 |
||||
<br /> |
||||
<span className='user-search-id'> |
||||
{userId?.data.userId} |
||||
</span>{' '} |
||||
입니다. |
||||
{/* 회원님의 아이디는<br/><span className='user-search-id'>{result?.data.userId}</span> 입니다. */} |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color='primary' onClick={props.handlerClose}> |
||||
로그인 |
||||
</Button>{' '} |
||||
</ModalFooter> |
||||
</Modal> |
||||
</div> |
||||
</FormGroup> |
||||
|
||||
<div className='vertically-centered-modal'> |
||||
<Modal |
||||
isOpen={modal.isOpen} |
||||
toggle={() => setModal({ ...modal, isOpen: !modal.isOpen })} |
||||
modalClassName={modal.color} |
||||
className='modal-dialog-centered' |
||||
> |
||||
<ModalHeader |
||||
toggle={() => setModal({ ...modal, isOpen: !modal.isOpen })} |
||||
> |
||||
{modal.title} |
||||
</ModalHeader> |
||||
<ModalBody>{modal.desc}</ModalBody> |
||||
<ModalFooter> |
||||
<Button |
||||
color='danger' |
||||
onClick={() => setModal({ ...modal, isOpen: !modal.isOpen })} |
||||
> |
||||
확인 |
||||
</Button>{' '} |
||||
</ModalFooter> |
||||
</Modal> |
||||
</div> |
||||
</TabPane> |
||||
</> |
||||
); |
||||
}; |
@ -1,324 +0,0 @@
|
||||
// ** React Imports
|
||||
import { useState, useEffect } from 'react'; |
||||
|
||||
import { |
||||
Card, |
||||
CardBody, |
||||
Row, |
||||
Col, |
||||
Nav, |
||||
NavItem, |
||||
NavLink, |
||||
TabContent, |
||||
TabPane, |
||||
Alert, |
||||
FormGroup, |
||||
Form, |
||||
Input, |
||||
Label, |
||||
Button, |
||||
Modal, |
||||
ModalHeader, |
||||
ModalBody, |
||||
ModalFooter |
||||
} from 'reactstrap'; |
||||
|
||||
// ** Styles
|
||||
import '../../../assets/css/custom.css'; |
||||
//import {UserPageState,UserPageData,initResponseUserPageData} from '../../../../modules/account/login/models/authModel';
|
||||
//const [detailData, setDetailData] = useState(userPage.UserPageData);
|
||||
import { useHistory } from 'react-router-dom'; |
||||
|
||||
const AccountMypageForm = ({ |
||||
userInfo, |
||||
handlerSmsSend, |
||||
isCrtfy, |
||||
seconds_Counter, |
||||
handler, |
||||
minutes_Counter, |
||||
isRunning, |
||||
formModal, |
||||
handlerUpdate, |
||||
modal, |
||||
handlerSmsConfirm, |
||||
handlerChange, |
||||
handlerInput, |
||||
inputHpno, |
||||
inputCrtfy, |
||||
okinput, |
||||
|
||||
handlerWidthrow |
||||
}) => { |
||||
const history = useHistory(); |
||||
|
||||
function handleUseHitory() { |
||||
history.push('/'); |
||||
} |
||||
|
||||
return ( |
||||
<Row className='app-user-edit'> |
||||
<Col sm='12'> |
||||
<Card> |
||||
<CardBody className='card-body-tab-cont'> |
||||
<TabPane tabId='1'> |
||||
<div className='search-info-box'> |
||||
{userInfo ? ( |
||||
<Row> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label for='memberName'>이름</Label> |
||||
<Input |
||||
type='text' |
||||
id='memberName' |
||||
bsSize='sm' |
||||
placeholder='' |
||||
value={userInfo.memberName || ''} |
||||
disabled |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label for='brithdyDate'>생년월일</Label> |
||||
<Input |
||||
type='text' |
||||
id='brithdyDate' |
||||
bsSize='sm' |
||||
placeholder='' |
||||
value={userInfo.brthdyDate || ''} |
||||
disabled |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label for='cenderCD'>성별</Label> |
||||
<Input |
||||
type='select' |
||||
name='select' |
||||
bsSize='sm' |
||||
id='cenderCD' |
||||
value={userInfo.genderCd || ''} |
||||
disabled |
||||
> |
||||
<option>남자</option> |
||||
<option>여자</option> |
||||
</Input> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label for='cntryCD'>국가코드</Label> |
||||
<Input |
||||
type='select' |
||||
name='select' |
||||
bsSize='sm' |
||||
id='cntryCD' |
||||
> |
||||
<option>대한민국</option> |
||||
</Input> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label for='userId'>ID</Label> |
||||
<Input |
||||
type='text' |
||||
id='userId' |
||||
bsSize='sm' |
||||
placeholder='' |
||||
value={userInfo.userId || ''} |
||||
disabled |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label for='email'>E-mail</Label> |
||||
<Input |
||||
type='text' |
||||
id='email' |
||||
name='email' |
||||
bsSize='sm' |
||||
placeholder='' |
||||
defaultValue={userInfo.email} |
||||
onChange={e => handlerInput(e)} |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label className='form-label' for='clncd'> |
||||
휴대폰 번호 |
||||
</Label> |
||||
<div className='user-phone-btn'> |
||||
<Button.Ripple |
||||
type='button' |
||||
color='primary' |
||||
onClick={handler} |
||||
> |
||||
<span className='d-sm-inline-block'>변경</span> |
||||
</Button.Ripple> |
||||
</div> |
||||
<Input |
||||
type='number' |
||||
name='clncd' |
||||
id='hpno' |
||||
bsSize='sm' |
||||
placeholder='' |
||||
disabled |
||||
value={!okinput ? userInfo.hpno || '' : inputHpno} |
||||
/> |
||||
<div> |
||||
<Modal |
||||
isOpen={formModal} |
||||
toggle={handler} |
||||
className='modal-dialog-centered' |
||||
> |
||||
<ModalHeader toggle={handler}> |
||||
휴대폰번호 변경 |
||||
</ModalHeader> |
||||
<ModalBody> |
||||
<div className='modal-box'> |
||||
<p className='ti'>휴대폰 번호 변경</p> |
||||
<p className='txt'> |
||||
변경할 휴대폰 번호로 인증을 완료해 주세요. |
||||
</p> |
||||
</div> |
||||
<Row> |
||||
<Col className='list-input' md='12'> |
||||
<FormGroup> |
||||
<Row className='input-inline-btn'> |
||||
<Col md='8'> |
||||
<Label |
||||
className='form-label' |
||||
for='hpno' |
||||
> |
||||
휴대폰 번호 |
||||
</Label> |
||||
<Input |
||||
type='number' |
||||
name='hpno' |
||||
id='hpno' |
||||
bsSize='sm' |
||||
value={inputHpno} |
||||
onChange={handlerChange} |
||||
placeholder='01012345678' |
||||
/> |
||||
</Col> |
||||
<Col md='4' xs='12'> |
||||
{/* 발송 버튼을 누르면 남은시간 d-none를 빼주세여~ 그럼나타나여~ */} |
||||
<span |
||||
className={ |
||||
!isRunning || isCrtfy |
||||
? 'time d-none' |
||||
: 'time' |
||||
} |
||||
> |
||||
남은시간 {minutes_Counter}: |
||||
{seconds_Counter} |
||||
</span> |
||||
<Button.Ripple |
||||
type='button' |
||||
color='secondary' |
||||
onClick={handlerSmsSend} |
||||
> |
||||
<span className='d-sm-inline-block'> |
||||
인증번호 발송 |
||||
</span> |
||||
</Button.Ripple> |
||||
</Col> |
||||
</Row> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='12'> |
||||
<FormGroup> |
||||
<Row className='input-inline-btn'> |
||||
<Col md='8'> |
||||
<Label |
||||
className='form-label' |
||||
for='crtfyNo' |
||||
> |
||||
인증번호 |
||||
</Label> |
||||
<Input |
||||
type='number' |
||||
name='crtfyhpNo' |
||||
id='crtfyhpNo' |
||||
bsSize='sm' |
||||
value={inputCrtfy} |
||||
onChange={handlerChange} |
||||
{...(isRunning |
||||
? {} |
||||
: { disabled: true })} |
||||
/> |
||||
</Col> |
||||
<Col md='4' xs='12'> |
||||
<Button.Ripple |
||||
type='button' |
||||
color='secondary' |
||||
onClick={handlerSmsConfirm} |
||||
{...(isRunning |
||||
? {} |
||||
: { disabled: true })} |
||||
> |
||||
<span className='d-sm-inline-block'> |
||||
인증하기 |
||||
</span> |
||||
</Button.Ripple> |
||||
</Col> |
||||
</Row> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color='primary' onClick={handler}> |
||||
확인 |
||||
</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
</div> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
) : ( |
||||
<></> |
||||
)} |
||||
</div> |
||||
<div className='d-flex justify-content-between'> |
||||
<div> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
size='sm' |
||||
onClick={handlerUpdate} |
||||
> |
||||
저장 |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
color='danger' |
||||
size='sm' |
||||
onClick={handleUseHitory} |
||||
> |
||||
취소 |
||||
</Button.Ripple> |
||||
</div> |
||||
<div> |
||||
<Button.Ripple |
||||
color='danger' |
||||
size='sm' |
||||
onClick={() => handlerWidthrow()} |
||||
> |
||||
회원탈퇴 |
||||
</Button.Ripple> |
||||
</div> |
||||
</div> |
||||
</TabPane> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
); |
||||
}; |
||||
export default AccountMypageForm; |
@ -1,143 +0,0 @@
|
||||
// ** React Imports
|
||||
import { useState, useEffect } from 'react' |
||||
import { useSelector, useDispatch } from 'react-redux' |
||||
import { |
||||
Card, CardBody, Row, Col, Nav, NavItem, NavLink, TabContent, TabPane, Alert, FormGroup, FormFeedback, Form, Input, Label, Button, |
||||
Modal, ModalHeader, ModalBody, ModalFooter |
||||
} from 'reactstrap' |
||||
// ** Styles
|
||||
import '../../../assets/css/custom.css'; |
||||
import { pwUpdateAction, pwCheckAction } from '../../../modules/account/login/actions/authAction'; |
||||
import { useHistory } from 'react-router-dom'; |
||||
import { ErrorModal } from '../../modal/ErrorModal'; |
||||
|
||||
|
||||
const AccountMypagePwForm = ({ activeTab }) => { |
||||
const { result } = useSelector(state => state.UserPageState) |
||||
const [userPswd, setuserPswd] = useState(''); |
||||
const [inputs, setInputs] = useState({ |
||||
newPswd: '', |
||||
newPswdConfirm: '' |
||||
}); |
||||
const { newPswd, newPswdConfirm } = inputs; |
||||
|
||||
const [resultOk, setresultOk] = useState(true); |
||||
const [btnOk, setbtnOk] = useState(false); |
||||
const [modal, setModal] = useState({ |
||||
isOpen: false, |
||||
title: '', |
||||
desc: '' |
||||
}); |
||||
|
||||
useEffect(() => { |
||||
if (result) { |
||||
if (result.errorCode) { |
||||
setresultOk(true) |
||||
setbtnOk(false) |
||||
} else { |
||||
setresultOk(false) |
||||
setbtnOk(true) |
||||
} |
||||
} |
||||
}, [result]) |
||||
|
||||
useEffect(() => { |
||||
setresultOk(true) |
||||
setbtnOk(false) |
||||
}, [activeTab]) |
||||
|
||||
|
||||
const dispatch = useDispatch(); |
||||
|
||||
const history = useHistory(); |
||||
|
||||
const onChange = (e) => { |
||||
setuserPswd(e.target.value); |
||||
}; |
||||
|
||||
const onKeyPress = e => { |
||||
if (e.key == 'Enter') { |
||||
pwok(); |
||||
} |
||||
}; |
||||
const onChanges = (e) => { |
||||
const { value, name } = e.target; |
||||
setInputs({ |
||||
...inputs, |
||||
[name]: value |
||||
}); |
||||
}; |
||||
|
||||
function handleUseHitory() { |
||||
history.push('/'); |
||||
} |
||||
|
||||
function pwSubmit() { |
||||
const reg_pw = |
||||
/^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@$!%*#?&])[A-Za-z0-9@$!%*#?&]{8,20}$/; |
||||
if (!reg_pw.test(inputs.newPswd && inputs.newPswdConfirm)) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '필수값 입력 오류', |
||||
desc: '8 자 이상, 20 자 미만 영문자/숫자/특수문자(@$!%*#?&) 조합하여 입력해 주세요.', |
||||
}); |
||||
} |
||||
else if (inputs.newPswd != inputs.newPswdConfirm) { |
||||
setModal({ |
||||
isOpen: true, |
||||
title: '필수값 입력 오류', |
||||
desc: '비밀번호가 일치하지 않습니다.', |
||||
}); |
||||
} |
||||
else { |
||||
dispatch(pwUpdateAction.request(inputs)); |
||||
} |
||||
} |
||||
|
||||
function pwok() { |
||||
dispatch(pwCheckAction.request(userPswd)); |
||||
} |
||||
|
||||
return ( |
||||
<Card> |
||||
<CardBody className='card-body-tab-cont'> |
||||
<TabPane tabId='2'> |
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' md='3' sm='12'> |
||||
<FormGroup> |
||||
<Label for='userPswd'>기존 비밀번호</Label> |
||||
<Input type='password' readOnly={btnOk} onKeyPress={onKeyPress} id='userPswd' onChange={onChange} value={userPswd} name="userPswd" bsSize='sm' autoComplete='off' placeholder='' /> |
||||
</FormGroup> |
||||
</Col> |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple className='mr-1' color='primary' onClick={pwok} size='sm'>확인</Button.Ripple> |
||||
</div> |
||||
|
||||
<Col className='list-input' md='3' sm='12' style={{ display: resultOk ? 'none' : 'inline' }} > |
||||
<FormGroup> |
||||
<Label for='newPswd' >새로운 비밀번호</Label> |
||||
<Input type='password' id='newPswd' onChange={onChanges} value={newPswd} name="newPswd" bsSize='sm' autoComplete='off' placeholder='' /> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' md='3' sm='12' style={{ display: resultOk ? 'none' : 'inline' }}> |
||||
<FormGroup> |
||||
<Label for='newPswdConfirm'>새로운 비밀번호 확인</Label> |
||||
<Input type='password' id='newPswdConfirm' onChange={onChanges} value={newPswdConfirm} name="newPswdConfirm" bsSize='sm' autoComplete='off' placeholder='' /> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple className='mr-1' color='primary' onClick={pwSubmit} disabled={resultOk} size='sm'>저장</Button.Ripple> |
||||
<Button.Ripple color='danger' size='sm' onClick={handleUseHitory}>취소</Button.Ripple> |
||||
</div> |
||||
</TabPane> |
||||
</CardBody> |
||||
<ErrorModal modal={modal} setModal={setModal} /> |
||||
</Card > |
||||
) |
||||
} |
||||
|
||||
export default AccountMypagePwForm; |
||||
|
@ -1,61 +1,62 @@
|
||||
import { GridDatabase } from '../../../components/crud/grid/GridDatatable'; |
||||
import { Card, Spinner } from 'reactstrap'; |
||||
import { |
||||
Row, |
||||
Col, |
||||
Table, |
||||
Badge, |
||||
UncontrolledDropdown, |
||||
DropdownMenu, |
||||
DropdownItem, |
||||
DropdownToggle, |
||||
Card, |
||||
CardHeader, |
||||
CardBody, |
||||
CardTitle, |
||||
CardSubtitle, |
||||
ButtonGroup, |
||||
Button, |
||||
Input, |
||||
CustomInput, |
||||
FormGroup |
||||
} from 'reactstrap'; |
||||
import { ExcelExportButton } from '../../crud/excel/ExcelExportButton'; |
||||
import { useSelector } from 'react-redux'; |
||||
|
||||
export const AnalysisHistoryGrid = props => { |
||||
const { loading } = useSelector(state => state.loadingReducer); |
||||
return ( |
||||
// <div className='pal-card-box'>
|
||||
// <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>{props.title} 목록</h4> |
||||
<span className='search-case'>검색결과 총 {props.total}건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'> |
||||
<ExcelExportButton |
||||
filename={'비행이력.csv'} |
||||
data={props.data ? props.data : []} |
||||
headers={props.excelHeaders} |
||||
/> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
{/* <div className='no-dataTable'> |
||||
<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>{props.title} 목록</h4> |
||||
<span className='search-case'>검색결과 총 {props.count}건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'> |
||||
<ExcelExportButton |
||||
filename={'비행이력.csv'} |
||||
data={props.data ? props.data : []} |
||||
headers={props.excelHeaders} |
||||
/> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
{/* <div className='no-dataTable'> |
||||
표시할 데이터가 없습니다. |
||||
</div> */} |
||||
{loading ? ( |
||||
<div className='grid-loading'> |
||||
<div> |
||||
<Spinner color='primary' /> |
||||
<span>Loading...</span> |
||||
</div> |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={props.data} |
||||
count={props.count} |
||||
columns={props.columns} |
||||
pagination={props.pagination} |
||||
/> |
||||
</div> |
||||
) : null} |
||||
|
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={props.data} |
||||
count={props.count} |
||||
total={props.total} |
||||
columns={props.columns} |
||||
pagination={props.pagination} |
||||
handlerPageChange={props.handlerPageChange} |
||||
paginationPerPage={props.paginationPerPage} |
||||
paginationRowsPerPageOptions={props.paginationRowsPerPageOptions} |
||||
page={props.page} |
||||
/> |
||||
</Card> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
// </Col>
|
||||
// </Row>
|
||||
// </div>
|
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
}; |
||||
|
@ -1,123 +0,0 @@
|
||||
import moment from 'moment'; |
||||
import { useEffect, useState, useRef, useCallback } from 'react'; |
||||
import { useSelector } from 'react-redux'; |
||||
import { Spinner } from 'reactstrap'; |
||||
|
||||
export const AnalysimuationInfo = props => { |
||||
const [target, setTarget] = useState(null); |
||||
|
||||
const { loading } = useSelector(state => state.loadingReducer); |
||||
|
||||
const onIntersect = useCallback( |
||||
([entry], observer) => { |
||||
if (entry.isIntersecting) { |
||||
if (props.data?.filter(i => i === undefined).length <= 0) { |
||||
props.handlerPageList(); |
||||
} |
||||
} |
||||
}, |
||||
[props.handlerPageList] |
||||
); |
||||
|
||||
useEffect(() => { |
||||
let observer; |
||||
if (target) { |
||||
observer = new IntersectionObserver(onIntersect, { |
||||
threshold: 0.4 |
||||
}); |
||||
observer.observe(target); |
||||
} |
||||
return () => observer && observer.disconnect(); |
||||
}, [target, props.handlerPageList]); |
||||
|
||||
return ( |
||||
<div className='layer-content drone-list'> |
||||
{!props.data ? ( |
||||
<> |
||||
<div className='no-dataTable'>표시할 데이터가 없습니다.</div> |
||||
{loading && ( |
||||
<div |
||||
style={{ |
||||
display: 'flex', |
||||
justifyContent: 'center', |
||||
flexDirection: 'column', |
||||
alignItems: 'center' |
||||
}} |
||||
> |
||||
<Spinner color='primary' /> |
||||
<span>Loading...</span> |
||||
</div> |
||||
)} |
||||
</> |
||||
) : ( |
||||
<> |
||||
{props.data |
||||
?.filter(i => i !== undefined) |
||||
.map(item => { |
||||
// item.idntfNum,
|
||||
// ':::',
|
||||
// item.idntfNum.indexOf(props.filterId)
|
||||
// );
|
||||
|
||||
if (item.idntfNum) { |
||||
return ( |
||||
<div |
||||
className={`layer-content-list ${ |
||||
item.cntrlId === props.cntrlId ? 'on' : '' |
||||
}`}
|
||||
onClick={() => { |
||||
props.handlerDetail(item.cntrlId); |
||||
}} |
||||
key={Math.random()} |
||||
> |
||||
<dl> |
||||
<dt> |
||||
<div className='list-left-txt'>식별번호</div> |
||||
<div className='list-right-txt'>{item.idntfNum}</div> |
||||
</dt> |
||||
<dt> |
||||
<div className='list-left-txt'>일자</div> |
||||
<div className='list-right-txt'> |
||||
{moment(item.cntrlStDt).format('YYYY년MM월DD일')} |
||||
</div> |
||||
</dt> |
||||
<dt> |
||||
<div className='list-left-txt'>시작 위치</div> |
||||
<div className='list-right-txt'>{item.stArea}</div> |
||||
</dt> |
||||
<dt> |
||||
<div className='list-left-txt'>시작/종료 시간</div> |
||||
<div className='list-right-txt'> |
||||
{moment(item.cntrlStDt).format('HH:mm')} |
||||
{' '}/{' '} |
||||
{moment(item.cntrlEndDt).format('HH:mm')} |
||||
</div> |
||||
</dt> |
||||
{/* <dt> |
||||
<div className='list-left-txt'>총 비행거리/시간</div> |
||||
<div className='list-right-txt'>ddd</div> |
||||
</dt> */} |
||||
</dl> |
||||
</div> |
||||
); |
||||
} |
||||
})} |
||||
{loading && ( |
||||
<div |
||||
style={{ |
||||
display: 'flex', |
||||
justifyContent: 'center', |
||||
flexDirection: 'column', |
||||
alignItems: 'center' |
||||
}} |
||||
> |
||||
<Spinner color='primary' /> |
||||
<span>Loading...</span> |
||||
</div> |
||||
)} |
||||
<div ref={setTarget} /> |
||||
</> |
||||
)} |
||||
</div> |
||||
); |
||||
}; |
@ -1,132 +0,0 @@
|
||||
import React, { useEffect, useState } from 'react'; |
||||
import { Button, Card, Col, Row, Spinner } from 'reactstrap'; |
||||
import { GridDatabase } from '../../../crud/grid/GridDatatable'; |
||||
import { Link } from 'react-router-dom'; |
||||
import { selectableRowsComponent } from '../../../crud/grid/selectableRowsComponent'; |
||||
import { useSelector } from 'react-redux'; |
||||
|
||||
const FlightPlanAprvGrid = ({ |
||||
data, |
||||
handleChangeSelected, |
||||
handleClickAprv, |
||||
paginationPerPage, |
||||
pagination, |
||||
paginationRowsPerPageOptions, |
||||
handlerPageChange, |
||||
total, |
||||
isMyGroup |
||||
}) => { |
||||
const { loading } = useSelector(state => state.loadingReducer); |
||||
|
||||
const columns = [ |
||||
{ |
||||
id: 'planSno', |
||||
name: '번호', |
||||
cell: (row, i) => <div>{i + 1}</div> |
||||
}, |
||||
{ |
||||
id: 'fltPurpose', |
||||
name: '비행목적', |
||||
minWidth: '150px', |
||||
cell: (row, i) => <div>{row.fltPurpose}</div> |
||||
}, |
||||
{ |
||||
id: 'fltMethod', |
||||
name: '비행방식', |
||||
minWidth: '200px', |
||||
cell: row => { |
||||
const displayName = |
||||
(row.areaList && |
||||
row.areaList.length > 0 && |
||||
row.areaList[0].fltMethod) || |
||||
'-'; |
||||
return <div>{displayName}</div>; |
||||
} |
||||
}, |
||||
{ |
||||
id: 'schFltStDt', |
||||
name: '출발일', |
||||
minWidth: '200px', |
||||
cell: row => <div>{row.schFltStDt}</div> |
||||
}, |
||||
{ id: 'aprvlYn', name: '승인여부', cell: row => <div>{row.aprvlYn}</div> }, |
||||
{ |
||||
id: 'moveDetail', |
||||
name: '상세보기', |
||||
cell: row => { |
||||
return ( |
||||
<Link |
||||
to={`/basis/flight/plan/detail/${row.planSno}?type=aprv`} |
||||
size='sm' |
||||
> |
||||
상세보기 |
||||
</Link> |
||||
); |
||||
} |
||||
} |
||||
]; |
||||
|
||||
return ( |
||||
<> |
||||
<div className='mt-2 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')} |
||||
{...(isMyGroup ? {} : { disabled: true })} |
||||
> |
||||
승인 |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
style={{ marginLeft: 10 }} |
||||
onClick={handleClickAprv('notAprov')} |
||||
{...(isMyGroup ? {} : { disabled: true })} |
||||
> |
||||
미승인 |
||||
</Button.Ripple> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
{loading ? ( |
||||
<div className='grid-loading'> |
||||
<div> |
||||
<Spinner color='primary' /> |
||||
<span>Loading...</span> |
||||
</div> |
||||
</div> |
||||
) : null} |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={data} |
||||
columns={columns} |
||||
count={!!data ? data.length : 0} |
||||
// pagination={props.pagination}
|
||||
selectableRows |
||||
selectableRowsComponent={selectableRowsComponent} |
||||
onSelectedRowsChange={handleChangeSelected} |
||||
pagination={pagination} |
||||
paginationPerPage={paginationPerPage} |
||||
paginationRowsPerPageOptions={paginationRowsPerPageOptions} |
||||
handlerPageChange={handlerPageChange} |
||||
total={total} |
||||
/> |
||||
{/* 검색된 데이터가 없습니다. */} |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default FlightPlanAprvGrid; |
@ -1,27 +0,0 @@
|
||||
import React from 'react'; |
||||
import { GridDatabase } from '../../../crud/grid/GridDatatable'; |
||||
import { Card, Button } from 'reactstrap'; |
||||
|
||||
const FlightPlanAprvGroupGrid = ({ data, count, columns, pagination, paginationPerPage, paginationRowsPerPageOptions }) => { |
||||
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} |
||||
pagination={pagination} paginationPerPage={paginationPerPage} paginationRowsPerPageOptions={paginationRowsPerPageOptions} /> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default FlightPlanAprvGroupGrid; |
@ -1,174 +0,0 @@
|
||||
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> |
||||
<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' |
||||
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; |
@ -1,131 +0,0 @@
|
||||
import React from 'react'; |
||||
import {Button, Card, CardBody, Col, CustomInput, Row, FormGroup, Input, Label} from 'reactstrap'; |
||||
import {Search} from 'react-feather'; |
||||
import {GridDatabase} from '../../../crud/grid/GridDatatable'; |
||||
import '../../../../assets/css/custom.css'; |
||||
import '@styles/react/libs/tables/react-dataTable-component.scss'; |
||||
|
||||
const FlightPlanArcrft = ({ arcrftList, handleSelectArcrft, onClickEvent, name, returnArcrft,onChange }) => { |
||||
const columns = [ |
||||
{id: 'groupNm', name: '그룹 명', cell: row => (<div>{row.groupNm}</div>)}, |
||||
{id: 'arcrftModelNm', name: '모델 명', cell: row => (<div>{row.arcrftModelNm}</div>)}, |
||||
{id: 'idntfTypeCd', name: '종류', cell: row => (<div>{row.arcrftTypeCd}</div>)}, |
||||
{id: 'ownerNm', name: '소유자 명', cell: row => (<div>{row.ownerNm}</div>)}, |
||||
{id: 'idntfNum', name: '식별코드', cell: row => (<div>{row.idntfNum}</div>)}, |
||||
{ |
||||
id: 'selectPilot', name: '선택', cell: row => { |
||||
return <Button.Ripple color='primary' size='sm' onClick={() => { |
||||
handleSelectArcrft(row.idntfNum)
|
||||
} |
||||
}>선택</Button.Ripple>; |
||||
}
|
||||
} |
||||
]; |
||||
|
||||
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> |
||||
{arcrftList?( |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
onClick={onClickEvent} |
||||
> |
||||
<Search size={16}/> |
||||
검색 |
||||
</Button.Ripple> |
||||
</div> |
||||
) |
||||
: |
||||
( |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
onClick={onClickEvent} |
||||
disabled |
||||
> |
||||
<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='4' sm='12'> |
||||
<FormGroup className='form-label-group'> |
||||
<Input |
||||
type='text' |
||||
id='ownerNm' |
||||
name='ownerNm' |
||||
value={name} |
||||
onChange={onChange} |
||||
bsSize='sm' |
||||
// onKeyPress={props.onKeyPress}
|
||||
placeholder='소유자 명을 입력하세요' |
||||
/> |
||||
<Label for='test'>소유자 명</Label> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
|
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<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'>검색결과 총 {!!returnArcrft ? returnArcrft.length : 0}건</span> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase
|
||||
data={returnArcrft} |
||||
count={returnArcrft ? returnArcrft.length : 0} |
||||
columns={columns} |
||||
// pagination={props.pagination}
|
||||
/> |
||||
{/* 검색된 데이터가 없습니다. */} |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</> |
||||
) |
||||
|
||||
} |
||||
|
||||
export default FlightPlanArcrft; |
@ -1,266 +1,206 @@
|
||||
import React, { useEffect, useState } from 'react'; |
||||
import { useDispatch, useSelector } from 'react-redux'; |
||||
import { object } from 'prop-types'; |
||||
import { |
||||
Card, |
||||
CardBody, |
||||
Col, |
||||
Col,
|
||||
FormGroup, |
||||
Label, |
||||
Row, |
||||
Button, |
||||
InputGroupAddon, |
||||
InputGroup, |
||||
Input, |
||||
Table |
||||
Label, |
||||
Row,
|
||||
Button
|
||||
} from 'reactstrap'; |
||||
const FlightPlanAreaDetailForm = ({ |
||||
handleSave, |
||||
handleClose, |
||||
handleChange, |
||||
handleBufferList, |
||||
data, |
||||
mapControl, |
||||
isDone, |
||||
isDisabled |
||||
}) => { |
||||
const coordList = data ? data[0].coordList : null; |
||||
const dispatch = useDispatch(); |
||||
import { useDispatch, useSelector } from 'react-redux'; |
||||
import { FeatureAirZone } from '../../../map/naver/feature/FeatureAirZone'; |
||||
import { FlightPlanDraw } from '../../../map/naver/draw/FlightPlanDraw'; |
||||
import { drawTypeChangeAction, drawCheckAction } from '../../../../modules/control/map/actions/controlMapActions'; |
||||
import { FlightPlanDrawTest } from '../../../map/naver/draw/FlightPlanDrawTest'; |
||||
|
||||
const FlightPlanAreaDetailForm = (props) => { |
||||
const dispatch = useDispatch(); |
||||
const naver = window.naver; |
||||
// const airArea = props.airArea;
|
||||
|
||||
const mapControl = useSelector(state => state.controlMapReducer); |
||||
|
||||
return ( |
||||
<Card className='mb-0'> |
||||
<CardBody> |
||||
<Row> |
||||
<Col> |
||||
<Card> |
||||
<CardBody className='pal-card-body'> |
||||
<div className='search-cont search-info pd-0'> |
||||
<div className='cont-ti mb-1 d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>비행 구역 상세 정보</h4> |
||||
</div> |
||||
</div> |
||||
const [map, setMap] = useState(); |
||||
const [isMapLoad, setIsMapLoad] = useState(false); |
||||
const [mode, setMode] = useState(); |
||||
|
||||
// useEffect(() => {
|
||||
// setIsMapLoad(true);
|
||||
// }, [airArea]);
|
||||
|
||||
// useEffect(() => {
|
||||
// ModeInit();
|
||||
// }, [mapControl.drawType])
|
||||
|
||||
<dl> |
||||
<dt> |
||||
<div className='search-info-ti d-flex justify-content-between'> |
||||
<h4 className='ti'>좌표 정보</h4> |
||||
// const ModeInit = () => {
|
||||
// setMode(mapControl.drawType)
|
||||
// }
|
||||
|
||||
return ( |
||||
// <Card className='mb-0'>
|
||||
<Row> |
||||
<Col sm='12'> |
||||
<Card> |
||||
<CardBody className='pt-2 card-body-tab-cont'>
|
||||
<Row> |
||||
<Col> |
||||
<Card> |
||||
<CardBody className='pal-card-body'>
|
||||
<div className='search-cont search-info pd-0'> |
||||
<div className='cont-ti mb-1 d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>비행 구역 상세 정보</h4> |
||||
</div> |
||||
</div> |
||||
|
||||
<div className='search-info-box'> |
||||
<Row> |
||||
{coordList ? ( |
||||
coordList.map((coord, idx) => { |
||||
const latlon = coord.lat + ' / ' + coord.lon; |
||||
<dl> |
||||
<dt> |
||||
<div className='search-info-ti d-flex justify-content-between'> |
||||
<h4>좌표</h4> |
||||
</div> |
||||
|
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={4} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'><span className='necessary'>*</span>좌표1</Label> |
||||
<Input |
||||
type='text' |
||||
id='coord' |
||||
name='coord' |
||||
bsSize='sm' |
||||
placeholdeer='' |
||||
readOnly |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' lg={4} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'><span className='necessary'>*</span>좌표2</Label> |
||||
<Input |
||||
type='text' |
||||
id='coord' |
||||
name='coord' |
||||
bsSize='sm' |
||||
placeholdeer='' |
||||
readOnly |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
|
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={4} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'><span className='necessary'>*</span>좌표3</Label> |
||||
<Input |
||||
type='text' |
||||
id='coord' |
||||
name='coord' |
||||
bsSize='sm' |
||||
placeholdeer='' |
||||
readOnly |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' lg={4} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'><span className='necessary'>*</span>좌표4</Label> |
||||
<Input |
||||
type='text' |
||||
id='coord' |
||||
name='coord' |
||||
bsSize='sm' |
||||
placeholdeer='' |
||||
readOnly |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</dt> |
||||
|
||||
return ( |
||||
<Col |
||||
key={idx} |
||||
className='list-input' |
||||
lg={6} |
||||
md={6} |
||||
sm={12} |
||||
> |
||||
<FormGroup> |
||||
<dt> |
||||
<div className='search-info-ti d-flex justify-content-between'> |
||||
<h4>기타정보</h4> |
||||
</div> |
||||
|
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={5} md={7} sm={12}> |
||||
<FormGroup className='m_ft'> |
||||
<div className='m_ft_box'> |
||||
<Label for='test'> |
||||
<span className='necessary'>*</span>좌표{' '} |
||||
{idx + 1}{' '} |
||||
<span className='necessary'>*</span> 반경 / 고도 |
||||
</Label> |
||||
<Input |
||||
type='text' |
||||
name='coord' |
||||
id='ownerNm' |
||||
name='ownerNm'
|
||||
bsSize='sm' |
||||
placeholdeer='' |
||||
readOnly |
||||
value={latlon} |
||||
placeholder='반경'
|
||||
readOnly
|
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
); |
||||
}) |
||||
) : ( |
||||
<Col className='list-input' lg={6} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'> |
||||
<span className='necessary'>*</span>좌표 1 |
||||
</Label> |
||||
<Input |
||||
type='text' |
||||
name='coord' |
||||
bsSize='sm' |
||||
placeholdeer='' |
||||
readOnly |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
)} |
||||
</Row> |
||||
</div> |
||||
</dt> |
||||
|
||||
<dt> |
||||
<div className='search-info-ti d-flex justify-content-between'> |
||||
<h4 className='ti'>기타 정보</h4> |
||||
</div> |
||||
|
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={6} md={6} sm={12}> |
||||
<FormGroup className='m_ft'> |
||||
<div className='m_ft_box'> |
||||
<Label for='test'> |
||||
<span className='necessary'>*</span>반경(m) |
||||
</Label> |
||||
<Input |
||||
type='text' |
||||
id='bufferZone' |
||||
name='bufferZone' |
||||
bsSize='sm' |
||||
disabled={ |
||||
isDisabled || isDone |
||||
? true |
||||
: coordList[0].lat && |
||||
data[0].areaType && |
||||
data[0].areaType !== 'POLYGON' |
||||
? false |
||||
: true |
||||
} |
||||
placeholder='반경' |
||||
value={ |
||||
data[0].bufferZone ? data[0].bufferZone : '' |
||||
} |
||||
onChange={e => { |
||||
const { name, value } = e.target; |
||||
handleChange({ |
||||
name, |
||||
value |
||||
}); |
||||
}} |
||||
/> |
||||
</div> |
||||
<div className='m_ft_box'> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
size='sm' |
||||
disabled={ |
||||
isDisabled || isDone |
||||
? true |
||||
: coordList[0].lat && |
||||
data[0].areaType && |
||||
data[0].areaType !== 'POLYGON' |
||||
? false |
||||
: true |
||||
} |
||||
onClick={() => handleBufferList()} |
||||
> |
||||
적용 |
||||
</Button.Ripple> |
||||
</div> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={6} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'> |
||||
<span className='necessary'>*</span>고도(ft) |
||||
</Label> |
||||
|
||||
<Input |
||||
type='text' |
||||
id='fltElev' |
||||
name='fltElev' |
||||
bsSize='sm' |
||||
placeholder='고도' |
||||
value={data[0].fltElev ? data[0].fltElev : ''} |
||||
onChange={e => { |
||||
const { name, value } = e.target; |
||||
handleChange({ |
||||
name, |
||||
value |
||||
}); |
||||
}} |
||||
disabled={isDisabled || isDone} |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={6} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'> |
||||
<span className='necessary'>*</span>비행 방식 |
||||
</Label> |
||||
<Input |
||||
type='text' |
||||
id='fltMethod' |
||||
name='fltMethod' |
||||
bsSize='sm' |
||||
placeholder='비행 방식' |
||||
value={ |
||||
data[0].fltMethod ? data[0].fltMethod : '' |
||||
} |
||||
onChange={e => { |
||||
const { name, value } = e.target; |
||||
handleChange({ |
||||
name, |
||||
value |
||||
}); |
||||
}} |
||||
disabled={isDisabled || isDone} |
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
|
||||
<div className='d-flex align-items-center mt-2'> |
||||
{isDisabled || isDone ? ( |
||||
<Button.Ripple |
||||
type='submit' |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handleSave()} |
||||
disabled={isDisabled || isDone} |
||||
> |
||||
등록 |
||||
</Button.Ripple> |
||||
) : ( |
||||
<Button.Ripple |
||||
type='submit' |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handleSave()} |
||||
disabled={!coordList[0].lat ? true : false} |
||||
> |
||||
등록 |
||||
</Button.Ripple> |
||||
)} |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handleClose()} |
||||
> |
||||
닫기 |
||||
</Button.Ripple> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
</CardBody> |
||||
</Card> |
||||
); |
||||
</div> |
||||
<div className='m_ft_box'> |
||||
<Input |
||||
type='text' |
||||
id='ownerNm' |
||||
name='ownerNm'
|
||||
bsSize='sm' |
||||
placeholder='고도'
|
||||
readOnly
|
||||
/> |
||||
</div> |
||||
</FormGroup> |
||||
</Col> |
||||
<Col className='list-input' lg={4} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'><span className='necessary'>*</span>비행방식</Label> |
||||
<Input |
||||
type='text' |
||||
id='ownerNm' |
||||
name='ownerNm'
|
||||
bsSize='sm' |
||||
placeholder=''
|
||||
readOnly
|
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
|
||||
<div className='d-flex align-items-center mt-2'> |
||||
<Button.Ripple |
||||
type='submit' |
||||
className='mr-1' |
||||
color='primary' |
||||
> |
||||
등록 |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
> |
||||
닫기 |
||||
</Button.Ripple> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
) |
||||
} |
||||
|
||||
export default FlightPlanAreaDetailForm; |
||||
export default FlightPlanAreaDetailForm; |
@ -0,0 +1,40 @@
|
||||
import { useEffect, useState } from 'react'; |
||||
import { Modal, ModalHeader, ModalBody } from 'reactstrap'; |
||||
import FlightPlanAreaDetailContainer from '../../../../containers/basis/flight/plan/FlightPlanAreaDetailContainer'; |
||||
|
||||
export const FlightPlanAreaDetailModal = props => {
|
||||
|
||||
const [onSubmit, setOnSubmit] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
console.log('비행구역 상세정보 모달') |
||||
}, []) |
||||
|
||||
return ( |
||||
<div className='vertically-centered-modal'> |
||||
<Modal |
||||
isOpen={props.modal.isOpen} |
||||
// toggle={() =>
|
||||
// props.setModal({ ...props.modal, isOpen: !props.modal.isOpen })
|
||||
// }
|
||||
className='modal-dialog-centered modal-xl' |
||||
> |
||||
<ModalHeader |
||||
toggle={() => |
||||
props.setModal({ ...props.modal, isOpen: !props.modal.isOpen }) |
||||
} |
||||
> |
||||
{props.modal.title} |
||||
</ModalHeader> |
||||
<ModalBody> |
||||
<FlightPlanAreaDetailContainer |
||||
modal={props.modal} |
||||
setModal={props.setModal}
|
||||
onSubmit={onSubmit}
|
||||
setOnSubmit={setOnSubmit}
|
||||
/> |
||||
</ModalBody> |
||||
</Modal> |
||||
</div> |
||||
); |
||||
}; |
@ -0,0 +1,115 @@
|
||||
import React, { useState, useEffect } from 'react'; |
||||
import classnames from 'classnames'; |
||||
import { |
||||
Card, |
||||
CardBody, |
||||
Col,
|
||||
FormGroup, |
||||
FormFeedback, |
||||
Input, |
||||
Label, |
||||
Row,
|
||||
Button, |
||||
Form |
||||
} from 'reactstrap'; |
||||
|
||||
|
||||
const FlightPlanAreaForm = (props) => {
|
||||
|
||||
return (
|
||||
<Card> |
||||
<CardBody>
|
||||
<div className='search-cont search-info pd-0'> |
||||
<div className='cont-ti mb-1 d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>상세 정보</h4> |
||||
</div> |
||||
<div className='final'> |
||||
{/* {props.type === 'update' ? ( |
||||
<span>최종 수정일자 : {props.updateDt}</span> |
||||
) : null} */} |
||||
</div> |
||||
</div> |
||||
|
||||
<dl> |
||||
<dt>
|
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={6} md={6} sm={12}> |
||||
<FormGroup> |
||||
<Label for='test'> |
||||
<span className='necessary'></span>반경(m) |
||||
</Label> |
||||
<Input |
||||
type='text' |
||||
id='radius' |
||||
name='radius'
|
||||
size='sm' |
||||
placeholder=''
|
||||
innerRef={props.data}
|
||||
/> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<div className='search-info-box'> |
||||
<Row> |
||||
<Col className='list-input' lg={6} md={6} sm={12}> |
||||
<FormGroup className='m_ft'> |
||||
<div className='m_ft_box'> |
||||
<Label for='test'> |
||||
<span className='necessary'></span>고도(m/ft) |
||||
</Label> |
||||
<Input |
||||
type='text' |
||||
id='altitude_m' |
||||
name='altitude_m'
|
||||
size='sm' |
||||
placeholder='m'
|
||||
innerRef={props.data}
|
||||
/> |
||||
</div> |
||||
<div className='m_ft_box'>
|
||||
<Input |
||||
type='text' |
||||
id='altitude' |
||||
name='altitude'
|
||||
size='sm' |
||||
placeholder='ft'
|
||||
innerRef={props.data}
|
||||
/> |
||||
</div> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
|
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
size='sm' |
||||
onClick={ |
||||
props.submit |
||||
} |
||||
> |
||||
확인 |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='danger' |
||||
size='sm' |
||||
onClick={() =>
|
||||
props.setModal({ ...props.modal, isOpen: !props.modal.isOpen }) |
||||
} |
||||
> |
||||
취소 |
||||
</Button.Ripple> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
) |
||||
} |
||||
|
||||
export default FlightPlanAreaForm; |
@ -1,443 +1,174 @@
|
||||
import React, { useEffect, useState } from 'react'; |
||||
import { |
||||
Card, |
||||
CardBody, |
||||
Button, |
||||
Input, |
||||
InputGroup, |
||||
InputGroupAddon, |
||||
InputGroupText, |
||||
Modal, |
||||
ModalHeader, |
||||
ModalBody, |
||||
ModalFooter |
||||
Card, |
||||
CardBody, |
||||
Button |
||||
} from 'reactstrap'; |
||||
import { Search } from 'react-feather'; |
||||
import { useDispatch, useSelector } from 'react-redux'; |
||||
import { FeatureAirZone } from '../../../map/naver/feature/FeatureAirZone'; |
||||
import { drawTypeChangeAction } from '../../../../modules/control/map/actions/controlMapActions'; |
||||
import { FlightPlanDraw_init } from '../../../map/naver/draw/FlightPlanDraw'; |
||||
import { initFlightBas } from '../../../../modules/basis/flight/models/basisFlightModel'; |
||||
import { |
||||
AREA_COORDINATE_LIST_SAVE, |
||||
AREA_DETAIL_INIT |
||||
} from '../../../../modules/basis/flight/actions/basisFlightAction'; |
||||
import { flightPlanAPI } from '../../../../modules/basis/flight/apis/basisFlightApi'; |
||||
import { WeatherContainer } from '../../../../containers/basis/flight/plan/WeatherContainer'; |
||||
import gimpo from '../../../map/geojson/airportAirArea.json'; |
||||
const FlightPlanAreaMap = props => { |
||||
const dispatch = useDispatch(); |
||||
const naver = window.naver; |
||||
const airArea = props.airArea; |
||||
const mapControl = useSelector(state => state.controlMapReducer); |
||||
const { areaCoordList } = useSelector(state => state.flightState); |
||||
|
||||
const [map, setMap] = useState(); |
||||
const [isMapLoad, setIsMapLoad] = useState(false); |
||||
const [mode, setMode] = useState(); |
||||
const [mapAreaCoordList, setMapAreaCoordList] = useState( |
||||
initFlightBas.initDetail.areaList |
||||
); |
||||
|
||||
const [query, setQuery] = useState(''); |
||||
const [searchRes, setSearchRes] = useState([]); |
||||
const [isSearch, setIsSearch] = useState(false); |
||||
|
||||
const [dragSize, setDragSize] = useState(70); |
||||
const [pastDragCircle, setDragCircle] = useState([]); |
||||
|
||||
const [number, setNumber] = useState(0); |
||||
import { drawTypeChangeAction, drawCheckAction } from '../../../../modules/control/map/actions/controlMapActions'; |
||||
import { FlightPlanDrawTest } from '../../../map/naver/draw/FlightPlanDrawTest'; |
||||
|
||||
const [formModal, setFormModal] = useState(false); |
||||
const FlightPlanAreaMap = (props) => { |
||||
const dispatch = useDispatch(); |
||||
const naver = window.naver; |
||||
const airArea = props.airArea; |
||||
const openModal = props.openModal; |
||||
|
||||
const [coordCenter, setCoordCenter] = useState([]); // 격자 센터값
|
||||
const mapControl = useSelector(state => state.controlMapReducer); |
||||
|
||||
let gimPofeatures = gimpo.features; |
||||
|
||||
useEffect(() => { |
||||
NaverMapInit(); |
||||
|
||||
const coords = []; |
||||
gimPofeatures.map(air => { |
||||
coords.push({ |
||||
lat: |
||||
(Math.max( |
||||
air.geometry.coordinates[0][0][1], |
||||
air.geometry.coordinates[0][1][1], |
||||
air.geometry.coordinates[0][2][1], |
||||
air.geometry.coordinates[0][3][1] |
||||
) + |
||||
Math.min( |
||||
air.geometry.coordinates[0][0][1], |
||||
air.geometry.coordinates[0][1][1], |
||||
air.geometry.coordinates[0][2][1], |
||||
air.geometry.coordinates[0][3][1] |
||||
)) / |
||||
2, |
||||
lng: |
||||
(Math.max( |
||||
air.geometry.coordinates[0][0][0], |
||||
air.geometry.coordinates[0][1][0], |
||||
air.geometry.coordinates[0][2][0], |
||||
air.geometry.coordinates[0][3][0] |
||||
) + |
||||
Math.min( |
||||
air.geometry.coordinates[0][0][0], |
||||
air.geometry.coordinates[0][1][0], |
||||
air.geometry.coordinates[0][2][0], |
||||
air.geometry.coordinates[0][3][0] |
||||
)) / |
||||
2, |
||||
airspace: air.properties.airspace |
||||
}); |
||||
}); |
||||
setCoordCenter(coords); |
||||
|
||||
return () => { |
||||
dispatch(AREA_DETAIL_INIT()); |
||||
}; |
||||
}, []); |
||||
const [map, setMap] = useState(); |
||||
const [isMapLoad, setIsMapLoad] = useState(false); |
||||
const [mode, setMode] = useState(); |
||||
|
||||
useEffect(() => { |
||||
pastDragCircle.forEach(c => c.setRadius(dragSize)); |
||||
}, [dragSize]); |
||||
useEffect(() => { |
||||
NaverMapInit(); |
||||
}, []); |
||||
|
||||
useEffect(() => { |
||||
setIsMapLoad(true); |
||||
}, [airArea]); |
||||
useEffect(() => {
|
||||
setIsMapLoad(true); |
||||
}, [airArea]); |
||||
|
||||
useEffect(() => { |
||||
coordCenter.map((val, idx) => { |
||||
const position = new naver.maps.LatLng( |
||||
val.lat.toFixed(6), |
||||
val.lng.toFixed(6) |
||||
); |
||||
const marker = new naver.maps.Marker({ |
||||
position: position, |
||||
map: map, |
||||
icon: { |
||||
content: `<div style="color:#000000;font-size:10px;">${val.airspace}</div>`, |
||||
size: new naver.maps.Size(0, 0), |
||||
origin: new naver.maps.Point(0, 0), |
||||
anchor: new naver.maps.Point(7, 5), |
||||
align: 'center' |
||||
} |
||||
}); |
||||
}); |
||||
}, [coordCenter]); |
||||
useEffect(() => { |
||||
ModeInit(); |
||||
}, [mapControl.drawType]); |
||||
useEffect(() => { |
||||
ModeInit(); |
||||
}, [mapControl.drawType]) |
||||
|
||||
useEffect(() => { |
||||
if (areaCoordList) { |
||||
if ( |
||||
areaCoordList[0].coordList[0].lat !== 0 && |
||||
areaCoordList[0].coordList[0].lon !== 0 |
||||
) { |
||||
if (number === 0) { |
||||
if (map) { |
||||
map.setCenter( |
||||
new naver.maps.LatLng( |
||||
areaCoordList[0].coordList[0].lat, |
||||
areaCoordList[0].coordList[0].lon |
||||
) |
||||
); |
||||
setNumber(number + 1); |
||||
} |
||||
} |
||||
setMapAreaCoordList(areaCoordList); |
||||
} |
||||
const ModeInit = () => { |
||||
setMode(mapControl.drawType) |
||||
} |
||||
}, [areaCoordList, map, number]); |
||||
|
||||
const ModeInit = () => { |
||||
setMode(mapControl.drawType); |
||||
}; |
||||
|
||||
const NaverMapInit = () => { |
||||
const bufferzoom = {}; |
||||
if (areaCoordList) { |
||||
if ( |
||||
areaCoordList[0].bufferZone >= 0 && |
||||
areaCoordList[0].bufferZone < 2000 |
||||
) { |
||||
bufferzoom.bufferzoom = 13; |
||||
} else if ( |
||||
areaCoordList[0].bufferZone >= 2000 && |
||||
areaCoordList[0].bufferZone < 5000 |
||||
) { |
||||
bufferzoom.bufferzoom = 12; |
||||
} else if ( |
||||
areaCoordList[0].bufferZone >= 5000 && |
||||
areaCoordList[0].bufferZone <= 9000 |
||||
) { |
||||
bufferzoom.bufferzoom = 11; |
||||
} else { |
||||
bufferzoom.bufferzoom = 10; |
||||
} |
||||
} |
||||
const mapOptions = { |
||||
// center: new naver.maps.LatLng(36.56793936069445, 127.85101412107547),
|
||||
center: new naver.maps.LatLng(37.558522, 126.793722), |
||||
zoom: !areaCoordList ? 11 : bufferzoom.bufferzoom, |
||||
zoomControl: true, |
||||
mapTypeId: naver.maps.MapTypeId.NORMAL, |
||||
zoomControlOptions: { |
||||
position: naver.maps.Position.RIGHT_CENTER, |
||||
style: naver.maps.ZoomControlStyle.SMALL |
||||
} |
||||
const NaverMapInit = () => { |
||||
const mapOptions = { |
||||
// center: new naver.maps.LatLng(36.56793936069445, 127.85101412107547),
|
||||
center: new naver.maps.LatLng(37.520357, 126.610166), |
||||
// zoom: 10,
|
||||
zoom:15, |
||||
zoomControl: true, |
||||
mapTypeId: naver.maps.MapTypeId.NORMAL, |
||||
zoomControlOptions: { |
||||
position: naver.maps.Position.LEFT_CENTER, |
||||
|
||||
style: naver.maps.ZoomControlStyle.SMALL |
||||
} |
||||
};
|
||||
|
||||
setMap(new naver.maps.Map('map', mapOptions)); |
||||
|
||||
// const mapOptions = {
|
||||
// center: new naver.maps.LatLng(37.520357, 126.610166),
|
||||
// zoom: 15,
|
||||
// zoomControl: true,
|
||||
// zoomControlOptions: {
|
||||
// position: naver.maps.Position.LEFT_CENTER,
|
||||
// style: naver.maps.ZoomControlStyle.SMALL
|
||||
// },
|
||||
// mapTypeControl: true,
|
||||
// mapTypeControlOptions: {
|
||||
// style: naver.maps.MapTypeControlStyle.DROPDOWN
|
||||
// }
|
||||
// }
|
||||
|
||||
// const openStreetMapType = new naver.maps.ImageMapType({
|
||||
// name: 'OSM',
|
||||
// minZoom: 0,
|
||||
// maxZoom: 19,
|
||||
// tileSize: new naver.maps.Size(256, 256),
|
||||
// projection: naver.maps.EPSG3857,
|
||||
// repeatX: true,
|
||||
// tileSet: "https://c.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
// provider: [{
|
||||
// title: " /OpenStreetMap", // 출처 표기는 이미지 제공처의 정책을 따라야 합니다.
|
||||
// link: "http://www.openstreetmap.org/copyright"
|
||||
// }]
|
||||
// })
|
||||
|
||||
// const map = new naver.maps.Map('map', mapOptions);
|
||||
// map.mapTypes.set('osm', openStreetMapType);
|
||||
// map.setMapTypeId('osm');
|
||||
// setMap(map);
|
||||
}; |
||||
const mapp = new naver.maps.Map('map', mapOptions); |
||||
// naver.maps.Event.addListener(mapp, 'idle', function () {
|
||||
// // console.log(dragSize);
|
||||
// });
|
||||
naver.maps.Event.addListener(mapp, 'zoom_changed', function () { |
||||
let radius = 17920; |
||||
for (let i = 6; i < 22; i++) { |
||||
if (i == mapp.zoom) { |
||||
setDragSize(radius); |
||||
} |
||||
radius = radius / 2; |
||||
} |
||||
}); |
||||
setMap(mapp); |
||||
}; |
||||
|
||||
const handlerDrawType = val => { |
||||
dispatch(drawTypeChangeAction(val)); |
||||
}; |
||||
|
||||
const handleInitCoordinates = () => { |
||||
const init = initFlightBas.initDetail.areaList.concat(); |
||||
dispatch(AREA_COORDINATE_LIST_SAVE(init)); |
||||
}; |
||||
|
||||
const handleCoordinates = areaInfo => { |
||||
const initAreaList = initFlightBas.initDetail.areaList.concat(); |
||||
|
||||
const coordList = []; |
||||
|
||||
// radius = 10;
|
||||
areaInfo.coordinates.forEach((c, i) => { |
||||
const coord = Object.assign({}, initFlightBas['coord']); |
||||
coord.lat = c.lat; |
||||
coord.lon = c.lon; |
||||
|
||||
coordList.push(coord); |
||||
}); |
||||
|
||||
// initAreaList[0].bufferZone = areaInfo.bufferZone;
|
||||
// initAreaList[0].areaType = areaInfo.areaType;
|
||||
|
||||
const areaList = initAreaList.map((area, i) => { |
||||
return { |
||||
...area, |
||||
bufferZone: areaInfo.bufferZone, |
||||
areaType: areaInfo.areaType, |
||||
coordList: coordList |
||||
}; |
||||
}); |
||||
|
||||
// dispatch(AREA_COORDINATE_LIST_SAVE(areaList))
|
||||
setMapAreaCoordList(areaList); |
||||
}; |
||||
|
||||
const handleSearch = async () => { |
||||
const res = await flightPlanAPI.searchArea({ query: query }); |
||||
setIsSearch(true); |
||||
setSearchRes(res.data.items); |
||||
}; |
||||
|
||||
const handleChange = e => { |
||||
const { name, value } = e.target; |
||||
|
||||
if (name == 'searchInput') { |
||||
setQuery(value); |
||||
} |
||||
}; |
||||
|
||||
const handleCoord = (mapx, mapy) => { |
||||
let utmk = naver.maps.TransCoord.fromTM128ToUTMK( |
||||
naver.maps.Point(mapx, mapy) |
||||
); |
||||
let latlng = naver.maps.TransCoord.fromUTMKToLatLng(utmk); |
||||
|
||||
setIsSearch(false); |
||||
|
||||
let options = { |
||||
duration: 800, |
||||
easing: 'easeOutCubic' |
||||
const handlerDrawType = val => { |
||||
dispatch(drawTypeChangeAction(val)); |
||||
}; |
||||
map.morph(latlng, 16, options); |
||||
}; |
||||
|
||||
const handleEnter = e => { |
||||
if (e.key == 'Enter') { |
||||
handleSearch(); |
||||
} |
||||
}; |
||||
const handler = () => { |
||||
setFormModal(!formModal); |
||||
}; |
||||
return ( |
||||
<Card className='mb-0'> |
||||
<CardBody> |
||||
<div className='search-cont search-info pd-0'> |
||||
<div className='cont-ti mb-1 d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>지도 영역</h4> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div style={{ position: 'relative' }}> |
||||
<div id='map' style={{ width: '100%', height: '60vh' }}> |
||||
{map ? ( |
||||
<FlightPlanDraw_init |
||||
map={map} |
||||
naver={naver} |
||||
mode={mode} |
||||
areaCoordList={mapAreaCoordList} |
||||
// areaCoordList={areaCoordList}
|
||||
handleCoordinates={handleCoordinates} |
||||
handleInitCoordinates={handleInitCoordinates} |
||||
handleConfirm={props.handleConfirm} |
||||
isDone={props.isDone} |
||||
isDisabled={props.isDisabled} |
||||
dragSize={dragSize} |
||||
pastDragCircle={pastDragCircle} |
||||
setDragCircle={setDragCircle} |
||||
/> |
||||
) : null} |
||||
|
||||
<div className='d-flex search-comp'> |
||||
<div className=''> |
||||
<InputGroup className='search-feather'> |
||||
<InputGroupAddon addonType='prepend'> |
||||
<InputGroupText> |
||||
<Search size={14} onClick={handleSearch} /> |
||||
</InputGroupText> |
||||
</InputGroupAddon> |
||||
<Input |
||||
type='text' |
||||
id='searchInput' |
||||
name='searchInput' |
||||
bsSize='sm' |
||||
autoComplete='off' |
||||
placeholder='검색명을 입력하세요.' |
||||
onChange={handleChange} |
||||
onKeyPress={handleEnter} |
||||
/> |
||||
</InputGroup> |
||||
<div className='search-result-comp'> |
||||
<ul> |
||||
{searchRes?.length !== 0 && isSearch ? ( |
||||
searchRes?.map((prev, idx) => { |
||||
let title = prev.title.replaceAll('<b>', ''); |
||||
title = title.replaceAll('</b>', ''); |
||||
const handlerDrawCheck = val => { |
||||
dispatch(drawCheckAction(val)); |
||||
}; |
||||
|
||||
return ( |
||||
<li |
||||
key={prev.mapx + prev.mapy} |
||||
onClick={() => handleCoord(prev.mapx, prev.mapy)} |
||||
> |
||||
<a> |
||||
<div className='search-result'> |
||||
<div className='title'> |
||||
<span> |
||||
<strong>{title}</strong> |
||||
</span> |
||||
</div> |
||||
<div className='address'> |
||||
{/* <span>{prev.address}</span> */} |
||||
<span>{prev.roadAddress}</span> |
||||
</div> |
||||
</div> |
||||
</a> |
||||
</li> |
||||
); |
||||
}) |
||||
) : ( |
||||
<></> |
||||
)} |
||||
</ul> |
||||
return ( |
||||
<Card className='mb-0'> |
||||
<CardBody>
|
||||
<div className='search-cont search-info pd-0'> |
||||
<div className='cont-ti mb-1 d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>지도 영역</h4> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
{isMapLoad ? ( |
||||
<FeatureAirZone map={map} naver={naver} features={airArea.features} /> |
||||
) : null} |
||||
|
||||
<div className='d-flex align-items-center mt-2'> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handlerDrawType('LINE')} |
||||
disabled={props.isDisabled || props.isDone} |
||||
> |
||||
WayPoint |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handlerDrawType('CIRCLE')} |
||||
disabled={props.isDisabled || props.isDone} |
||||
> |
||||
Circle |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handlerDrawType('POLYGON')} |
||||
disabled={props.isDisabled || props.isDone} |
||||
> |
||||
Polygon |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
color='primary' |
||||
className='mr-1' |
||||
onClick={e => handlerDrawType('RESET')} |
||||
// {...props.test? (
|
||||
// {}
|
||||
// ):(
|
||||
// {disabled:false}
|
||||
// )}
|
||||
disabled={props.isDisabled || props.isDone} |
||||
> |
||||
초기화 |
||||
</Button.Ripple> |
||||
{areaCoordList ? ( |
||||
areaCoordList[0].coordList[0].lat ? ( |
||||
<Button.Ripple color='primary' onClick={handler}> |
||||
날씨 |
||||
</Button.Ripple> |
||||
) : null |
||||
) : ( |
||||
<></> |
||||
)} |
||||
</div> |
||||
<Modal |
||||
isOpen={formModal} |
||||
toggle={handler} |
||||
className='modal-dialog-centered' |
||||
> |
||||
<ModalHeader toggle={handler}>날씨 정보</ModalHeader> |
||||
<ModalBody> |
||||
<WeatherContainer mapAreaCoordList={mapAreaCoordList} /> |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color='primary' onClick={handler}> |
||||
확인 |
||||
</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
</CardBody> |
||||
</Card> |
||||
); |
||||
}; |
||||
<div style={{position:'relative'}}> |
||||
<div id="map" style={{ width: '100%', height: '60vh', position: 'absoulte'}}> |
||||
<FlightPlanDrawTest |
||||
map = {map} |
||||
naver = {naver} |
||||
mode = {mode} |
||||
openModal={openModal} |
||||
/> |
||||
|
||||
<Button.Ripple |
||||
color='primary' |
||||
className='area-button' |
||||
onClick = {props.openModal} |
||||
> |
||||
확인 |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
color='primary' |
||||
className='area-button' |
||||
onClick={e => handlerDrawType('RESET')} |
||||
> |
||||
초기화 |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
color='primary' |
||||
className='area-button' |
||||
> |
||||
적용 |
||||
</Button.Ripple> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
{isMapLoad ? (
|
||||
<FeatureAirZone map={map} naver={naver} features={airArea.features} />
|
||||
) : null} |
||||
|
||||
<div className='d-flex align-items-center mt-2'> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handlerDrawType('LINE')} |
||||
> |
||||
WayPoint |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
className='mr-1' |
||||
color='primary' |
||||
onClick={e => handlerDrawType('CIRCLE')} |
||||
> |
||||
Circle |
||||
</Button.Ripple> |
||||
<Button.Ripple |
||||
color='primary' |
||||
onClick={e => handlerDrawType('POLYGON')} |
||||
> |
||||
Polygon |
||||
</Button.Ripple> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
) |
||||
} |
||||
|
||||
export default FlightPlanAreaMap; |
||||
export default FlightPlanAreaMap; |
@ -0,0 +1,41 @@
|
||||
import { useEffect, useState } from 'react'; |
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; |
||||
import FlightPlanAreaContainer from '../../../../containers/basis/flight/plan/FlightPlanAreaContainer'; |
||||
|
||||
export const FlightPlanAreaModal = props => {
|
||||
|
||||
const [onSubmit, setOnSubmit] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
console.log('비행구역설정 모달') |
||||
}, []) |
||||
|
||||
return ( |
||||
<div className='vertically-centered-modal'> |
||||
<Modal |
||||
isOpen={props.modal.isOpen} |
||||
//없어도 문제되는거 없는더 왜 있지
|
||||
// toggle={() =>
|
||||
// props.setModal({ ...props.modal, isOpen: !props.modal.isOpen })
|
||||
// }
|
||||
className='modal-dialog-centered modal-xl' |
||||
> |
||||
<ModalHeader |
||||
toggle={() => |
||||
props.setModal({ ...props.modal, isOpen: !props.modal.isOpen }) |
||||
} |
||||
> |
||||
{props.modal.title} |
||||
</ModalHeader> |
||||
<ModalBody> |
||||
<FlightPlanAreaContainer |
||||
modal={props.modal} |
||||
setModal={props.setModal}
|
||||
// onSubmit={onSubmit}
|
||||
// setOnSubmit={setOnSubmit}
|
||||
/> |
||||
</ModalBody> |
||||
</Modal> |
||||
</div> |
||||
); |
||||
}; |
@ -1,143 +1,66 @@
|
||||
import React from 'react'; |
||||
import { Button, Card, Col, Row, Spinner } from 'reactstrap'; |
||||
import { |
||||
Row, |
||||
Col, |
||||
Table, |
||||
Badge, |
||||
UncontrolledDropdown, |
||||
DropdownMenu, |
||||
DropdownItem, |
||||
DropdownToggle, |
||||
Card, |
||||
CardHeader, |
||||
CardBody, |
||||
CardTitle, |
||||
CardSubtitle, |
||||
ButtonGroup, |
||||
Button, |
||||
Input, |
||||
CustomInput, |
||||
FormGroup |
||||
} from 'reactstrap'; |
||||
import { GridDatabase } from '../../../crud/grid/GridDatatable'; |
||||
import { Redirect } from 'react-router-dom'; |
||||
import { Link, useHistory } from 'react-router-dom'; |
||||
import { useSelector } from 'react-redux'; |
||||
|
||||
const FlightPlanGrid = ({ |
||||
movePage, |
||||
planListData, |
||||
pagination, |
||||
paginationPerPage, |
||||
paginationRowsPerPageOptions, |
||||
isMyGroup, |
||||
user, |
||||
handlerPageChange, |
||||
total |
||||
}) => { |
||||
const { loading } = useSelector(state => state.loadingReducer); |
||||
const columns = [ |
||||
// { id: 'planSno', name: '번호', cell: (row, i) => <div>{i + 1}</div> },
|
||||
{ |
||||
id: 'fltPurpose', |
||||
name: '비행목적', |
||||
cell: row => <div>{row.fltPurpose}</div> |
||||
}, |
||||
{ |
||||
id: 'fltMethod', |
||||
name: '비행방식', |
||||
minWidth: '150px', |
||||
cell: row => { |
||||
const displayName = |
||||
(row.areaList && |
||||
row.areaList.length > 0 && |
||||
row.areaList[0].fltMethod) || |
||||
'-'; |
||||
return <div>{displayName}</div>; |
||||
} |
||||
}, |
||||
{ |
||||
id: 'schFltStDt', |
||||
name: '출발일', |
||||
minWidth: '200px', |
||||
cell: row => <div>{row.schFltStDt}</div> |
||||
}, |
||||
{ id: 'aprvlYn', name: '승인여부', cell: row => <div>{row.aprvlYn}</div> }, |
||||
{ |
||||
id: 'moveDetail', |
||||
name: '상세보기', |
||||
cell: row => { |
||||
return ( |
||||
<Link |
||||
to={`/basis/flight/plan/detail/${row.planSno}?type=plan`} |
||||
size='sm' |
||||
> |
||||
상세보기 |
||||
</Link> |
||||
); |
||||
} |
||||
}, |
||||
{ |
||||
id: 'ORG', |
||||
name: 'ORG', |
||||
cell: row => <div>zzzz</div> |
||||
}, |
||||
{ |
||||
id: 'ETD', |
||||
name: 'ETD', |
||||
cell: row => <div>zzzz</div> |
||||
}, |
||||
{ |
||||
id: 'ATD', |
||||
name: 'ATD', |
||||
cell: row => <div>zzzz</div> |
||||
}, |
||||
{ |
||||
id: 'DES', |
||||
name: 'DES', |
||||
cell: row => <div>zzzz</div> |
||||
}, |
||||
{ |
||||
id: 'ETA', |
||||
name: 'ETA', |
||||
cell: row => <div>zzzz</div> |
||||
}, |
||||
{ |
||||
id: 'ATA', |
||||
name: 'ATA', |
||||
cell: row => <div>zzzz</div> |
||||
} |
||||
]; |
||||
|
||||
const FlightPlanGrid = (props) => { |
||||
return ( |
||||
<> |
||||
<div className='mt-2 cont-ti d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>비행계획서 신청 목록</h4> |
||||
<span className='search-case'> |
||||
검색결과 총 {!!planListData ? planListData.length : 0}건 |
||||
</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
onClick={movePage} |
||||
{...(isMyGroup ? {} : { disabled: true })} |
||||
> |
||||
비행계획서 신청 |
||||
</Button.Ripple> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
{loading ? ( |
||||
<div className='grid-loading'> |
||||
<div> |
||||
<Spinner color='primary' /> |
||||
<span>Loading...</span> |
||||
</div> |
||||
</div> |
||||
) : null} |
||||
<GridDatabase |
||||
<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> */} |
||||
<h4>{"비행계획서 신청"} 목록</h4> |
||||
<span className='search-case'>검색결과 총 0건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
onClick={props.moveFlightPlan} |
||||
> |
||||
{/* 계획서 생성 */} |
||||
비행계획서 신청 |
||||
</Button.Ripple> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={planListData} |
||||
columns={columns} |
||||
count={!!planListData ? planListData.length : 0} |
||||
pagination={pagination} |
||||
paginationPerPage={paginationPerPage} |
||||
paginationRowsPerPageOptions={paginationRowsPerPageOptions} |
||||
handlerPageChange={handlerPageChange} |
||||
total={total} |
||||
/> |
||||
{/* 검색된 데이터가 없습니다. */} |
||||
// data={props.data}
|
||||
count={0} |
||||
// columns={props.columns}
|
||||
// pagination={props.pagination}
|
||||
/> |
||||
{/* 검색된 데이터가 없습니다. */} |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
); |
||||
}; |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default FlightPlanGrid; |
||||
export default FlightPlanGrid; |
@ -1,105 +0,0 @@
|
||||
import React from 'react'; |
||||
import { GridDatabase } from '../../../crud/grid/GridDatatable'; |
||||
import { Card, Button } from 'reactstrap'; |
||||
|
||||
const FlightPlanGroupGrid = ({ |
||||
data, |
||||
count, |
||||
selectGroup, |
||||
handlerGroupCancel, |
||||
handleGroupSelect, |
||||
paginationRowsPerPageOptions, |
||||
pagination |
||||
}) => { |
||||
const columns = [ |
||||
{ |
||||
// id: 'groupNm',
|
||||
name: '그룹 명', |
||||
selector: row => row.groupNm, |
||||
minWidth: '102px', |
||||
sortable: true, |
||||
cell: row => <div>{row.groupNm}</div> |
||||
}, |
||||
{ |
||||
// id: 'groupId',
|
||||
name: '그룹 코드', |
||||
selector: row => row.groupId, |
||||
minWidth: '102px', |
||||
sortable: true, |
||||
cell: row => <div>{row.groupId}</div> |
||||
}, |
||||
{ |
||||
name: '생성일시', |
||||
selector: row => row?.createDt, |
||||
sortable: true, |
||||
cell: row => { |
||||
return row?.createDt ? row.createDt : '-'; |
||||
} |
||||
}, |
||||
{ |
||||
name: '가입일시', |
||||
selector: row => row?.joinDt, |
||||
sortable: true, |
||||
cell: row => { |
||||
return row?.joinDt ? row.joinDt : '-'; |
||||
} |
||||
}, |
||||
{ |
||||
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, |
||||
myGroupAuthCd: row?.myGroupAuthCd |
||||
}); |
||||
}} |
||||
> |
||||
상세보기 |
||||
</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} |
||||
pagination={pagination} |
||||
paginationPerPage={5} |
||||
paginationRowsPerPageOptions={paginationRowsPerPageOptions} |
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
export default FlightPlanGroupGrid; |
@ -1,29 +0,0 @@
|
||||
import { useState } from 'react'; |
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; |
||||
import FlightPlanAreaContainer from '../../../../containers/basis/flight/plan/FlightPlanAreaContainer'; |
||||
|
||||
export const FlightPlanModal = ({isOpen, title, description, type, handleModal}) => {
|
||||
|
||||
return ( |
||||
<div className='vertically-centered-modal'> |
||||
<Modal |
||||
isOpen={isOpen} |
||||
toggle={() => |
||||
handleModal(({target: type, isOpen: false})) |
||||
}
|
||||
className='modal-dialog-centered modal-xl' |
||||
> |
||||
<ModalHeader |
||||
toggle={() => |
||||
handleModal(({target: type, isOpen: false})) |
||||
} |
||||
> |
||||
{title} |
||||
</ModalHeader> |
||||
<ModalBody className='pal-modal-body'> |
||||
{description} |
||||
</ModalBody> |
||||
</Modal> |
||||
</div> |
||||
); |
||||
}; |
@ -1,157 +0,0 @@
|
||||
import React from 'react'; |
||||
import {Button, Card, CardBody, Col, CustomInput, Row, FormGroup, Input, Label} from 'reactstrap'; |
||||
import {Search} from 'react-feather'; |
||||
import {GridDatabase} from '../../../crud/grid/GridDatatable'; |
||||
import { AiOutlineSearch } from 'react-icons/ai'; |
||||
import '../../../../assets/css/custom.css'; |
||||
import '@styles/react/libs/tables/react-dataTable-component.scss'; |
||||
|
||||
const FlightPlanPilot = ({ handleSelectPilot, returnPilot, onClickEvent, onChange,name}) => { |
||||
|
||||
const columns = [ |
||||
{id: 'groupNm', name: '그룹 명', cell: row => (<div>{row.groupNm}</div>)}, |
||||
{id: 'memberName', name: '성명', cell: row => (<div>{row.memberName}</div>)}, |
||||
{id: 'hpno', name: '핸드폰 번호', cell: row => (<div>{row.hpno}</div>)}, |
||||
{id: 'email', name: '이메일', cell: row => (<div>{row.email}</div>)}, |
||||
{ |
||||
id: 'selectPilot', name: '선택', cell: row => { |
||||
return <Button.Ripple color='primary' size='sm' onClick={() => {
|
||||
handleSelectPilot(row.cstmrSno)
|
||||
} |
||||
}>선택</Button.Ripple>; |
||||
}
|
||||
} |
||||
]; |
||||
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={onClickEvent} |
||||
> |
||||
<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='4' sm='12'> |
||||
<FormGroup className='form-label-group' > |
||||
<Input |
||||
type='text' |
||||
id='memberName' |
||||
name='memberName' |
||||
value = {name} |
||||
onChange = {onChange} |
||||
bsSize='sm' |
||||
// onKeyPress={props.onKeyPress}
|
||||
placeholder='성명을 입력하세요' |
||||
/> |
||||
<Label for='test'>성명</Label> |
||||
</FormGroup> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
|
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
<div className='pal-card-box'>
|
||||
<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'>검색결과 총 {!!returnPilot ? returnPilot.length : 0}건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'></div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase
|
||||
data={returnPilot} |
||||
count={returnPilot ? returnPilot.length : 0} |
||||
columns={columns} |
||||
// pagination={props.pagination}
|
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
{/* {inputVal !== '' ? ( |
||||
<div className='pal-card-box'>
|
||||
<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'>검색결과 총 {!!returnPilot ? [returnPilot].length : 0}건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'></div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase
|
||||
data={[returnPilot]} |
||||
count={returnPilot ? [returnPilot].length : 0} |
||||
columns={columns} |
||||
// pagination={props.pagination}
|
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</div> |
||||
):( |
||||
<div className='pal-card-box'>
|
||||
<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'>검색결과 총 {!!pilotList ? pilotList.length : 0}건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'></div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase
|
||||
data={pilotList} |
||||
count={pilotList ? pilotList.length : 0} |
||||
columns={columns} |
||||
// pagination={props.pagination}
|
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</div> |
||||
)} */} |
||||
</> |
||||
) |
||||
|
||||
} |
||||
|
||||
export default FlightPlanPilot; |
@ -1,408 +0,0 @@
|
||||
import { |
||||
Table |
||||
} from 'reactstrap'; |
||||
import { |
||||
Search, |
||||
Compass, |
||||
Sun, |
||||
CloudLightning, |
||||
Cloud, |
||||
CloudRain, |
||||
CloudDrizzle, |
||||
CloudSnow, |
||||
Navigation2 |
||||
} from 'react-feather'; |
||||
|
||||
|
||||
export function TodayWeather({ todayData }) { |
||||
todayData?.fcstTime?.sort([compareFunction]); |
||||
const dayres = todayData?.filter(dayData => { |
||||
switch (dayData?.fcstTime) { |
||||
case "0200": |
||||
case "0500": |
||||
case "0500": |
||||
case "0800": |
||||
case "1100": |
||||
case "1400": |
||||
case "1700": |
||||
case "2000": |
||||
case "2300": |
||||
return { ...dayData?.todayData } |
||||
} |
||||
}); |
||||
// 배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);
|
||||
const groupValues = dayres.reduce((acc, current) => { |
||||
acc[current.fcstTime] = acc[current.fcstTime] || []; |
||||
acc[current.fcstTime].push({ category: current.category, fcstValue: current.fcstValue }); |
||||
return acc; |
||||
}, {}); |
||||
// 위에서 만든 객체를 key로 돌려서 새로운 객체 return
|
||||
const groups = Object.keys(groupValues).map((key) => { |
||||
return { fcstTime: key, category: groupValues[key] }; |
||||
}); |
||||
|
||||
return ( |
||||
<> |
||||
{dayres.length > 0 ? ( |
||||
|
||||
<Table responsive> |
||||
<thead> |
||||
<tr> |
||||
<th>시각</th> |
||||
<th>날씨</th> |
||||
<th>기온</th> |
||||
<th>풍향</th> |
||||
<th>풍속</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{groups.map((i, index) => { |
||||
return ( |
||||
<tr key={index}> |
||||
<td >{i.fcstTime.substring(0, 2)}시</td> |
||||
{i.category[4].fcstValue == "0" ? |
||||
<td> |
||||
{i.category[3].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{i.category[4].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{i.category[0].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${i.category[1]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{i.category[2].fcstValue} m/s</td> |
||||
</tr> |
||||
) |
||||
})} |
||||
</tbody> |
||||
</Table> |
||||
) : |
||||
null} |
||||
</> |
||||
) |
||||
} |
||||
|
||||
|
||||
export function TomorrowWeahter({ tomorrowData }) { |
||||
tomorrowData?.fcstTime?.sort([compareFunction]); |
||||
const dayres = tomorrowData?.filter(dayData => { |
||||
switch (dayData?.fcstTime) { |
||||
case "0200": |
||||
case "0500": |
||||
case "0500": |
||||
case "0800": |
||||
case "1100": |
||||
case "1400": |
||||
case "1700": |
||||
case "2000": |
||||
case "2300": |
||||
return { ...dayData?.tomorrowData } |
||||
} |
||||
}); |
||||
return ( |
||||
<Table responsive> |
||||
<thead> |
||||
<tr> |
||||
<th>시각</th> |
||||
<th>날씨</th> |
||||
<th>기온</th> |
||||
<th>풍향</th> |
||||
<th>풍속</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<td>{dayres[0]?.fcstTime.substring(0, 2)}시</td> |
||||
{dayres[3].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[3].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[4].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[0].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[1]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[2].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[5].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[8].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[8].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[9].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[5].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[6]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[7].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[10].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[13].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[13].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[14].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[10].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[11]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[12].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[15].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[18].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[18].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[19].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[15].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[16]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[17].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[20].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[23].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[23].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[24].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[20].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[21]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[22].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[25].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[28].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[28].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[29].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[25].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[26]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[27].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[30].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[33].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[33].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[34].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[30].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[31]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[32].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[35].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[38].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[38].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[39].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[35].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[36]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[37].fcstValue} m/s</td> |
||||
</tr> |
||||
</tbody> |
||||
</Table> |
||||
) |
||||
} |
||||
export function AfterTomorrowWeahter({ afterData }) { |
||||
afterData?.fcstTime?.sort([compareFunction]); |
||||
const dayres = afterData?.filter(dayData => { |
||||
switch (dayData?.fcstTime) { |
||||
case "0200": |
||||
case "0500": |
||||
case "0500": |
||||
case "0800": |
||||
case "1100": |
||||
case "1400": |
||||
case "1700": |
||||
case "2000": |
||||
case "2300": |
||||
return { ...dayData?.afterData } |
||||
} |
||||
}); |
||||
|
||||
return ( |
||||
<Table responsive> |
||||
<thead> |
||||
<tr> |
||||
<th>시각</th> |
||||
<th>날씨</th> |
||||
<th>기온</th> |
||||
<th>풍향</th> |
||||
<th>풍속</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<td>{dayres[0].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[3].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[3].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[4].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[0].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[1]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[2].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[5].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[8].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[8].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[9].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[5].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[6]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[7].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[10].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[13].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[13].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[14].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[10].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[11]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[12].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[15].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[18].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[18].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[19].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[15].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[16]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[17].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[20].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[23].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[23].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[24].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[20].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[21]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[22].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[25].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[28].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[28].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[29].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[25].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[26]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[27].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[30].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[33].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[33].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[34].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[30].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[31]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[32].fcstValue} m/s</td> |
||||
</tr> |
||||
<tr> |
||||
<td>{dayres[35].fcstTime.substring(0, 2)}시</td> |
||||
{dayres[38].fcstValue != "0" ? |
||||
<td> |
||||
{dayres[38].fcstValue == "1" ? <Sun /> : <Cloud />} |
||||
</td> |
||||
: <td> |
||||
{dayres[39].fcstValue == "3" ? <CloudSnow /> : <CloudRain />} |
||||
</td> |
||||
} |
||||
<td>{dayres[35].fcstValue}℃</td> |
||||
<td> |
||||
<Navigation2 style={{ transform: `rotate(${dayres[36]?.fcstValue}deg)` }} /> |
||||
</td> |
||||
<td>{dayres[37].fcstValue} m/s</td> |
||||
</tr> |
||||
</tbody> |
||||
</Table> |
||||
) |
||||
} |
@ -1,344 +0,0 @@
|
||||
import { useRef, useState } from 'react'; |
||||
import { GridDatabase } from '@src/components/crud/grid/GridDatatable'; |
||||
import { Row, Col, Card, Spinner } from 'reactstrap'; |
||||
import FlightScheduleRealTime from './FlightScheduleRealTime'; |
||||
import { useSelector } from 'react-redux'; |
||||
import moment from 'moment'; |
||||
|
||||
/** |
||||
* 비행 전 : B |
||||
* 비행 중 : F |
||||
* 비행 완료 : S |
||||
*/ |
||||
function FlightScheduleGrid() { |
||||
const timeRef = useRef(null); |
||||
|
||||
const { scheduleList } = useSelector(state => state.flightState); |
||||
const { loading } = useSelector(state => state.loadingReducer); |
||||
|
||||
const fillZero = (width, str) => { |
||||
return str.length >= width |
||||
? str |
||||
: new Array(width - str.length + 1).join('0') + str; //남는 길이만큼 0으로 채움
|
||||
}; |
||||
|
||||
const columns = [ |
||||
{ |
||||
name: '그룹 명', |
||||
selector: row => row.groupNm, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
return row.groupNm; |
||||
} |
||||
}, |
||||
{ |
||||
name: '기체 소유자', |
||||
selector: row => row.ownerNm, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
return row.ownerNm; |
||||
} |
||||
}, |
||||
{ |
||||
name: '기체 식별번호', |
||||
selector: row => row.idntfNum, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
return row.idntfNum; |
||||
} |
||||
}, |
||||
{ |
||||
name: '출발지', |
||||
selector: row => row.startAddress, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
return row.startAddress; |
||||
} |
||||
}, |
||||
{ |
||||
name: '비행 시작 시간', |
||||
selector: row => row.schFltStDt, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
return moment(row.schFltStDt).format('YYYY-MM-DD HH:mm'); |
||||
} |
||||
}, |
||||
{ |
||||
name: '도착지', |
||||
selector: row => row.endAddress, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
return row.endAddress; |
||||
} |
||||
}, |
||||
{ |
||||
name: '비행 종료 시간', |
||||
selector: row => row.schFltEndDt, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
return moment(row.schFltEndDt).format('YYYY-MM-DD HH:mm'); |
||||
} |
||||
}, |
||||
{ |
||||
name: '총 예상 비행시간', |
||||
selector: row => row.groupNm, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
const endDate = moment(row.schFltEndDt); |
||||
const startDate = moment(row.schFltStDt); |
||||
|
||||
const hours = Math.floor( |
||||
moment.duration(endDate.diff(startDate)).asHours() |
||||
); |
||||
|
||||
const minute = |
||||
moment.duration(endDate.diff(startDate)).asMinutes() % 60; |
||||
|
||||
return `${fillZero(2, String(hours))} : ${fillZero(2, String(minute))}`; |
||||
} |
||||
}, |
||||
{ |
||||
name: '상태', |
||||
selector: row => row.statusCd, |
||||
minWidth: '150px', |
||||
sortable: true, |
||||
cell: row => { |
||||
switch (row.statusCd) { |
||||
case 'B': |
||||
return '비행전'; |
||||
case 'F': |
||||
return '비행중'; |
||||
default: |
||||
return '비행완료'; |
||||
} |
||||
} |
||||
} |
||||
]; |
||||
|
||||
const conditionalRowStyles = [ |
||||
{ |
||||
when: row => row.statusCd === 'S', |
||||
classNames: ['secondary'] |
||||
}, |
||||
{ |
||||
when: row => { |
||||
if (row.statusCd !== 'S') { |
||||
// 현재시간
|
||||
const currTime = |
||||
timeRef?.current?.lastChild?.data |
||||
.replace(/\:/g, '') |
||||
.substring(0, 4) || ''; |
||||
|
||||
// 현재날짜
|
||||
const currDay = Number(moment().format('YYYYMMDD')); |
||||
const currDateTime = moment(); |
||||
|
||||
// 데이터 시작날짜
|
||||
// const itemStartDay = Number(moment(row.schFltStDt).format('YYYYMMDD'));
|
||||
// 데이터 종료날짜
|
||||
const itemEndDay = Number(moment(row.schFltEndDt).format('YYYYMMDD')); |
||||
|
||||
const itemStartTime = moment(row.schFltStDt).format('HHmm'); |
||||
const itemEndTime = moment(row.schFltEndDt); |
||||
const diffTime = |
||||
moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % 60 > |
||||
-0 |
||||
? moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % 60 |
||||
: Math.ceil( |
||||
moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % |
||||
60 |
||||
); |
||||
|
||||
// 현재날짜 - 종료날짜
|
||||
if (currDay - itemEndDay > 0) { |
||||
return false; |
||||
} |
||||
if (row.statusCd === 'B') { |
||||
if ( |
||||
currTime - itemStartTime >= 10 && |
||||
currTime - itemStartTime <= 19 |
||||
) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
if (row.statusCd === 'F') { |
||||
if (diffTime >= 10 && diffTime <= 19) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
return false; |
||||
} |
||||
return false; |
||||
}, |
||||
classNames: ['yellow'] |
||||
}, |
||||
{ |
||||
when: row => { |
||||
if (row.statusCd !== 'S') { |
||||
// 현재시간
|
||||
const currTime = timeRef.current.lastChild.data |
||||
.replace(/\:/g, '') |
||||
.substring(0, 4); |
||||
// 현재날짜
|
||||
const currDay = Number(moment().format('YYYYMMDD')); |
||||
const currDateTime = moment(); |
||||
|
||||
// 데이터 시작날짜
|
||||
// const itemStartDay = Number(moment(row.schFltStDt).format('YYYYMMDD'));
|
||||
// 데이터 종료날짜
|
||||
const itemEndDay = Number(moment(row.schFltEndDt).format('YYYYMMDD')); |
||||
|
||||
const itemStartTime = moment(row.schFltStDt).format('HHmm'); |
||||
const itemEndTime = moment(row.schFltEndDt); |
||||
const diffTime = |
||||
moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % 60 > |
||||
-0 |
||||
? moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % 60 |
||||
: Math.ceil( |
||||
moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % |
||||
60 |
||||
); |
||||
|
||||
// 현재날짜 - 종료날짜
|
||||
if (currDay - itemEndDay > 0) { |
||||
return false; |
||||
} |
||||
// 비행전 체크
|
||||
if (row.statusCd === 'B') { |
||||
if ( |
||||
currTime - itemStartTime >= 20 && |
||||
currTime - itemStartTime <= 29 |
||||
) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
// 비행중 체크
|
||||
if (row.statusCd === 'F') { |
||||
if (diffTime >= 20 && diffTime <= 29) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
return false; |
||||
} |
||||
return false; |
||||
}, |
||||
classNames: ['warning'] |
||||
}, |
||||
{ |
||||
when: row => { |
||||
if (row.statusCd !== 'S') { |
||||
// 현재시간
|
||||
const currTime = timeRef.current.lastChild.data |
||||
.replace(/\:/g, '') |
||||
.substring(0, 4); |
||||
// 현재날짜
|
||||
const currDay = Number(moment().format('YYYYMMDD')); |
||||
const currDateTime = moment(); |
||||
// 데이터 시작날짜
|
||||
// const itemStartDay = Number(moment(row.schFltStDt).format('YYYYMMDD'));
|
||||
// 데이터 종료날짜
|
||||
const itemEndDay = Number(moment(row.schFltEndDt).format('YYYYMMDD')); |
||||
|
||||
const itemStartTime = moment(row.schFltStDt).format('HHmm'); |
||||
const itemEndTime = moment(row.schFltEndDt); |
||||
const diffTime = |
||||
moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % 60 > |
||||
-0 |
||||
? moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % 60 |
||||
: Math.ceil( |
||||
moment.duration(currDateTime.diff(itemEndTime)).asMinutes() % |
||||
60 |
||||
); |
||||
|
||||
// 현재날짜 - 종료날짜
|
||||
if (currDay - itemEndDay > 0) { |
||||
return true; |
||||
} |
||||
// 비행전 체크
|
||||
if (row.statusCd === 'B') { |
||||
if (currTime - itemStartTime >= 30) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
// 비행중 체크
|
||||
if (row.statusCd === 'F') { |
||||
if (currDay - itemEndDay < 0) { |
||||
return false; |
||||
} |
||||
if (diffTime > 30) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
return false; |
||||
} |
||||
return false; |
||||
}, |
||||
classNames: ['danger'] |
||||
} |
||||
]; |
||||
|
||||
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 |
||||
style={{ |
||||
display: 'flex', |
||||
justifyContent: 'space-between', |
||||
alignItems: 'center', |
||||
width: '100%' |
||||
}} |
||||
> |
||||
<div style={{ display: 'flex', alignItems: 'center' }}> |
||||
<h4>비행운항 스케줄 목록</h4> |
||||
<span className='search-case'> |
||||
검색결과 총 {scheduleList.length}건 |
||||
</span> |
||||
</div> |
||||
<FlightScheduleRealTime ref={timeRef} /> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
{loading ? ( |
||||
<div className='grid-loading'> |
||||
<div> |
||||
<Spinner color='primary' /> |
||||
<span>Loading...</span> |
||||
</div> |
||||
</div> |
||||
) : null} |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={scheduleList} |
||||
count={scheduleList.length} |
||||
columns={columns} |
||||
pagination={false} |
||||
conditionalRowStyles={conditionalRowStyles} |
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default FlightScheduleGrid; |
@ -1,22 +0,0 @@
|
||||
import { useState, forwardRef } from 'react'; |
||||
import moment from 'moment'; |
||||
import useInterval from '@src/utility/hooks/useInterval'; |
||||
|
||||
const KR_TIME_DIFF = 9 * 60 * 60 * 1000; |
||||
|
||||
const FlightScheduleRealTime = forwardRef(({}, ref) => { |
||||
const [currTime, setCurrTime] = useState(new Date()); |
||||
const utc = currTime.getTime() + currTime.getTimezoneOffset() * 60 * 1000; |
||||
const kr_curr = new Date(utc + KR_TIME_DIFF); |
||||
|
||||
useInterval(() => { |
||||
setCurrTime(new Date()); |
||||
setTime(moment(new Date()).format('HH:mm:ss')); |
||||
}, [1000]); |
||||
|
||||
const [time, setTime] = useState(moment(kr_curr).format('HH:mm:ss')); |
||||
|
||||
return <div ref={ref}>현재시간 : {time.toString()}</div>; |
||||
}); |
||||
|
||||
export default FlightScheduleRealTime; |
@ -1,92 +0,0 @@
|
||||
import { useEffect, useState } from 'react'; |
||||
import { Row, Col, Button, Card, CardBody } from 'reactstrap'; |
||||
import { Search, Calendar } from 'react-feather'; |
||||
import moment from 'moment'; |
||||
import Flatpickr from 'react-flatpickr'; |
||||
import { FLIGHT_SCHEDULE_LIST } from '@src/modules/basis/flight/actions/basisFlightAction'; |
||||
import { useDispatch } from 'react-redux'; |
||||
import useInterval from '@src/utility/hooks/useInterval'; |
||||
|
||||
function FlightScheduleSearch() { |
||||
const dispatch = useDispatch(); |
||||
|
||||
const [date, setDate] = useState( |
||||
moment().subtract('day').format('YYYY-MM-DD') |
||||
); |
||||
const [isSearch, setIsSearch] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
setIsSearch(false); |
||||
}, [date]); |
||||
|
||||
useInterval(() => { |
||||
if (isSearch) { |
||||
dispatch(FLIGHT_SCHEDULE_LIST.request(date)); |
||||
} |
||||
}, [10000]); |
||||
|
||||
const handlerChangeDate = val => { |
||||
setDate(moment(val[0]).format('YYYY-MM-DD')); |
||||
}; |
||||
|
||||
const handlerSearch = () => { |
||||
setIsSearch(true); |
||||
dispatch(FLIGHT_SCHEDULE_LIST.request(date)); |
||||
}; |
||||
|
||||
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={handlerSearch}> |
||||
<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 |
||||
placeholder='날짜를 선택해주세요' |
||||
id='searchDate' |
||||
value={date} |
||||
options={{ |
||||
mode: 'single' |
||||
}} |
||||
onChange={handlerChangeDate} |
||||
className='form-control flat-picker bg-transparent border-0 shadow-none' |
||||
/> |
||||
<Calendar size={14} /> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default FlightScheduleSearch; |
@ -1,33 +1,61 @@
|
||||
import { GridDatabase } from '../../crud/grid/GridDatatable'; |
||||
import { Card } from 'reactstrap'; |
||||
import { |
||||
Row, |
||||
Col, |
||||
Table, |
||||
Badge, |
||||
UncontrolledDropdown, |
||||
DropdownMenu, |
||||
DropdownItem, |
||||
DropdownToggle, |
||||
Card, |
||||
CardHeader, |
||||
CardBody, |
||||
CardTitle, |
||||
CardSubtitle, |
||||
ButtonGroup, |
||||
Button, |
||||
Input, |
||||
CustomInput, |
||||
FormGroup |
||||
} from 'reactstrap'; |
||||
import { ExcelExportButton } from '../../crud/excel/ExcelExportButton'; |
||||
|
||||
export const BasisGroupApprovalGrid = props => { |
||||
return ( |
||||
<> |
||||
<div className='mt-2 cont-ti d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>{props.title} 목록</h4> |
||||
<span className='search-case'>검색결과 총 {props.total}건</span> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={props.data} |
||||
count={props.count} |
||||
columns={props.columns} |
||||
pagination={props.pagination} |
||||
paginationPerPage={props.paginationPerPage} |
||||
paginationRowsPerPageOptions={props.paginationRowsPerPageOptions} |
||||
handlerPageChange={props.handlerPageChange} |
||||
total={props.total} |
||||
/> |
||||
<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>{props.title} 목록</h4> |
||||
<span className='search-case'>검색결과 총 {props.count}건</span> |
||||
</div> |
||||
{/* <div className='d-flex align-items-center'> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
onClick={props.handlerGroupCreate} |
||||
> |
||||
그룹생성 |
||||
</Button.Ripple> |
||||
</div> */} |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={props.data} |
||||
count={props.count} |
||||
columns={props.columns} |
||||
pagination={props.pagination} |
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
}; |
||||
|
@ -1,30 +1,61 @@
|
||||
import { GridDatabase } from '../../crud/grid/GridDatatable'; |
||||
import { Card, Row, Col, Button } from 'reactstrap'; |
||||
import { |
||||
Row, |
||||
Col, |
||||
Table, |
||||
Badge, |
||||
UncontrolledDropdown, |
||||
DropdownMenu, |
||||
DropdownItem, |
||||
DropdownToggle, |
||||
Card, |
||||
CardHeader, |
||||
CardBody, |
||||
CardTitle, |
||||
CardSubtitle, |
||||
ButtonGroup, |
||||
Button, |
||||
Input, |
||||
CustomInput, |
||||
FormGroup |
||||
} from 'reactstrap'; |
||||
import { ExcelExportButton } from '../../crud/excel/ExcelExportButton'; |
||||
|
||||
export const BasisGroupGrid = props => { |
||||
return ( |
||||
<> |
||||
<div className='cont-ti d-flex justify-content-between align-items-sm-center align-items-start flex-sm-row'> |
||||
<div> |
||||
<h4>{props.title} 목록</h4> |
||||
<span className='search-case'>검색결과 총 {props.count}건</span> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={props.data} |
||||
count={props.count} |
||||
columns={props.columns} |
||||
pagination={props.pagination} |
||||
paginationPerPage={props.paginationPerPage} |
||||
paginationRowsPerPageOptions={props.paginationRowsPerPageOptions} |
||||
/> |
||||
<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>{props.title} 목록</h4> |
||||
<span className='search-case'>검색결과 총 {props.count}건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
onClick={props.handlerGroupCreate} |
||||
> |
||||
그룹생성 |
||||
</Button.Ripple> |
||||
</div> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={props.data} |
||||
count={props.count} |
||||
columns={props.columns} |
||||
pagination={props.pagination} |
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
}; |
||||
|
@ -1,46 +0,0 @@
|
||||
import { GridDatabase } from '../../crud/grid/GridDatatable'; |
||||
import { Card, Row, Col, Button } from 'reactstrap'; |
||||
|
||||
export const BasisGroupMyGrid = props => { |
||||
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>{props.title} 목록</h4> |
||||
<span className='search-case'>검색결과 총 {props.count}건</span> |
||||
</div> |
||||
<div className='d-flex align-items-center'> |
||||
<Button.Ripple |
||||
color='primary' |
||||
size='sm' |
||||
onClick={props.handlerGroupCreate} |
||||
> |
||||
그룹생성 |
||||
</Button.Ripple> |
||||
</div> |
||||
</div> |
||||
<div className='invoice-list-wrapper'> |
||||
<Card> |
||||
{/* <div className='grid-loading'> |
||||
<div><Spinner color='primary' /><span>Loading...</span></div> |
||||
</div> */} |
||||
<div className='invoice-list-dataTable'> |
||||
<GridDatabase |
||||
title={'비행이력'} |
||||
data={props.data} |
||||
count={props.count} |
||||
columns={props.columns} |
||||
pagination={props.pagination} |
||||
/> |
||||
</div> |
||||
</Card> |
||||
</div> |
||||
</> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
}; |
@ -1,24 +0,0 @@
|
||||
import { CustomInput, Input } from 'reactstrap'; |
||||
import React from 'react'; |
||||
|
||||
export const selectableRowsComponent = React.forwardRef( |
||||
({ onClick, ...rest }, ref) => { |
||||
let c = new Date().getTime() + Math.random(); |
||||
return ( |
||||
<div |
||||
className='custom-checkbox custom-control' |
||||
style={{ paddingLeft: 0 }} |
||||
> |
||||
<input |
||||
className='custom-control-input' |
||||
id={c} |
||||
type='checkbox' |
||||
ref={ref} |
||||
onClick={onClick} |
||||
{...rest} |
||||
/> |
||||
<label className='custom-control-label' htmlFor={c} /> |
||||
</div> |
||||
); |
||||
} |
||||
); |