Browse Source

아이디찾기, 비밀번호 찾기 작업

pull/2/head
junh_eee 2 years ago
parent
commit
febd1c49da
  1. 517
      src/components/account/find/AccountFindPassword.js
  2. 4
      src/components/account/find/AccountFindTab.js
  3. 409
      src/components/account/find/AccountFindUserId.js
  4. 52
      src/modules/account/find/actions/findAction.ts
  5. 21
      src/modules/account/find/apis/findApi.ts
  6. 19
      src/modules/account/find/models/findModel.ts
  7. 55
      src/modules/account/find/reducers/findReducer.ts
  8. 67
      src/modules/account/find/sagas/findSaga.ts
  9. 6
      src/redux/reducers/rootReducer.ts

517
src/components/account/find/AccountFindPassword.js

@ -1,108 +1,463 @@
import * as yup from 'yup';
import classnames from 'classnames';
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { useParams, Link } from 'react-router-dom' import { useParams, Link } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux' 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, 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 { User, Info, CreditCard, Lock, Check, X } from 'react-feather'
import loginImg from '../../../assets/images/login01.png'; import loginImg from '../../../assets/images/login01.png';
import '../../../assets/css/custom.css'; 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 => { export const AccountFindPassword = props => {
// 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('1') const [activeTab, setActiveTab] = useState('1')
// ** Function to toggle tabs // ** Function to toggle tabs
const toggle = tab => setActiveTab(tab) 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( return(
<> <>
<TabPane tabId='2'> <TabPane tabId='2'>
<Form> <FormGroup className='form-label-group position-relative has-icon-left'>
<FormGroup className='form-label-group position-relative has-icon-left'> <InputGroup className=''>
<InputGroup className=''> <InputGroupAddon addonType='prepend'>
<InputGroupAddon addonType='prepend'> <InputGroupText>
<InputGroupText> <User size={14} />
<User size={14} /> </InputGroupText>
</InputGroupText> </InputGroupAddon>
</InputGroupAddon> <Input
<Input placeholder='아이디' /> type='text'
</InputGroup> id='userId'
</FormGroup> name='userId'
<FormGroup> placeholder='아이디'
<div className='input-btn'> value={inputId}
<Col md='3' xs='12'> onChange={handlerChange}
<Input type='select' placeholder='+(국가번호)'> />
<option>+82</option> </InputGroup>
<option>21111</option> </FormGroup>
</Input> <FormGroup>
</Col> <div className='input-btn'>
<Col md='6' xs='12'> <Col md='3' xs='12'>
<Input type='number' placeholder='휴대폰번호'/> <Input type='select' placeholder='+(국가번호)'>
</Col> <option>+82</option>
<Col md='3' xs='12'> </Input>
<Button color='primary' type='button'>인증번호 발송</Button> </Col>
</Col> <Col md='6' xs='12'>
</div> <Input
</FormGroup> type='number'
<FormGroup> id='hpno'
<div className='input-btn time-span'> name='hpno'
<Col md='9' xs='12' className='timeInput'> placeholder='01012345678'
<Input type='number' placeholder='인증번호 입력'/> value={inputHpno}
<span className='time'>남은시간 : 3:00</span> onChange={handlerChange}
</Col> />
<Col md='3' xs='12'> </Col>
<Button color='primary' type='button'>인증번호 확인</Button> <Col md='3' xs='12'>
</Col> <Button
</div> color='primary'
</FormGroup> type='button'
<FormGroup> onClick={handlerSend}
<div className='full-btn-2n vertically-centered-modal'> >인증번호 발송</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='인증번호 입력'
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 <Button
color='secondary' color='primary'
type='button' type='button'
onClick={props.handlerClose} onClick={handlerConfirm}
> {...sendCount > 0 ?
취소 {}
</Button> :
<Button color='primary' type='button' onClick={() => setModal(!modal)} >확인</Button> {disabled: true}
<Modal isOpen={modal} toggle={() => setModal(!modal)} className='modal-dialog-centered user-search-modal'> }
<ModalHeader toggle={() => setModal(!modal)}>비밀번호 확인</ModalHeader> >인증번호 확인</Button>
<ModalBody> </Col>
<span class="etc-txt">새로운 비밀번호로 변경해주세요.</span> </div>
<FormGroup className='form-label-group position-relative has-icon-left'> </FormGroup>
<InputGroup> <FormGroup>
<InputGroupAddon addonType='prepend'> <div className='full-btn-2n vertically-centered-modal'>
<InputGroupText> <Button
<Lock size={14} /> color='secondary'
</InputGroupText> type='button'
</InputGroupAddon> onClick={props.handlerClose}
<Input placeholder='새로운 비밀번호' type='password'/> >
</InputGroup> 취소
</FormGroup> </Button>
<FormGroup className='form-label-group position-relative has-icon-left mb-0'> <Button
<InputGroup> color='primary'
<InputGroupAddon addonType='prepend'> type='button'
<InputGroupText> onClick={() => setConfirmModal(!confirmModal)}
<Lock size={14} /> // onClick={handlerChangePw}
</InputGroupText> // {...isCrtfy ?
</InputGroupAddon> // {}
<Input placeholder='새로운 비밀번호 확인' type='password'/> // :
</InputGroup> // {disabled: true}
// }
>확인</Button>
{/* <Form onSubmit={handleSubmit(onSubmit)}> */}
<Modal isOpen={confirmModal} toggle={() => setConfirmModal(!confirmModal)} className='modal-dialog-centered user-search-modal'>
<ModalHeader toggle={() => setConfirmModal(!confirmModal)}>비밀번호 확인</ModalHeader>
<ModalBody>
<span class="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}
className={classnames({
'is-invalid': errors.newPw
})}
/>
{errors && errors.newPw && (
<FormFeedback>{errors.newPw.message}</FormFeedback>
)}
</InputGroup>
</FormGroup> </FormGroup>
</ModalBody> <FormGroup className='form-label-group position-relative has-icon-left mb-0'>
<ModalFooter> <InputGroup>
<Button color='primary' onClick={() => setModal(!modal)}> <InputGroupAddon addonType='prepend'>
저장 <InputGroupText>
</Button> <Lock size={14} />
</ModalFooter> </InputGroupText>
</Modal> </InputGroupAddon>
</div> <Input
</FormGroup> type='password'
</Form> id='newPwCk'
name='newPwCk'
placeholder='새로운 비밀번호 확인'
value={inputNewPwCk}
onChange={handlerChange}
className={classnames({
'is-invalid': errors.newPwCk
})}
/>
{errors && errors.newPwCk && (
<FormFeedback>{errors.newPwCk.message}</FormFeedback>
)}
</InputGroup>
</FormGroup>
</ModalBody>
<ModalFooter>
<Button
color='primary'
// type='submit'
type='button'
// onClick={() => setModal(!modal)}
onClick={handlerUpdatePw}
>저장</Button>
</ModalFooter>
</Modal>
{/* </Form> */}
</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>
{
udResult?.data.code === 0 ?
<Button
color='danger'
// onClick={() => setModal({ ...modal, isOpen: !modal.isOpen })}
// onClick={props.handlerClose}
onClick={handlerClose}
>
로그인
</Button>
:
<Button
color='danger'
onClick={() => setModal({ ...modal, isOpen: !modal.isOpen })}
>
확인
</Button>
}
</ModalFooter>
</Modal>
</div>
</TabPane> </TabPane>
</> </>
) )

4
src/components/account/find/AccountFindTab.js

@ -27,15 +27,13 @@ export const AccountFindTab = props => {
const history = useHistory(); const history = useHistory();
const toggle = tab => setActiveTab(tab) const toggle = tab => setActiveTab(tab)
const [centeredModal, setCenteredModal] = useState(false)
const [centeredModal02, setCenteredModal02] = useState(false)
// const toggle = tab => { // const toggle = tab => {
// if (activeTab !== tab) setActiveTab(tab); // if (activeTab !== tab) setActiveTab(tab);
// }; // };
const handlerClose = () => { const handlerClose = () => {
history.push(`/account/login/AccountLogin`) history.push(`/account/login`)
} }
return( return(

409
src/components/account/find/AccountFindUserId.js

@ -1,117 +1,362 @@
import * as yup from 'yup'; import * as yup from 'yup';
import classnames from 'classnames';
import { yupResolver } from '@hookform/resolvers/yup'; import { yupResolver } from '@hookform/resolvers/yup';
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { useParams, Link } from 'react-router-dom' import { useForm } from 'react-hook-form';
import { useSelector, useDispatch } from 'react-redux' 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, 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 { User, Info, CreditCard, Lock, Check, X } from 'react-feather'
import loginImg from '../../../assets/images/login01.png';
import '../../../assets/css/custom.css'; 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 => { 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('1')
// ** Function to toggle tabs // ** Function to toggle tabs
const toggle = tab => setActiveTab(tab) const toggle = tab => setActiveTab(tab)
//modal
const [confirmModal, setConfirmModal] = useState(false) const [confirmModal, setConfirmModal] = useState(false)
const [valiModal, setValiModal] = useState({ const [modal, setModal] = useState({
isOpen: false, isOpen: false,
title: '', title: '',
desc: '' desc: '',
}); color: ''
const crtfyhpVali = yup.object().shape({
memberName: yup.string().trim().required('이름을 입력해 주세요.'),
hpno: yup.string().required('휴대폰번호를 입력해 주세요.')
}) })
const handlerCrtfySend = () => { //state값
// const vData = getValues(); const { idResult, userId, pwResult, udResult } = useSelector(state => state.findState);
setValiModal({
isOpen: true, //param으로 넘기기 위한 값
title: '인증번호 발송', const [inputName, setInputName] = useState('');
desc: '인증번호 발송은 3회 까지만 가능합니다.' const [inputHpno, setInputHpno] = useState('');
}); const [inputCrtfy, setInputCrtfy] = useState('');
return false;
} //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( return(
<> <>
<TabPane tabId='1'> <TabPane tabId='1'>
<Form> <FormGroup className='form-label-group position-relative has-icon-left'>
<FormGroup className='form-label-group position-relative has-icon-left'>
<InputGroup className=''> <InputGroup className=''>
<InputGroupAddon addonType='prepend'> <InputGroupAddon addonType='prepend'>
<InputGroupText> <InputGroupText>
<User size={14} /> <User size={14}/>
</InputGroupText> </InputGroupText>
</InputGroupAddon> </InputGroupAddon>
<Input placeholder='이름' /> <Input
type='text'
id='memberName'
name='memberName'
placeholder='이름'
value={inputName}
onChange={handlerChange}
// className={classnames({
// 'is-invalid': errors.memberName
// })}
/>
{/* {errors && errors.memberName && (
<FormFeedback>{errors.memberName.message}</FormFeedback>
)} */}
</InputGroup> </InputGroup>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<div className='input-btn'> <div className='input-btn'>
<Col md='3' xs='12'> <Col md='3' xs='12'>
<Input type='select' placeholder='+(국가번호)'> <Input type='select' id='cntryCd' name='cntryCd' placeholder='+(국가번호)'>
<option>+82</option> <option>+82</option>
{/* <option>21111</option> */} {/* <option>21111</option> */}
</Input> </Input>
</Col> </Col>
<Col md='6' xs='12'> <Col md='6' xs='12'>
<Input type='number' placeholder='휴대폰번호'/> <Input
</Col> type='number'
<Col md='3' xs='12'> id='hpno'
<Button name='hpno'
color='primary' placeholder='01012345678'
type='button' value={inputHpno}
onClick={handlerCrtfySend} onChange={handlerChange}
> // className={classnames({
인증번호 발송 // 'is-invalid': errors.hpno
</Button> // })}
</Col> />
</div> {/* {errors && errors.hpno && (
</FormGroup> <FormFeedback>{errors.hpno.message}</FormFeedback>
<FormGroup> )} */}
<div className='input-btn'> </Col>
<Col md='9' xs='12' className='timeInput'> <Col md='3' xs='12'>
<Input type='number' placeholder='인증번호 입력'/>
<span className='time'>남은시간 : 3:00</span>
</Col>
<Col md='3' xs='12'>
<Button color='primary' type='button'>인증번호 확인</Button>
</Col>
</div>
</FormGroup>
<FormGroup>
<div className='full-btn-2n vertically-centered-confirmModal'>
<Button <Button
color='secondary' 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='인증번호 입력'
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' type='button'
onClick={props.handlerClose} onClick={handlerConfirm}
{...sendCount > 0 ?
{}
:
{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)} className='modal-dialog-centered user-search-modal'>
<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> </Button>{' '}
<Button color='primary' type='button' onClick={() => setConfirmModal(!confirmModal)} >확인</Button> </ModalFooter>
<Modal isOpen={confirmModal} toggle={() => setConfirmModal(!confirmModal)} className='confirmModal-dialog-centered user-search-confirmModal'> </Modal>
<ModalHeader toggle={() => setConfirmModal(!confirmModal)}>아이디 확인</ModalHeader> </div>
<ModalBody>
회원님의 아이디는<br/><span className='user-search-id'>TEST123123</span> .
</ModalBody>
<ModalFooter>
{/* <Button color='primary' onClick={() => setConfirmModal(!confirmModal)}> */}
<Button color='primary' onClick={props.handlerClose}>
로그인
</Button>{' '}
</ModalFooter>
</Modal>
</div>
</FormGroup>
</Form>
</TabPane> </TabPane>
</> </>
) )

52
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<typeof actions>;

21
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}`);
}
}

19
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
}

55
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<findState, FindAction>(
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;
})
)

67
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<typeof Actions.sendForIdAction.request>
) {
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<typeof Actions.findUserIdAction.request>
) {
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<typeof Actions.sendForPwAction.request>
) {
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<typeof Actions.updatePwAction.request>
) {
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);
}

6
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 { basGroupSaga } from '../../modules/basis/group/sagas/basisGroupSaga';
import { messageReducer } from '../../modules/comn/message/reducers/comnMessageReducer'; import { messageReducer } from '../../modules/comn/message/reducers/comnMessageReducer';
import { mypageReducer, userPwReducer } from '../../modules/account/login/reducers/authReducer'; 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 { import {
controlGpDtlReducer, controlGpDtlReducer,
@ -52,6 +54,7 @@ export function* saga() {
yield all([fork(dronSaga)]); yield all([fork(dronSaga)]);
yield all([fork(analysisSimulatorSaga)]); yield all([fork(analysisSimulatorSaga)]);
yield all([fork(flightSaga)]); yield all([fork(flightSaga)]);
yield all([fork(findSaga)]);
} }
const rootReducer = combineReducers({ const rootReducer = combineReducers({
@ -76,7 +79,8 @@ const rootReducer = combineReducers({
menuState: menuReducer, menuState: menuReducer,
analysisHistoryState: analysisHistoryReducer, analysisHistoryState: analysisHistoryReducer,
analysisSimulatorState: analysisSimulatorReducer, analysisSimulatorState: analysisSimulatorReducer,
flightState: flightReducer flightState: flightReducer,
findState: findAccountReducer,
}); });
export default rootReducer; export default rootReducer;

Loading…
Cancel
Save