-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 비밀번호 변경 api 구현 * feat: 비밀번호 변경 api 로그인 정보 및 유저 정보 확인 * feat: 변경 성공 시 새로운 accessToken 쿠키 설정 * refactor: 이전 비밀번호와 같은 비밀번호 입력 시 새로운 에러메세지 출력 * fix: 비밀번호 확인 시 에러메세지 표시되지 않는 버그 수정 * refactor: state 줄이고 if return 문으로 구조 변경 * fix: package-lock.json 제거 * refactor: newPasswordForm 컴포넌트 react-hook-form으로 리팩토링 * refactor: 비밀번호 확인 유효성 검사 로직 수정 및 api 호출부 함수 분리 * refactor : mutation으로 api 호출 후 동작 위임, 맞춰서 PostChangePassword api 수정 * fix: import 오류 fix, 비밀번호 정규식 통일 * fix: api error throw 삭제 * fix: 사용하지 않는 import 삭제 * fix: userState 사용하는 로직 삭제
- Loading branch information
Showing
9 changed files
with
136 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { authClient } from '@/apis'; | ||
import { SessionTokenType } from '@/home/types/password.type'; | ||
|
||
import { PostAuthSignInData } from '../types/Auth.type'; | ||
|
||
interface changePasswordProps { | ||
email: string; | ||
newPassword: string; | ||
sessionToken: SessionTokenType; | ||
} | ||
|
||
export const postChangePassword = async ({ | ||
email, | ||
sessionToken, | ||
newPassword, | ||
}: changePasswordProps): Promise<PostAuthSignInData> => { | ||
const res = await authClient.post('/auth/change-password', { | ||
email: email, | ||
newPassword: newPassword, | ||
sessionToken: sessionToken.sessionToken, | ||
}); | ||
return res.data; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 58 additions & 46 deletions
104
src/home/components/ChangePasswordContents/NewPasswordForm/useNewPasswordForm.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,81 @@ | ||
import { useState, useEffect } from 'react'; | ||
|
||
import { hasNumberAndEnglishWithSymbols } from '@yourssu/utils'; | ||
import { useForm } from 'react-hook-form'; | ||
import { useNavigate } from 'react-router-dom'; | ||
import { useRecoilValue } from 'recoil'; | ||
|
||
import { SessionTokenType } from '@/home/types/GetPassword.type'; | ||
import { api } from '@/service/TokenService'; | ||
import { useGetUserData } from '@/home/hooks/useGetUserData'; | ||
import { usePostChangePassword } from '@/home/hooks/usePostChangePassword'; | ||
import { LogInState } from '@/home/recoil/LogInState'; | ||
import { NewPasswordFormProps } from '@/home/types/password.type'; | ||
|
||
export const useNewPasswordForm = (sessionToken: SessionTokenType) => { | ||
const [newPassword, setNewPassword] = useState(''); | ||
const [newPasswordCheck, setNewPasswordCheck] = useState(''); | ||
const [isNewPasswordError, setIsNewPasswordError] = useState(false); | ||
const [isNewPasswordCheckError, setIsNewPasswordCheckError] = useState(false); | ||
const [isFirstRender, setIsFirstRender] = useState(true); | ||
const [validationAttempted, setValidationAttempted] = useState(false); | ||
export const useNewPasswordForm = (props: NewPasswordFormProps) => { | ||
const { sessionToken, previousPassword } = props; | ||
const [isFirstRender, setIsFirstRender] = useState<boolean>(true); | ||
const { | ||
register, | ||
watch, | ||
formState: { errors }, | ||
getValues, | ||
setValue, | ||
setError, | ||
} = useForm({ | ||
mode: 'onChange', | ||
}); | ||
|
||
const isLoggedIn = useRecoilValue(LogInState); | ||
const { data: currentUser } = useGetUserData(); | ||
const navigate = useNavigate(); | ||
const postChangePassword = usePostChangePassword(); | ||
|
||
const newPassword = watch('newPassword'); | ||
|
||
const regexp = new RegExp('^(?=.*[a-zA-Z])(?=.*[0-9]).{8,}$'); | ||
useEffect(() => { | ||
setIsFirstRender(!newPassword || newPassword.length < 8); | ||
}, [newPassword]); | ||
|
||
const handleNewPasswordChange = (password: string) => { | ||
setNewPassword(password); | ||
if (password.length >= 8) { | ||
setIsFirstRender(false); | ||
setIsNewPasswordError(!regexp.test(password)); | ||
} else { | ||
setIsNewPasswordError(true); | ||
const passwordValidate = (newPassword: string) => { | ||
if (newPassword === previousPassword) { | ||
setValue('newPasswordCheck', ''); | ||
return '현재 비밀번호와 다른 비밀번호를 입력해주세요.'; | ||
} | ||
|
||
if (hasNumberAndEnglishWithSymbols(newPassword) && newPassword.length <= 100) return true; | ||
|
||
setValue('newPasswordCheck', ''); | ||
return '숫자, 영문자, 특수문자 조합으로 8자 이상 입력해주세요.'; | ||
}; | ||
|
||
const handleSubmit = () => { | ||
if (sessionToken === null) { | ||
const onSubmit = () => { | ||
const newPasswordCheck = getValues('newPasswordCheck'); | ||
|
||
if (newPassword !== newPasswordCheck) { | ||
setError('newPasswordCheck', { | ||
type: 'manual', | ||
message: '비밀번호가 일치하지 않습니다.', | ||
}); | ||
return; | ||
} | ||
|
||
setValidationAttempted(true); | ||
const isValid = regexp.test(newPassword); | ||
if (isValid && newPassword === newPasswordCheck) { | ||
const accessToken = api.getAccessToken(); | ||
if (!accessToken) { | ||
alert('로그인이 필요합니다.'); | ||
navigate('/Login'); | ||
return; | ||
} | ||
setIsNewPasswordCheckError(false); | ||
if (!isLoggedIn || !currentUser) { | ||
navigate('/Login'); | ||
return; | ||
} | ||
|
||
if (!isValid) setIsNewPasswordError(true); | ||
if (newPassword !== newPasswordCheck) setIsNewPasswordCheckError(true); | ||
postChangePassword.mutate({ | ||
email: currentUser.email, | ||
newPassword, | ||
sessionToken, | ||
}); | ||
}; | ||
|
||
useEffect(() => { | ||
if (newPassword.length < 8) { | ||
setIsNewPasswordCheckError(false); | ||
setNewPasswordCheck(''); | ||
setValidationAttempted(false); | ||
} | ||
}, [newPassword]); | ||
|
||
return { | ||
newPassword, | ||
newPasswordCheck, | ||
isNewPasswordError, | ||
isNewPasswordCheckError, | ||
isFirstRender, | ||
validationAttempted, | ||
setNewPasswordCheck, | ||
handleNewPasswordChange, | ||
handleSubmit, | ||
register, | ||
onSubmit, | ||
passwordValidate, | ||
errors, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { useMutation } from '@tanstack/react-query'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import { postChangePassword } from '@/home/apis/postChangePassword'; | ||
import { api } from '@/service/TokenService'; | ||
|
||
export const usePostChangePassword = () => { | ||
const navigate = useNavigate(); | ||
|
||
return useMutation({ | ||
mutationFn: postChangePassword, | ||
onSuccess: (data) => { | ||
api.setAccessToken(data.accessToken, data.accessTokenExpiredIn); | ||
api.setRefreshToken(data.refreshToken, data.refreshTokenExpiredIn); | ||
navigate('/mypage'); | ||
}, | ||
onError: () => { | ||
navigate('/Login'); | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters