<개인>
<함께 진행 한 것>
모든 과정을 거치면 모달이 뜨고 모달에 있는 확인을 누르면 로그인 페이지로 넘어가도록 했다.
비슷한 기능은 다시 재활용 할 수 있도록 만든 것이 작업 속도를 줄여준다는 것을 체감 하게 되는 순간이었다.
기능은 완성했지만 콘솔에 에러가 많이 찍혀있다.
get 404에러는 아마 비밀번호 재설정 전에 있는 인증번호 부분이 서버단에서 완성이 되지 않아 그런 듯 하다. 내일중으로 백엔드분께 여쭤보기로 한다!
patch해 주는 데이터는 콘솔에 잘 찍히는 것을 확인했다!
비밀번호 완성 코드
petchPassword.tsx
import axios from "axios";
interface ResetPwData {
id: string;
email: string;
password: string;
}
const petchPassword = async ({ id, email, password }: ResetPwData) => {
const data = {
id: id,
email: email,
password: password,
};
return await axios.patch(`http://13.209.7.184:8080/members`, data);
};
export default petchPassword;
usePatchPw.tsx
import { useMutation } from "react-query";
import petchPassword from "../../apis/user/petchPassword";
interface ResetPwData {
id: string;
email: string;
password: string;
}
const usePatchPwData = ({ id, email, password }: ResetPwData) => {
return useMutation(petchPassword);
};
export default usePatchPwData;
resetpw.tsx
import CertifyPageLayout from "../components/CertifyPageLayout";
import { useForm } from "react-hook-form";
import { ErrorMessage } from "@hookform/error-message";
import { useCallback, useState } from "react";
import useCheckUserId from "../hooks/user/useCheckUserId";
import AuthBtn from "../components/AuthBtn";
import EmailCheckNumberLayout from "../components/EmailCheckNumberLayout";
import SubmitBtn from "../components/SubmitBtn";
import useCheckEmail from "../hooks/user/useCheckEmail";
import useCheckAuthNum from "../hooks/user/useCheckAuthNum";
import usePatchPw from "../hooks/user/usePatchPw";
import ResetPwModal from "../components/ResetPwModal";
const ResetPw = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormInputs>();
interface FormInputs {
idErrorInput: string;
emailErrorInput: string;
passwordErrorInput: string;
repasswordErrorInput: string;
}
interface ResetPwData {
id: string;
email: string;
password: string;
}
const [idValue, setIdValue] = useState<string>("");
const [checkId, setCheckId] = useState<boolean>(false);
const [emailValue, setEmailValue] = useState<string>("");
const [checkEmail, setCheckEmail] = useState<boolean>(false);
const [isSameEmail, setIsSameEmail] = useState<boolean>(false);
const [isCheckEmail, setIsCheckEmail] = useState<boolean>(false);
const [pwValue, setPwValue] = useState<string>("");
const [checkPw, setCheckPw] = useState<boolean>(false);
const [rePwValue, setRePwValue] = useState<string>("");
const [checkRePw, setCheckRePw] = useState<boolean>(false);
const [authInputView, setAuthInputView] = useState<boolean>(false);
const [authNumValue, setAuthNumValue] = useState<string>("");
const [checkAuthNum, setCheckAuthNum] = useState<boolean>(true);
const [pwInputView, setPwInputView] = useState<boolean>(false);
const [patchPwData, setPatchPwData] = useState<ResetPwData>({
id: idValue,
email: emailValue,
password: pwValue,
});
const [modalView, setModalView] = useState<boolean>(false);
const { data: idData, refetch: idRefetch } = useCheckUserId(idValue);
const { data: emailData, refetch: emailRefetch } = useCheckEmail(emailValue);
const { data: authNumData, refetch: authNumRefetch } = useCheckAuthNum(
authNumValue,
emailValue,
);
const { data: resetPw, mutate: singUpMute } = usePatchPw(patchPwData);
const emailRex = /\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b/gi;
const pwRex =
/^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,23}$/;
const idRex = /^[a-zA-Z0-9]{5,20}$/;
const handleAuthClick = () => {
setAuthInputView(true);
};
const handleIdChange = (e: any) => {
setIdValue(e.target.value);
};
const handleEmailChange = (e: any) => {
if (emailRex.test(e.target.value)) {
setCheckEmail(true);
} else {
setCheckEmail(false);
}
setEmailValue(e.target.value);
};
const handlePressEnter = (e: any) => {
if (e.keyCode === 13) {
e.preventDefault();
if (idValue.length >= 5) {
idRefetch();
console.log(idData);
}
}
};
const handleEmailEnter = (e: any) => {
e.preventDefault();
if (e.keyCode === 13 && checkEmail) {
// console.log(emailData);
emailRefetch();
setIsCheckEmail(true);
}
};
const handlePwChange = (e: any) => {
if (pwRex.test(e.target.value)) {
setCheckPw(true);
} else {
setCheckPw(false);
}
setPwValue(e.target.value);
};
const handleRePwChange = (e: any) => {
if (e.target.value === pwValue) {
setCheckRePw(true);
setPatchPwData({
id: idValue,
email: emailValue,
password: e.target.value,
});
} else {
setCheckRePw(false);
}
setRePwValue(e.target.value);
};
const handleAuthNumChange = (e: any) => {
setAuthNumValue(e.target.value);
};
const handleClickAuthNumBtn = () => {
// 조건문 추가
authNumRefetch();
setCheckAuthNum(true);
setAuthInputView(false);
setPwInputView(true);
const idPwTag = document.getElementById("idPwTag");
idPwTag!.style.display = "none";
};
const handleClickSubmit = (e: any) => {
e.preventDefault();
// console.log(idValue, emailValue, pwValue);
singUpMute(patchPwData);
console.log(patchPwData);
console.log(resetPw);
setModalView(true);
};
return (
<>
{modalView && checkRePw && checkPw ? <ResetPwModal /> : null}
<CertifyPageLayout>
<div className="flex flex-col items-start justify-start w-full h-full">
<div className="relative items-center justify-center w-fit h-7 ">
<div className="z-10 text-base md:text-xl lg:text-2xl text-zinc-500 font-SCDream6">
비밀번호 재설정
</div>
<div className="absolute left-0 right-0 top-5 md:top-6 lg:top-7 bottom-1 md:bottom-0 lg:-bottom-1 bg-mainOrange/40"></div>
</div>
<div id="idPwTag" className="w-full">
<form className="w-full mt-7">
<div className="flex flex-col w-full h-fit">
<div className="relative items-center justify-center w-fit h-7 mt-7">
<label
htmlFor="identity"
className="text-base text-gray-500 font-SCDream5"
>
ID
</label>
<div className="absolute top-4 md:top-4.5 lg:top-4 left-0 right-0 bottom-2 md:bottom-1.5 lg:bottom-1.5 bg-mainOrange/40"></div>
</div>
<input
className="font-SCDream3 text-gray-500 w-full text-xs md:text-sm mt-2 border-b-[1px] border-mainOrange/40 outline-none"
id="identity"
autoComplete="off"
type="text"
value={idValue}
onKeyDown={handlePressEnter}
placeholder="ID를 입력 후 Enter를 눌러주세요"
{...register("idErrorInput", {
required: "ID는 필수 입력입니다.",
onChange: handleIdChange,
minLength: 5,
pattern: {
value: /^(?=.[A-Za-z])(?=.\d)[A-Za-z\d]{5,}$/,
message: "ID는 영문,숫자 5자 이상 입력되어야합니다.",
},
})}
/>
<ErrorMessage
errors={errors}
name="idErrorInput"
render={({ message }) => (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
{message}
</div>
)}
/>
{idValue.length !== 0 &&
(idValue.length < 5 || !idRex.test(idValue)) ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
ID는 영문,숫자포함 5자 이상 입력되어야합니다.
</div>
) : null}
{/* API 구현 뒤 수정 필요 */}
{idData && idData.data.length > 0 ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-mainOrange h-fit font-SCDream2">
존재하는 ID입니다
</div>
) : idData && idData.data.length === 0 ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
존재하지 않는 ID입니다
</div>
) : null}
</div>
</form>
<form className="w-full" onSubmit={handleEmailEnter}>
<div className="flex flex-col w-full h-fit">
<div className="relative items-center justify-center w-fit h-7 mt-7">
<label
htmlFor="email"
className="text-base text-gray-500 font-SCDream5"
>
E-mail
</label>
<div className="absolute top-4 md:top-4.5 lg:top-4 left-0 right-0 bottom-2 md:bottom-1.5 lg:bottom-1.5 bg-mainOrange/40"></div>
</div>
<div className="flex flex-row items-end justify-center w-full h-fit">
<input
className="font-SCDream3 text-gray-500 w-full text-xs md:text-sm mt-2 border-b-[1px] border-mainOrange/40 outline-none"
id="email"
autoComplete="off"
type="text"
value={emailValue}
onKeyUp={handleEmailEnter}
placeholder="Email 입력 후 Enter를 눌러주세요"
{...register("emailErrorInput", {
required: "Email은 필수 입력입니다.",
onChange: handleEmailChange,
})}
/>
{emailValue.length !== 0 && isCheckEmail && checkAuthNum ? (
<AuthBtn onClick={handleAuthClick}>인증요청</AuthBtn>
) : checkAuthNum ? (
<AuthBtn
onClick={() => {
return 0;
}}
>
인증완료
</AuthBtn>
) : emailValue.length !== 0 &&
isCheckEmail &&
!checkAuthNum ? (
<AuthBtn
onClick={() => {
return 0;
}}
>
인증완료
</AuthBtn>
) : null}
{/* <AuthBtn>인증완료</AuthBtn> */}
</div>
<ErrorMessage
errors={errors}
name="emailErrorInput"
render={({ message }) => (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
{message}
</div>
)}
/>
{emailValue.length !== 0 && !checkEmail ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
올바르지않은 이메일 형식입니다
</div>
) : null}
{/* isSameEmail 상태 활용 */}
{/* api완성 시 수정필요 */}
{emailValue.length !== 0 && isSameEmail && isCheckEmail ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-mainOrange h-fit font-SCDream2">
존재 하지 않는 Email입니다
</div>
) : emailValue.length !== 0 && !isSameEmail && isCheckEmail ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
존재하는 Email입니다. 인증요청 버튼을 클릭해주세요
</div>
) : null}
</div>
</form>
{authInputView ? (
<EmailCheckNumberLayout>
<div
id=""
className="text-xs text-mainOrange font-SCDream4 md:text-sm"
>
입력하신 Email로 인증번호가 발송되었습니다
</div>
{authNumValue.length !== 0 && !checkAuthNum ? (
<div className=" text-nagativeMessage font-SCDream3 text-[11px] md:text-[12px] mt-2">
인증번호가 올바르지 않습니다
</div>
) : (
<div className=" text-nagativeMessage font-SCDream3 text-[11px] md:text-[12px] mt-2">
5분이내에 입력해주세요
</div>
)}
<input
className="flex pl-5 pr-5 pt-1 pb-1 mt-3 mb-3 font-SCDream3 text-gray-500 w-60 h-fit text-xs md:text-sm outline-none text-center rounded-md border-b-[1px] border-mainOrange/40"
placeholder="인증번호를 입력하세요"
value={authNumValue}
onChange={handleAuthNumChange}
/>
<AuthBtn onClick={handleClickAuthNumBtn}>인증</AuthBtn>
</EmailCheckNumberLayout>
) : null}
</div>
<div className="w-full mt-7">
{isCheckEmail && !authInputView && pwInputView ? (
<form className="w-full" onSubmit={handleClickSubmit}>
<div className="flex flex-col w-full h-fit">
<div className="flex flex-col w-full md:flex-row h-fit">
<div className="relative items-center justify-center w-fit h-7 mt-3">
<label
htmlFor="password"
className="text-base text-gray-500 font-SCDream5"
>
비밀번호
</label>
<div className="absolute top-4 md:top-4.5 lg:top-4 left-0 right-0 bottom-2 md:bottom-1.5 lg:bottom-1.5 bg-mainOrange/40"></div>
</div>
<div className="font-SCDream3 text-gray-400 w-fit h-fit text-[10px] mt-0 md:mt-5 ml-0 md:ml-2">
특수문자, 영문자, 숫자 포함 8글자 이상으로 입력해주세요
</div>
</div>
<input
className="font-SCDream3 text-gray-500 w-full text-xs md:text-sm mt-2 border-b-[1px] border-mainOrange/40 outline-none"
id="email"
autoComplete="off"
type="password"
value={pwValue}
placeholder="비밀번호를 입력하세요"
{...register("passwordErrorInput", {
required: "비밀번호는 필수 입력입니다.",
onChange: handlePwChange,
})}
/>
<ErrorMessage
errors={errors}
name="passwordErrorInput"
render={({ message }) => (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
{message}
</div>
)}
/>
{pwValue.length !== 0 && checkPw ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-mainOrange h-fit font-SCDream2">
올바른 비밀번호 형식입니다
</div>
) : pwValue.length !== 0 && !checkPw ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
비밀번호 형식이 올바르지 않습니다
</div>
) : null}
</div>
<div className="flex flex-col w-full h-fit">
<div className="relative items-center justify-center w-fit h-7 mt-3">
<label
htmlFor="checkpassword"
className="text-base text-gray-500 font-SCDream5"
>
비밀번호 확인
</label>
<div className="absolute top-4 md:top-4.5 lg:top-4 left-0 right-0 bottom-2 md:bottom-1.5 lg:bottom-1.5 bg-mainOrange/40"></div>
</div>
<input
className="font-SCDream3 text-gray-500 w-full text-xs md:text-sm mt-2 mb-0 border-b-[1px] border-mainOrange/40 outline-none"
id="checkpassword"
autoComplete="off"
type="password"
value={rePwValue}
placeholder="다시 한번 비밀번호를 입력하세요"
{...register("repasswordErrorInput", {
required: "비밀번호를 확인하세요",
onChange: handleRePwChange,
})}
/>
<ErrorMessage
errors={errors}
name="repasswordErrorInput"
render={({ message }) => (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
{message}
</div>
)}
/>
{rePwValue.length !== 0 && checkRePw ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-mainOrange h-fit font-SCDream2">
비밀번호가 일치합니다
</div>
) : rePwValue.length !== 0 && !checkRePw ? (
<div className="flex flex-row items-end justify-end w-full mt-1 text-xs text-nagativeMessage h-fit font-SCDream2">
비밀번호가 일치하지 않습니다
</div>
) : null}
</div>
<div className="flex flex-row items-center justify-end w-full h-fit mt-4">
<SubmitBtn onClick={() => handleClickSubmit} />
</div>
</form>
) : null}
</div>
</div>
</CertifyPageLayout>
</>
);
};
export default ResetPw;
//수정 전
/**
* @description 사용 예시 : CertifyPageLayout태그 안에서 코드 작성
**/
//수정 후
/**
* @author yeowool
* @description 사용 예시 : CertifyPageLayout태그 안에서 코드 작성
**/
케케케 이번 주 넘 정신이 없어서 회고를 왕창밀렸다!
원래 하루하루 안 밀리고 잘 썼었는데 23일부터 밀렸다! 빨랑 쓰자~~
열심히 회고를 정리 하는 것으로 이번 한 주를 마무리하고 내일 새롭게 달려보도록 한다!
참 여러모로 도움이 많이 되는 시간이었다.
내용을 정리한 링크 1125백엔드 멘토링 참관
오늘 오후 데일리스크럼에서 팀원분들이 그려주신
헬짱여울이다
맘에든다!ㅎㅎ
오늘 백엔드 멘토링 시간에 이런저런 말씀을 많이 들어서 넘 좋았다
특히 책을 아무리 읽어도 이해가 가지 않는 부분이 많아서 책을 읽는 것이 의미가 있는가에 대해 고민을 하던 차 였는데 그 부분에 대해서도 속 시원한 해답을 얻게 되어 좋았다.
배포 시에 각자 페이지가 로드 되는 순서가 다른데 그 부분에 대해서도 좋은 답을 얻어 좋았다
다음 주는 시간을 내서라도 멘토링에 들어가고싶다 꼭~!!
이번 주 초반에는 내가 브랜치를 꼬아놔서 팀원분들이 고생하셨는데
자책감에 너무 마음이 괴로웠지만..
그래도 함께 해 주시는 분들이 너무 잘 도와주셔서 멘탈도 잘 회복되었다
다음 주도 불태워보자~~~