diff --git a/src/api/auth/auth.ts b/src/api/auth/auth.ts index ef2dc1c..6860d30 100644 --- a/src/api/auth/auth.ts +++ b/src/api/auth/auth.ts @@ -4,6 +4,8 @@ import type { IEmailSendRequest, IEmailSendResponse, IEmailVerifyRequest, + ILoginRequest, + ILoginResponse, ISignUpRequest, ISignUpResponse, } from "../../types/auth/auth"; @@ -40,3 +42,15 @@ export const signUp = async ( ); return responseData; }; + +// 로그인 +export const login = async ( + data: ILoginRequest, +): Promise> => { + const { data: responseData } = await axiosInstance.post( + "/api/auth/login", + data, + ); + + return responseData; +}; diff --git a/src/hooks/auth/useAuth.ts b/src/hooks/auth/useAuth.ts index a410563..dc0e39a 100644 --- a/src/hooks/auth/useAuth.ts +++ b/src/hooks/auth/useAuth.ts @@ -1,15 +1,17 @@ import { useCoreMutation } from "@/hooks/customQuery"; -import { sendEmail, signUp, verifyEmail } from "@/api/auth/auth"; +import { login, sendEmail, signUp, verifyEmail } from "@/api/auth/auth"; export const useAuth = () => { const useSendCode = useCoreMutation(sendEmail); const useCheckCode = useCoreMutation(verifyEmail); const useSignUp = useCoreMutation(signUp); + const useLogin = useCoreMutation(login); return { useSendCode, useCheckCode, useSignUp, + useLogin, }; }; diff --git a/src/pages/auth/Login.tsx b/src/pages/auth/Login.tsx index 17acdb4..dccc00f 100644 --- a/src/pages/auth/Login.tsx +++ b/src/pages/auth/Login.tsx @@ -1,17 +1,20 @@ import { type SubmitHandler, useForm } from "react-hook-form"; -import { Link } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import { zodResolver } from "@hookform/resolvers/zod"; import { toast } from "sonner"; import type { z } from "zod"; import { loginSchema } from "@/utils/validation"; +import { useAuth } from "@/hooks/auth/useAuth"; + import CommonAuthInput from "@/components/auth/common/CommonAuthInput"; import Button from "@/components/common/Button"; import GoogleIcon from "@/assets/auth/social/google.svg?react"; import KakaoIcon from "@/assets/auth/social/kakao.svg?react"; import NaverIcon from "@/assets/auth/social/naver.svg?react"; +import useAuthStore from "@/store/useAuthStore"; type TLoginFormValues = z.infer; @@ -25,11 +28,22 @@ export default function Login() { resolver: zodResolver(loginSchema), }); + const navigate = useNavigate(); + const { useLogin } = useAuth(); + const { login: loginAction } = useAuthStore(); + const onSubmit: SubmitHandler = (data) => { - // 임시 로그인 처리 - console.log("Login submit:", data); - toast.success("로그인 성공!", { - description: `이메일: ${data.email}`, + useLogin.mutate(data, { + onSuccess: (response) => { + const { accessToken } = response.data; + localStorage.setItem("accessToken", accessToken); + loginAction(data.email); + navigate("/", { replace: true }); + }, + onError: (error: any) => { + console.error("Login error:", error); + toast.error(error.response?.data?.message || "로그인에 실패했습니다."); + }, }); }; diff --git a/src/routes/Router.tsx b/src/routes/Router.tsx index 83a9942..8f9c76e 100644 --- a/src/routes/Router.tsx +++ b/src/routes/Router.tsx @@ -11,7 +11,7 @@ import Error from "@/pages/common/Error"; function AuthGuard({ children }: { children: React.ReactNode }) { // 실제 인증 상태 확인 로직으로 대체 예정 - const isAuthenticated = false; + const isAuthenticated = true; if (!isAuthenticated) { return ; diff --git a/src/store/useAuthStore.ts b/src/store/useAuthStore.ts index 5de35f4..7795ea9 100644 --- a/src/store/useAuthStore.ts +++ b/src/store/useAuthStore.ts @@ -1,9 +1,12 @@ import { create } from "zustand"; interface IAuthState { + isLoggedIn: boolean; email: string; password: string; socialId: number; + login: (email: string) => void; + logout: () => void; setEmail: (email: string) => void; setPassword: (password: string) => void; setSocialId: (socialId: number) => void; @@ -11,9 +14,15 @@ interface IAuthState { } const useAuthStore = create((set) => ({ + isLoggedIn: false, email: "", password: "", socialId: -1, + login: (email) => set({ isLoggedIn: true, email }), + logout: () => { + localStorage.removeItem("accessToken"); + set({ isLoggedIn: false, email: "", password: "", socialId: -1 }); + }, setEmail: (email) => set({ email }), setPassword: (password) => set({ password }), setSocialId: (socialId) => set({ socialId }), diff --git a/src/types/auth/auth.ts b/src/types/auth/auth.ts index b7cd098..aa8c8a1 100644 --- a/src/types/auth/auth.ts +++ b/src/types/auth/auth.ts @@ -29,3 +29,16 @@ export interface ISignUpResponse { userId: number; createdAt: string; } + +// 로그인 요청 타입 +export interface ILoginRequest { + email: string; + password: string; +} + +// 로그인 응답 타입 +export interface ILoginResponse { + grantType: string; + accessToken: string; + accessTokenExpiresIn: number; +}