Skip to content

Commit

Permalink
Merge pull request #115 from fcstudy-project/feature/refactor-firebas…
Browse files Browse the repository at this point in the history
…e-to-s3

Refactor: 전반적인 코드 수정
  • Loading branch information
Lee JaeJun authored Feb 1, 2024
2 parents 8b8aa09 + e5e0bea commit 9260f58
Show file tree
Hide file tree
Showing 51 changed files with 3,649 additions and 365 deletions.
3,321 changes: 3,227 additions & 94 deletions package-lock.json

Large diffs are not rendered by default.

19 changes: 5 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,17 @@
"dependencies": {
"@tanstack/react-query": "^5.0.0",
"@tanstack/react-query-devtools": "^5.14.1",
"@tiptap/extension-blockquote": "^2.1.11",
"@tiptap/extension-bold": "^2.1.11",
"@tiptap/extension-bullet-list": "^2.1.11",
"@tiptap/extension-code-block": "^2.1.11",
"@tiptap/extension-color": "^2.1.11",
"@tiptap/extension-document": "^2.1.11",
"@tiptap/extension-hard-break": "^2.1.11",
"@tiptap/extension-heading": "^2.1.11",
"@tiptap/extension-history": "^2.1.11",
"@tiptap/extension-horizontal-rule": "^2.1.11",
"@tiptap/extension-image": "^2.1.11",
"@tiptap/extension-italic": "^2.1.11",
"@tiptap/extension-list-item": "^2.1.11",
"@tiptap/extension-ordered-list": "^2.1.11",
"@tiptap/extension-paragraph": "^2.1.11",
"@tiptap/extension-placeholder": "^2.1.11",
"@tiptap/extension-strike": "^2.1.11",
"@tiptap/extension-text": "^2.1.11",
"@tiptap/extension-text-style": "^2.1.11",
"@tiptap/extension-underline": "^2.1.11",
"@tiptap/pm": "^2.1.11",
"@tiptap/extension-underline": "^2.2.1",
"@tiptap/react": "^2.1.11",
"@tiptap/starter-kit": "^2.1.11",
"aws-sdk": "^2.1532.0",
"axios": "^1.5.0",
"classnames": "^2.3.2",
"cors": "^2.8.5",
Expand All @@ -45,7 +33,9 @@
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.12",
"react-hook-form": "^7.46.1",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.11.0",
"react-image-file-resizer": "^0.4.8",
"react-loading-skeleton": "^3.3.1",
"react-router-dom": "^6.16.0",
"recoil": "^0.7.7",
Expand All @@ -54,6 +44,7 @@
"vercel": "^32.5.2"
},
"devDependencies": {
"@svgr/rollup": "^8.1.0",
"@types/classnames": "^2.3.1",
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
Expand Down
2 changes: 1 addition & 1 deletion src/api/apiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export const API_VERSION = '/api/v2';

export const ENDPOINTS = {
articles: `${API_VERSION}/articles`,
login: `/api/v1/login`,
login: import.meta.env.DEV ? `${API_VERSION}/login` : `/api/v1/login`,
refreshToken: `${API_VERSION}/refresh`,
members: `/api/v1/members`,
comments: `/api/v1/comments`,
Expand Down
53 changes: 46 additions & 7 deletions src/api/authApi.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,62 @@
import { instance } from './client';
type RefreshTokenData = {
import axios from 'axios';
import { ENDPOINTS } from './apiConfig';
interface RefreshTokenData {
token: {
accessToken: string;
refreshToken: string;
};
};
}

type RefreshTokenResponse = {
interface RefreshTokenResponse {
code: number;
data: RefreshTokenData;
};
}

interface SignInRequestBody {
email: string;
password: string;
}

interface SignInResponseData {
code: number;
message: string;
data: {
member: {
memberId: number;
email: string;
nickname: string;
image: string;
};
token: {
grantType: string;
accessToken: string;
accessTokenExpiresIn: number;
refreshToken: string;
};
};
}

const authInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
},
});

export const getNewAccessToken = async (accessToken: string, refreshToken: string) => {
const response = await instance.post<RefreshTokenResponse>(
'/api/v2/refresh',
const response = await authInstance.post<RefreshTokenResponse>(
`${ENDPOINTS.refreshToken}`,
{ accessToken, refreshToken },
{
headers: { Authorization: `Bearer ${refreshToken}` },
}
);
return response.data;
};

export const userSignIn = async (data: SignInRequestBody) => {
const response = await authInstance.post<SignInResponseData>(`${ENDPOINTS.login}`, data);

return response.data;
};
33 changes: 22 additions & 11 deletions src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from '@/components/signIn/utils/getToken';
import axios from 'axios';
import { getNewAccessToken } from './authApi';
import toast from 'react-hot-toast';

export const instance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
Expand Down Expand Up @@ -32,27 +33,37 @@ instance.interceptors.response.use(
async (error) => {
const {
config,
response: { status },
response: { status, data },
} = error;

if (status === 403 || status === 401) {
const originalRequest = config;
const { accessToken, refreshToken } = getTokenFromLocalStorage();

if (accessToken && refreshToken) {
const { data, code } = await getNewAccessToken(accessToken, refreshToken);
if (code === 200) {
const { accessToken: newAccessToken, refreshToken: newRefreshToken } = data.token;
setTokenToLocalStorage(newAccessToken, newRefreshToken);
axios.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
originalRequest.headers.authorization = `Bearer ${newAccessToken}`;

return axios(originalRequest);
try {
const { data, code } = await getNewAccessToken(accessToken, refreshToken);
if (code === 200) {
const { accessToken: newAccessToken, refreshToken: newRefreshToken } = data.token;
setTokenToLocalStorage(newAccessToken, newRefreshToken);
axios.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
originalRequest.headers.authorization = `Bearer ${newAccessToken}`;

return axios(originalRequest);
}
} catch (error) {
// TODO: 토스트 한 번만 뜨게하기, 리다이렉트 효과적으로 처리할 방법
toast.error('접근 권한이 없습니다.');
}
}
// TODO: 리프레시 토큰 기한이 만료되었을 때
// 리프레시 토큰이 없거나 만료되었을 때
if (data.path.startsWith('/api/v2/articles')) {
toast.error('접근 권한이 없습니다.');
return Promise.reject(error);
}
toast.error('다시 로그인 해주세요.');
return Promise.reject(error);
}

return Promise.reject(error);
}
);
2 changes: 1 addition & 1 deletion src/assets/icons/check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icons/heart_filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/heart_lined.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icons/pen_square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 7 additions & 5 deletions src/components/atoms/button/Button.module.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@use '@/styles/abstracts/variables' as v;

.button {
display: flex;
justify-content: center;
Expand All @@ -8,21 +10,21 @@
border-radius: 4px;

font-weight: 400;
font-size: $text-sm;
font-size: v.$text-sm;

color: #fff;
background-color: #f8607a;
transition: background-color 0.2s ease;

&.secondary {
color: $gray;
color: v.$gray;
background-color: #fff;
border: 1px solid $gray;
border: 1px solid v.$gray;

&:hover {
color: $black;
color: v.$black;
background-color: #fff;
border: 1px solid $black;
border: 1px solid v.$black;
}
}
}
48 changes: 25 additions & 23 deletions src/components/atoms/button/index.module.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@use '@/styles/abstracts/variables' as v;

@function next-color($current-index) {
$keys: map-keys($red-list);
$currentIndex: index($keys, $current-index);
Expand All @@ -9,11 +11,11 @@
}

$red-list: (
'100': $red-100,
'200': $red-200,
'300': $red-300,
'400': $red-400,
'500': $red-500,
'100': v.$red-100,
'200': v.$red-200,
'300': v.$red-300,
'400': v.$red-400,
'500': v.$red-500,
);

button {
Expand All @@ -23,66 +25,66 @@ button {
}

@mixin tag-red-style($bgColor) {
color: $white;
color: v.$white;
background-color: $bgColor;
padding: 8px 12px;
border-radius: 50px;
font-size: $text-xs;
font-size: v.$text-xs;
}

@mixin round-red-style($bgColor) {
color: $white;
color: v.$white;
background-color: $bgColor;
padding: 4px 16px;
border-radius: 50px;
font-size: $text-sm;
font-size: v.$text-sm;
transition: all 0.3s;

&:disabled {
color: $gray;
background-color: $light-gray;
color: v.$gray;
background-color: v.$light-gray;
padding: 4px 16px;
}
}

@mixin default-red-style($bgColor) {
color: $white;
color: v.$white;
background-color: $bgColor;
padding: 6px 16px;
font-size: $text-sm;
font-size: v.$text-sm;
transition: all 0.3s;

&:disabled {
color: $gray;
background-color: $light-gray;
color: v.$gray;
background-color: v.$light-gray;
padding: 6px 16px;
}
}

@mixin large-red-style($bgColor) {
color: $white;
color: v.$white;
background-color: $bgColor;
padding: 12px 32px;
font-size: $text-sm;
font-size: v.$text-sm;
transition: all 0.3s;

&:disabled {
color: $gray;
background-color: $light-gray;
color: v.$gray;
background-color: v.$light-gray;
padding: 12px 32px;
}
}

@mixin compact-red-style($bgColor) {
color: $white;
color: v.$white;
background-color: $bgColor;
padding: 12px 32px;
font-size: $text-sm;
font-size: v.$text-sm;
transition: all 0.3s;

&:disabled {
color: $gray;
background-color: $light-gray;
color: v.$gray;
background-color: v.$light-gray;
padding: 12px 32px;
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/components/atoms/flex/index.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
@use '@/styles/abstracts/mixins' as m;

.flex {
@include flex-center;
@include m.flex-center;
gap: var(--gap);

&.column {
Expand Down
4 changes: 2 additions & 2 deletions src/components/atoms/input/InputIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BsCheck2 } from 'react-icons/bs';
import { ReactComponent as Check } from '@/assets/icons/check.svg';

interface Props {
isValid: boolean;
Expand All @@ -8,7 +8,7 @@ interface Props {
const InputIcon = ({ isValid, type }: Props) => {
switch (type) {
case 'defaultInput':
return isValid && <BsCheck2 fill="#2273ed" />;
return isValid && <Check />;
default:
return null;
}
Expand Down
Loading

0 comments on commit 9260f58

Please sign in to comment.