From 0c73d9b25a33d7060b9630685593d402fa7d6904 Mon Sep 17 00:00:00 2001 From: "Ahyeon, Jung" <75254185+a-honey@users.noreply.github.com> Date: Sat, 17 Feb 2024 14:27:19 +0900 Subject: [PATCH] =?UTF-8?q?MARA-65=20=EC=97=90=EB=9F=AC=EB=B0=94=EC=9A=B4?= =?UTF-8?q?=EB=8D=94=EB=A6=AC,=20fallback=20(#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 카카오로그인 useQuery로 변경 * feat: 전역 에러바운더리 설정 * feat: 로딩중 로티 컴포넌트 추가 * fix: 경고 토스트로 변경 * fix: 요청 baseURL 환경변수 변경 * fix: 에러 다시 요청 * chore: 냉장고 페이지 api 요청 주석 처리 * chore: 테스트용 api 주소 설정 * fix: edit Suspense fallback component UI * chore: 다시 서버에 요청 * fix: 헤더 제거 및 flex 조정 * chore: 냉장고 페이지 api 요청 주석 처리 * fix: 냉장고 리스트 모달 chakra-ui 변경 for animation * fix: 식자재 추가 모달 chakra-ui 변경 * fix: 모달 컨테이너 스타일 추가 * fix: 친구 냉장고 페이지 모달 변경 * fix: 친구목록 페이지 순서 모달 변경 * fix: 친구목록 페이지 스타일 변경 * feat: 로고 이미지 추가 홈, 로그인 페이지 * fix: 모달컨테이너 article 태그, div 스타일 변경 * feat: 환경변수 타입 추가 --- .github/workflows/workflow-pr.yml | 1 + .vscode/settings.json | 1 + env.d.ts | 9 ++ package.json | 1 + src/api/axiosInstance.ts | 2 +- src/api/login/getToken.ts | 31 ------ src/assets/logos/text_logo_l.svg | 12 +++ src/assets/logos/text_logo_m.svg | 12 +++ src/assets/lottie.gif | Bin 0 -> 18313 bytes src/components/atoms/ModalBottom.tsx | 34 ------- src/components/atoms/ModalContainer.tsx | 16 +++ src/components/atoms/index.ts | 2 +- .../molecules/FriendsFridgeItem.tsx | 16 ++- src/components/organisms/FridgeListModal.tsx | 9 +- src/components/organisms/Header.tsx | 14 +-- .../organisms/IngredientAddModal.tsx | 7 +- src/components/organisms/OrderListModal.tsx | 9 +- src/components/templates/ErrorFallback.tsx | 32 ++++++ src/components/templates/SuspenseFallback.tsx | 15 +++ src/components/templates/index.ts | 2 + src/components/templates/withLogin.tsx | 4 +- .../queries/fridge/useGetIngredientList.ts | 2 + src/hooks/queries/login/index.ts | 1 + src/hooks/queries/login/useGetKakaoToken.ts | 14 +++ src/hooks/queries/queryKeys.ts | 3 +- src/hooks/queries/useBaseQuery.ts | 11 +-- src/pages/_app.tsx | 33 +++++-- src/pages/fridge/index.tsx | 92 ++++++++++++------ src/pages/friend/[id]/index.tsx | 49 +++++++--- src/pages/friends/index.tsx | 46 ++++++--- src/pages/home/index.tsx | 3 +- src/pages/login/index.tsx | 30 +++--- yarn.lock | 7 ++ 33 files changed, 335 insertions(+), 185 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 env.d.ts delete mode 100644 src/api/login/getToken.ts create mode 100644 src/assets/logos/text_logo_l.svg create mode 100644 src/assets/logos/text_logo_m.svg create mode 100644 src/assets/lottie.gif delete mode 100644 src/components/atoms/ModalBottom.tsx create mode 100644 src/components/atoms/ModalContainer.tsx create mode 100644 src/components/templates/ErrorFallback.tsx create mode 100644 src/components/templates/SuspenseFallback.tsx create mode 100644 src/hooks/queries/login/index.ts create mode 100644 src/hooks/queries/login/useGetKakaoToken.ts diff --git a/.github/workflows/workflow-pr.yml b/.github/workflows/workflow-pr.yml index bdb7386..e7c9c9a 100644 --- a/.github/workflows/workflow-pr.yml +++ b/.github/workflows/workflow-pr.yml @@ -29,6 +29,7 @@ jobs: # 환경 변수 추가 - name: Set Environment Variables run: | + echo "NEXT_PUBLIC_BASE_URI=${{ secrets.NEXT_PUBLIC_BASE_URI }}" >> .env echo "NEXT_PUBLIC_KAKAO_API_KEY=${{ secrets.NEXT_PUBLIC_KAKAO_API_KEY }}" >> .env echo "NEXT_PUBLIC_KAKAO_REDIRECT_URI=${{ secrets.NEXT_PUBLIC_KAKAO_REDIRECT_URI }}" >> .env echo "NEXT_PUBLIC_GOOGLE_API_KEY=${{ secrets.NEXT_PUBLIC_GOOGLE_API_KEY }}" >> .env diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..f9fe038 --- /dev/null +++ b/env.d.ts @@ -0,0 +1,9 @@ +declare namespace NodeJS { + interface ProcessEnv { + NEXT_PUBLIC_BASE_URI: string; + NEXT_PUBLIC_KAKAO_API_KEY: string; + NEXT_PUBLIC_KAKAO_REDIRECT_URI: string; + NEXT_PUBLIC_GOOGLE_API_KEY: string; + NEXT_PUBLIC_GOOGLE_REDIRECT_URI: string; + } +} diff --git a/package.json b/package.json index 319d0ef..916dcef 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "next": "14.0.3", "react": "^18", "react-dom": "^18", + "react-error-boundary": "^4.0.12", "recoil": "^0.7.7" }, "devDependencies": { diff --git a/src/api/axiosInstance.ts b/src/api/axiosInstance.ts index 7700f30..dd0fbbc 100644 --- a/src/api/axiosInstance.ts +++ b/src/api/axiosInstance.ts @@ -7,7 +7,7 @@ export interface ApiResponseDTO { } const axiosInstance = axios.create({ - baseURL: 'https://localhost:3000', + baseURL: process.env.NEXT_PUBLIC_BASE_URI, timeout: 5000, headers: { 'Content-Type': 'application/json', diff --git a/src/api/login/getToken.ts b/src/api/login/getToken.ts deleted file mode 100644 index 9a752f5..0000000 --- a/src/api/login/getToken.ts +++ /dev/null @@ -1,31 +0,0 @@ -import axiosInstance from '../axiosInstance'; - -interface LoginResponseType { - data: { accessToken: string; refreshToken: string; email: string }; -} - -const fetchKaKao = async (code: string): Promise => - await axiosInstance.get(`/users/kakao-login?code=${code}`); - -export const getKaKaoToken: (code: string) => Promise = async (code) => { - fetchKaKao(code) - .then((response: LoginResponseType) => { - localStorage.setItem('token', response.data.accessToken); - }) - .catch((error) => { - console.error(error); - }); -}; - -const fetchGoogle = async (code: string): Promise => - await axiosInstance.get(`/users/google-login?code=${code}`); - -export const getGoogleToken: (code: string) => Promise = async (code) => { - fetchGoogle(code) - .then((response: LoginResponseType) => { - localStorage.setItem('token', response.data.accessToken); - }) - .catch((error) => { - console.error(error); - }); -}; diff --git a/src/assets/logos/text_logo_l.svg b/src/assets/logos/text_logo_l.svg new file mode 100644 index 0000000..f4e7d4b --- /dev/null +++ b/src/assets/logos/text_logo_l.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/logos/text_logo_m.svg b/src/assets/logos/text_logo_m.svg new file mode 100644 index 0000000..dc2dfcf --- /dev/null +++ b/src/assets/logos/text_logo_m.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/lottie.gif b/src/assets/lottie.gif new file mode 100644 index 0000000000000000000000000000000000000000..1957240c76bb6ee24a2f1ec5c7335f39dbce8b7c GIT binary patch literal 18313 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 void; -} - -const ModalBox: React.FC = ({ children, blackClickHandler }) => { - const handleWhiteContentClick: (e: React.MouseEvent) => void = (e) => { - if (e.target === e.currentTarget) { - blackClickHandler(); - } - e.stopPropagation(); - }; - - return ( -
-
-
-
-
- {children} -
-
- ); -}; - -export default ModalBox; diff --git a/src/components/atoms/ModalContainer.tsx b/src/components/atoms/ModalContainer.tsx new file mode 100644 index 0000000..123a11c --- /dev/null +++ b/src/components/atoms/ModalContainer.tsx @@ -0,0 +1,16 @@ +import React from 'react'; + +interface ModalBoxProps { + children: React.ReactNode; +} + +const ModalContainer: React.FC = ({ children }) => { + return ( +
+
+ {children} +
+ ); +}; + +export default ModalContainer; diff --git a/src/components/atoms/index.ts b/src/components/atoms/index.ts index cedd6a3..c7206d7 100644 --- a/src/components/atoms/index.ts +++ b/src/components/atoms/index.ts @@ -4,7 +4,7 @@ export { default as Container } from './Container'; export { default as GrayBox } from './GrayBox'; export { default as IngredientDateTag } from './IngredientDateTag'; export { default as BorderTab } from './BorderTab'; -export { default as ModalBottom } from './ModalBottom'; +export { default as ModalContainer } from './ModalContainer'; export { default as ModalCenter } from './ModalCenter'; export { default as Toggle } from './Toggle'; export { default as ToastMessage } from './ToastMessage'; diff --git a/src/components/molecules/FriendsFridgeItem.tsx b/src/components/molecules/FriendsFridgeItem.tsx index 3854a08..936df9e 100644 --- a/src/components/molecules/FriendsFridgeItem.tsx +++ b/src/components/molecules/FriendsFridgeItem.tsx @@ -16,12 +16,20 @@ const FriendsFridgeItem: React.FC = ({ linkTo, }) => { return ( -
+
- {`누군가의 + {`누군가의
-
+
{name}
냉장고 저장 목록 {ingredientCount}개 @@ -31,7 +39,7 @@ const FriendsFridgeItem: React.FC = ({ -
+ ); }; diff --git a/src/components/organisms/FridgeListModal.tsx b/src/components/organisms/FridgeListModal.tsx index 048326a..d09deaa 100644 --- a/src/components/organisms/FridgeListModal.tsx +++ b/src/components/organisms/FridgeListModal.tsx @@ -1,4 +1,4 @@ -import { Button, ModalBottom } from '../atoms'; +import { Button, ModalContainer } from '../atoms'; import { PlusIcon, TrashcanIcon } from '@/assets/icons'; import React, { useState } from 'react'; @@ -6,13 +6,12 @@ import { FridgeListItem } from '../molecules'; const FridgeListModal: React.FC<{ isMyFridgeList?: boolean; - toggleIsOpenFridgeListModal: () => void; -}> = ({ toggleIsOpenFridgeListModal, isMyFridgeList }) => { +}> = ({ isMyFridgeList }) => { const [currentFridgeName, setCurrentFridgeName] = useState('기본 냉장고'); const FRIDGE_NAME_LIST = ['기본 냉장고', '김치 냉장고', '주류 냉장고']; return ( - +
냉장고 목록
@@ -41,7 +40,7 @@ const FridgeListModal: React.FC<{
- + ); }; diff --git a/src/components/organisms/Header.tsx b/src/components/organisms/Header.tsx index 00313ed..6a5ad7b 100644 --- a/src/components/organisms/Header.tsx +++ b/src/components/organisms/Header.tsx @@ -32,7 +32,7 @@ const Header: React.FC<{ return (
{headerLeft ?? ( )} -
-

- {typeof headerTitle === 'string' ? headerTitle : ''} -

-
+ {!headerLeft && ( +
+

+ {typeof headerTitle === 'string' ? headerTitle : ''} +

+
+ )} {headerRight ??
}
); diff --git a/src/components/organisms/IngredientAddModal.tsx b/src/components/organisms/IngredientAddModal.tsx index cb2f6cd..d416610 100644 --- a/src/components/organisms/IngredientAddModal.tsx +++ b/src/components/organisms/IngredientAddModal.tsx @@ -1,11 +1,12 @@ import { BoxIcon, CalendarIcon, FreezerIcon, MemoIcon } from '@/assets/icons'; -import { Button, ModalBottom, Toggle } from '@/components/atoms'; +import { Button, Toggle } from '@/components/atoms'; import { Counter, IngredientAddItemContainer } from '../molecules'; import React, { useState } from 'react'; import { AppleIcon } from '../atoms/IngredientIcons'; import useCount from '@/hooks/useCount'; import useToast from '@/hooks/useToast'; +import ModalContainer from '../atoms/ModalContainer'; const IngredientAddModal: React.FC<{ toggleIsOpenIngredientAddModal: () => void; @@ -27,7 +28,7 @@ const IngredientAddModal: React.FC<{ }; return ( - +
@@ -88,7 +89,7 @@ const IngredientAddModal: React.FC<{ onClick={handleSubmit} />
- + ); }; diff --git a/src/components/organisms/OrderListModal.tsx b/src/components/organisms/OrderListModal.tsx index f9a8d7e..e60af25 100644 --- a/src/components/organisms/OrderListModal.tsx +++ b/src/components/organisms/OrderListModal.tsx @@ -1,15 +1,14 @@ -import { Button, ModalBottom, Radio } from '../atoms'; +import { Button, ModalContainer, Radio } from '../atoms'; import React from 'react'; const OrderListModal: React.FC<{ currentOrder: string; - toggleIsOpenOrderListModal: () => void; -}> = ({ toggleIsOpenOrderListModal, currentOrder }) => { +}> = ({ currentOrder }) => { const ORDER_LIST = ['등록순', '이름순']; return ( - +
{ORDER_LIST.map((order) => (
@@ -19,7 +18,7 @@ const OrderListModal: React.FC<{ ))}
+
+ ); +}; + +export default ErrorFallback; diff --git a/src/components/templates/SuspenseFallback.tsx b/src/components/templates/SuspenseFallback.tsx new file mode 100644 index 0000000..da0a170 --- /dev/null +++ b/src/components/templates/SuspenseFallback.tsx @@ -0,0 +1,15 @@ +import Image from 'next/image'; +import React from 'react'; +import LottieGif from '@/assets/lottie.gif'; + +const SuspenseFallback: React.FC = () => { + return ( +
+
+ 로딩중 +
+
+ ); +}; + +export default SuspenseFallback; diff --git a/src/components/templates/index.ts b/src/components/templates/index.ts index c946b91..b1a7b9e 100644 --- a/src/components/templates/index.ts +++ b/src/components/templates/index.ts @@ -1,3 +1,5 @@ export { default as Layout } from './Layout'; export { default as FriendListTemplate } from './FriendListTemplate'; export { default as AddFriendTemplate } from './AddFriendTemplate'; +export { default as ErrorFallback } from './ErrorFallback'; +export { default as SuspenseFallback } from './SuspenseFallback'; diff --git a/src/components/templates/withLogin.tsx b/src/components/templates/withLogin.tsx index 1ad69e5..a722b8c 100644 --- a/src/components/templates/withLogin.tsx +++ b/src/components/templates/withLogin.tsx @@ -1,14 +1,16 @@ import React, { useEffect } from 'react'; import { useRouter } from 'next/router'; +import useToast from '@/hooks/useToast'; const withLogin = (InnerComponent: React.FC) => { return () => { const router = useRouter(); const token = localStorage.getItem('token'); + const { showToast } = useToast(); const redirectToLogin: () => Promise = async () => { if (!token) { - alert('로그인이 필요합니다.'); + showToast('로그인이 필요합니다.', 'info'); try { await router.push('/login'); } catch (error) { diff --git a/src/hooks/queries/fridge/useGetIngredientList.ts b/src/hooks/queries/fridge/useGetIngredientList.ts index d3e126e..c98760a 100644 --- a/src/hooks/queries/fridge/useGetIngredientList.ts +++ b/src/hooks/queries/fridge/useGetIngredientList.ts @@ -3,6 +3,8 @@ import { queryKeys } from '../queryKeys'; import { useBaseQuery } from '../useBaseQuery'; const useGetIngredientList = () => { + // const testApiEndpoint = 'https://jsonplaceholder.typicode.com/todos'; + return useBaseQuery(queryKeys.INGREDIENT(), '/ingrs'); }; diff --git a/src/hooks/queries/login/index.ts b/src/hooks/queries/login/index.ts new file mode 100644 index 0000000..cd9fc0e --- /dev/null +++ b/src/hooks/queries/login/index.ts @@ -0,0 +1 @@ +export { default as useGetKakaoToken } from './useGetKakaoToken'; diff --git a/src/hooks/queries/login/useGetKakaoToken.ts b/src/hooks/queries/login/useGetKakaoToken.ts new file mode 100644 index 0000000..8b1d9d3 --- /dev/null +++ b/src/hooks/queries/login/useGetKakaoToken.ts @@ -0,0 +1,14 @@ +import { queryKeys } from '../queryKeys'; +import { useBaseQuery } from '../useBaseQuery'; + +const useGetKakaoToken = (code: string | null = '') => { + const { data } = useBaseQuery<{ data: { accessToken: string } }>( + queryKeys.KAKAO(), + `/users/kakao-login?code=${code}`, + ); + if (data) { + localStorage.setItem('token', data.data.accessToken); + } +}; + +export default useGetKakaoToken; diff --git a/src/hooks/queries/queryKeys.ts b/src/hooks/queries/queryKeys.ts index d4896fc..670e47a 100644 --- a/src/hooks/queries/queryKeys.ts +++ b/src/hooks/queries/queryKeys.ts @@ -1,5 +1,6 @@ export const queryKeys = { - INGREDIENT: (id?: number) => ['ingredient', id] as const, + INGREDIENT: (id?: number) => (id ? ['ingredient', id] : ['ingredient']), + KAKAO: () => ['kakao'], } as const; export type QueryKeys = (typeof queryKeys)[keyof typeof queryKeys]; diff --git a/src/hooks/queries/useBaseQuery.ts b/src/hooks/queries/useBaseQuery.ts index c3cf378..61eb4ae 100644 --- a/src/hooks/queries/useBaseQuery.ts +++ b/src/hooks/queries/useBaseQuery.ts @@ -1,5 +1,5 @@ import axiosInstance from '@/api/axiosInstance'; -import { useQuery } from '@tanstack/react-query'; +import { useSuspenseQuery } from '@tanstack/react-query'; export const fetchData = async (url: string) => { const response = await axiosInstance.get<{ data: T }>(url); @@ -7,13 +7,8 @@ export const fetchData = async (url: string) => { }; export const useBaseQuery = (queryKey: any, url: string) => { - return useQuery({ + return useSuspenseQuery({ queryKey, - queryFn: async () => - await fetchData(url) - .then((res) => res.data) - .catch((error) => { - console.error(error); - }), + queryFn: async () => await fetchData(url).then((res) => res.data), }); }; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 47fa34c..3f8cb95 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -3,9 +3,16 @@ import Layout from '@/components/templates/Layout'; import '@/styles/globals.css'; import type { AppProps } from 'next/app'; import { RecoilRoot } from 'recoil'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { + QueryClient, + QueryClientProvider, + QueryErrorResetBoundary, +} from '@tanstack/react-query'; +import React from 'react'; import 'dayjs/locale/ko'; import dayjs from 'dayjs'; +import { ErrorBoundary } from 'react-error-boundary'; +import { ErrorFallback, SuspenseFallback } from '@/components/templates'; dayjs.locale('ko'); const theme = extendTheme({ @@ -26,14 +33,22 @@ const queryClient = new QueryClient({ export default function App({ Component, pageProps }: AppProps): JSX.Element { return ( - - - - - - - - + + {({ reset }) => ( + + }> + + + + + + + + + + + )} + ); } diff --git a/src/pages/fridge/index.tsx b/src/pages/fridge/index.tsx index 73d827c..4b9423e 100644 --- a/src/pages/fridge/index.tsx +++ b/src/pages/fridge/index.tsx @@ -6,44 +6,80 @@ import { IngredientAddModal, } from '@/components/organisms'; import { type NextPage } from 'next'; -import { useState } from 'react'; -import { useGetIngredientList } from '@/hooks/queries/fridge'; +import { + Modal, + ModalOverlay, + ModalBody, + ModalContent, + useDisclosure, +} from '@chakra-ui/react'; +// import { useGetIngredientList } from '@/hooks/queries/fridge'; const FridgePage: NextPage = () => { - const [isOpenIngredientAddModal, setIsOpenIngredientAddModal] = - useState(false); - const [isOpenFridgeListModal, setIsOpenFridgeListModal] = useState(false); - - const data = useGetIngredientList(); - console.log('받아올 데이터', data); + const { + isOpen: isOpenIngredientAddModal, + onOpen: onOpenIngredientAddModal, + onClose: onCloseIngredientAddModal, + } = useDisclosure(); - const toggleIsOpenIngredientAddModal: () => void = () => { - setIsOpenIngredientAddModal((prev) => !prev); - }; - - const toggleIsOpenFridgeListModal: () => void = () => { - setIsOpenFridgeListModal((prev) => !prev); - }; + const { + isOpen: isOpenFridgeListModal, + onOpen: onOpenFridgeListModal, + onClose: onCloseFridgeListModal, + } = useDisclosure(); + // const data = useGetIngredientList(); + // console.log('받아올 데이터', data); return ( <> - {isOpenFridgeListModal && ( - - )} - - {isOpenIngredientAddModal && ( - - )} + + + + + + + + + + + + + + + +
diff --git a/src/pages/friend/[id]/index.tsx b/src/pages/friend/[id]/index.tsx index a20b89a..727e4fa 100644 --- a/src/pages/friend/[id]/index.tsx +++ b/src/pages/friend/[id]/index.tsx @@ -5,29 +5,46 @@ import { } from '@/components/organisms'; import Header from '@/components/organisms/Header'; import { type NextPage } from 'next'; -import { useState } from 'react'; - +import { + Modal, + ModalOverlay, + ModalBody, + ModalContent, + useDisclosure, +} from '@chakra-ui/react'; const FriendIdPage: NextPage = () => { - const [isOpenFridgeListModal, setIsOpenFridgeListModal] = useState(false); - - const toggleIsOpenFridgeListModal: () => void = () => { - setIsOpenFridgeListModal((prev) => !prev); - }; + const { + isOpen: isOpenFridgeListModal, + onOpen: onOpenFridgeListModal, + onClose: onCloseFridgeListModal, + } = useDisclosure(); return ( <> - {isOpenFridgeListModal && ( - - )} + + + + + + + +
- +
diff --git a/src/pages/friends/index.tsx b/src/pages/friends/index.tsx index c3c22a1..c314a56 100644 --- a/src/pages/friends/index.tsx +++ b/src/pages/friends/index.tsx @@ -4,30 +4,50 @@ import { OrderListModal, } from '@/components/organisms'; import Header from '@/components/organisms/Header'; +import { + Modal, + ModalBody, + ModalContent, + ModalOverlay, + useDisclosure, +} from '@chakra-ui/react'; import { type NextPage } from 'next'; -import { useState } from 'react'; const FriendsPage: NextPage = () => { - const [isOpenOrderListModal, setIsOpenOrderListModal] = useState(false); - - const toggleIsOpenOrderListModal: () => void = () => { - setIsOpenOrderListModal((prev) => !prev); - }; + const { + isOpen: isOpenOrderListModal, + onOpen: onOpenOrderListModal, + onClose: onCloseOrderListModal, + } = useDisclosure(); return ( <> - {isOpenOrderListModal && ( - - )} + + + + + + + +
diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 4b4f364..a3180ad 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -1,5 +1,6 @@ import { type NextPage } from 'next'; import MyFridgeImg from '@/assets/images/img_home_my.svg'; +import LogoTextImg from '@/assets/logos/text_logo_m.svg'; import FriendsFridgeImg from '@/assets/images/img_home_friend.svg'; import { GreenArrowButton } from '@/components/atoms'; import { NearExpirationWarnBox, SvgAndTextBox } from '@/components/molecules'; @@ -14,7 +15,7 @@ const Home: NextPage = () => {
} + headerLeft={} headerRight={
diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index 946d9b7..59d3cc3 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -1,9 +1,9 @@ import MonstersImg from '@/assets/images/img_login_monsters.svg'; import KaKaoImg from '@/assets/images/img_login_kakao.svg'; import GoogleImg from '@/assets/images/img_login_google.svg'; +import LogoTextImg from '@/assets/logos/text_logo_l.svg'; import { type NextPage } from 'next'; -import { useEffect } from 'react'; -import { getKaKaoToken } from '@/api/login/getToken'; +import { useGetKakaoToken } from '@/hooks/queries/login'; const LoginPage: NextPage = () => { const kakaoURL = `https://kauth.kakao.com/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_KAKAO_API_KEY}&redirect_uri=${process.env.NEXT_PUBLIC_KAKAO_REDIRECT_URI}&response_type=code`; @@ -17,21 +17,15 @@ const LoginPage: NextPage = () => { window.location.href = `${googleURL}&type=google`; }; - useEffect(() => { - const fetchData = async (): Promise => { - const urlParams = new URLSearchParams(window.location.search); - const code = urlParams.get('code'); - // const type = urlParams.get('type'); - // 구글 추가시 타입 redirect_uri 변경 + const urlParams = + typeof window !== 'undefined' + ? new URLSearchParams(window.location.search) + : null; + const code = urlParams?.get('code'); - if (code) { - await getKaKaoToken(code); - } - }; - - // eslint-disable-next-line @typescript-eslint/no-floating-promises - fetchData(); - }, []); + if (code) { + useGetKakaoToken(code); + } return (
{
냉장고 관리, 얼른 시작해봐요
-
로고
+
@@ -51,8 +45,8 @@ const LoginPage: NextPage = () => {
- +
diff --git a/yarn.lock b/yarn.lock index bd2ca0c..198fa33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10097,6 +10097,13 @@ react-element-to-jsx-string@^15.0.0: is-plain-object "5.0.0" react-is "18.1.0" +react-error-boundary@^4.0.12: + version "4.0.12" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.12.tgz#59f8f1dbc53bbbb34fc384c8db7cf4082cb63e2c" + integrity sha512-kJdxdEYlb7CPC1A0SeUY38cHpjuu6UkvzKiAmqmOFL21VRfMhOcWxTCBgLVCO0VEMh9JhFNcVaXlV4/BTpiwOA== + dependencies: + "@babel/runtime" "^7.12.5" + react-fast-compare@3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"