diff --git a/src/components/account/find/AccountFindPassword.js b/src/components/account/find/AccountFindPassword.js index 2ada5e5..19fd03a 100644 --- a/src/components/account/find/AccountFindPassword.js +++ b/src/components/account/find/AccountFindPassword.js @@ -1,108 +1,458 @@ +import * as yup from 'yup'; +import classnames from 'classnames'; import { useState, useEffect } from 'react' import { useParams, Link } from 'react-router-dom' import { useSelector, useDispatch } from 'react-redux' +import { useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; 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' + Modal, ModalHeader, ModalBody, ModalFooter, FormFeedback } from 'reactstrap' import { User, Info, CreditCard, Lock, Check, X } from 'react-feather' import loginImg from '../../../assets/images/login01.png'; 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 [activeTab, setActiveTab] = useState('1') + // const validationSchema = yup.object().shape({ + // newPw: yup + // .string() + // .required('비밀번호를 입력주세요.') + // .matches( + // /^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@$!%*#?&])[A-Za-z0-9@$!%*#?&]{8,20}$/, + // '8자 이상, 20자 미만 영문자/숫자/특수문자(@$!%*#?&) 조합하여 입력해주세요.' + // ), + // newPwCk: yup + // .string() + // .required('비밀번호 확인을 입력해 주세요.') + // .oneOf([yup.ref('userPswd'), null], '비밀번호가 일치하지 않습니다.') + // }) + + // const { register, getValues, setValue, errors, handleSubmit } = useForm({ + // defaultValues: { + // newPw: '', + // newPwCk: '', + // }, + // resolver: yupResolver(validationSchema) + // }) + + const dispatch = useDispatch(); + const [activeTab, setActiveTab] = useState('2') // ** Function to toggle tabs const toggle = tab => setActiveTab(tab) - const [modal, setModal] = useState(false) + //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 [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(() => { + if(isRunning) clearInterval(timer); + return () => { clearInterval(timer); } + }, []); + + const handlerSend = async() => { + if(!inputId || !inputHpno) { + setModal({ + isOpen: true, + title: '인증번호 발송', + desc: '빈칸을 채워주세요.', + color: 'modal-danger' + }) + return; + } + + if(sendCount >= 3) { + setModal({ + isOpen: true, + title: '인증번호 발송', + desc: '인증번호가 발송은 3회 까지만 가능합니다.', + 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(''); + } + }, 1000); + setTimer(timer); + return () => { + clearInterval(timer); + } + } + + const handlerConfirm = async() => { + if(!inputId || !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; + } + + 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})); + + setModal({ + isOpen: true, + title: '비밀번호 변경', + desc: '변경이 완료되었습니다. 다시 로그인 해주세요.', + color: 'modal-primary' + }) + return; + } + } + + const handlerChange = (e) => { + const {name, value} = e.target; + + if(name == 'userId') { + setInputId(value); + } else if(name == 'hpno') { + setInputHpno(value); + } else if(name == 'crtfyhpNo') { + setInputCrtfy(value); + } else if(name == 'newPw') { + setInputNewPw(value); + } else if(name == 'newPwCk') { + setInputNewPwCk(value); + } + } + + const handlerClose = () => { + setModal({ ...modal, isOpen: !modal.isOpen }); + setConfirmModal({ ...confirmModal, isOpen: !confirmModal.isOpen}); + props.handlerClose(); + } return( <> -
- - - - - - - - - - - -
- - - - - - - - - - - - -
-
- -
- - - 남은시간 : 3:00 - - - - -
-
- -
+ + + + + + + + + + + +
+ + + + + + + + + + + +
+
+ +
+ + 0 ? + {} + : + {disabled: true} + } + /> + {/* 남은시간 : 3:00 */} + + 남은시간 {minutes_Counter}:{seconds_Counter} + + + - - setModal(!modal)} className='modal-dialog-centered user-search-modal'> - setModal(!modal)}>비밀번호 확인 - - 새로운 비밀번호로 변경해주세요. - - - - - - - - - - - - - - - - - - - + onClick={handlerConfirm} + {...sendCount > 0 ? + {} + : + {disabled: true} + } + >인증번호 확인 + +
+
+ +
+ + + + {/* */} + setConfirmModal(!confirmModal)} className='modal-dialog-centered user-search-modal'> + setConfirmModal(!confirmModal)}>비밀번호 확인 + + 새로운 비밀번호로 변경해주세요. + + + + + + + + + {/* {errors && errors.newPw && ( + {errors.newPw.message} + )} */} + - - - - - -
-
- + + + + + + + + + {/* {errors && errors.newPwCk && ( + {errors.newPwCk.message} + )} */} + + + + + + + + {/* */} +
+
+ +
+ setModal({ ...modal, isOpen: !modal.isOpen })} + modalClassName={modal.color} + className='modal-dialog-centered' + > + setModal({ ...modal, isOpen: !modal.isOpen })} + > + {modal.title} + + {modal.desc} + + { + udResult?.data.code === 0 ? + + : + + } + + +
+
) diff --git a/src/components/account/find/AccountFindTab.js b/src/components/account/find/AccountFindTab.js index a430f60..f7295b5 100644 --- a/src/components/account/find/AccountFindTab.js +++ b/src/components/account/find/AccountFindTab.js @@ -23,19 +23,17 @@ import { AccountFindPasswordContainer } from "../../../containers/account/find/A import { useHistory } from 'react-router-dom' export const AccountFindTab = props => { - const [activeTab, setActiveTab] = useState('1'); + const [activeTab, setActiveTab] = useState('2'); const history = useHistory(); const toggle = tab => setActiveTab(tab) - const [centeredModal, setCenteredModal] = useState(false) - const [centeredModal02, setCenteredModal02] = useState(false) // const toggle = tab => { // if (activeTab !== tab) setActiveTab(tab); // }; const handlerClose = () => { - history.push(`/account/login/AccountLogin`) + history.push(`/account/login`) } return( diff --git a/src/components/account/find/AccountFindUserId.js b/src/components/account/find/AccountFindUserId.js index e718027..27e8d62 100644 --- a/src/components/account/find/AccountFindUserId.js +++ b/src/components/account/find/AccountFindUserId.js @@ -1,117 +1,362 @@ import * as yup from 'yup'; +import classnames from 'classnames'; import { yupResolver } from '@hookform/resolvers/yup'; import { useState, useEffect } from 'react' -import { useParams, Link } from 'react-router-dom' -import { useSelector, useDispatch } from 'react-redux' +import { useForm } from 'react-hook-form'; +import { useDispatch, useSelector } from 'react-redux'; 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' + Modal, ModalHeader, ModalBody, ModalFooter, FormFeedback } from 'reactstrap' import { User, Info, CreditCard, Lock, Check, X } from 'react-feather' -import loginImg from '../../../assets/images/login01.png'; 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 [activeTab, setActiveTab] = useState('1') + // const validationSchema = yup.object().shape({ + // memberName: yup + // .string() + // .required('이름을 입력해 주세요.'), + // hpno: yup.string().required('휴대폰번호를 입력해 주세요.') + // }) + // const { register, getValues, setValue, errors, handleSubmit } = useForm({ + // defaultValues: { + // memberName: '', + // hpno: '', + // }, + // resolver: yupResolver(validationSchema) + // }) + const dispatch = useDispatch(); + const [activeTab, setActiveTab] = useState('2') + // ** Function to toggle tabs const toggle = tab => setActiveTab(tab) + + //modal const [confirmModal, setConfirmModal] = useState(false) - const [valiModal, setValiModal] = useState({ + const [modal, setModal] = useState({ isOpen: false, title: '', - desc: '' - }); - - const crtfyhpVali = yup.object().shape({ - memberName: yup.string().trim().required('이름을 입력해 주세요.'), - hpno: yup.string().required('휴대폰번호를 입력해 주세요.') + desc: '', + color: '' }) - const handlerCrtfySend = () => { - // const vData = getValues(); - setValiModal({ - isOpen: true, - title: '인증번호 발송', - desc: '인증번호 발송은 3회 까지만 가능합니다.' - }); - return false; - } + //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(() => { + if(isRunning) clearInterval(timer); + return () => { clearInterval(timer); } + }, []); + + const handlerSend = async() => { + if(!inputName || !inputHpno) { + setModal({ + isOpen: true, + title: '인증번호 발송', + desc: '빈칸을 채워주세요.', + color: 'modal-danger' + }) + return; + } + + if(sendCount >= 3) { + setModal({ + isOpen: true, + title: '인증번호 발송', + desc: '인증번호가 발송은 3회 까지만 가능합니다.', + 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(''); + } + }, 1000); + + setTimer(timer); + + return () => { + clearInterval(timer); + } + } + + const handlerConfirm = async() => { + if(!inputName || !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 handlerChange = (e) => { + const {name, value} = e.target; + + if(name == 'memberName') { + setInputName(value); + } else if(name == 'hpno') { + setInputHpno(value); + } else if(name == 'crtfyhpNo') { + setInputCrtfy(value); + } + } + + //모든 인증 완료 후 확인버튼 + const handlerFindId = () => { + dispatch(findUserIdAction.request({memberName: inputName, hpno: inputHpno})); + setConfirmModal(!confirmModal); + } - return( <> -
- + - + - + + {/* {errors && errors.memberName && ( + {errors.memberName.message} + )} */} - - -
- - - - {/* */} - - - - - - - - -
-
- -
- - - 남은시간 : 3:00 - - - - -
-
- -
+ + +
+ + + + {/* */} + + + + + {/* {errors && errors.hpno && ( + {errors.hpno.message} + )} */} + + + +
+
+ + +
+ + 0 ? + {} + : + {disabled: true} + } + /> + + 남은시간 {minutes_Counter}:{seconds_Counter} + + + + + +
+
+ +
+ + + setConfirmModal(!confirmModal)} className='modal-dialog-centered user-search-modal'> + setConfirmModal(!confirmModal)}>아이디 확인 + + 회원님의 아이디는
{userId?.data.userId} 입니다. + {/* 회원님의 아이디는
{result?.data.userId} 입니다. */} +
+ + {' '} + +
+
+
+ +
+ setModal({ ...modal, isOpen: !modal.isOpen })} + modalClassName={modal.color} + className='modal-dialog-centered' + > + setModal({ ...modal, isOpen: !modal.isOpen })} + > + {modal.title} + + {modal.desc} + + - - setConfirmModal(!confirmModal)} className='confirmModal-dialog-centered user-search-confirmModal'> - setConfirmModal(!confirmModal)}>아이디 확인 - - 회원님의 아이디는
TEST123123 입니다. -
- - {/* {' '} - -
-
- - + 확인 + {' '} + + +
+
) diff --git a/src/components/account/mypage/AccountMypagePwForm.js b/src/components/account/mypage/AccountMypagePwForm.js index 75a3593..fe322ec 100644 --- a/src/components/account/mypage/AccountMypagePwForm.js +++ b/src/components/account/mypage/AccountMypagePwForm.js @@ -53,7 +53,7 @@ const AccountMypagePwForm = ({user}) => { - + {errors && errors.userPswd && ( {errors.userPswd.message} )} @@ -62,7 +62,7 @@ const AccountMypagePwForm = ({user}) => { - + {errors && errors.newPswd && ( {errors.newPswd.message} )} @@ -71,7 +71,7 @@ const AccountMypagePwForm = ({user}) => { - + {errors && errors.newPswdConfirm && ( {errors.newPswdConfirm.message} )} diff --git a/src/components/account/register/AccountRegisterForm.js b/src/components/account/register/AccountRegisterForm.js index 7e42d56..4b3c972 100644 --- a/src/components/account/register/AccountRegisterForm.js +++ b/src/components/account/register/AccountRegisterForm.js @@ -479,13 +479,13 @@ export const AccountRegisterForm = ({ stepper, type, movePage }) => { ) : ( ) ) : ( )}
diff --git a/src/components/account/register/AccountRegisterTerm.js b/src/components/account/register/AccountRegisterTerm.js index e955c71..10efc24 100644 --- a/src/components/account/register/AccountRegisterTerm.js +++ b/src/components/account/register/AccountRegisterTerm.js @@ -165,6 +165,7 @@ export const AccountRegisterTerm = ({ stepper, type, movePage }) => { className='custom-control-Primary' id='termAll' checked={termChecked.all} + readOnly onClick={e => handlerChecked('all')} label='전체 이용약관에 모두 동의합니다.' /> @@ -176,6 +177,7 @@ export const AccountRegisterTerm = ({ stepper, type, movePage }) => { className='custom-control-Primary' id='termService' checked={termChecked.service} + readOnly onClick={e => handlerChecked('service')} label={terms.termServiceTitle} /> @@ -187,6 +189,7 @@ export const AccountRegisterTerm = ({ stepper, type, movePage }) => { className='custom-control-Primary' id='termPrivacy' checked={termChecked.privacy} + readOnly onClick={e => handlerChecked('privacy')} label={terms.termPrivacyTitle} /> diff --git a/src/modules/account/find/actions/findAction.ts b/src/modules/account/find/actions/findAction.ts new file mode 100644 index 0000000..230cf8b --- /dev/null +++ b/src/modules/account/find/actions/findAction.ts @@ -0,0 +1,52 @@ +import { AxiosError } from 'axios'; +import { string } from 'prop-types'; +import { ActionType, createAsyncAction } from 'typesafe-actions'; + +const SEND_FORID_REQUEST = 'find/SEND_FORID_REQUEST'; +const SEND_FORID_SUCCESS = 'find/SEND_FORID_SUCCESS'; +const SEND_FORID_FAILURE = 'find/SEND_FORID_FAILURE'; + +const FIND_USERID_REQUEST = 'find/FIND_USERID_REQUEST'; +const FIND_USERID_SUCCESS = 'find/FIND_USERID_SUCCESS'; +const FIND_USERID_FAILURE = 'find/FIND_USERID_FAILURE'; + +const SEND_FORPW_REQUEST = 'find/SEND_FORPW_REQUEST'; +const SEND_FORPW_SUCCESS = 'find/SEND_FORPW_SUCCESS'; +const SEND_FORPW_FAILURE = 'find/SEND_FORPW_FAILURE'; + +const UPDATE_USERPW_REQUEST = 'find/UPDATE_USERPW_REQUEST' +const UPDATE_USERPW_SUCCESS = 'find/UPDATE_USERPW_SUCCESS' +const UPDATE_USERPW_FAILURE = 'find/UPDATE_USERPW_FAILURE' + +export const sendForIdAction = createAsyncAction( + SEND_FORID_REQUEST, + SEND_FORID_SUCCESS, + SEND_FORID_FAILURE +)<{memberName: string, hpno: string}, string, AxiosError>(); + +export const findUserIdAction = createAsyncAction( + FIND_USERID_REQUEST, + FIND_USERID_SUCCESS, + FIND_USERID_FAILURE +)<{memberName: string, hpno: string}, string, AxiosError>(); + +export const sendForPwAction = createAsyncAction( + SEND_FORPW_REQUEST, + SEND_FORPW_SUCCESS, + SEND_FORPW_FAILURE +)<{userId: string, hpno: string}, string, AxiosError>(); + +export const updatePwAction = createAsyncAction( + UPDATE_USERPW_REQUEST, + UPDATE_USERPW_SUCCESS, + UPDATE_USERPW_FAILURE +)<{userId: string, hpno: string, newPw: string}, string, AxiosError>(); + +const actions = { + sendForIdAction, + findUserIdAction, + sendForPwAction, + updatePwAction +}; + +export type FindAction = ActionType; diff --git a/src/modules/account/find/apis/findApi.ts b/src/modules/account/find/apis/findApi.ts new file mode 100644 index 0000000..bf76512 --- /dev/null +++ b/src/modules/account/find/apis/findApi.ts @@ -0,0 +1,21 @@ +import axios from '../../../utils/customAxiosUtil'; + +import qs from 'qs'; + +export const findAPI = { + sendForId: async(param) => { + return await axios.get(`api/acnt/crtfyhp/find/sendForId?memberName=${param.memberName}&hpno=${param.hpno}`); + }, + + getUserId: async(param) => { + return await axios.get(`api/acnt/crtfyhp/find/findUserId?memberName=${param.memberName}&hpno=${param.hpno}`); + }, + + sendForPw: async(param) => { + return await axios.get(`api/acnt/crtfyhp/find/sendForPw?userId=${param.userId}&hpno=${param.hpno}`); + }, + + updatePw: async(param) => { + return await axios.get(`api/acnt/crtfyhp/find/updatePw?userId=${param.userId}&hpno=${param.hpno}&newPw=${param.newPw}`); + } +} \ No newline at end of file diff --git a/src/modules/account/find/models/findModel.ts b/src/modules/account/find/models/findModel.ts new file mode 100644 index 0000000..2086628 --- /dev/null +++ b/src/modules/account/find/models/findModel.ts @@ -0,0 +1,19 @@ +export interface AccountFindState { + accountFind: AccountFindData | undefined; +} +export interface AccountFindData { + cstmrSno: number; + userId: string; + memberName: string; + hpno: string; + cntfyhpNo: string; + crtfyhpYn: string; +} + +export interface IsCntfyhpSend { + +} + +export const initResponseFindData = { + accountFind: undefined +} diff --git a/src/modules/account/find/reducers/findReducer.ts b/src/modules/account/find/reducers/findReducer.ts new file mode 100644 index 0000000..37c17b8 --- /dev/null +++ b/src/modules/account/find/reducers/findReducer.ts @@ -0,0 +1,55 @@ +// base +import produce from 'immer'; + +import { createReducer } from 'typesafe-actions'; + +// action +import { + FindAction, + findUserIdAction, + sendForIdAction, + sendForPwAction, + updatePwAction +} from '../actions/findAction'; + +// +export interface findState { + idResult: string | undefined; + userId: string | undefined; + pwResult: string | undefined; + udResult: string | undefined; +} +const initFindState : findState = { + idResult: undefined, + userId: undefined, + pwResult: undefined, + udResult: undefined +} + +export const findAccountReducer = createReducer( + initFindState +).handleAction(sendForIdAction.success, (state, action) => + produce(state, draft => { + const data = action.payload; + + draft.idResult = data; + }) +).handleAction(findUserIdAction.success, (state, action) => + produce(state, draft => { + const data = action.payload; + + draft.userId = data; + }) +).handleAction(sendForPwAction.success, (state, action) => + produce(state, draft => { + const data = action.payload; + + draft.pwResult = data; + }) +).handleAction(updatePwAction.success, (state, action) => + produce(state, draft => { + const data = action.payload; + + draft.udResult = data; + }) +) \ No newline at end of file diff --git a/src/modules/account/find/sagas/findSaga.ts b/src/modules/account/find/sagas/findSaga.ts new file mode 100644 index 0000000..e4c8793 --- /dev/null +++ b/src/modules/account/find/sagas/findSaga.ts @@ -0,0 +1,67 @@ +import { call, put, takeEvery } from 'redux-saga/effects'; +// packages +import { ActionType } from 'typesafe-actions'; +// modules +import * as Actions from '../actions/findAction'; +import { findAPI } from '../apis/findApi'; + + +function* sendForIdSaga( + action: ActionType +) { + try{ + const {memberName, hpno} = action.payload; + + const res = yield call(findAPI.sendForId, { memberName, hpno }); + yield put(Actions.sendForIdAction.success(res)); + } catch (error) { + yield put(Actions.sendForIdAction.failure(error)); + } +} + +function* findUserIdSaga( + action: ActionType +) { + try{ + const {memberName, hpno} = action.payload; + + const res = yield call(findAPI.getUserId, { memberName, hpno }); + yield put(Actions.findUserIdAction.success(res)); + } catch (error) { + yield put(Actions.findUserIdAction.failure(error)); + } +} + +function* sendForPwSaga( + action: ActionType +) { + try{ + const {userId, hpno} = action.payload; + + const res = yield call(findAPI.sendForPw, {userId, hpno}); + yield put(Actions.sendForPwAction.success(res)); + } catch (error) { + yield put(Actions.sendForPwAction.failure(error)); + } +} + +function* updatePwSaga( + action: ActionType +) { + try{ + const {userId, hpno, newPw} = action.payload; + + const res = yield call(findAPI.updatePw, {userId, hpno, newPw}); + console.log(res, '>>>') + yield put(Actions.updatePwAction.success(res)); + } catch (error) { + yield put(Actions.updatePwAction.failure(error)); + } +} + +export function* findSaga() { + yield takeEvery(Actions.sendForIdAction.request, sendForIdSaga); + yield takeEvery(Actions.findUserIdAction.request, findUserIdSaga); + yield takeEvery(Actions.sendForPwAction.request, sendForPwSaga); + yield takeEvery(Actions.updatePwAction.request, updatePwSaga); +} \ No newline at end of file diff --git a/src/redux/reducers/rootReducer.ts b/src/redux/reducers/rootReducer.ts index 969c34a..c9e901a 100644 --- a/src/redux/reducers/rootReducer.ts +++ b/src/redux/reducers/rootReducer.ts @@ -15,6 +15,8 @@ import { groupReducer } from '../../modules/basis/group/reducers/basisGroupReduc import { basGroupSaga } from '../../modules/basis/group/sagas/basisGroupSaga'; import { messageReducer } from '../../modules/comn/message/reducers/comnMessageReducer'; import { mypageReducer, userPwReducer } from '../../modules/account/login/reducers/authReducer'; +import { findSaga } from '../../modules/account/find/sagas/findSaga'; +import { findAccountReducer } from '../../modules/account/find/reducers/findReducer'; import { controlGpDtlReducer, @@ -52,6 +54,7 @@ export function* saga() { yield all([fork(dronSaga)]); yield all([fork(analysisSimulatorSaga)]); yield all([fork(flightSaga)]); + yield all([fork(findSaga)]); } const rootReducer = combineReducers({ @@ -76,7 +79,8 @@ const rootReducer = combineReducers({ menuState: menuReducer, analysisHistoryState: analysisHistoryReducer, analysisSimulatorState: analysisSimulatorReducer, - flightState: flightReducer + flightState: flightReducer, + findState: findAccountReducer, }); export default rootReducer; diff --git a/src/views/control/alarm/ControlAlarmList.js b/src/views/control/alarm/ControlAlarmList.js index 8c20553..1aeb4c9 100644 --- a/src/views/control/alarm/ControlAlarmList.js +++ b/src/views/control/alarm/ControlAlarmList.js @@ -3,6 +3,7 @@ import { X } from 'react-feather'; import { useDispatch, useSelector } from 'react-redux'; import { controlGpArcrftWarnAction, controlGpLogAction } from '../../../modules/control/gp/actions/controlGpAction'; import ControlAlarmDetail from './ControlAlarmDetail'; +import { Badge } from 'reactstrap'; const ControlAlarmList = props => { const dispatch = useDispatch(); @@ -12,6 +13,8 @@ const ControlAlarmList = props => { const { controlGpList } = useSelector(state => state.controlGpState); const { controlGpArcrftWarnList } = useSelector(state => state.controlGpLogState); const { controlGpWarnLog } = useSelector(state => state.controlGpLogState); + const { objectId, isClickObject } = useSelector(state => state.controlMapReducer); + const [total, setTotal] = useState({ totalDroneCnt: 0, @@ -25,6 +28,13 @@ const ControlAlarmList = props => { dispatch(controlGpLogAction.request({id : cntrlId})); } + useEffect(() => { + if(isClickObject) { + props.setOpenAlarmList(false); + } + + }, [objectId, isClickObject]) + useEffect(() => { if(controlGpArcrftWarnList) { let totalWarnCnt = 0; @@ -89,8 +99,22 @@ const ControlAlarmList = props => {
-
{total? total.totalDroneCnt: 0}대 비행 중
-
전체 {total? total.totalWarnCnt : 0}건
+
드론 현황
+
+ + {total? total.totalDroneCnt: 0}대 비행 중 + +
+
+
+
+
+
비정상 알림 전체
+
+ + {total? total.totalWarnCnt : 0}건 + +
diff --git a/src/views/control/main/ControlMain.js b/src/views/control/main/ControlMain.js index 0b38daf..3a0b023 100644 --- a/src/views/control/main/ControlMain.js +++ b/src/views/control/main/ControlMain.js @@ -5,7 +5,8 @@ import logo from '../../../assets/images/pal_logo.png'; import { Sun, Map, Bell } from 'react-feather'; -import { AiOutlinePoweroff } from 'react-icons/ai'; +import { AiOutlinePoweroff, AiOutlineExclamation } from 'react-icons/ai'; +import { IoAlertOutline } from 'react-icons/io5'; import { ReactComponent as DroneMenuIcon } from '../../../assets/images/drone_menu_icon.svg'; @@ -19,11 +20,15 @@ import WebsocketClient from '../../../components/websocket/WebsocketClient'; import { useDispatch, useSelector } from 'react-redux'; import * as Actions from '../../../modules/account/login/actions/authAction'; +import { objectUnClickAction } from '../../../modules/control/map/actions/controlMapActions'; const ControlMain = () => { const dispatch = useDispatch(); const { isClickObject } = useSelector(state => state.controlMapReducer); + const { controlGpList } = useSelector(state => state.controlGpState); + + const [alarm, setAlarm] = useState(false); const [oepnReportList, setOpenReportList] = useState(false); const [openReportDetail, setOpenReportDetail] = useState(false); @@ -45,10 +50,14 @@ const ControlMain = () => { setOpenWeatherList(true); setOpenAlarmList(false); } else if (val === 'alarmList') { + dispatch(objectUnClickAction()); + setOpenReportList(false); setOpenReportDetail(false); setOpenWeatherList(false); setOpenAlarmList(true); + + setAlarm(false); } }; @@ -61,6 +70,20 @@ const ControlMain = () => { dispatch(Actions.logout.request()); }; + useEffect(() => { + + if(controlGpList) { + const warnGps = controlGpList.find(gps => { + return gps.controlWarnNotyCd === true + }) + + if(warnGps) { + setAlarm(true); + } + } + + }, [controlGpList]); + return ( <> @@ -88,7 +111,7 @@ const ControlMain = () => { */}