Skip to content
Snippets Groups Projects
Commit 64aa439b authored by 석찬 윤's avatar 석찬 윤
Browse files

feat: 로그인 페이지 개발 (#10)

parent 39016ad6
Branches
No related tags found
1 merge request!8[#10] 로그인 페이지 개발
// src/api/auth.js
/**
* Google 로그인 URL 반환
* @returns {string} 로그인 엔드포인트 URL
*/
export const getLoginUrl = () => {
return `${process.env.REACT_APP_BASE_URL}/api/auth/login`;
};
/**
* 로그아웃 API 호출
* @returns {Promise<void>}
*/
export const logout = async () => {
try {
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/auth/logout`,
{
method: "GET",
credentials: "include", // 세션 쿠키 포함
}
);
if (!response.ok) {
throw new Error("Failed to logout");
}
} catch (error) {
console.error("Error during logout:", error);
throw error;
}
};
/**
* 세션 정보 확인 API 호출
* @returns {Promise<Object|null>} 세션이 있으면 사용자 정보 반환, 없으면 null 반환
*/
export const getSessionInfo = async () => {
try {
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}/api/session/info`,
{
method: "GET",
credentials: "include", // 세션 쿠키 포함
}
);
if (response.ok) {
return await response.json(); // 사용자 정보 반환
}
return null; // 세션 없음
} catch (error) {
console.error("Error checking session info:", error);
throw error;
}
};
export default function GoogleLogo({ className, ...props }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
>
<path
d="M16.5883 17.58C18.951 15.3748 20.0011 11.6995 19.371 8.18164H9.97266V12.067H15.3281C15.1181 13.3271 14.3831 14.3772 13.333 15.0598L16.5883 17.58Z"
fill="#4285F4"
/>
<path
d="M1.04688 14.4824C1.73758 15.843 2.72813 17.0291 3.94387 17.9512C5.15962 18.8733 6.56882 19.5074 8.06526 19.8056C9.5617 20.1039 11.1063 20.0586 12.5827 19.6731C14.0591 19.2876 15.4287 18.572 16.5883 17.5802L13.333 15.06C10.5502 16.8976 5.92982 16.2151 4.35467 11.9097L1.04688 14.4824Z"
fill="#34A853"
/>
<path
d="M4.35584 11.9095C3.93581 10.5969 3.93581 9.38926 4.35584 8.07664L1.04804 5.50391C-0.159565 7.91912 -0.527099 11.3319 1.04804 14.4822L4.35584 11.9095Z"
fill="#FBBC02"
/>
<path
d="M4.35467 8.07674C5.50978 4.45391 10.4452 2.35372 13.753 5.4515L16.6408 2.61624C12.5454 -1.32161 4.56469 -1.1641 1.04688 5.50401L4.35467 8.07674Z"
fill="#EA4335"
/>
</svg>
);
}
import React from "react"; import React, { useEffect, useState } from "react";
import GoogleLogo from "../components/icons/GoogleLogoIcon";
import Button from "../components/Button";
import { getLoginUrl } from "../api/auth";
import useAuthStore from "../store/authStore";
const LoginPage = () => { const LoginPage = () => {
return <></>; const { user, fetchSession, logoutUser } = useAuthStore();
const [loading, setLoading] = useState(true);
// 페이지 로드 시 세션 확인
useEffect(() => {
const fetchSessionInfo = async () => {
setLoading(true);
try {
await fetchSession(); // 세션 정보 가져오기
} catch (error) {
console.error("Failed to fetch session info:", error);
} finally {
setLoading(false);
}
};
fetchSessionInfo();
}, [fetchSession]);
// Google 로그인 처리
const handleGoogleLogin = () => {
const loginUrl = getLoginUrl(); // 로그인 URL 가져오기
window.location.href = loginUrl; // 리다이렉트
};
// 로그아웃 처리
const handleLogout = async () => {
try {
setLoading(true);
await logoutUser();
} catch (error) {
console.error("Failed to logout:", error);
} finally {
setLoading(false);
}
};
if (loading) {
return (
<div className="flex items-center justify-center min-h-screen">
<p>Loading...</p>
</div>
);
}
if (user) {
return (
<div className="flex items-center justify-center min-h-screen p-4 bg-gray-100">
<div className="flex flex-col items-center justify-center min-w-[260px] w-1/2 max-w-md p-8 space-y-4 bg-white rounded-lg shadow-lg">
<div>
<h2 className="text-center heading-2">환영합니다!</h2>
<h2 className="text-center heading-1">
<span className="text-primary-500">{user.name}</span>
</h2>
</div>
<p className="text-center text-gray-700">
<span className="text-primary-500 title-1">번개모임</span>을 생성해
보세요!
</p>
<Button size="md" theme="black" onClick={handleLogout}>
로그아웃
</Button>
</div>
</div>
);
}
return (
<div className="flex items-center justify-center min-h-screen p-4 bg-gray-100">
<div className="flex flex-col items-center min-w-[260px] justify-center w-1/2 max-w-md p-8 space-y-6 bg-white rounded-lg shadow-lg">
<h2 className="text-2xl font-bold text-center text-gray-900">로그인</h2>
<Button
size="md"
theme="white"
icon={<GoogleLogo />}
onClick={handleGoogleLogin}
>
구글로 로그인
</Button>
</div>
</div>
);
}; };
export default LoginPage; export default LoginPage;
import { create } from "zustand";
import { getSessionInfo, logout } from "../api/auth";
const useAuthStore = create((set) => ({
user: null, // 사용자 정보
// 세션 정보 가져오기
fetchSession: async () => {
try {
const userInfo = await getSessionInfo();
set({ user: userInfo });
} catch (error) {
console.error("Failed to fetch session info:", error);
set({ user: null });
}
},
// 로그아웃 처리
logoutUser: async () => {
try {
await logout();
set({ user: null });
} catch (error) {
console.error("Failed to logout:", error);
}
},
}));
export default useAuthStore;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment