-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #284 from Jaymyong66/feat/signup_login
회원가입 / 로그인 페이지 구현, 기능 구현
- Loading branch information
Showing
27 changed files
with
712 additions
and
48 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { LoginRequest, SignupRequest } from '@/types/authentication'; | ||
import { customFetch } from './customFetch'; | ||
|
||
const API_URL = process.env.REACT_APP_API_URL; | ||
|
||
export const SIGNUP_API_URL = `${API_URL}/signup`; | ||
export const LOGIN_API_URL = `${API_URL}/login`; | ||
export const LOGIN_STATE_API_URL = `${API_URL}/login/check`; | ||
export const CHECK_USERNAME_API_URL = `${API_URL}/check-username`; | ||
export const CHECK_EMAIL_API_URL = `${API_URL}/check-email`; | ||
|
||
export const postSignup = async (signupInfo: SignupRequest) => | ||
await customFetch({ | ||
method: 'POST', | ||
url: `${SIGNUP_API_URL}`, | ||
body: JSON.stringify(signupInfo), | ||
}); | ||
|
||
export const postLogin = async (loginInfo: LoginRequest) => { | ||
const response = await customFetch({ | ||
method: 'POST', | ||
url: `${LOGIN_API_URL}`, | ||
body: JSON.stringify(loginInfo), | ||
}); | ||
|
||
return response; | ||
}; | ||
|
||
export const getLoginState = async () => { | ||
const url = `${LOGIN_STATE_API_URL}`; | ||
|
||
const response = await customFetch({ url }); | ||
|
||
if (response.status === 401) { | ||
throw new Error('로그인을 해주세요.'); | ||
} | ||
|
||
if (!response.ok) { | ||
throw new Error('서버 에러가 발생했습니다.'); | ||
} | ||
|
||
return {}; | ||
}; | ||
|
||
export const checkEmail = async (email: string) => { | ||
const params = new URLSearchParams({ email }); | ||
const url = `${CHECK_EMAIL_API_URL}?${params}`; | ||
|
||
const response = await customFetch({ url }); | ||
|
||
if (response.status === 409) { | ||
throw new Error('중복된 이메일입니다.'); | ||
} | ||
|
||
if (!response.ok) { | ||
throw new Error('서버 에러가 발생했습니다.'); | ||
} | ||
|
||
return {}; | ||
}; | ||
|
||
export const checkUsername = async (username: string) => { | ||
const params = new URLSearchParams({ username }); | ||
const url = `${CHECK_USERNAME_API_URL}?${params}`; | ||
|
||
const response = await customFetch({ url }); | ||
|
||
if (response.status === 409) { | ||
throw new Error('중복된 닉네임입니다.'); | ||
} | ||
|
||
if (!response.ok) { | ||
throw new Error('서버 에러가 발생했습니다.'); | ||
} | ||
|
||
return {}; | ||
}; |
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 |
---|---|---|
@@ -1,4 +1,7 @@ | ||
export const QUERY_KEY = { | ||
TEMPLATE: 'template', | ||
TEMPLATE_LIST: 'templateList', | ||
LOGIN_STATE: 'loginState', | ||
CHECK_EMAIL: 'checkEmail', | ||
CHECK_USERNAME: 'userName', | ||
}; |
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,3 @@ | ||
export { useShowPassword } from './useShowPassword'; | ||
export { useSignupForm } from './useSignupForm'; | ||
export { useCheckLoginState } from './useCheckLoginState'; |
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,20 @@ | ||
import { useCallback, useEffect } from 'react'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import { useLoginStateQuery } from '@/queries/authentication/useLoginStateQuery'; | ||
|
||
export const useCheckLoginState = () => { | ||
const { error, isError } = useLoginStateQuery(); | ||
const navigate = useNavigate(); | ||
|
||
const handleLoginNavigate = useCallback(() => { | ||
navigate('/login'); | ||
}, [navigate]); | ||
|
||
useEffect(() => { | ||
if (isError) { | ||
alert(error.message); | ||
handleLoginNavigate(); | ||
} | ||
}, [error, isError, handleLoginNavigate]); | ||
}; |
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,53 @@ | ||
import { FormEvent } from 'react'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import { postLogin } from '@/api/authentication'; | ||
import { useInputWithValidate } from '../useInputWithValidate'; | ||
import { validateEmail, validatePassword } from './validates'; | ||
|
||
export const useLoginForm = () => { | ||
const navigate = useNavigate(); | ||
|
||
const { | ||
value: email, | ||
errorMessage: emailError, | ||
handleChange: handleEmailChange, | ||
} = useInputWithValidate('', validateEmail); | ||
|
||
const { | ||
value: password, | ||
errorMessage: passwordError, | ||
handleChange: handlePasswordChange, | ||
} = useInputWithValidate('', validatePassword); | ||
|
||
const isFormValid = () => !emailError && !passwordError && email && password; | ||
|
||
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => { | ||
e.preventDefault(); | ||
|
||
if (isFormValid()) { | ||
const response = await postLogin({ email, password }); | ||
|
||
if (!response.ok) { | ||
console.error(response); | ||
|
||
return; | ||
} | ||
|
||
navigate('/'); | ||
} | ||
}; | ||
|
||
return { | ||
email, | ||
password, | ||
errors: { | ||
email: emailError, | ||
password: passwordError, | ||
}, | ||
handleEmailChange, | ||
handlePasswordChange, | ||
isFormValid, | ||
handleSubmit, | ||
}; | ||
}; |
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,14 @@ | ||
import { useState } from 'react'; | ||
|
||
export const useShowPassword = () => { | ||
const [showPassword, setShowPassword] = useState(false); | ||
|
||
const handlePasswordToggle = () => { | ||
setShowPassword((prevShowPassword) => !prevShowPassword); | ||
}; | ||
|
||
return { | ||
showPassword, | ||
handlePasswordToggle, | ||
}; | ||
}; |
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,112 @@ | ||
import { FormEvent, useEffect } from 'react'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import { postSignup } from '@/api/authentication'; | ||
import { useCheckEmailQuery } from '@/queries/authentication'; | ||
import { useCheckUsernameQuery } from '@/queries/authentication/useCheckUsernameQuery'; | ||
import { useInputWithValidate } from '../useInputWithValidate'; | ||
import { validateEmail, validateUsername, validatePassword, validateConfirmPassword } from './validates'; | ||
|
||
export const useSignupForm = () => { | ||
const navigate = useNavigate(); | ||
|
||
const { | ||
value: email, | ||
errorMessage: emailError, | ||
handleChange: handleEmailChange, | ||
handleErrorMessage: handleEmailErrorMessage, | ||
} = useInputWithValidate('', validateEmail); | ||
|
||
const { | ||
value: username, | ||
errorMessage: usernameError, | ||
handleChange: handleUsernameChange, | ||
handleErrorMessage: handleUsernameErrorMessage, | ||
} = useInputWithValidate('', validateUsername); | ||
|
||
const { | ||
value: password, | ||
errorMessage: passwordError, | ||
handleChange: handlePasswordChange, | ||
} = useInputWithValidate('', validatePassword); | ||
|
||
const { | ||
value: confirmPassword, | ||
errorMessage: confirmPasswordError, | ||
handleChange: handleConfirmPasswordChange, | ||
handleErrorMessage: handleConfirmPasswordErrorMessage, | ||
} = useInputWithValidate('', (value, compareValue) => validateConfirmPassword(value, compareValue ?? '')); | ||
|
||
const { refetch: checkEmailQuery } = useCheckEmailQuery(email); | ||
const { refetch: checkUsernameQuery } = useCheckUsernameQuery(username); | ||
|
||
const handleEmailCheck = async () => { | ||
const { error } = await checkEmailQuery(); | ||
|
||
// refetch does not exist onError | ||
if (error) { | ||
handleEmailErrorMessage(error.message); | ||
} | ||
}; | ||
|
||
const handleUsernameCheck = async () => { | ||
const { error } = await checkUsernameQuery(); | ||
|
||
// refetch does not exist onError | ||
if (error) { | ||
handleUsernameErrorMessage(error.message); | ||
} | ||
}; | ||
|
||
// only change password not confirmPassword | ||
useEffect(() => { | ||
handleConfirmPasswordErrorMessage(validateConfirmPassword(password, confirmPassword)); | ||
}, [password, confirmPassword, handleConfirmPasswordErrorMessage]); | ||
|
||
const isFormValid = () => | ||
!emailError && | ||
!usernameError && | ||
!passwordError && | ||
!confirmPasswordError && | ||
email && | ||
username && | ||
password && | ||
confirmPassword; | ||
|
||
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => { | ||
e.preventDefault(); | ||
|
||
if (isFormValid()) { | ||
const response = await postSignup({ email, username, password }); | ||
|
||
if (!response.ok) { | ||
console.error(response); | ||
|
||
return; | ||
} | ||
|
||
navigate('/login'); | ||
} | ||
}; | ||
|
||
return { | ||
email, | ||
username, | ||
password, | ||
confirmPassword, | ||
errors: { | ||
email: emailError, | ||
username: usernameError, | ||
password: passwordError, | ||
confirmPassword: confirmPasswordError, | ||
}, | ||
handleEmailChange, | ||
handleUsernameChange, | ||
handlePasswordChange, | ||
handleConfirmPasswordChange, | ||
isFormValid, | ||
handleSubmit, | ||
handleEmailCheck, | ||
handleUsernameCheck, | ||
}; | ||
}; |
Oops, something went wrong.