diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 81b964c6c..22c296123 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -63,7 +63,13 @@ export const CATEGORY_TYPE = { export const IMAGE_MAX_SIZE = 5 * 1024 * 1024; -export const ENVIRONMENT = window.location.href.includes('dev') ? 'dev' : 'prod'; +export const ENVIRONMENT = window.location.href.includes('dev') + ? 'dev' + : process.env.NODE_ENV === 'production' + ? 'prod' + : 'local'; export const IMAGE_URL = ENVIRONMENT === 'dev' ? process.env.S3_DEV_CLOUDFRONT_PATH : process.env.S3_PROD_CLOUDFRONT_PATH; + +export const PRODUCT_PATH_LOCAL_STORAGE_KEY = `funeat-last-product-path-${ENVIRONMENT}`; diff --git a/frontend/src/hooks/common/index.ts b/frontend/src/hooks/common/index.ts index 61c985f67..199ae608a 100644 --- a/frontend/src/hooks/common/index.ts +++ b/frontend/src/hooks/common/index.ts @@ -12,4 +12,3 @@ export { default as useTabMenu } from './useTabMenu'; export { default as useScrollRestoration } from './useScrollRestoration'; export { default as useToast } from './useToast'; export { default as useGA } from './useGA'; - diff --git a/frontend/src/pages/AuthPage.tsx b/frontend/src/pages/AuthPage.tsx index a840cb978..e5f60c954 100644 --- a/frontend/src/pages/AuthPage.tsx +++ b/frontend/src/pages/AuthPage.tsx @@ -2,8 +2,10 @@ import { useEffect, useState } from 'react'; import { Navigate, useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { loginApi } from '@/apis'; +import { PRODUCT_PATH_LOCAL_STORAGE_KEY } from '@/constants'; import { PATH } from '@/constants/path'; import { useMemberQuery } from '@/hooks/queries/members'; +import { getLocalStorage, removeLocalStorage } from '@/utils/localstorage'; export const AuthPage = () => { const { authProvider } = useParams(); @@ -14,10 +16,6 @@ export const AuthPage = () => { const [location, setLocation] = useState(''); const navigate = useNavigate(); - if (member) { - return ; - } - const getSessionId = async () => { const response = await loginApi.get({ params: `/oauth2/code/${authProvider}`, @@ -51,9 +49,17 @@ export const AuthPage = () => { return; } + const productPath = getLocalStorage(PRODUCT_PATH_LOCAL_STORAGE_KEY); + const redirectLocation = productPath ? productPath : location; + + navigate(redirectLocation, { replace: true }); + removeLocalStorage(PRODUCT_PATH_LOCAL_STORAGE_KEY); refetchMember(); - navigate(location, { replace: true }); }, [location]); + if (member) { + return ; + } + return <>; }; diff --git a/frontend/src/pages/ProductDetailPage.tsx b/frontend/src/pages/ProductDetailPage.tsx index f41985856..82c8ce4e0 100644 --- a/frontend/src/pages/ProductDetailPage.tsx +++ b/frontend/src/pages/ProductDetailPage.tsx @@ -1,7 +1,7 @@ -import { BottomSheet, Spacing, useBottomSheet, Text, Link } from '@fun-eat/design-system'; +import { BottomSheet, Spacing, useBottomSheet, Text, Button } from '@fun-eat/design-system'; import { useQueryErrorResetBoundary } from '@tanstack/react-query'; import { useState, useRef, Suspense } from 'react'; -import { useParams, Link as RouterLink } from 'react-router-dom'; +import { useParams, useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import { @@ -17,12 +17,13 @@ import { } from '@/components/Common'; import { ProductDetailItem, ProductRecipeList } from '@/components/Product'; import { BestReviewItem, ReviewList, ReviewRegisterForm } from '@/components/Review'; -import { RECIPE_SORT_OPTIONS, REVIEW_SORT_OPTIONS } from '@/constants'; +import { PRODUCT_PATH_LOCAL_STORAGE_KEY, RECIPE_SORT_OPTIONS, REVIEW_SORT_OPTIONS } from '@/constants'; import { PATH } from '@/constants/path'; import ReviewFormProvider from '@/contexts/ReviewFormContext'; import { useGA, useSortOption, useTabMenu } from '@/hooks/common'; import { useMemberQuery } from '@/hooks/queries/members'; import { useProductDetailQuery } from '@/hooks/queries/product'; +import { setLocalStorage } from '@/utils/localstorage'; const LOGIN_ERROR_MESSAGE_REVIEW = '로그인 후 상품 리뷰를 볼 수 있어요.\n펀잇에 가입하고 편의점 상품 리뷰를 확인해보세요 😊'; @@ -31,6 +32,9 @@ const LOGIN_ERROR_MESSAGE_RECIPE = export const ProductDetailPage = () => { const { category, productId } = useParams(); + const { pathname } = useLocation(); + const navigate = useNavigate(); + const { data: member } = useMemberQuery(); const { data: productDetail } = useProductDetailQuery(Number(productId)); @@ -46,7 +50,7 @@ export const ProductDetailPage = () => { const productDetailPageRef = useRef(null); - if (!category) { + if (!category || !productId) { return null; } @@ -73,6 +77,11 @@ export const ProductDetailPage = () => { selectSortOption(currentSortOption); }; + const handleLoginButtonClick = () => { + setLocalStorage(PRODUCT_PATH_LOCAL_STORAGE_KEY, pathname); + navigate(PATH.LOGIN); + }; + return ( @@ -107,9 +116,15 @@ export const ProductDetailPage = () => { {isReviewTab ? LOGIN_ERROR_MESSAGE_REVIEW : LOGIN_ERROR_MESSAGE_RECIPE} - + 로그인하러 가기 - + )} @@ -171,10 +186,8 @@ const ErrorDescription = styled(Text)` white-space: pre-wrap; `; -const LoginLink = styled(Link)` - padding: 16px 24px; +const LoginButton = styled(Button)` border: 1px solid ${({ theme }) => theme.colors.gray4}; - border-radius: 8px; `; const ReviewRegisterButtonWrapper = styled.div` diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index 0103d0fc7..440ef2cc1 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -1,4 +1,4 @@ -import { createBrowserRouter } from 'react-router-dom'; +import { Navigate, createBrowserRouter } from 'react-router-dom'; import App from './App'; @@ -15,7 +15,7 @@ const router = createBrowserRouter([ ), - errorElement: , + errorElement: , children: [ { path: `${PATH.RECIPE}/:recipeId`, diff --git a/frontend/src/utils/localStorage.ts b/frontend/src/utils/localStorage.ts new file mode 100644 index 000000000..91ce0c762 --- /dev/null +++ b/frontend/src/utils/localStorage.ts @@ -0,0 +1,26 @@ +export const getLocalStorage = (key: string) => { + const item = localStorage.getItem(key); + + if (item) { + try { + return JSON.parse(item); + } catch (error) { + return item; + } + } + + return null; +}; + +export const setLocalStorage = (key: string, newValue: unknown) => { + if (typeof newValue === 'string') { + localStorage.setItem(key, newValue); + return; + } + + localStorage.setItem(key, JSON.stringify(newValue)); +}; + +export const removeLocalStorage = (key: string) => { + localStorage.removeItem(key); +};