Skip to content

Commit

Permalink
Merge pull request #172 from SCBJ-7/#169-password_reset_refactor
Browse files Browse the repository at this point in the history
[#169] 비밀번호 찾기 페이지 리팩토링
  • Loading branch information
im-na0 authored Jan 25, 2024
2 parents 3665106 + 57bf940 commit 2f74a71
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 187 deletions.
198 changes: 11 additions & 187 deletions src/pages/passwordResetPage/PasswordReset.tsx
Original file line number Diff line number Diff line change
@@ -1,200 +1,24 @@
import { useForm } from "react-hook-form";
import { FormProvider, useForm } from "react-hook-form";
import * as S from "./PasswordReset.style";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import axios from "axios";
import { EMAIL_REGEX } from "@constants/regex";

type FormValues = {
email: string;
password: string;
checkPassword: string;
code: string;
isCodeCorrect: boolean;
};
import FieldValues from "./components/fieldValues/FieldValues";
import PasswordResetSubmitBtn from "./components/passwordResetSubmitBtn.tsx/PasswordResetSubmitBtn";

const PasswordReset = () => {
const navigate = useNavigate();

const {
register,
getValues,
setValue,
formState: { errors, isValid },
handleSubmit,
setError,
clearErrors,
} = useForm({
defaultValues: {
email: "",
code: "",
password: "",
checkPassword: "",
isCodeCorrect: false,
},
const method = useForm({
mode: "onChange",
shouldUnregister: false,
});

const [isEmailValidated, setIsEmailValidated] = useState(false);
const [codeState, setCodeState] = useState("######");

const handleOnSubmit = async (data: FormValues) => {
const { password, email } = data;
await axios
.patch("https://3.34.147.187.nip.io/v1/members/password", {
email,
password,
})
.then(() => {
navigate("/signin");
})
.catch(({ response }) => {
console.log(response);
alert(response.data.message);
});
};

const handleEmailValidateClick = async () => {
await axios
.post("https://3.34.147.187.nip.io/v1/members/email", {
email: getValues("email"),
})
.then((response) => {
if (response.status === 200) {
clearErrors("email");
setCodeState(response.data.data);
setIsEmailValidated(true);
}
})
.catch(({ response }) => {
setError("email", { message: response.data.message });
setIsEmailValidated(false);
});
};

const handleValidationCodeClick = () => {
const code = getValues("code");
if (code === codeState) {
setValue("isCodeCorrect", true);
clearErrors("isCodeCorrect");
} else {
setValue("isCodeCorrect", false);
setError("isCodeCorrect", { message: "잘못된 인증번호입니다" });
}
};

return (
<S.PasswordResetContainer onSubmit={handleSubmit(handleOnSubmit)}>
<S.PasswordResetContainer>
<S.PasswordResetTitleContainer>
<S.PasswordResetTitle>비밀번호 변경</S.PasswordResetTitle>
</S.PasswordResetTitleContainer>

<S.PasswordResetInputContainer>
<S.PasswordResetInputWrapper>
<S.PasswordResetInputTitle>이메일</S.PasswordResetInputTitle>
<S.PasswordResetRelativeWrapper>
<S.PasswordResetInput
{...register("email", {
required: "이메일을 입력해주세요",
pattern: {
value: EMAIL_REGEX,
message: "이메일 양식이 올바르지 않습니다",
},
})}
placeholder="이메일을 입력해주세요"
/>
<S.PasswordResetInputBtn
type="button"
$isCodeCorrect={isEmailValidated}
onClick={handleEmailValidateClick}
>
{isEmailValidated ? "재요청" : "인증 요청"}{" "}
</S.PasswordResetInputBtn>
</S.PasswordResetRelativeWrapper>
<S.PasswordResetInputCaption>
{errors.email?.message}{" "}
</S.PasswordResetInputCaption>
</S.PasswordResetInputWrapper>

<S.PasswordResetInputWrapper>
<S.PasswordResetInputTitle>인증번호 입력</S.PasswordResetInputTitle>
<S.PasswordResetRelativeWrapper>
<S.PasswordResetInput
{...register("code")}
type="number"
maxLength={6}
placeholder="코드 6자리를 입력해주세요"
/>
<input
style={{ display: "none" }}
type="checkbox"
{...register("isCodeCorrect", {
required: true,
validate: (isCodeCorrect) => {
return isCodeCorrect === true || "잘못된 인증번호입니다";
},
})}
/>
<S.PasswordResetInputBtn
$isCodeCorrect={getValues("isCodeCorrect")}
onClick={handleValidationCodeClick}
type="button"
>
{getValues("isCodeCorrect") ? "인증확인" : "확인"}{" "}
</S.PasswordResetInputBtn>
</S.PasswordResetRelativeWrapper>
<S.PasswordResetInputCaption
$isCodeCorrect={getValues("isCodeCorrect")}
>
{getValues("isCodeCorrect") ? "인증이 완료되었습니다" : ""}
{errors.isCodeCorrect?.message}{" "}
</S.PasswordResetInputCaption>
</S.PasswordResetInputWrapper>

<S.PasswordResetInputWrapper>
<S.PasswordResetInputTitle>새 비밀번호</S.PasswordResetInputTitle>
<S.PasswordResetInput
{...register("password", {
required: "비빌번호를 설정해주세요.",
pattern: {
value: /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{7,}$/,
message:
"영문, 숫자, 특수기호중 2개 이상을 포함해 8자 이상이여야 합니다.",
},
})}
type="password"
placeholder="비밀번호를 설정해주세요"
/>
<S.PasswordResetInputCaption>
{errors.password?.message}
</S.PasswordResetInputCaption>
</S.PasswordResetInputWrapper>

<S.PasswordResetInputWrapper>
<S.PasswordResetInputTitle>
새 비밀번호 확인
</S.PasswordResetInputTitle>
<S.PasswordResetInput
{...register("checkPassword", {
required: "입력하신 비밀번호와 다릅니다.",
validate: (checkPassword) => {
return (
getValues("password") === checkPassword ||
"입력하신 비밀번호와 다릅니다."
);
},
})}
type="password"
placeholder="동일한 비밀번호를 입력해주세요"
/>
<S.PasswordResetInputCaption>
{errors.checkPassword?.message}
</S.PasswordResetInputCaption>
</S.PasswordResetInputWrapper>
</S.PasswordResetInputContainer>

<S.PasswordResetSubmitBtn $isValid={isValid} type="submit">
비밀번호 변경
</S.PasswordResetSubmitBtn>
<FormProvider {...method}>
<FieldValues />
<PasswordResetSubmitBtn />
</FormProvider>
</S.PasswordResetContainer>
);
};
Expand Down
150 changes: 150 additions & 0 deletions src/pages/passwordResetPage/components/fieldValues/FieldValues.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import InputField from "@components/inputField/InputField";
import * as S from "../../PasswordReset.style";
import { EMAIL_REGEX } from "@constants/regex";
import { useFormContext } from "react-hook-form";
import { useEffect, useState } from "react";
import { useValidateEmailMutation } from "@hooks/api/mutation/useValidateEmailMutation";
import axios from "axios";

type FormValues = {
email: string;
password: string;
checkPassword: string;
code: string;
isCodeCorrect: boolean;
};

const FieldValues = () => {
const { setError, clearErrors, control, watch, getValues } =
useFormContext<FormValues>();

const [isEmailValidated, setIsEmailValidated] = useState(false);
const [isCodeValidated, setIsCodeValidated] = useState(false);
const [codeState, setCodeState] = useState("######");

const validateEmailMutation = useValidateEmailMutation();

const handleEmailValidateClick = async () => {
const email = getValues("email");
validateEmailMutation.mutate(
{ email },
{
onSuccess: (response) => {
clearErrors("email");
setCodeState(response);
setIsEmailValidated(true);
},
onError: (error) => {
if (axios.isAxiosError(error) && error.response) {
setError("email", { message: error.response.data.message });
setIsEmailValidated(false);
}
},
},
);
};

const code = watch("code");
useEffect(() => {
setIsCodeValidated(false);
}, [code]);

const handleValidationCodeClick = () => {
const isValid = code === codeState;

setIsCodeValidated(isValid);
if (code === codeState) {
setIsCodeValidated(true);
clearErrors("code");
} else {
setIsCodeValidated(false);
setError("code", { message: "인증번호를 다시 입력해주세요" });
}
};

return (
<S.PasswordResetInputContainer>
<InputField
name="email"
control={control}
label="이메일"
placeholder="이메일을 입력해주세요"
rules={{
required: "이메일을 입력해주세요",
pattern: {
value: EMAIL_REGEX,
message: "이메일 양식이 올바르지 않습니다",
},
}}
defaultValue=""
onButtonClick={handleEmailValidateClick}
buttonText={isEmailValidated ? "재요청" : "인증 요청"}
buttonVariant={isEmailValidated ? "solid" : "outline"}
buttonColor="percentOrange"
color="black"
/>

<InputField
type="number"
name="code"
control={control}
label="인증번호 입력"
placeholder="코드 6자리를 입력해주세요"
rules={{
required: "인증번호를 입력해주세요",
minLength: {
value: 6,
message: "6자리 이상 입력해주세요",
},
}}
defaultValue=""
onButtonClick={handleValidationCodeClick}
buttonText={isCodeValidated ? "인증 완료" : "인증 확인"}
buttonVariant={isCodeValidated ? "solid" : "outline"}
isSuccess={isCodeValidated}
successMessage="인증이 완료되었습니다"
buttonColor="percentOrange"
color="black"
/>

<InputField
type="password"
name="password"
control={control}
label="비밀번호"
placeholder="비빌번호를 설정해주세요"
rules={{
required: "비빌번호를 설정해주세요",
pattern: {
value: /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{7,}$/,
message:
"영문, 숫자, 특수기호중 2개 이상을 포함해 8자 이상이여야 합니다.",
},
}}
defaultValue=""
color="black"
/>

<InputField
type="password"
name="checkPassword"
control={control}
label="비밀번호 확인"
placeholder="동일한 비밀번호를 입력해주세요"
rules={{
required: "입력하신 비밀번호와 다릅니다.",
validate: (checkPassword) => {
return (
getValues("password") === checkPassword ||
"입력하신 비밀번호와 다릅니다."
);
},
}}
defaultValue=""
color="black"
/>
</S.PasswordResetInputContainer>
);
};

export default FieldValues;
Loading

0 comments on commit 2f74a71

Please sign in to comment.