Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

카카오로그인 수정 및 토큰 저장 #18

Merged
merged 10 commits into from
Feb 18, 2024
8 changes: 4 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ module.exports = {
es2021: true,
},
globals: {
'JSX': true
JSX: true,
},
extends: [
'standard-with-typescript',
'eslint:recommended',
'plugin:prettier/recommended',
'next/core-web-vitals'
'next/core-web-vitals',
],
parserOptions: {
ecmaVersion: 'latest',
Expand All @@ -19,7 +19,7 @@ module.exports = {
ignorePatterns: ['/src/assets/**', '/src/styles/**'],
rules: {
'@typescript-eslint/strict-boolean-expressions': 'off',
'prettier/prettier': ["error", { "endOfLine": "auto" }],
'@typescript-eslint/explicit-function-return-type': 'off'
'prettier/prettier': ['error', { endOfLine: 'auto' }],
'@typescript-eslint/explicit-function-return-type': 'off',
},
};
7 changes: 5 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
domains: ['mara-s3bucket.s3.ap-northeast-2.amazonaws.com'],
},
webpack: (config) => {
return {
...config,
Expand All @@ -22,8 +25,8 @@ const nextConfig = {
source: '/',
destination: '/home',
permanent: true,
}
]
},
];
},
};

Expand Down
47 changes: 44 additions & 3 deletions src/api/axiosInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,50 @@ export interface ApiResponseDTO<T> {
const axiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_BASE_URI,
timeout: 5000,
headers: {
'Content-Type': 'application/json',
},
});

axiosInstance.interceptors.request.use((config) => {
config.headers['Content-Type'] = 'application/json';

if (typeof window !== 'undefined') {
config.headers.Authorization = `Bearer ${localStorage.getItem('accessToken')}`;
}

return config;
});

axiosInstance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;

if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;

const refreshToken =
typeof window !== 'undefined'
? localStorage.getItem('refreshToken')
: null;

try {
const refreshResponse = await axios.post('/users/kakao-login', {
refreshToken,
});

if (typeof window !== 'undefined') {
localStorage.setItem('accessToken', refreshResponse.data.accessToken);
}

originalRequest.headers.Authorization = `Bearer ${refreshResponse.data.accessToken}`;
return await axiosInstance(originalRequest);
} catch (refreshError) {
console.error('Error refreshing token:', refreshError);
throw refreshError;
}
}

return await Promise.reject(error);
},
);

export default axiosInstance;
6 changes: 2 additions & 4 deletions src/components/organisms/FridgeBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,20 @@ import {
IngredientItemBox,
} from '@/components/molecules';

const FridgeBoard: React.FC = () => {
const FridgeBoard: React.FC<{ data?: any | null }> = ({ data }) => {
const [currentTabName, setCurrentTabName] = useState<'냉장' | '냉동'>('냉장');

const handleTabNameChange: (tabName: '냉장' | '냉동') => void = (tabName) => {
setCurrentTabName(tabName);
};

const datas = ['d'];

return (
<Container className="p-[20px] bg-white">
<FridgeTab
currentTabName={currentTabName}
handleTabNameChange={handleTabNameChange}
/>
{datas.length !== 0 ? (
{data !== null || (Array.isArray(data) && data?.length !== 0) ? (
<div className="flex flex-col w-full gap-[24px]">
<IngredientItemBox />
<IngredientItemBox />
Expand Down
1 change: 1 addition & 0 deletions src/components/organisms/FridgeListModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const FridgeListModal: React.FC<{
<div className="flex flex-col gap-[10px] mt-[25px] mb-[32px]">
{FRIDGE_NAME_LIST.map((fridgeName) => (
<FridgeListItem
key={fridgeName}
isCurrentFridge={currentFridgeName === fridgeName}
fridgeName={fridgeName}
onClick={() => {
Expand Down
5 changes: 1 addition & 4 deletions src/components/templates/withLogin.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
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 token = localStorage.getItem('accessToken');

const redirectToLogin: () => Promise<void> = async () => {
if (!token) {
showToast('로그인이 필요합니다.', 'info');
try {
await router.push('/login');
} catch (error) {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/queries/fridge/useGetIngredientList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useBaseQuery } from '../useBaseQuery';
const useGetIngredientList = () => {
// const testApiEndpoint = 'https://jsonplaceholder.typicode.com/todos';

return useBaseQuery<IngredientType>(queryKeys.INGREDIENT(), '/ingrs');
return useBaseQuery<IngredientType>(queryKeys.INGREDIENT(), '/regrigs/my');
};

export default useGetIngredientList;
1 change: 1 addition & 0 deletions src/hooks/queries/login/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as useGetKakaoToken } from './useGetKakaoToken';
export { default as usePostUser } from './usePostUser';
24 changes: 18 additions & 6 deletions src/hooks/queries/login/useGetKakaoToken.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { useRouter } from 'next/router';
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);
const router = useRouter();
const { data } = useBaseQuery<{
accessToken: string;
refreshToken: string;
kakaoId: number;
kakaoEmail: string;
}>(queryKeys.KAKAO(), `/users/kakao-login?code=${code}`, true);

if (data?.data?.accessToken === undefined) {
void router.push(
`/mypage/profile?kakaoId=${data?.data?.kakaoId}&kakaoEmail=${data?.data?.kakaoEmail}`,
);
}
if (data?.data) {
localStorage.setItem('accessToken', data.data.accessToken);
localStorage.setItem('refreshToken', data.data.refreshToken);
void router.push('/home');
}
};

Expand Down
35 changes: 35 additions & 0 deletions src/hooks/queries/login/usePostUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useRouter } from 'next/router';
import { queryKeys } from '../queryKeys';
import { useBaseMutation } from '../useBaseMutation';

interface PostUserBodyType {
nickName: string;
kakaoId: number;
kakaoEmail: string;
googleEmail: string;
profileImage: string;
}

const usePostUser = () => {
const router = useRouter();
const onSuccess = ({
data,
}: {
data: {
accessToken: string;
refreshToken: string;
email: string;
nickName: string;
};
}) => {
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
void router.push('/home');
};
return useBaseMutation<PostUserBodyType>(
queryKeys.KAKAO(),
`/users`,
onSuccess,
);
};
export default usePostUser;
22 changes: 22 additions & 0 deletions src/hooks/queries/useBaseMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import axiosInstance from '@/api/axiosInstance';
import { useMutation } from '@tanstack/react-query';

export const fetchData = async <T>(url: string, body: T) => {
const response = await axiosInstance.post<{ data: T }>(url, body);
return response.data;
};

export const useBaseMutation = <T>(
mutationKey: any,
url: string,
onSuccess: (any: any) => void,
) => {
return useMutation({
mutationKey,
mutationFn: async (body: T) => {
const response = await fetchData<T>(url, body);

onSuccess(response.data);
},
});
};
27 changes: 21 additions & 6 deletions src/hooks/queries/useBaseQuery.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import axiosInstance from '@/api/axiosInstance';
import { useSuspenseQuery } from '@tanstack/react-query';

export const fetchData = async <T>(url: string) => {
const response = await axiosInstance.get<{ data: T }>(url);
return response.data;
export const fetchData = async <T>(url: string, isNotCatch: boolean) => {
try {
const response = await axiosInstance.get<{ data: T; status?: number }>(url);
return response.data;
} catch (error: any) {
if (!isNotCatch) {
if (error.response && error.response.status === 404) {
return await Promise.resolve({ data: null });
} else {
throw error;
}
}
}
};

export const useBaseQuery = <T>(queryKey: any, url: string) => {
export const useBaseQuery = <T>(
queryKey: any,
url: string,
isNotCatch: boolean = false,
) => {
return useSuspenseQuery({
queryKey,
queryFn: async () => await fetchData<T>(url).then((res) => res.data),
queryFn: async () => {
return await fetchData<T>(url, isNotCatch);
},
});
};
8 changes: 4 additions & 4 deletions src/pages/fridge/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
ModalContent,
useDisclosure,
} from '@chakra-ui/react';
// import { useGetIngredientList } from '@/hooks/queries/fridge';
import { useGetIngredientList } from '@/hooks/queries/fridge';

const FridgePage: NextPage = () => {
const {
Expand All @@ -27,8 +27,8 @@ const FridgePage: NextPage = () => {
onOpen: onOpenFridgeListModal,
onClose: onCloseFridgeListModal,
} = useDisclosure();
// const data = useGetIngredientList();
// console.log('받아올 데이터', data);

const { data } = useGetIngredientList();

return (
<>
Expand Down Expand Up @@ -81,7 +81,7 @@ const FridgePage: NextPage = () => {
toggleIsOpenFridgeListModal={onOpenFridgeListModal}
toggleIsOpenIngredientAddModal={onOpenIngredientAddModal}
/>
<FridgeBoard />
<FridgeBoard data={data?.data} />
</section>
</div>
</>
Expand Down
10 changes: 7 additions & 3 deletions src/pages/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { IngredientBoard } from '@/components/organisms';
import Header from '@/components/organisms/Header';
import Link from 'next/link';
import { AlarmIcon } from '@/assets/icons';
import withLogin from '@/components/templates/withLogin';

const NEAR_EXPIRATION_COUNT_MOCK_DATA=2;
const NEAR_EXPIRATION_COUNT_MOCK_DATA = 2;

const Home: NextPage = () => {
const isNearExpirationWarn = true;
Expand All @@ -26,7 +27,10 @@ const Home: NextPage = () => {
/>
<section className={`flex flex-col min-h-screen p-20 bg-gray1`}>
{isNearExpirationWarn && (
<NearExpirationWarnBox className="mt-12" count={NEAR_EXPIRATION_COUNT_MOCK_DATA} />
<NearExpirationWarnBox
className="mt-12"
count={NEAR_EXPIRATION_COUNT_MOCK_DATA}
/>
)}
<div className="flex gap-8.5 mt-12">
<SvgAndTextBox
Expand All @@ -53,4 +57,4 @@ const Home: NextPage = () => {
</div>
);
};
export default Home;
export default withLogin(Home);
Loading
Loading