Browse Source

회원가입 폼 컨테이너 생성

master
junh_eee(이준희) 7 months ago
parent
commit
e1d633c51a
  1. 4
      src/components/account/register/AccountRegister.js
  2. 245
      src/components/account/register/AccountRegisterForm.js
  3. 64
      src/containers/account/mypage/ParentsContainer.js
  4. 219
      src/containers/account/register/AccountRegisterFormContainer.js
  5. 4
      src/redux/features/account/register/registerThunk.ts

4
src/components/account/register/AccountRegister.js

@ -4,6 +4,7 @@ import { useRef, useState } from 'react';
import Wizard from '@core@components/wizard'; import Wizard from '@core@components/wizard';
import '@styles/base/pages/page-auth.scss'; import '@styles/base/pages/page-auth.scss';
import { AccountRegisterComplete } from './AccountRegisterComplete'; import { AccountRegisterComplete } from './AccountRegisterComplete';
import { AccountRegisterFormContainer } from '@src/containers/account/register/AccountRegisterFormContainer';
export const AccountRegister = ({ props }) => { export const AccountRegister = ({ props }) => {
// step // step
@ -37,11 +38,10 @@ export const AccountRegister = ({ props }) => {
title: '가입정보 입력', title: '가입정보 입력',
subtitle: 'STEP02', subtitle: 'STEP02',
content: ( content: (
<AccountRegisterForm <AccountRegisterFormContainer
stepper={stepper} stepper={stepper}
type='wizard-horizontal' type='wizard-horizontal'
movePage={movePage} movePage={movePage}
memberName={memberName}
setMemberName={setMemberName} setMemberName={setMemberName}
/> />
) )

245
src/components/account/register/AccountRegisterForm.js

@ -1,10 +1,6 @@
import { useDispatch, useSelector } from '@src/redux/store'; import { useSelector } from '@src/redux/store';
import * as yup from 'yup';
import { Fragment, useEffect, useRef, useState } from 'react'; import { Fragment, useEffect, useRef, useState } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import { isObjEmpty } from '@utils';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { import {
Form, Form,
Label, Label,
@ -20,207 +16,24 @@ import {
confirmCrtfyhp, confirmCrtfyhp,
sendCrtfyhp sendCrtfyhp
} from '@src/redux/features/account/register/registerThunk'; } from '@src/redux/features/account/register/registerThunk';
import { openModal } from '@src/redux/features/comn/message/messageSlice';
import { MODAL_CRTFYHP, MODAL_BODY, MODAL_HEADER } from '@src/configs/msgConst';
import { createRegister } from '@src/redux/features/account/register/registerThunk';
import {
isSendCrtfyhp,
isConfirmCrtfyhp
} from '@src/redux/features/comn/crtfyhp/crtfyhpSlice';
import { CrtfyhpUtil } from '@src/utility/crtfyhpUtil'; import { CrtfyhpUtil } from '@src/utility/crtfyhpUtil';
export const AccountRegisterForm = ({ export const AccountRegisterForm = ({
stepper, errors,
type, register,
movePage, getValues,
testName, onSubmit,
setMemberName handleSubmit,
handlerCancel,
handlerChange,
handlerSmsConfirm
}) => { }) => {
const dispatch = useDispatch();
// 약관동의 내용
const { agreeTerms } = useSelector(state => state.registerState);
const hookRef = useRef(); const hookRef = useRef();
const { isRunning, isCrtfyhp, counter } = useSelector( const { isRunning, isCrtfyhp, counter } = useSelector(
state => state.crtfyhpState state => state.crtfyhpState
); );
// 단순 메시지 표출 모달
const handlerOpenModal = (header, body) => {
dispatch(
openModal({
header: header,
body: body
})
);
};
// 회원가입 폼 유효성 검사
const SignupSchema = yup.object().shape({
userId: yup.string().trim().required('ID를 입력해 주세요.'),
// .matches(
// /^[a-z]+[a-z0-9]{5,19}$/g,
// '4자 이상, 20자 미만 영문자 또는 숫자로 입력해 주세요.'
// ),
userPswd: yup.string().required('비밀번호를 입력해 주세요.'),
// genderCd: yup.string().required('성별을 선택해 주세요.'),
brthdyDate: yup
.string()
.required('생년월일을 입력해 주세요.')
.matches(
/^(19[0-9][0-9]|20\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$/,
'올바른 생년월일을 입력해 주세요.'
),
memberName: yup
.string()
.required('이름을 입력해 주세요.')
.min(3, '최소 2 자 이상 입력 부탁드립니다.')
.max(20, '최대 10 자 이하 입력 부탁드립니다.'),
email: yup.string().required('이메일을 입력해 주세요.'),
hpno: yup
.string()
.required('휴대폰번호를 입력해 주세요.')
.matches(
/^(01[0-1])([1-9][0-9]{3})([0-9]{4})$/,
'올바른 휴대폰번호를 입력해 주세요.'
),
// cntryCd: yup.string().required('국가를 선택해 주세요.'),
clncd: yup.string().required('국가번호를 선택해 주세요.'),
userPswd: yup
.string()
.required('비밀번호를 입력해 주세요.')
.matches(
/^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@$!%*#?&])[A-Za-z0-9@$!%*#?&]{8,20}$/,
'8 자 이상, 20 자 미만 영문자/숫자/특수문자(@$!%*#?&) 조합하여 입력해 주세요.'
),
confirmUserPaswd: yup
.string()
.required('비밀번호 확인을 입력해 주세요.')
.oneOf([yup.ref('userPswd'), null], '비밀번호가 일치하지 않습니다.')
});
const { register, getValues, setValue, errors, handleSubmit } = useForm({
defaultValues: {
userId: '',
userPswd: '',
confirmUserPaswd: '',
cntryCd: 'KOR',
genderCd: '',
memberName: '',
brthdyDate: '',
email: '',
hpno: '',
clncd: '+82',
crtfyNo: '',
company: '팔네트웍스',
trmnlId: 'SANDBOX-001'
},
resolver: yupResolver(SignupSchema)
});
// 취소 헨들러
const handlerCancel = async () => {
movePage('/account/login');
};
// 회원가입 버튼 헨들러
const onSubmit = async rq => {
if (isObjEmpty(errors)) {
if (!isCrtfy) {
handlerOpenModal('회원가입 실패', '휴대폰 인증을 진행해주세요.');
return false;
}
const data = await dispatch(createRegister({ ...rq, terms: agreeTerms }));
if (data?.payload.errCode === -1) {
handlerOpenModal(
'회원가입 실패',
'동일한 아이디가 존재합니다. 다른 아이디로 가입 신청해주세요.'
);
return;
}
if (data?.payload.errCode === 1) {
stepper.next();
} else {
handlerOpenModal('회원가입 실패', '회원 가입에 실패하였습니다.');
return;
}
}
};
// 인증번호 인증 헨들러
const handlerSmsConfirm = async () => {
const vData = getValues();
if (!vData.clncd || !vData.hpno) {
handlerOpenModal(
MODAL_HEADER.crtfyhp,
'휴대폰 번호를' + MODAL_BODY.valid
);
return false;
}
if (!vData.crtfyNo) {
handlerOpenModal(MODAL_HEADER.crtfyhp, MODAL_CRTFYHP.valid);
return false;
}
const { payload: data } = await dispatch(
confirmCrtfyhp({ hpno: vData.hpno, crtfyNo: vData.crtfyNo })
);
if (!data.result) {
handlerOpenModal(MODAL_HEADER.crtfyhp, MODAL_CRTFYHP.failed);
dispatch(isConfirmCrtfyhp(false));
return;
} else {
handlerOpenModal(MODAL_HEADER.crtfyhp, MODAL_CRTFYHP.confirm);
dispatch(isSendCrtfyhp(false));
dispatch(isConfirmCrtfyhp(true));
return;
}
};
let hpno = '';
let brthdyDate = '';
let trmnlId = '';
// 회원가입 폼 변경 헨들러
const onChangeHandler = e => {
const { name, value } = e.target;
if (name === 'company') {
trmnlId = value;
setValue('trmnlId', trmnlId);
}
if (name === 'memberName') {
setMemberName(value);
}
if (name === 'brthdyDate') {
const regex = /^[0-9\b]{0,8}$/;
if (regex.test(value)) {
brthdyDate = value;
// setValue(name, value);
} else {
setValue(name, brthdyDate);
}
} else if (name === 'hpno') {
const regex = /^[0-9\b]{0,11}$/;
if (regex.test(value)) {
hpno = value;
// setValue(name, value);
} else {
setValue(name, hpno);
}
}
};
return ( return (
<Fragment> <Fragment>
<Form onSubmit={handleSubmit(onSubmit)}> <Form onSubmit={handleSubmit(onSubmit)}>
@ -239,7 +52,7 @@ export const AccountRegisterForm = ({
name='memberName' name='memberName'
id='memberName' id='memberName'
// value={registerInfo.memberName} // value={registerInfo.memberName}
onChange={onChangeHandler} onChange={handlerChange}
placeholder='홍길동' placeholder='홍길동'
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
@ -261,7 +74,7 @@ export const AccountRegisterForm = ({
name='brthdyDate' name='brthdyDate'
id='brthdyDate' id='brthdyDate'
// value={registerInfo.brthdyDate} // value={registerInfo.brthdyDate}
onChange={onChangeHandler} onChange={handlerChange}
placeholder='19950915' placeholder='19950915'
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
@ -284,7 +97,7 @@ export const AccountRegisterForm = ({
name='genderCd' name='genderCd'
id='genderCd' id='genderCd'
// value={registerInfo.genderCd} // value={registerInfo.genderCd}
onChange={onChangeHandler} onChange={handlerChange}
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
className={classnames({ className={classnames({
@ -310,7 +123,7 @@ export const AccountRegisterForm = ({
name='cntryCd' name='cntryCd'
id='cntryCd' id='cntryCd'
// value={registerInfo.cntryCd} // value={registerInfo.cntryCd}
onChange={onChangeHandler} onChange={handlerChange}
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
className={classnames({ className={classnames({
@ -337,7 +150,7 @@ export const AccountRegisterForm = ({
id='clncd' id='clncd'
readOnly={isCrtfyhp} readOnly={isCrtfyhp}
// value={registerInfo.clncd} // value={registerInfo.clncd}
onChange={onChangeHandler} onChange={handlerChange}
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
className={classnames({ className={classnames({
@ -358,7 +171,7 @@ export const AccountRegisterForm = ({
id='hpno' id='hpno'
readOnly={isCrtfyhp} readOnly={isCrtfyhp}
// value={registerInfo.hpno} // value={registerInfo.hpno}
onChange={onChangeHandler} onChange={handlerChange}
placeholder='01000000000' placeholder='01000000000'
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
@ -391,12 +204,6 @@ export const AccountRegisterForm = ({
</div> </div>
) : null} ) : null}
</FormGroup> </FormGroup>
<CrtfyhpUtil
ref={hookRef}
sendCrtfyhp={sendCrtfyhp}
modalMessage='이미 가입된 휴대폰입니다.'
type='1'
/>
<FormGroup tag={Col} md='6'> <FormGroup tag={Col} md='6'>
<Label className='form-label' for='crtfyNo'> <Label className='form-label' for='crtfyNo'>
<span className='necessary'>*</span> <span className='necessary'>*</span>
@ -410,7 +217,7 @@ export const AccountRegisterForm = ({
name='crtfyNo' name='crtfyNo'
id='crtfyNo' id='crtfyNo'
// value={registerInfo.crtfyNo} // value={registerInfo.crtfyNo}
onChange={onChangeHandler} onChange={handlerChange}
placeholder='' placeholder=''
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
@ -454,7 +261,7 @@ export const AccountRegisterForm = ({
id='userId' id='userId'
placeholder='johndoe' placeholder='johndoe'
// value={registerInfo.userId} // value={registerInfo.userId}
onChange={onChangeHandler} onChange={handlerChange}
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
className={classnames({ className={classnames({
@ -476,7 +283,7 @@ export const AccountRegisterForm = ({
name='email' name='email'
id='email' id='email'
// value={registerInfo.email} // value={registerInfo.email}
onChange={onChangeHandler} onChange={handlerChange}
placeholder='john.doe@email.com' placeholder='john.doe@email.com'
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
@ -501,7 +308,7 @@ export const AccountRegisterForm = ({
name='userPswd' name='userPswd'
id='userPswd' id='userPswd'
// value={registerInfo.userPswd} // value={registerInfo.userPswd}
onChange={onChangeHandler} onChange={handlerChange}
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
className={classnames({ className={classnames({
@ -523,7 +330,7 @@ export const AccountRegisterForm = ({
type='select' type='select'
name='company' name='company'
id='company' id='company'
onChange={onChangeHandler} onChange={handlerChange}
// ref={register} // ref={register}
className={classnames({ className={classnames({
'is-invalid': errors.company 'is-invalid': errors.company
@ -542,7 +349,7 @@ export const AccountRegisterForm = ({
name='trmnlId' name='trmnlId'
id='trmnlId' id='trmnlId'
readOnly={true} readOnly={true}
onChange={onChangeHandler} onChange={handlerChange}
ref={register} ref={register}
className={classnames({ className={classnames({
'is-invalid': errors.trmnlId 'is-invalid': errors.trmnlId
@ -564,7 +371,7 @@ export const AccountRegisterForm = ({
name='confirmUserPaswd' name='confirmUserPaswd'
id='confirmUserPaswd' id='confirmUserPaswd'
// value={registerInfo.confirmUserPaswd} // value={registerInfo.confirmUserPaswd}
onChange={onChangeHandler} onChange={handlerChange}
ref={register} ref={register}
// ref={register({ required: true })} // ref={register({ required: true })}
className={classnames({ className={classnames({
@ -590,6 +397,12 @@ export const AccountRegisterForm = ({
</ConfirmButton> </ConfirmButton>
</div> </div>
</Form> </Form>
<CrtfyhpUtil
ref={hookRef}
sendCrtfyhp={sendCrtfyhp}
modalMessage='이미 가입된 휴대폰입니다.'
type='1'
/>
</Fragment> </Fragment>
); );
}; };

64
src/containers/account/mypage/ParentsContainer.js

@ -1,64 +0,0 @@
import { sendCrtfyhp } from '@src/redux/features/account/register/registerThunk';
import { useSelector } from '@src/redux/store';
import { Button, Label, Row, Col, Input } from '@src/components/ui';
import { useRef, useState } from 'react';
import { CrtfyhpUtil } from '@src/utility/crtfyhpUtil';
export const ParentsContainer = () => {
const hookRef = useRef();
const { isRunning, isCrtfyhp, counter } = useSelector(
state => state.crtfyhpState
);
const [hpno, setHpno] = useState('');
const handlerChange = e => {
const { name, value } = e.target;
if (name == 'hpno') {
const regex = /^[0-9]{0,11}$/;
if (regex.test(value)) {
setHpno(value);
}
}
};
return (
<>
<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={hpno}
onChange={handlerChange}
placeholder='01012345678'
/>
</Col>
<Col md='4' xs='12'>
<span className={!isRunning || isCrtfyhp ? 'time d-none' : 'time'}>
남은시간 {counter.min}:{counter.sec}
</span>
<Button
type='button'
color='secondary'
onClick={() => hookRef?.current?.handlerSendCrtfyhp({ hpno })}
>
<span className='d-sm-inline-block'>인증번호 발송</span>
</Button>
</Col>
</Row>
<CrtfyhpUtil
ref={hookRef}
sendCrtfyhp={sendCrtfyhp}
modalMessage='이미 가입된 어쩌구 입니다.'
type='1'
/>
</>
);
};

219
src/containers/account/register/AccountRegisterFormContainer.js

@ -0,0 +1,219 @@
import * as yup from 'yup';
import { isObjEmpty } from '@utils';
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import {
confirmCrtfyhp,
sendCrtfyhp
} from '@src/redux/features/account/register/registerThunk';
import { openModal } from '@src/redux/features/comn/message/messageSlice';
import { MODAL_CRTFYHP, MODAL_BODY, MODAL_HEADER } from '@src/configs/msgConst';
import { createRegister } from '@src/redux/features/account/register/registerThunk';
import {
isSendCrtfyhp,
isConfirmCrtfyhp
} from '@src/redux/features/comn/crtfyhp/crtfyhpSlice';
import { useRef } from 'react';
import { useDispatch, useSelector } from '@src/redux/store';
import { AccountRegisterForm } from '@src/components/account/register/AccountRegisterForm';
export const AccountRegisterFormContainer = ({
stepper,
type,
movePage,
setMemberName
}) => {
const dispatch = useDispatch();
const { isCrtfyhp } = useSelector(state => state.crtfyhpState);
// 약관동의 내용
const { agreeTerms } = useSelector(state => state.registerState);
// 단순 메시지 표출 모달
const handlerOpenModal = (header, body) => {
dispatch(
openModal({
header: header,
body: body
})
);
};
// 회원가입 폼 유효성 검사
const SignupSchema = yup.object().shape({
userId: yup.string().trim().required('ID를 입력해 주세요.'),
// .matches(
// /^[a-z]+[a-z0-9]{5,19}$/g,
// '4자 이상, 20자 미만 영문자 또는 숫자로 입력해 주세요.'
// ),
userPswd: yup.string().required('비밀번호를 입력해 주세요.'),
brthdyDate: yup
.string()
.required('생년월일을 입력해 주세요.')
.matches(
/^(19[0-9][0-9]|20\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$/,
'올바른 생년월일을 입력해 주세요.'
),
memberName: yup
.string()
.required('이름을 입력해 주세요.')
.min(3, '최소 2 자 이상 입력 부탁드립니다.')
.max(20, '최대 10 자 이하 입력 부탁드립니다.'),
email: yup.string().required('이메일을 입력해 주세요.'),
hpno: yup
.string()
.required('휴대폰번호를 입력해 주세요.')
.matches(
/^(01[0-1])([1-9][0-9]{3})([0-9]{4})$/,
'올바른 휴대폰번호를 입력해 주세요.'
),
// cntryCd: yup.string().required('국가를 선택해 주세요.'),
clncd: yup.string().required('국가번호를 선택해 주세요.'),
userPswd: yup
.string()
.required('비밀번호를 입력해 주세요.')
.matches(
/^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@$!%*#?&])[A-Za-z0-9@$!%*#?&]{8,20}$/,
'8 자 이상, 20 자 미만 영문자/숫자/특수문자(@$!%*#?&) 조합하여 입력해 주세요.'
),
confirmUserPaswd: yup
.string()
.required('비밀번호 확인을 입력해 주세요.')
.oneOf([yup.ref('userPswd'), null], '비밀번호가 일치하지 않습니다.')
});
const { register, getValues, setValue, errors, handleSubmit } = useForm({
defaultValues: {
userId: '',
userPswd: '',
confirmUserPaswd: '',
cntryCd: 'KOR',
genderCd: '',
memberName: '',
brthdyDate: '',
email: '',
hpno: '',
clncd: '+82',
crtfyNo: '',
company: '팔네트웍스',
trmnlId: 'SANDBOX-001'
},
resolver: yupResolver(SignupSchema)
});
// 취소 헨들러
const handlerCancel = async () => {
movePage('/account/login');
};
// 회원가입 버튼 헨들러
const onSubmit = async rq => {
if (isObjEmpty(errors)) {
if (!isCrtfyhp) {
handlerOpenModal('회원가입 실패', '휴대폰 인증을 진행해주세요.');
return false;
}
const { payload: data } = await dispatch(
createRegister({ ...rq, terms: agreeTerms })
);
if (data?.errCode === -1) {
handlerOpenModal(
'회원가입 실패',
'동일한 아이디가 존재합니다. 다른 아이디로 가입 신청해주세요.'
);
return;
} else if (data?.errCode === 1) {
stepper.next();
} else {
handlerOpenModal('회원가입 실패', '회원 가입에 실패하였습니다.');
return;
}
}
};
// 인증번호 인증 헨들러
const handlerSmsConfirm = async () => {
const vData = getValues();
if (!vData.clncd || !vData.hpno) {
handlerOpenModal(
MODAL_HEADER.crtfyhp,
'휴대폰 번호를' + MODAL_BODY.valid
);
return false;
}
if (!vData.crtfyNo) {
handlerOpenModal(MODAL_HEADER.crtfyhp, MODAL_CRTFYHP.valid);
return false;
}
const { payload: data } = await dispatch(
confirmCrtfyhp({ hpno: vData.hpno, crtfyNo: vData.crtfyNo })
);
if (!data.result) {
handlerOpenModal(MODAL_HEADER.crtfyhp, MODAL_CRTFYHP.failed);
dispatch(isConfirmCrtfyhp(false));
return;
} else {
handlerOpenModal(MODAL_HEADER.crtfyhp, MODAL_CRTFYHP.confirm);
dispatch(isSendCrtfyhp(false));
dispatch(isConfirmCrtfyhp(true));
return;
}
};
let hpno = '';
let brthdyDate = '';
let trmnlId = '';
// 회원가입 폼 변경 헨들러
const handlerChange = e => {
const { name, value } = e.target;
if (name === 'company') {
trmnlId = value;
setValue('trmnlId', trmnlId);
}
if (name === 'memberName') {
setMemberName(value);
}
if (name === 'brthdyDate') {
const regex = /^[0-9\b]{0,8}$/;
if (regex.test(value)) {
brthdyDate = value;
// setValue(name, value);
} else {
setValue(name, brthdyDate);
}
} else if (name === 'hpno') {
const regex = /^[0-9\b]{0,11}$/;
if (regex.test(value)) {
hpno = value;
// setValue(name, value);
} else {
setValue(name, hpno);
}
}
};
return (
<AccountRegisterForm
errors={errors}
register={register}
getValues={getValues}
onSubmit={onSubmit}
handleSubmit={handleSubmit}
handlerCancel={handlerCancel}
handlerChange={handlerChange}
handlerSmsConfirm={handlerSmsConfirm}
/>
);
};

4
src/redux/features/account/register/registerThunk.ts

@ -27,11 +27,7 @@ export const createRegister = createAsyncThunk(
}; };
} = await axios.post('api/acnt/cstmr/register', param); } = await axios.post('api/acnt/cstmr/register', param);
if (data.errCode > 0) {
return data; return data;
} else {
throw new Error();
}
} catch (error) { } catch (error) {
thunkAPI.dispatch( thunkAPI.dispatch(
openModal({ openModal({

Loading…
Cancel
Save