Skip to content

Commit

Permalink
[Feature/BAR-238] 최근 로그인 정보 반영 (#68)
Browse files Browse the repository at this point in the history
* feat: 최근 로그인 정보 반영하기

* refactor: storage key 상수화
  • Loading branch information
miro-ring authored Feb 18, 2024
1 parent 25b3666 commit d571cab
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 50 deletions.
2 changes: 2 additions & 0 deletions pages/redirect/[authType]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEffect } from 'react';
import { getToken } from '@api/auth';
import { type OAuthType } from '@api/auth/types';
import { ROUTES } from '@constants/routes';
import { STORAGE_KEY } from '@models/storage';
import { saveToken } from '@utils/token';

const Bridge = () => {
Expand All @@ -27,6 +28,7 @@ const Bridge = () => {
}

saveToken({ accessToken, refreshToken });
localStorage.setItem(STORAGE_KEY.RECENT_LOGIN_TYPE, authType);

router.replace(ROUTES.MAIN);
})();
Expand Down
5 changes: 3 additions & 2 deletions src/api/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import axios, { type AxiosRequestConfig } from 'axios';
import Cookies from 'js-cookie';

import { ROUTES } from '@constants/routes';
import { STORAGE_KEY } from '@models/storage';
import { saveToken } from '@utils/token';

import { getRenewToken } from './auth';
Expand All @@ -22,7 +23,7 @@ interface BaroErrorType {
}

instance.interceptors.request.use((config) => {
const accessToken = localStorage.getItem('accessToken');
const accessToken = localStorage.getItem(STORAGE_KEY.ACCESS_TOKEN);
config.headers.Authorization = `Bearer ${accessToken}`;
return config;
});
Expand All @@ -48,7 +49,7 @@ instance.interceptors.response.use(
const tokenRefreshCondition = ['JW01', 'JW02'];

if (tokenRefreshCondition.includes(error.response.data.errorCode)) {
const prevRefreshToken = Cookies.get('refreshToken') as string;
const prevRefreshToken = Cookies.get(STORAGE_KEY.REFRESH_TOKEN) as string;

const { accessToken, refreshToken } =
(await getRenewToken(prevRefreshToken)) || {};
Expand Down
5 changes: 3 additions & 2 deletions src/components/Layout/components/ProfileButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { type MyProfile } from '@api/members/types';
import Dropdown from '@components/Dropdown';
import Icon from '@components/Icon';
import { ROUTES } from '@constants/routes';
import { STORAGE_KEY } from '@models/storage';

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

Expand All @@ -16,8 +17,8 @@ const ProfileButton = () => {
const data = queryClient.getQueryData<MyProfile>(['my-profile']);

const handleLogoutClick = () => {
localStorage.removeItem('accessToken');
Cookies.remove('refreshToken');
localStorage.removeItem(STORAGE_KEY.ACCESS_TOKEN);
Cookies.remove(STORAGE_KEY.REFRESH_TOKEN);
router.push(ROUTES.LANDING);
};

Expand Down
3 changes: 2 additions & 1 deletion src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type PropsWithChildren, useEffect, useState } from 'react';
import { assignInlineVars } from '@vanilla-extract/dynamic';

import { type HeaderType } from '@models/layout';
import { STORAGE_KEY } from '@models/storage';
import { COLORS } from '@styles/tokens';

import Footer from './components/Footer';
Expand All @@ -23,7 +24,7 @@ const Layout = ({
const [type, setType] = useState<HeaderType>('intro');

useEffect(() => {
const accessToken = localStorage?.getItem('accessToken');
const accessToken = localStorage?.getItem(STORAGE_KEY.ACCESS_TOKEN);
const headerType = accessToken ? 'normal' : 'intro';
setType(headerType);
}, []);
Expand Down
83 changes: 56 additions & 27 deletions src/components/Modal/modals/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,38 @@ import Button from '@components/Button';
import Icon from '@components/Icon';
import ModalContainer from '@components/Modal/components/ModalContainer';
import { ROUTES } from '@constants/routes';
import { STORAGE_KEY } from '@models/storage';
import useLogin from '@queries/useLogin';

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

const buttons = [
{
type: 'google',
name: '구글',
wrapperClassName: styles.googleLogin,
iconClassName: styles.googleIcon,
iconWidth: 18,
iconHeight: 18,
},
{
type: 'naver',
name: '네이버',
wrapperClassName: styles.naverLogin,
iconClassName: styles.naverIcon,
iconWidth: 15,
iconHeight: 14,
},
{
type: 'kakao',
name: '카카오',
wrapperClassName: styles.kakaoLogin,
iconClassName: styles.kakaoIcon,
iconWidth: 19,
iconHeight: 18,
},
] as const;

const Login = () => {
const { mutateAsync } = useLogin();

Expand All @@ -20,6 +48,8 @@ const Login = () => {
window.location.href = data.url;
};

const recentLoginType = localStorage.getItem(STORAGE_KEY.RECENT_LOGIN_TYPE);

return (
<ModalContainer type="login">
<div className={styles.helloImage}>
Expand All @@ -34,33 +64,32 @@ const Login = () => {
</span>
</div>
<div className={styles.loginButtonsWrapper}>
<Button
className={styles.googleLogin}
onClick={handleSocialLoginClick('google')}
>
<div className={styles.googleIcon}>
<Icon icon="google" width={18} height={18} />
</div>
구글로 로그인하기
</Button>
<Button
className={styles.naverLogin}
onClick={handleSocialLoginClick('naver')}
>
<div className={styles.naverIcon}>
<Icon icon="naver" width={15} height={14} />
</div>
네이버로 로그인하기
</Button>
<Button
className={styles.kakaoLogin}
onClick={handleSocialLoginClick('kakao')}
>
<div className={styles.kakaoIcon}>
<Icon icon="kakao" width={19} height={18} />
</div>
카카오로 로그인하기
</Button>
{buttons.map(
({
type,
name,
wrapperClassName,
iconClassName,
iconWidth,
iconHeight,
}) => (
<Button
key={type}
className={wrapperClassName({ recent: recentLoginType === type })}
onClick={handleSocialLoginClick(type)}
>
<div className={iconClassName}>
<Icon icon={type} width={iconWidth} height={iconHeight} />
</div>
{name}로 로그인하기
{recentLoginType === type && (
<span className={styles.recentLoginMessage}>
마지막으로 로그인했어요!
</span>
)}
</Button>
),
)}
</div>
<div className={styles.agreeDescription}>
로그인은&nbsp;
Expand Down
66 changes: 50 additions & 16 deletions src/components/Modal/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,41 +156,75 @@ const loginButton = style([
},
]);

export const googleLogin = style([
loginButton,
export const recentLoginMessage = style([
sprinkles({
typography: '11/Caption/Regular',
}),
{
color: COLORS['Grey/800'],
backgroundColor: COLORS['Grey/100'],
marginTop: '-3px',
display: 'block',
},
]);

export const googleLogin = recipe({
base: [
loginButton,
{
color: COLORS['Grey/800'],
backgroundColor: COLORS['Grey/100'],
},
],
variants: {
recent: {
true: { padding: '12.5px 40px' },
false: { padding: '20px 40px' },
},
},
});

export const googleIcon = style({
display: 'inline-block',
verticalAlign: '-4px',
marginRight: '9px',
});

export const naverLogin = style([
loginButton,
{
color: COLORS['Grey/White'],
backgroundColor: '#03c75a',
export const naverLogin = recipe({
base: [
loginButton,
{
color: COLORS['Grey/White'],
backgroundColor: '#03c75a',
},
],
variants: {
recent: {
true: { padding: '12.5px 40px' },
false: { padding: '20px 40px' },
},
},
]);
});

export const naverIcon = style({
display: 'inline-block',
verticalAlign: '-1px',
marginRight: '6px',
});

export const kakaoLogin = style([
loginButton,
{
color: COLORS['Grey/800'],
backgroundColor: '#fee502',
export const kakaoLogin = recipe({
base: [
loginButton,
{
color: COLORS['Grey/800'],
backgroundColor: '#fee502',
},
],
variants: {
recent: {
true: { padding: '12.5px 40px' },
false: { padding: '20px 40px' },
},
},
]);
});

export const kakaoIcon = style({
display: 'inline-block',
Expand Down
5 changes: 5 additions & 0 deletions src/models/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const STORAGE_KEY = {
ACCESS_TOKEN: 'accessToken',
REFRESH_TOKEN: 'refreshToken',
RECENT_LOGIN_TYPE: 'recentLoginType',
} as const;
6 changes: 4 additions & 2 deletions src/utils/token.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import Cookies from 'js-cookie';

import { STORAGE_KEY } from '@models/storage';

interface SaveTokenParams {
accessToken: string;
refreshToken: string;
}

export const saveToken = ({ accessToken, refreshToken }: SaveTokenParams) => {
localStorage.setItem('accessToken', accessToken);
Cookies.set('refreshToken', refreshToken);
localStorage.setItem(STORAGE_KEY.ACCESS_TOKEN, accessToken);
Cookies.set(STORAGE_KEY.REFRESH_TOKEN, refreshToken);
};

0 comments on commit d571cab

Please sign in to comment.