-
Notifications
You must be signed in to change notification settings - Fork 2
refactor: #75/로그인, 회원가입 페이지 API 연결 #105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,59 @@ | ||
| "use client"; | ||
| import Input from "@/components/common/input/Input"; | ||
| import { AuthLayout } from "@/app/(before-login)/(without-navbar)/layout"; | ||
| import { useForm } from "react-hook-form"; | ||
| import { zodResolver } from "@hookform/resolvers/zod"; | ||
| import Input from "@/components/common/input/Input"; | ||
| import { AuthLayout } from "@/app/(before-login)/(without-navbar)/layout"; | ||
| import { loginSchema, LoginFormData } from "@/lib/utils/validationSchema"; | ||
| import { useAlertStore } from "@/lib/store/useAlertStore"; | ||
| import { fetchLogin } from "@/lib/apis/authApi"; | ||
| import { useState } from "react"; | ||
| import { useRouter } from "next/navigation"; | ||
|
|
||
| export default function Page() { | ||
| const { openAlert } = useAlertStore(); | ||
| const [isLoading, setIsLoading] = useState(false); | ||
| const router = useRouter(); | ||
|
|
||
| const { | ||
| register, | ||
| handleSubmit, | ||
| formState: { errors }, | ||
| formState: { errors, isValid }, | ||
| } = useForm<LoginFormData>({ | ||
| resolver: zodResolver(loginSchema), | ||
| mode: "onBlur", | ||
| }); | ||
|
|
||
| const onSubmit = (data: LoginFormData) => { | ||
| console.log("로그인 데이터:", data); | ||
| const onSubmit = async (data: LoginFormData) => { | ||
| setIsLoading(true); | ||
| try { | ||
| const response = await fetchLogin(data); | ||
| setIsLoading(false); | ||
| localStorage.setItem("accessToken", response.accessToken); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. localStorage에 액세스 토큰을 저장하는군요. 로그아웃 기능 구현할 때 참고하겠습니다! |
||
| openAlert("loginSuccess"); | ||
| router.push("/mydashboard"); | ||
| } catch (error: unknown) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러 처리까지 꼼꼼하게! 너무 멋집니다! |
||
| setIsLoading(false); | ||
| if (error instanceof Error) { | ||
| const errorInfo: { status: number; message: string } = JSON.parse( | ||
| error.message | ||
| ); | ||
| if (errorInfo.status === 400) { | ||
| openAlert("wrongPassword"); | ||
| } | ||
| if (errorInfo.status === 404) { | ||
| openAlert("userNotFound"); | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <AuthLayout | ||
| buttonText="로그인" | ||
| linkText="회원이 아니신가요?" | ||
| linkPath="/signup" | ||
| isLoading={isLoading} | ||
| isFormValid={isValid} | ||
| > | ||
| <form id="auth-form" onSubmit={handleSubmit(onSubmit)} className="w-full"> | ||
| <div className="pb-4"> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,35 +4,56 @@ import { zodResolver } from "@hookform/resolvers/zod"; | |
| import Input from "@/components/common/input/Input"; | ||
| import { AuthLayout } from "@/app/(before-login)/(without-navbar)/layout"; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분도 위에서 말한 것 같이 지워도 괜찮을 것 같습니다! |
||
| import { signupSchema, SignupFormData } from "@/lib/utils/validationSchema"; | ||
| import { useAlertStore } from "@/lib/store/useAlertStore"; | ||
| import { fetchSignup } from "@/lib/apis/authApi"; | ||
| import { useState } from "react"; | ||
| import { useRouter } from "next/navigation"; | ||
|
|
||
| export default function Page() { | ||
| const { openAlert } = useAlertStore(); | ||
| const [isLoading, setIsLoading] = useState(false); | ||
| const router = useRouter(); | ||
|
|
||
| const { | ||
| register, | ||
| handleSubmit, | ||
| formState: { errors }, | ||
| formState: { errors, isValid }, | ||
| } = useForm<SignupFormData>({ | ||
| resolver: zodResolver(signupSchema), | ||
| mode: "onBlur", | ||
| defaultValues: { | ||
| terms: false, | ||
| }, | ||
| }); | ||
|
|
||
| const onSubmit = (data: SignupFormData) => { | ||
| console.log("회원가입 데이터:", data); | ||
| const onSubmit = async (data: SignupFormData) => { | ||
| setIsLoading(true); | ||
| try { | ||
| await fetchSignup(data); | ||
| setIsLoading(false); | ||
| openAlert("signupSuccess"); | ||
| router.push("/login"); | ||
| } catch (error: unknown) { | ||
| setIsLoading(false); | ||
| if (error instanceof Error) { | ||
| const errorInfo: { status: number; message: string } = JSON.parse( | ||
| error.message | ||
| ); | ||
| if (errorInfo.status === 409) { | ||
| openAlert("emailDuplicated"); | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <AuthLayout | ||
| buttonText="가입하기" | ||
| linkText="이미 회원이신가요?" | ||
| linkPath="/login" | ||
| isLoading={isLoading} | ||
| isFormValid={isValid} | ||
| > | ||
| <form | ||
| id="auth-form" // Button과 연결 | ||
| onSubmit={handleSubmit(onSubmit)} | ||
| className="w-full" | ||
| > | ||
| <form id="auth-form" onSubmit={handleSubmit(onSubmit)} className="w-full"> | ||
| <div className="pb-4"> | ||
| <Input | ||
| label="이메일" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import { LoginFormData, SignupFormData } from "@/lib/utils/validationSchema"; | ||
| import { BASE_URL } from "@/lib/constants/urls"; | ||
|
|
||
| export async function fetchLogin(data: LoginFormData) { | ||
| const requestBody = { | ||
| email: data.email, | ||
| password: data.password, | ||
| }; | ||
|
|
||
| const response = await fetch(`${BASE_URL}/auth/login`, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| accept: "application/json", | ||
| }, | ||
| body: JSON.stringify(requestBody), | ||
| cache: "no-store", | ||
| }); | ||
|
|
||
| if (!response.ok) { | ||
| const errorData = await response.json(); | ||
| throw new Error( | ||
| JSON.stringify({ | ||
| status: response.status, | ||
| message: errorData.message || "로그인에 실패했습니다.", | ||
| }) | ||
| ); | ||
| } | ||
|
|
||
| return response.json(); | ||
| } | ||
|
|
||
| export async function fetchSignup(data: SignupFormData) { | ||
| const requestBody = { | ||
| email: data.email, | ||
| password: data.password, | ||
| nickname: data.nickname, | ||
| }; | ||
|
|
||
| const response = await fetch(`${BASE_URL}/users`, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| accept: "application/json", | ||
| }, | ||
| body: JSON.stringify(requestBody), | ||
| cache: "no-store", | ||
| }); | ||
|
|
||
| if (!response.ok) { | ||
| const errorData = await response.json(); | ||
| throw new Error( | ||
| JSON.stringify({ | ||
| status: response.status, | ||
| message: errorData.message || "회원가입에 실패했습니다.", | ||
| }) | ||
| ); | ||
| } | ||
|
|
||
| return response.json(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
layout.tsx는 따로 import 해줄 필요 없이 children인 페이지의 레이아웃이 됩니다. 이 import 부분 삭제해보신 뒤 문제 없는지 확인해보시고, 문제 없다면 지워도 될 것 같습니다!