From 17b5b33ae57e868b7c56b5e8f5c9b5c4720ae715 Mon Sep 17 00:00:00 2001 From: leechan Date: Wed, 18 Dec 2024 01:23:53 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[Feat]=20=EC=96=B4=EB=93=9C=EB=AF=BC?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=9D=BC=EC=9A=B0=ED=84=B0=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/admin/AdminRoute.tsx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/admin/AdminRoute.tsx diff --git a/src/admin/AdminRoute.tsx b/src/admin/AdminRoute.tsx new file mode 100644 index 0000000..47118d5 --- /dev/null +++ b/src/admin/AdminRoute.tsx @@ -0,0 +1,27 @@ +import { Navigate } from 'react-router'; +import { useSelector } from 'react-redux'; +import { RootState } from '@/store/rootReducer'; + +interface ProtectedRouteProps { + allowedRoles: string[]; + children: React.ReactNode; +} + +const ProtectedRoute = ({ allowedRoles, children }: ProtectedRouteProps) => { + const { userInfo } = useSelector((state: RootState) => state.user); + + // 로그인하지 않은 경우 + if (!userInfo) { + return ; + } else if (!allowedRoles.includes(userInfo.role)) { + } + + // 역할이 허용되지 않은 경우 + if (!allowedRoles.includes(userInfo.role)) { + return ; + } + + return <>{children}; // 자식 요소 렌더링 +}; + +export default ProtectedRoute; From f56832277503dcb780902d3d0c66b96868357997 Mon Sep 17 00:00:00 2001 From: leechan Date: Wed, 18 Dec 2024 01:24:15 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[Refactor]=20=EB=A1=9C=EA=B3=A0=20=EB=88=84?= =?UTF-8?q?=EB=A5=B4=EB=A9=B4=20=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Header.tsx | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 690cda9..b31e1f2 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,15 +1,24 @@ import styled from 'styled-components'; import logo from '@/assets/logo.svg'; import MenuButton from './MenuButton'; +import { useNavigate } from 'react-router'; -const Header = () => ( - - - Logo - - - -); +const Header = () => { + const navigate = useNavigate(); + + const handleLogoClick = () => { + navigate('/'); // 메인 페이지로 이동 + }; + + return ( + + + + + + + ); +}; export default Header; @@ -28,3 +37,8 @@ const HeaderWrapper = styled.div` align-items: center; justify-content: space-between; `; + +// 클릭 가능한 스타일을 추가한 로고 +const Logo = styled.img` + cursor: pointer; // 커서를 클릭 가능한 손가락 모양으로 변경 +`; From 81364daa0c3bc881db06b672288a00ab18142b53 Mon Sep 17 00:00:00 2001 From: leechan Date: Wed, 18 Dec 2024 01:24:55 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[Refactor]=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=8B=9C=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EA=B0=80=20=EC=95=84=EB=8B=8C=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=8F=99=ED=95=A0=EC=88=98=EC=9E=88=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/MenuButton.tsx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/components/MenuButton.tsx b/src/components/MenuButton.tsx index e78fe03..24cdf35 100644 --- a/src/components/MenuButton.tsx +++ b/src/components/MenuButton.tsx @@ -14,6 +14,7 @@ const MenuButton = () => { const navigate = useNavigate(); const dispatch = useDispatch(); const isLoggedIn = useSelector((state: RootState) => state.user.isLoggedIn); + const role = useSelector((state: RootState) => state.user.userInfo?.role); const handleLogin = () => { // 로그인 페이지로 이동 @@ -24,6 +25,10 @@ const MenuButton = () => { navigate('/mypage'); }; + const handleAdminPage = () => { + navigate('/adminpage'); + }; + const handleLogout = () => { // Redux 상태 초기화 dispatch(logout()); @@ -56,7 +61,17 @@ const MenuButton = () => { {isOpen && (
    -
  • {} : handleLogin}> +
  • { + if (isLoggedIn) { + role === 'admin' + ? navigate('/adminpage') + : navigate('/mypage'); + } else { + handleLogin(); + } + }} + > {/* 아바타 표시 */} {
  • {isLoggedIn ? ( <> -
  • 마이페이지
  • + {role === 'admin' ? ( +
  • 관리자페이지
  • + ) : ( +
  • 마이페이지
  • + )}
  • 문의하기
  • 서비스 소개
  • 로그아웃
  • From c62a43ab80ae8b48358d79c0c0857b6fd9fa829b Mon Sep 17 00:00:00 2001 From: leechan Date: Wed, 18 Dec 2024 01:25:06 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[Feat]=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/AdminPage.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/pages/AdminPage.tsx diff --git a/src/pages/AdminPage.tsx b/src/pages/AdminPage.tsx new file mode 100644 index 0000000..b1c6f4d --- /dev/null +++ b/src/pages/AdminPage.tsx @@ -0,0 +1,10 @@ +const AdminPage = () => { + return ( +
    +

    어드민 페이지

    +

    이 페이지는 관리자만 접근할 수 있습니다.

    +
    + ); +}; + +export default AdminPage; From e9310d1b93bd8401c69eb22d5e1e795a9d7c65a0 Mon Sep 17 00:00:00 2001 From: leechan Date: Wed, 18 Dec 2024 01:25:22 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[Refactor]=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=9D=BC=EC=9A=B0=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/router.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/routes/router.tsx b/src/routes/router.tsx index 49bab7a..3718e99 100644 --- a/src/routes/router.tsx +++ b/src/routes/router.tsx @@ -2,10 +2,12 @@ import Layout from '@/components/layout/Layout'; import Scraps from '@/components/my-page/Scraps'; import UserContents from '@/components/my-page/UserContents'; import UserPosts from '@/components/my-page/UserPosts'; +import AdminPage from '@/pages/AdminPage'; import HomePage from '@/pages/HomePage'; import JoinPage from '@/pages/JoinPage'; import LoginPage from '@/pages/LoginPage'; import MyPage from '@/pages/MyPage'; +import ProtectedRoute from '@/admin/AdminRoute'; const router = [ { @@ -34,6 +36,14 @@ const router = [ }, ], }, + { + path: '/adminpage', + element: ( + + + + ), + }, ], }, { From ef81295768ca6c61941fe3dee928963e1512ff18 Mon Sep 17 00:00:00 2001 From: leechan Date: Wed, 18 Dec 2024 01:38:04 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[Refactor]=20=EB=A9=94=EB=89=B4=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20close?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/MenuButton.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/MenuButton.tsx b/src/components/MenuButton.tsx index 24cdf35..02705db 100644 --- a/src/components/MenuButton.tsx +++ b/src/components/MenuButton.tsx @@ -16,25 +16,25 @@ const MenuButton = () => { const isLoggedIn = useSelector((state: RootState) => state.user.isLoggedIn); const role = useSelector((state: RootState) => state.user.userInfo?.role); - const handleLogin = () => { - // 로그인 페이지로 이동 - navigate('/login'); - }; - const handleMyPage = () => { + setIsOpen(false); // 드롭다운 먼저 닫기 navigate('/mypage'); }; const handleAdminPage = () => { + setIsOpen(false); // 드롭다운 먼저 닫기 navigate('/adminpage'); }; + const handleLogin = () => { + setIsOpen(false); // 드롭다운 먼저 닫기 + navigate('/login'); + }; + const handleLogout = () => { - // Redux 상태 초기화 dispatch(logout()); - // 토큰 제거 removeToken(); - // 로그아웃 후 메인 페이지 이동(필요하다면) + setIsOpen(false); navigate('/'); }; @@ -63,6 +63,7 @@ const MenuButton = () => {
    • { + setIsOpen(false); // 드롭다운 먼저 닫기 if (isLoggedIn) { role === 'admin' ? navigate('/adminpage')