-
Notifications
You must be signed in to change notification settings - Fork 1
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 #11 from JECT-Study/feature/auth
[TASK-30] 로그인/회원가입 페이지 구현
- Loading branch information
Showing
29 changed files
with
1,738 additions
and
1,026 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
Large diffs are not rendered by default.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
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,26 @@ | ||
import { USER } from '@/constants/API'; | ||
import { useMutation } from '@tanstack/react-query'; | ||
import { useRouter } from 'next/navigation'; | ||
|
||
import defaultClient from '..'; | ||
|
||
const postLogin = async (formData: LoginFormType) => { | ||
const { data } = await defaultClient.post<ResponseRootType<DefaultAuthType>>( | ||
USER.login, | ||
formData, | ||
); | ||
|
||
return data; | ||
}; | ||
|
||
const usePostLogin = () => { | ||
const router = useRouter(); | ||
|
||
return useMutation({ | ||
mutationKey: [USER.login], | ||
mutationFn: (formData: LoginFormType) => postLogin(formData), | ||
onSuccess: () => router.push('/'), | ||
}); | ||
}; | ||
|
||
export default usePostLogin; |
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,25 @@ | ||
import { USER } from '@/constants/API'; | ||
import { useMutation } from '@tanstack/react-query'; | ||
import { useRouter } from 'next/navigation'; | ||
import defaultClient from '..'; | ||
|
||
const postSignUp = async (formData: SignUpFormType) => { | ||
const { data } = await defaultClient.post<ResponseRootType<DefaultAuthType>>( | ||
USER.signup, | ||
formData, | ||
); | ||
|
||
return data; | ||
}; | ||
|
||
const usePostSignUp = () => { | ||
const router = useRouter(); | ||
|
||
return useMutation({ | ||
mutationKey: [USER.signup], | ||
mutationFn: (formData: SignUpFormType) => postSignUp(formData), | ||
onSuccess: () => router.push('/'), | ||
}); | ||
}; | ||
|
||
export default usePostSignUp; |
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,40 @@ | ||
import { USER } from '@/constants/API'; | ||
import { useQuery } from '@tanstack/react-query'; | ||
import defaultClient from '..'; | ||
|
||
const getSocialLogin = async (queryUrl: string) => { | ||
const { data } = | ||
await defaultClient.get<ResponseRootType<SocialLoginAuthType>>(queryUrl); | ||
|
||
return data; | ||
}; | ||
|
||
const useGetSocialLogin = ({ | ||
provider, | ||
params, | ||
}: { | ||
provider: string; | ||
params: string; | ||
}) => { | ||
const queryUrl = `${USER.socialLogin}/${provider}?${params}`; | ||
const { data, isLoading } = useQuery({ | ||
queryKey: [`${USER.socialLogin}/${provider}`], | ||
queryFn: () => getSocialLogin(queryUrl), | ||
}); | ||
|
||
const hasData = !!data; | ||
|
||
const authorizedRes: SocialLoginAuthType = hasData | ||
? data.value | ||
: { | ||
isRegistered: false, | ||
token: { | ||
accessToken: '', | ||
refreshToken: '', | ||
}, | ||
}; | ||
|
||
return { hasData, authorizedRes, isLoading }; | ||
}; | ||
|
||
export default useGetSocialLogin; |
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,39 @@ | ||
import { USER } from '@/constants/API'; | ||
import { useQuery } from '@tanstack/react-query'; | ||
import defaultClient from '..'; | ||
|
||
const getValidateEmail = async (email: string): Promise<ValidateResponse> => { | ||
const { data } = await defaultClient.get<ResponseRootType<null>>( | ||
USER.validateEmail, | ||
{ | ||
params: { | ||
email, | ||
}, | ||
}, | ||
); | ||
|
||
const { code, message } = data; | ||
|
||
return { | ||
isValid: code === 204, | ||
message, | ||
}; | ||
}; | ||
|
||
const useGetValidateEmail = (email: string, mode: string) => { | ||
const { data, isLoading } = useQuery({ | ||
queryKey: [USER.validateEmail, email], | ||
queryFn: () => getValidateEmail(email), | ||
enabled: email.trim() !== '' && mode === 'sign-up', | ||
}); | ||
|
||
const hasData = !!data; | ||
|
||
const validInfo = hasData | ||
? { isValid: data.isValid, message: data.message } | ||
: { isValid: false, message: '' }; | ||
|
||
return { isLoading, ...validInfo }; | ||
}; | ||
|
||
export default useGetValidateEmail; |
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,39 @@ | ||
import { USER } from '@/constants/API'; | ||
import { useQuery } from '@tanstack/react-query'; | ||
import defaultClient from '..'; | ||
|
||
const getValidateNickname = async ( | ||
nickname: string, | ||
): Promise<ValidateResponse> => { | ||
const { data } = await defaultClient.get<ResponseRootType<null>>( | ||
USER.validateNickname, | ||
{ | ||
params: { | ||
nickname, | ||
}, | ||
}, | ||
); | ||
|
||
return { | ||
isValid: data.code === 204, | ||
message: data.message, | ||
}; | ||
}; | ||
|
||
const useGetValidateNickName = (nickName: string) => { | ||
const { data, isLoading } = useQuery({ | ||
queryKey: [USER.validateNickname, nickName], | ||
queryFn: () => getValidateNickname(nickName), | ||
enabled: nickName.trim() !== '', | ||
}); | ||
|
||
const hasData = !!data; | ||
|
||
const validInfo = hasData | ||
? { isValid: data.isValid, message: data.message } | ||
: { isValid: false, message: '' }; | ||
|
||
return { isLoading, ...validInfo }; | ||
}; | ||
|
||
export default useGetValidateNickName; |
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,17 @@ | ||
import Image from 'next/image'; | ||
import { ReactNode } from 'react'; | ||
|
||
import logo from '@/../public/images/momentiaLogoSymbol.png'; | ||
|
||
interface LayoutProps { | ||
readonly children: ReactNode; | ||
} | ||
|
||
export default function layout({ children }: LayoutProps) { | ||
return ( | ||
<div className='m-auto h-full w-[420px] flex flex-col justify-center items-center gap-[25px]'> | ||
<Image src={logo} alt='모멘티아 로고' width={45} priority /> | ||
{children} | ||
</div> | ||
); | ||
} |
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,64 @@ | ||
'use client'; | ||
|
||
import usePostLogin from '@/apis/user/login'; | ||
import SquareButtonL from '@/components/Button/SquareButtonL'; | ||
import EmailInput from '@/components/Input/EmailInput'; | ||
import PasswordInput from '@/components/Input/PasswordInput'; | ||
import SocialLoginSection from '@/components/SocialLoginSection'; | ||
|
||
import Link from 'next/link'; | ||
|
||
import { FormProvider, useForm } from 'react-hook-form'; | ||
|
||
export default function LogInPage() { | ||
const { mutate } = usePostLogin(); | ||
|
||
const methods = useForm<LoginFormType>({ | ||
defaultValues: { | ||
email: '', | ||
password: '', | ||
}, | ||
}); | ||
|
||
const onValid = (data: LoginFormType) => { | ||
console.log(data); | ||
mutate(data); | ||
}; | ||
|
||
const allFieldsFilled = Object.values(methods.watch()).every( | ||
(value) => value !== '', | ||
); | ||
|
||
return ( | ||
<div className='flex flex-col justify-center items-center gap-[60px]'> | ||
<h4>로그인</h4> | ||
|
||
<FormProvider {...methods}> | ||
<form | ||
name='login-form' | ||
onSubmit={methods.handleSubmit(onValid)} | ||
className='w-full flex flex-col gap-[60px]' | ||
> | ||
<div className='flex flex-col gap-[30px]'> | ||
<EmailInput mode={'sign-in'} /> | ||
<PasswordInput mode={'sign-in'} /> | ||
</div> | ||
<SquareButtonL | ||
type='submit' | ||
textSize={''} | ||
backgroundColor={allFieldsFilled ? 'bg-main' : 'bg-gray-800'} | ||
> | ||
<p>로그인</p> | ||
</SquareButtonL> | ||
</form> | ||
</FormProvider> | ||
<div className='w-full flex flex-col gap-[30px] justify-center text-center'> | ||
<SocialLoginSection /> | ||
<div className='flex gap-2.5 justify-center items-center mt-[13px]'> | ||
<p className='text-gray-600'>아직 회원이 아니신가요?</p> | ||
<Link href='/auth/signup'>회원가입하기</Link> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
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,59 @@ | ||
'use client'; | ||
|
||
import usePostSignUp from '@/apis/user/signUp'; | ||
import SquareButtonL from '@/components/Button/SquareButtonL'; | ||
import EmailInput from '@/components/Input/EmailInput'; | ||
import NicknameInput from '@/components/Input/NicknameInput'; | ||
import PasswordInput from '@/components/Input/PasswordInput'; | ||
|
||
import Link from 'next/link'; | ||
import { FormProvider, useForm } from 'react-hook-form'; | ||
|
||
export default function SignUpPage() { | ||
const { mutate } = usePostSignUp(); | ||
const methods = useForm<SignUpFormType>({ | ||
defaultValues: { | ||
email: '', | ||
password: '', | ||
nickname: '', | ||
}, | ||
mode: 'onChange', | ||
}); | ||
|
||
const onValidForm = (data: SignUpFormType) => { | ||
mutate(data); | ||
}; | ||
|
||
const { isValid } = methods.formState; | ||
|
||
return ( | ||
<div className='flex flex-col justify-center items-center gap-[60px]'> | ||
<h4>회원가입</h4> | ||
<FormProvider {...methods}> | ||
<form | ||
onSubmit={methods.handleSubmit(onValidForm)} | ||
className='w-full flex flex-col gap-[60px]' | ||
> | ||
<div className='flex flex-col gap-[30px]'> | ||
<EmailInput mode={'sign-up'} /> | ||
<PasswordInput mode={'sign-up'} /> | ||
<NicknameInput /> | ||
</div> | ||
<SquareButtonL | ||
type='submit' | ||
textSize={''} | ||
backgroundColor={isValid ? 'bg-main' : 'bg-gray-800'} | ||
disabled={!isValid} | ||
> | ||
<p>회원가입</p> | ||
</SquareButtonL> | ||
</form> | ||
</FormProvider> | ||
|
||
<div className='flex gap-2.5 justify-center items-center mt-[13px]'> | ||
<p className='text-gray-600'>이미 가입된 계정이 있으신가요?</p> | ||
<Link href='/auth/login'>로그인하러가기</Link> | ||
</div> | ||
</div> | ||
); | ||
} |
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,27 @@ | ||
'use client'; | ||
|
||
import useGetSocialLogin from '@/apis/user/socialLogIn'; | ||
|
||
import { useRouter, useSearchParams } from 'next/navigation'; | ||
import { useEffect } from 'react'; | ||
|
||
interface ProviderPageProps { | ||
provider: string; | ||
} | ||
|
||
function ProviderPage({ provider }: ProviderPageProps) { | ||
const router = useRouter(); | ||
const searchParams = useSearchParams(); | ||
const { hasData, isLoading } = useGetSocialLogin({ | ||
provider, | ||
params: searchParams.toString(), | ||
}); | ||
|
||
useEffect(() => { | ||
if (hasData) router.replace('/'); | ||
}, [hasData, isLoading]); | ||
|
||
return <></>; | ||
} | ||
|
||
export default ProviderPage; |
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,24 @@ | ||
'use client'; | ||
|
||
import Script from 'next/script'; | ||
|
||
declare global { | ||
interface Window { | ||
Kakao: any; | ||
} | ||
} | ||
|
||
export default function KakaoProvider() { | ||
const initKakao = () => { | ||
window.Kakao.init(process.env.NEXT_PUBLIC_KAKAO_API_KEY); | ||
}; | ||
|
||
return ( | ||
<Script | ||
src='https://t1.kakaocdn.net/kakao_js_sdk/2.7.4/kakao.min.js' | ||
integrity='sha384-DKYJZ8NLiK8MN4/C5P2dtSmLQ4KwPaoqAfyA/DfmEc1VDxu4yyC7wy6K1Hs90nka' | ||
crossOrigin='anonymous' | ||
onLoad={initKakao} | ||
/> | ||
); | ||
} |
Oops, something went wrong.