Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/common/components/AuthGuard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import useGetIsLogin from '@/common/hooks/apis/useGetIsLogin';
import { useEffect } from 'react';
import { Outlet, useNavigate } from 'react-router';

/**
* 로그인 해야만 들어갈 수 있는 페이지를 감싸주는 컴포넌트
*/
const AuthGuard = () => {
const navigate = useNavigate();
const { data: isLogin, isSuccess } = useGetIsLogin();

useEffect(() => {
if (isSuccess && !isLogin) {
navigate('/login', { replace: true });
}
}, [isLogin, isSuccess, navigate]);

if (!isLogin) return null;

return <Outlet />;
};
export default AuthGuard;
1 change: 1 addition & 0 deletions src/common/hooks/apis/useGetIsLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const useGetIsLogin = () => {
return useQuery({
queryKey: ['isLogin'],
queryFn: getIsLogin,
staleTime: 0, // 매번 확인
});
};

Expand Down
36 changes: 36 additions & 0 deletions src/libs/assets/GoogleLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const GoogleLogo = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="15" fill="none" viewBox="0 0 14 15">
<mask
id="mask0_560_3237"
Comment thread
halionaz marked this conversation as resolved.
width="14"
height="15"
x="0"
y="0"
maskUnits="userSpaceOnUse"
style={{ maskType: 'luminance' }}
>
<path fill="#fff" d="M14 .143H0v14h14z"></path>
</mask>
<g mask="url(#mask0_560_3237)">
<path
fill="#4285F4"
d="M13.72 7.302q-.002-.744-.127-1.432H7v2.708h3.767a3.22 3.22 0 0 1-1.397 2.113v1.756h2.263c1.323-1.218 2.087-3.013 2.087-5.145"
></path>
<path
fill="#34A853"
d="M7 14.143c1.89 0 3.475-.627 4.633-1.696L9.37 10.691c-.626.42-1.428.668-2.37.668-1.823 0-3.366-1.231-3.917-2.886H.745v1.814A7 7 0 0 0 7 14.143"
></path>
<path
fill="#FBBC04"
d="M3.083 8.473c-.14-.42-.22-.868-.22-1.33 0-.461.08-.91.22-1.33V4H.745a7 7 0 0 0 0 6.287z"
></path>
<path
fill="#E94235"
d="M7 2.927c1.028 0 1.95.353 2.676 1.047l2.008-2.008C10.47.836 8.887.143 7 .143A7 7 0 0 0 .745 4l2.338 1.814C3.633 4.16 5.177 2.927 7 2.927"
></path>
</g>
</svg>
);
};
export default GoogleLogo;
13 changes: 13 additions & 0 deletions src/libs/assets/KakaoLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const KakaoLogo = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="14" fill="none" viewBox="0 0 15 14">
<path
fill="#000"
fillRule="evenodd"
d="M7.523.461c-3.954 0-7.16 2.476-7.16 5.53 0 1.9 1.24 3.574 3.128 4.57l-.794 2.902c-.07.256.223.46.448.312l3.482-2.298q.44.044.896.045c3.954 0 7.159-2.476 7.159-5.53S11.476.461 7.522.461"
clipRule="evenodd"
></path>
</svg>
);
};
export default KakaoLogo;
39 changes: 36 additions & 3 deletions src/pages/LoginPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,47 @@
import { useEffect } from 'react';
import { useNavigate } from 'react-router';

import * as s from './style.css';

import SafeArea from '@/common/components/SafeArea';
import useGetIsLogin from '@/common/hooks/apis/useGetIsLogin';
import GoogleLogo from '@/libs/assets/GoogleLogo';
import KakaoLogo from '@/libs/assets/KakaoLogo';

const LoginPage = () => {
const navigate = useNavigate();
const { data: isLogin, isLoading } = useGetIsLogin();

useEffect(() => {
// TODO: 원래 있던 페이지로
if (isLogin) {
navigate(-1);
Comment on lines +14 to +18

Copilot AI Jul 15, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using navigate(-1) can lead to unexpected navigation loops or unclear fallback targets; consider capturing the original location in state and redirecting there explicitly.

Suggested change
useEffect(() => {
// TODO: 원래 있던 페이지로
if (isLogin) {
navigate(-1);
useEffect(() => {
// Store the original location when navigating to the login page
const originalLocation = window.location.pathname;
sessionStorage.setItem('originalLocation', originalLocation);
}, []);
useEffect(() => {
// Redirect to the original location after login
if (isLogin) {
const originalLocation = sessionStorage.getItem('originalLocation') || '/';
navigate(originalLocation);

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}, [isLogin, navigate]);

if (isLoading || isLogin) return null;

return (
<SafeArea>
<div className={s.Container}>
<h1>임시 로그인 페이지</h1>
<a href={`${import.meta.env.VITE_API_URL}/oauth2/authorization/kakao`}>카카오 로그인</a>
<a href={`${import.meta.env.VITE_API_URL}/oauth2/authorization/google`}>구글 로그인</a>
<p className={s.Label}>SNS 계정으로 로그인하기</p>
<div className={s.ButtonContainer}>
{/* TODO: 애플 로그인 추가 */}
<a
className={s.LoginButton({ src: 'google' })}
href={`${import.meta.env.VITE_API_URL}/oauth2/authorization/google`}
>
<GoogleLogo />
Google로 로그인
</a>
<a
className={s.LoginButton({ src: 'kakao' })}
href={`${import.meta.env.VITE_API_URL}/oauth2/authorization/kakao`}
>
<KakaoLogo />
카카오톡으로 로그인
</a>
</div>
</div>
</SafeArea>
);
Expand Down
57 changes: 55 additions & 2 deletions src/pages/LoginPage/style.css.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,60 @@
import { css } from '@styled-system/css';
import { css, cva } from '@styled-system/css';

export const Container = css({
height: 'full',
display: 'flex',
flexDir: 'column',
gap: '1rem',
justifyContent: 'flex-end',
alignItems: 'center',
pb: '3.75rem',
px: '1rem',
gap: '1.875rem',
});

export const Label = css({
color: '80',
fontSize: '0.875rem',
fontWeight: 500,
lineHeight: 'normal',
});

export const ButtonContainer = css({
display: 'flex',
flexDir: 'column',
gap: '0.5rem',
width: 'full',
});

export const LoginButton = cva({
base: {
display: 'flex',
width: 'full',
height: '3.125rem',
rounded: '0.375rem',
justifyContent: 'center',
alignItems: 'center',
fontSize: '1.125rem',
fontWeight: 600,
lineHeight: 1.5,
},
variants: {
src: {
apple: {
bgColor: '#FFF',
color: '#000',
fontWeight: 590,
fontFamily: 'SF Pro',
},
google: {
bgColor: '#F2F2F2',
gap: '0.75rem',
color: '#1F1F1F',
},
kakao: {
bgColor: '#FEE500',
gap: '0.8rem',
color: 'rgba(0, 0, 0, 0.85)',
},
},
},
});
26 changes: 16 additions & 10 deletions src/pages/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,45 @@ import type { RouteObject } from 'react-router';
import HomePage from '@/pages/HomePage';
import Layout from '@/pages/Layout';
import PickPage from '@/pages/PickPage';
import PostPage from './PostPages';
import PostPageRoutes from '@/pages/PostPages';
import NotFoundPage from '@/pages/NotFoundPage';
import DetailPage from '@/pages/DetailPage';
import LoginPage from '@/pages/LoginPage';
import AuthGuard from '@/common/components/AuthGuard';

/**
* 새로운 페이지 추가하고 싶으면 여기에 추가하면 됩니다
*/
const routes: RouteObject[] = [
{
path: '/',
element: <Layout />,
children: [
{
path: '/',
element: <HomePage />,
},
{
path: '/pick',
element: <PickPage />,
},
{
path: '/post',
element: <PostPageRoutes />,
},
{
path: '/detail/:id',
element: <DetailPage />,
},
{
path: '/my', // TODO: 임시
path: '/login', // TODO: 임시
element: <LoginPage />,
},
{
element: <AuthGuard />, // 로그인 해야만 들어갈 수 있는 페이지는 이 아래다가 넣어주셈
children: [
{
path: '/pick',
element: <PickPage />,
},
{
path: '/post',
element: <PostPage />,
},
],
},
{
path: '*', // 못 찾았을 때 404 페이지로 이동
element: <NotFoundPage />,
Expand Down
2 changes: 1 addition & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import tsconfigPaths from 'vite-tsconfig-paths';

// https://vite.dev/config/
export default defineConfig({
base: '/repicka-web/', // TODO: BASE_URL 추후 수정
base: '/repicka-web', // TODO: BASE_URL 추후 수정
plugins: [react(), tsconfigPaths()],
});