Skip to content

Commit

Permalink
bug: 로그인 시 이전 페이지로 리다이렉트 중 관련 에러 + 로그아웃 버튼 클릭 관련 에러 해결 (#527)
Browse files Browse the repository at this point in the history
* refactor: getQueryString -> getRestaurantQueryString으로 네이밍 변경

* fix: 로그인 리다이렉트 시 query 구문 전달하지 않는 에러 해결(#526)

* refactor: 로그인, 로그아웃 요청하는 useAuth 훅 구현 (#528)

logout 로직을 useMutation을 활용하여 해결

* refactor: 로그인 버튼과 로그아웃 버튼에 useAuth 적용 (#528)

* refactor: getRestaurantQueryString함수에 리팩터링 (#526)

Changed:
getRestaurantQueryString함수에 getQueryString사용

* refactor: isEqual 함수 제거 (#526)
  • Loading branch information
turtle601 authored Sep 27, 2023
1 parent be3baeb commit b42661a
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 67 deletions.
4 changes: 2 additions & 2 deletions frontend/src/api/restaurant.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import getQueryString from '~/utils/getQueryString';
import { getRestaurantQueryString } from '~/utils/getQueryString';
import { apiClient, apiUserClient } from './apiClient';
import type { RestaurantListData } from '~/@types/api.types';
import type { RestaurantsQueryParams } from '~/@types/restaurant.types';

export const getRestaurants = async (queryParams: RestaurantsQueryParams) => {
if (queryParams.boundary) {
const queryString = getQueryString(queryParams);
const queryString = getRestaurantQueryString(queryParams);
const response = await apiUserClient.get<RestaurantListData>(`/restaurants?${queryString}`);

return response.data;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/user.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { apiUserClient } from './apiClient';
import type { Oauth } from '~/@types/oauth.types';

export const getAccessToken = async (type: Oauth, code: string) => {
export const getAccessToken = async ({ type, code }: { type: Oauth; code: string }) => {
const response = await apiUserClient.get(`/oauth/login/${type}?code=${code}`);
return response.data;
};
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/@common/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { styled } from 'styled-components';
import { useQueryClient } from '@tanstack/react-query';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { Wrapper } from '@googlemaps/react-wrapper';
import { useQueryClient } from '@tanstack/react-query';

import Logo from '~/assets/icons/logo.svg';

import InfoDropDown from '~/components/InfoDropDown';
import LoginModal from '~/components/LoginModal';
import SearchBar from '~/components/SearchBar';

import useAuth from '~/hooks/server/useAuth';
import useBooleanState from '~/hooks/useBooleanState';

import Logo from '~/assets/icons/logo.svg';

import type { ProfileData } from '~/@types/api.types';
import { getLogout } from '~/api/user';

function Header() {
const qc = useQueryClient();
const navigator = useNavigate();
const { pathname } = useLocation();
const { value: isModalOpen, setTrue: openModal, setFalse: closeModal } = useBooleanState(false);
const { doLogoutMutation } = useAuth();

const handleInfoDropDown = (event: React.MouseEvent<HTMLElement>) => {
const currentOption = event.currentTarget.dataset.name;
Expand All @@ -27,8 +28,7 @@ function Header() {
if (currentOption === '위시리스트') navigator('/restaurants/like');
if (currentOption === '회원 탈퇴') navigator('/withdrawal');
if (currentOption === '로그아웃') {
getLogout(profileData.oauthServer);
window.location.reload();
doLogoutMutation(profileData.oauthServer);
}
};

Expand Down
30 changes: 21 additions & 9 deletions frontend/src/components/@common/LoginButton/LoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { OAUTH_BUTTON_MESSAGE, OAUTH_LINK } from '~/constants/api';
import KaKao from '~/assets/icons/oauth/kakao.svg';
import Naver from '~/assets/icons/oauth/naver.svg';
import Google from '~/assets/icons/oauth/google.svg';
import { Oauth } from '~/@types/oauth.types';

import { FONT_SIZE } from '~/styles/common';
import usePathNameState from '~/hooks/store/usePathnameState';
import { getUrlStringWithQuery } from '~/utils/getQueryString';
import { MSW_GET_OAUTH_CODE_URL, MSW_LOGIN_URL } from '~/constants/url';

import type { Oauth } from '~/@types/oauth.types';

interface LoginButtonProps {
type: Oauth;
Expand All @@ -20,19 +23,28 @@ const LoginIcon: Record<string, React.ReactNode> = {
google: <Google width={24} />,
};

const doLogin = (type: Oauth) => {
if (process.env.NODE_ENV === 'development') {
window.location.href = MSW_LOGIN_URL;
window.location.href = MSW_GET_OAUTH_CODE_URL;
return;
}

window.location.href = OAUTH_LINK[type];
};

function LoginButton({ type }: LoginButtonProps) {
const location = useLocation();
const setPath = usePathNameState(state => state.setPath);

const loginBeforeUrl =
location.pathname === '/signUp'
? getUrlStringWithQuery(location.state.from)
: getUrlStringWithQuery(location.pathname);

const onClick = () => {
setPath(location.pathname === '/signUp' ? location.state.from : location.pathname);

if (process.env.NODE_ENV === 'development') {
window.location.href = 'https://d.api.celuveat.com/login/local?id=abc';
window.location.href = '/oauth/redirect/kakao?code=12312421';
} else {
window.location.href = OAUTH_LINK[type];
}
setPath(loginBeforeUrl);
doLogin(type);
};

return (
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/components/BottomNavBar/FilterOptionsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import useRestaurantsQueryStringState from '~/hooks/store/useRestaurantsQueryStr
import ProfileImage from '../@common/ProfileImage';
import RESTAURANT_CATEGORY from '~/constants/restaurantCategory';
import NavItem from '../@common/NavItem';
import { isEqual } from '~/utils/compare';
import { RestaurantCategory } from '~/@types/restaurant.types';

interface FilterOptionsModalProps {
Expand Down Expand Up @@ -76,7 +75,7 @@ function FilterOptionsModal({ isModalOpen, closeModal, celebOptions }: FilterOpt
type="button"
onClick={clickRestaurantCategory}
>
<NavItem label={label} icon={icon} isShow={isEqual(category, label)} />
<NavItem label={label} icon={icon} isShow={category === label} />
</StyledNavItemButton>
))}
</li>
Expand Down
12 changes: 5 additions & 7 deletions frontend/src/components/BottomNavBar/UserButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,29 @@ import { styled } from 'styled-components';
import UserIcon from '~/assets/icons/etc/user.svg';
import ProfileImage from '../@common/ProfileImage';
import NavItem from '../@common/NavItem';
import { getLogout, getProfile } from '~/api/user';
import { getProfile } from '~/api/user';
import type { ProfileData } from '~/@types/api.types';
import useAuth from '~/hooks/server/useAuth';

function UserButton() {
const navigator = useNavigate();
const location = useLocation();
const { doLogoutMutation } = useAuth();

const { data: profile, isSuccess: isLogin } = useQuery<ProfileData>({
queryKey: ['profile'],
queryFn: () => getProfile(),
});

const clickLogin = () => navigator('/signUp', { state: { from: location.pathname } });

const clickLogout = () => {
getLogout(profile.oauthServer);
window.location.href = '/';
};

const clickLoginNavItem = () => {
if (!isLogin) {
clickLogin();
return;
}

clickLogout();
doLogoutMutation(profile.oauthServer);
};

return (
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/components/CategoryNavbar/CategoryNavbar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useState } from 'react';
import { styled } from 'styled-components';
import NavItem from '~/components/@common/NavItem/NavItem';
import { isEqual } from '~/utils/compare';

import type { RestaurantCategory } from '~/@types/restaurant.types';
import { hideScrollBar } from '~/styles/common';
Expand Down Expand Up @@ -29,7 +28,7 @@ function CategoryNavbar({ categories, externalOnClick }: CategoryProps) {
<StyledCategoryNavbarWrapper aria-hidden>
{categories.map(({ icon, label }) => (
<StyledNavItemButton aria-label={label} data-label={label} type="button" onClick={clickCategory(label)}>
<NavItem label={label} icon={icon} isShow={isEqual(selected, label)} />
<NavItem label={label} icon={icon} isShow={selected === label} />
</StyledNavItemButton>
))}
</StyledCategoryNavbarWrapper>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/constants/url.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export const SERVER_IMG_URL = 'https://www.celuveat.com/images-data/';

export const MSW_LOGIN_URL = 'https://d.api.celuveat.com/login/local?id=abc';

export const MSW_GET_OAUTH_CODE_URL = '/oauth/redirect/kakao?code=12312421';
39 changes: 39 additions & 0 deletions frontend/src/hooks/server/useAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import { getAccessToken, getLogout } from '~/api/user';

import usePathNameState from '~/hooks/store/usePathnameState';

const useAuth = () => {
const navigator = useNavigate();
const path = usePathNameState(state => state.path);

const doLoginMutation = useMutation({
mutationFn: getAccessToken,
onSuccess: () => {
navigator(path);
},
onError: () => {
navigator('/');
alert('서버 문제로 인해 로그인에 실패하였습니다.');

Check warning on line 18 in frontend/src/hooks/server/useAuth.ts

View workflow job for this annotation

GitHub Actions / 🍔테스트 딱 대라 💢👊

Unexpected alert
},
});

const doLogoutMutation = useMutation({
mutationFn: getLogout,
onSuccess: () => {
window.location.reload();
},
onError: () => {
navigator('/');
alert('서버 문제로 인해 로그아웃에 실패하였습니다.');

Check warning on line 29 in frontend/src/hooks/server/useAuth.ts

View workflow job for this annotation

GitHub Actions / 🍔테스트 딱 대라 💢👊

Unexpected alert
},
});

return {
doLoginMutation: doLoginMutation.mutate,
doLogoutMutation: doLogoutMutation.mutate,
};
};

export default useAuth;
34 changes: 4 additions & 30 deletions frontend/src/pages/OauthRedirectPage.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,26 @@
import { useMutation } from '@tanstack/react-query';
import React, { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useLocation } from 'react-router-dom';
import { styled } from 'styled-components';
import { getAccessToken } from '~/api/user';
import LoadingIndicator from '~/components/@common/LoadingIndicator';
import usePathNameState from '~/hooks/store/usePathnameState';
import useAuth from '~/hooks/server/useAuth';

interface OauthRedirectProps {
type: 'google' | 'kakao' | 'naver';
}

function OauthRedirectPage({ type }: OauthRedirectProps) {
const location = useLocation();
const navigator = useNavigate();
const path = usePathNameState(state => state.path);

const searchParams = new URLSearchParams(location.search);
const code = searchParams.get('code');

const oauthTokenMutation = useMutation({
mutationFn: () => getAccessToken(type, code),
onSuccess: () => {
navigator(path);
},
onError: () => {
navigator('/');
alert('서버 문제로 인해 로그인에 실패하였습니다.');
},
});
const { doLoginMutation } = useAuth();

useEffect(() => {
if (code) {
oauthTokenMutation.mutate();
doLoginMutation({ type, code });
}
}, [code]);

useEffect(() => {
if (process.env.NODE_ENV === 'development') {
fetch('https://d.api.celuveat.com/login/local?id=abc').then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}

navigator(path);
});
}
}, []);

return (
<StyledProcessing>
<LoadingIndicator size={32} />
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/utils/compare.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export const isEqual = (targetA: string | number, targetB: string | number) => targetA === targetB;

export const isEmptyString = (target: string) => target.length === 0;

export const isEmptyList = (target: unknown[]) => target.length === 0;
Expand Down
13 changes: 7 additions & 6 deletions frontend/src/utils/getQueryString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ interface ParamTypes extends CoordinateBoundary {
sort: 'distance' | 'like';
}

const getQueryString = ({ boundary, celebId, category, page, sort }: RestaurantsQueryParams) => {
export const getRestaurantQueryString = ({ boundary, celebId, category, page, sort }: RestaurantsQueryParams) => {
let params: ParamTypes = { ...boundary, sort };

if (celebId !== -1) params = { ...params, celebId: String(celebId) };

if (category !== '전체') params = { ...params, category };

if (page !== 0) params = { ...params, page: String(page) };

const queryString = new URLSearchParams(Object.assign(params)).toString();
return getQuerySting(Object.assign(params));
};

return queryString;
const getQuerySting = (target: string | string[][] | Record<string, string> | URLSearchParams) => {
const searchParams = new URLSearchParams(target);
return searchParams.toString();
};

export default getQueryString;
export const getUrlStringWithQuery = (url: string) => `${url}${getQuerySting(window.location.search)}`;

0 comments on commit b42661a

Please sign in to comment.