From ece2ec1ad60a5fd1eda6b893dd61412e92876c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=B1=84=EB=AF=BC?= <87525734+cmlim0070@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:16:49 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20=EC=83=88=EB=A1=9C=EA=B3=A0=EC=B9=A8?= =?UTF-8?q?=20=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=95=84=EC=9B=83=20=EC=83=81=ED=83=9C=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80=20(#178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat : 로고 메인으로 연결 * feat : Layout에서 로그인 상태를 처리할 수 있는 로직 작성 * feat : 로그아웃 & AuthProvider 추가 * feat : 헤더 로그아웃 아이템 추가 --- src/app/AuthProvider.tsx | 60 +++++++++++++++++++++++++++ src/app/layout/Layout.tsx | 8 ++-- src/features/login/hooks/useLogout.ts | 25 +++++++++++ src/widgets/header/ui/Header.tsx | 18 ++++++-- 4 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 src/app/AuthProvider.tsx create mode 100644 src/features/login/hooks/useLogout.ts diff --git a/src/app/AuthProvider.tsx b/src/app/AuthProvider.tsx new file mode 100644 index 0000000..99728b5 --- /dev/null +++ b/src/app/AuthProvider.tsx @@ -0,0 +1,60 @@ +import { useAuthStore } from '@/features/login/hooks/useAuthStore'; +import useLogout from '@/features/login/hooks/useLogout'; +import { decodeJwtPayload } from '@/features/login/util/decodeJwtPayload '; +import useLocalStorage from '@/shared/hooks/useLocalStorage'; +import { ReactNode, useEffect } from 'react'; + +interface AuthLayoutProps { + children: ReactNode; +} + +interface userType { + email: string; + username: string; +} + +// 토큰 만료 체크 테스트 함수 + +// 성공 +function TestVerifyTokenTrue(token: string) { + return true; +} +// 실패 +function TestVerifyTokenFalse(token: string) { + return false; +} + +const AuthProvider = ({ children }: AuthLayoutProps) => { + const { setUserInfo } = useAuthStore(); + const { storedValue: token } = useLocalStorage('token', ''); + const { handleLogout } = useLogout(); + + useEffect(() => { + const initializeAuth = async () => { + if (token) { + try { + // await axios.get('/api/verify-token'); + if (TestVerifyTokenTrue(token)) { + const payload = decodeJwtPayload(token); + if (payload) { + console.log('토큰 유효'); + setUserInfo(payload.email, payload.username, true); + } + } else { + console.log('토큰 만료'); + handleLogout(); + } + } catch { + console.log('토큰 없음'); + handleLogout(); + } + } + }; + initializeAuth(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return children; +}; + +export default AuthProvider; diff --git a/src/app/layout/Layout.tsx b/src/app/layout/Layout.tsx index da6717a..f5ff7ce 100644 --- a/src/app/layout/Layout.tsx +++ b/src/app/layout/Layout.tsx @@ -1,12 +1,14 @@ import Header from '@/widgets/header/ui/Header'; -import React from 'react'; import { Outlet } from 'react-router-dom'; +import AuthProvider from '../AuthProvider'; const Layout = () => { return (
-
- + +
+ +
); }; diff --git a/src/features/login/hooks/useLogout.ts b/src/features/login/hooks/useLogout.ts new file mode 100644 index 0000000..d122be1 --- /dev/null +++ b/src/features/login/hooks/useLogout.ts @@ -0,0 +1,25 @@ +import { useToastStore } from '@/features/Toast/hooks/useToastStore'; +import useLocalStorage from '@/shared/hooks/useLocalStorage'; +import { useNavigate } from 'react-router-dom'; +import { useAuthStore } from './useAuthStore'; + +const useLogout = () => { + const navigate = useNavigate(); + const { addToast } = useToastStore(); + const { setValue: setToken } = useLocalStorage('token', ''); + const { setUserInfo } = useAuthStore(); + + const handleLogout = () => { + try { + setToken(''); + setUserInfo('', '', false); + addToast('로그아웃되었습니다.', 'success'); + navigate('/login'); + } catch (error) { + addToast('로그아웃 처리에 실패했어요.', 'error'); + } + }; + return { handleLogout }; +}; + +export default useLogout; diff --git a/src/widgets/header/ui/Header.tsx b/src/widgets/header/ui/Header.tsx index 65c3455..45fd377 100644 --- a/src/widgets/header/ui/Header.tsx +++ b/src/widgets/header/ui/Header.tsx @@ -3,14 +3,24 @@ import { Container, Logo, Nav, NavItem, LoginButton } from './Header.styled'; import LogoImage from '@/shared/assets/logo.svg'; import { useAuthStore } from '@/features/login/hooks/useAuthStore'; import { Link, useNavigate } from 'react-router-dom'; +import useLogout from '@/features/login/hooks/useLogout'; const Header = () => { const navigate = useNavigate(); - const { email, userName, isLoggedin, setUserInfo } = useAuthStore(); + const { userName, isLoggedin } = useAuthStore(); + const { handleLogout } = useLogout(); + + const handleLogoutClick = (e: React.MouseEvent) => { + e.preventDefault(); + handleLogout(); + }; + return ( - logo + + logo +