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

시간표 페이지 퍼블리싱 #36

Merged
merged 47 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
d4f346c
chore(package): moment 라이브러리 추가
Ubinquitous Jul 19, 2023
44b2d2e
refactor(schedule): schedule에서 calender로 라우터명 변경
Ubinquitous Jul 19, 2023
46007be
feat(timetable): 시간표 페이지 퍼블리싱
Ubinquitous Jul 19, 2023
f446ead
feat(atoms): custom select 컴포넌트 생성
Ubinquitous Jul 19, 2023
4aadf8d
feat(hooks): useDate hook 추가 (추후 기능 추가 예정)
Ubinquitous Jul 19, 2023
23ef4c2
chore(assets): down arrow svg 모듈로 추가
Ubinquitous Jul 19, 2023
4072f48
chore(timetable bar): 시간표 막대 움직이는 기능 구현
Ubinquitous Jul 19, 2023
f71079c
chore(timetable box): 시간표 컴포넌트 퍼블리싱, 추후 데이터 파싱 필요
Ubinquitous Jul 19, 2023
aae5572
feat(apis): 예외처리 함수 추가
Ubinquitous Jul 20, 2023
06dd18c
chore(httpClient): postInQuery method 추가
Ubinquitous Jul 20, 2023
bc61526
refactor(constant): constant type 선언, upper 리네이밍
Ubinquitous Jul 20, 2023
0a99f23
feat(oauth): 로그인 처리 페이지 퍼블리싱
Ubinquitous Jul 20, 2023
98514c5
chore(assets): loading gif 추가
Ubinquitous Jul 20, 2023
9b521d4
feat(api): oauth httpClient 세팅
Ubinquitous Jul 20, 2023
2d2b1a4
chore(httpClient): default import 세팅
Ubinquitous Jul 20, 2023
32b2a3f
feat(service): 로그인 관련 로직 세팅
Ubinquitous Jul 20, 2023
5405a85
refactor(httpClient): any 사용 지양
Ubinquitous Jul 20, 2023
5dd73ad
refactor(constant): token constant 사용
Ubinquitous Jul 20, 2023
c5b2ee1
refactor(httpClient): index 파일 이름 변경
Ubinquitous Jul 20, 2023
a8b8870
refactor(imageWithFallback): 기존 Image props도 받게함
Ubinquitous Jul 20, 2023
a2d95a2
chore(aside): user api 연결 및 값 제공, 조건부 렌더링
Ubinquitous Jul 20, 2023
8e098e3
chore(infomation box): 유저 api값 공급
Ubinquitous Jul 20, 2023
b44bcad
chore(assets): icons 하위로 디렉터리 이동
Ubinquitous Jul 20, 2023
46791a1
chore(assets): default profile 이미지 추가
Ubinquitous Jul 20, 2023
19903b3
chore(key): 리애트 쿼리 키 추가
Ubinquitous Jul 20, 2023
a922cb0
chore(router): mypage router 추가
Ubinquitous Jul 20, 2023
7220dca
chore(user): 유저 권한 키 추가
Ubinquitous Jul 20, 2023
ec0ac58
feat(helper): profileMaker 추가
Ubinquitous Jul 20, 2023
0829bd3
chore(modalStore): modal type 선언
Ubinquitous Jul 20, 2023
8dbcc2d
refactor(type): .type.ts로 모듈명 통일
Ubinquitous Jul 20, 2023
88c2759
chore(type): user type 지정
Ubinquitous Jul 20, 2023
7c390c6
feat(hooks): useModal 훅 선언
Ubinquitous Jul 20, 2023
28172ac
feat(hooks): useUser 훅 선언
Ubinquitous Jul 20, 2023
6a31c1b
feat(hooks): useWindow 훅 선언
Ubinquitous Jul 20, 2023
7758ca6
fix(adaptors): 디렉터리 내 adaptors 삭제 ( import 충돌 우려 )
Ubinquitous Jul 20, 2023
b5540cb
refactor(assets): SVG import 경로 수정
Ubinquitous Jul 20, 2023
ee77ac4
refactor(assets): image import 경로 수정
Ubinquitous Jul 20, 2023
1f2c774
fix(httpClient): adaptors 삭제 후 /apis로 직접 import
Ubinquitous Jul 20, 2023
3f9037b
refactor(assets): SVG import 경로 수정
Ubinquitous Jul 20, 2023
8adf374
chore(store): modalStore 선언
Ubinquitous Jul 20, 2023
5084427
chore(store): userStore 선언
Ubinquitous Jul 20, 2023
71ba888
fix(user): Student type으로 useQuery 타입 변경
Ubinquitous Jul 20, 2023
82523e7
feat(assets): 방향 회전 가능한 arrow 컴포넌트 추가
Ubinquitous Jul 21, 2023
9d7fd63
refactor(package): moment.js에서 day.js로 라이브러리 대체
Ubinquitous Jul 21, 2023
bc9b1bf
refactor(assets): svg 컴포넌트화
Ubinquitous Jul 21, 2023
829a152
refactor(assets): svg 컴포넌트화
Ubinquitous Jul 21, 2023
1c2d411
chore(listitem): svg 경로 변경
Ubinquitous Jul 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@typescript-eslint/eslint-plugin": "^5.43.0",
"axios": "^1.4.0",
"babel-plugin-styled-components": "^2.1.4",
"dayjs": "^1.11.9",
"dotenv": "^16.3.1",
"eslint": "^8.26.0",
"eslint-config-next": "13.0.0",
Expand Down
17 changes: 17 additions & 0 deletions src/apis/error/throwAxiosError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { isAxiosError } from "axios";

const throwAxiosError = (err: unknown) => {
if (!isAxiosError(err))
return {
data: "",
status: "",
message: "",
};

const data = err?.response?.data;
const { code, status, message } = data;

return { code, message, status };
};

export default throwAxiosError;
142 changes: 142 additions & 0 deletions src/apis/httpClient/httpClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { requestInterceptors, responseInterceptors } from "@/apis/interceptor";
import Storage from "@/apis/storage";
import refreshToken from "@/apis/token/refreshToken";
import TOKEN from "@/global/constants/token.constant";

export interface HttpClientConfig {
baseURL?: string;
timeout?: number;
headers?: { Authorization?: string };
}

export class HttpClient {
private api: AxiosInstance;

private static clientConfig: HttpClientConfig;

constructor(url: string, axiosConfig: HttpClientConfig) {
this.api = axios.create({
...axiosConfig,
baseURL: `${axiosConfig.baseURL}${url}`,
});
HttpClient.clientConfig = { headers: { Authorization: "" } };
this.setting();
}

get(requestConfig?: AxiosRequestConfig) {
return this.api.get("", { ...HttpClient.clientConfig, ...requestConfig });
}

getById(requestConfig?: AxiosRequestConfig) {
return this.api.get("/:id", {
...HttpClient.clientConfig,
...requestConfig,
});
}

getByTitle(url: string, requestConfig?: AxiosRequestConfig) {
return this.api.get(`/${url}`, {
...HttpClient.clientConfig,
...requestConfig,
});
}

getInQuery(
param: string,
data: string | number,
requestConfig?: AxiosRequestConfig,
) {
return this.api.get(`?${param}=${data}`, {
...HttpClient.clientConfig,
...requestConfig,
});
}

post(data: unknown, requestConfig?: AxiosRequestConfig) {
return this.api.post("", data, {
...HttpClient.clientConfig,
...requestConfig,
});
}

postInQuery(
param: string,
data: unknown,
requestConfig?: AxiosRequestConfig,
) {
return this.api.post(`?${param}=${data}`, {
...HttpClient.clientConfig,
...requestConfig,
});
}

put(data: unknown, requestConfig?: AxiosRequestConfig) {
return this.api.put("", data, {
...HttpClient.clientConfig,
...requestConfig,
});
}

putByTitle(title: string, data: unknown, requestConfig?: AxiosRequestConfig) {
return this.api.put(`/${title}`, data, {
...HttpClient.clientConfig,
...requestConfig,
});
}

delete(requestConfig?: AxiosRequestConfig) {
return this.api.delete("", {
...HttpClient.clientConfig,
...requestConfig,
});
}

deleteById(id: number, requestConfig?: AxiosRequestConfig) {
return this.api.delete(`/${id}`, {
...HttpClient.clientConfig,
...requestConfig,
});
}

private setting() {
HttpClient.setCommonInterceptors(this.api);
// const queryClient = new QueryClient();

this.api.interceptors.response.use(
(response) => response,
(error) => {
// queryClient.invalidateQueries("getUser");
refreshToken();
return Promise.reject(error);
},
);
}

static setAccessToken() {
const accessToken = Storage.getItem(TOKEN.ACCESS);
HttpClient.clientConfig.headers = {
...HttpClient.clientConfig.headers,
Authorization: accessToken || undefined,
};
}

static removeAccessToken() {
Storage.setItem(TOKEN.ACCESS, "");
}

private static setCommonInterceptors(instance: AxiosInstance) {
instance.interceptors.request.use(requestInterceptors as never);
instance.interceptors.response.use(responseInterceptors);
}
}

export const axiosConfig: HttpClientConfig = {
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
timeout: 10000,
};

export default {
oauth: new HttpClient("api/auth/oauth/bsm", axiosConfig),
user: new HttpClient("api/user", axiosConfig),
};
130 changes: 2 additions & 128 deletions src/apis/httpClient/index.ts
Original file line number Diff line number Diff line change
@@ -1,129 +1,3 @@
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { requestInterceptors, responseInterceptors } from "@/apis/interceptor";
import Storage from "@/apis/storage";
import refreshToken from "@/apis/token/refreshToken";
import { QueryClient } from "react-query";
import httpClient from "./httpClient";

export interface HttpClientConfig {
baseURL?: string;
timeout?: number;
headers?: { Authorization?: string };
}

export class HttpClient {
private api: AxiosInstance;

private static clientConfig: HttpClientConfig;

constructor(url: string, axiosConfig: HttpClientConfig) {
this.api = axios.create({
...axiosConfig,
baseURL: `${axiosConfig.baseURL}${url}`,
});
HttpClient.clientConfig = { headers: { Authorization: "" } };
this.setting();
}

get(requestConfig?: AxiosRequestConfig) {
return this.api.get("", { ...HttpClient.clientConfig, ...requestConfig });
}

getById(requestConfig?: AxiosRequestConfig) {
return this.api.get("/:id", {
...HttpClient.clientConfig,
...requestConfig,
});
}

getByTitle(url: string, requestConfig?: AxiosRequestConfig) {
return this.api.get(`/${url}`, {
...HttpClient.clientConfig,
...requestConfig,
});
}

getInQuery(
param: string,
data: string | number,
requestConfig?: AxiosRequestConfig,
) {
return this.api.get(`?${param}=${data}`, {
...HttpClient.clientConfig,
...requestConfig,
});
}

post(data: unknown, requestConfig?: AxiosRequestConfig) {
return this.api.post("", data, {
...HttpClient.clientConfig,
...requestConfig,
});
}

put(data: unknown, requestConfig?: AxiosRequestConfig) {
return this.api.put("", data, {
...HttpClient.clientConfig,
...requestConfig,
});
}

putByTitle(title: string, data: unknown, requestConfig?: AxiosRequestConfig) {
return this.api.put(`/${title}`, data, {
...HttpClient.clientConfig,
...requestConfig,
});
}

delete(requestConfig?: AxiosRequestConfig) {
return this.api.delete("", {
...HttpClient.clientConfig,
...requestConfig,
});
}

deleteById(id: number, requestConfig?: AxiosRequestConfig) {
return this.api.delete(`/${id}`, {
...HttpClient.clientConfig,
...requestConfig,
});
}

private setting() {
HttpClient.setCommonInterceptors(this.api);
const queryClient = new QueryClient();

this.api.interceptors.response.use(
(response) => response,
(error) => {
// const { status, code } = error.response.data
// if (status === 403 && code === exception.code.TOKEN_403_3) Storage.delItem('refresh_token')
Storage.delItem("access_token");
queryClient.invalidateQueries("getUser");
refreshToken();
return Promise.reject(error);
},
);
}

static setAccessToken() {
const accessToken = Storage.getItem("access_token");
HttpClient.clientConfig.headers = {
...HttpClient.clientConfig.headers,
Authorization: accessToken || undefined,
};
}

static removeAccessToken() {
Storage.setItem("access_token", "");
}

private static setCommonInterceptors(instance: AxiosInstance) {
instance.interceptors.request.use(requestInterceptors as any);
instance.interceptors.response.use(responseInterceptors);
}
}

export const axiosConfig: HttpClientConfig = {
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
timeout: 10000,
};
export default httpClient;
9 changes: 5 additions & 4 deletions src/apis/interceptor/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Storage from "@/apis/storage";
import { AxiosRequestConfig, AxiosResponse } from "axios";
import refreshToken from "@/apis/token/refreshToken";
import exception from "@/global/constants/exception.constant";
import ERROR from "@/global/constants/error.constant";
import TOKEN from "@/global/constants/token.constant";

export const requestInterceptors = (requestConfig: AxiosRequestConfig) => {
if (!Storage.getItem("access_token") && Storage.getItem("refresh_token"))
if (!Storage.getItem(TOKEN.ACCESS) && Storage.getItem(TOKEN.REFRESH))
refreshToken();

if (requestConfig.headers) {
requestConfig.headers.Authorization = Storage.getItem("access_token");
requestConfig.headers.Authorization = Storage.getItem(TOKEN.ACCESS);
}

const urlParams = requestConfig.url?.split("/:") || [];
Expand All @@ -31,7 +32,7 @@ export const requestInterceptors = (requestConfig: AxiosRequestConfig) => {
};

export const responseInterceptors = (originalResponse: AxiosResponse) => {
if (originalResponse.status !== exception.status.SUCCESS) refreshToken();
if (originalResponse.status !== ERROR.STATUS.SUCCESS) refreshToken();

return {
...originalResponse,
Expand Down
8 changes: 5 additions & 3 deletions src/apis/token/refreshToken.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import axios from "axios";
import Storage from "@/apis/storage";
import TOKEN from "@/global/constants/token.constant";

const refreshToken = async () => {
// fix 필요
try {
const res = (
await axios.put("/auth/refresh/access", {
refresh_token: Storage.getItem("refresh_token"),
refresh_token: Storage.getItem(TOKEN.REFRESH),
})
).data;
Storage.setItem("access_token", res.accessToken);
Storage.setItem(TOKEN.ACCESS, res.accessToken);
} catch (err) {
Storage.delItem("refresh_token");
Storage.delItem(TOKEN.REFRESH);
}
};

Expand Down
9 changes: 9 additions & 0 deletions src/app/calender/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client";

import CalenderPage from "@/page/calender";

const Calender = () => {
return <CalenderPage />;
};

export default Calender;
9 changes: 9 additions & 0 deletions src/app/oauth/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client";

import OAuthPage from "@/page/oauth";

const OAuth = () => {
return <OAuthPage />;
};

export default OAuth;
9 changes: 0 additions & 9 deletions src/app/schedule/page.tsx

This file was deleted.

9 changes: 9 additions & 0 deletions src/app/timetable/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use client";

import TimeTablePage from "@/page/timetable";

const TimeTable = () => {
return <TimeTablePage />;
};

export default TimeTable;
Loading