Skip to content

Commit e6d0cb7

Browse files
Merge pull request #43 from sparcs-kaist/chore/ServiceLayer
Post Api
2 parents b7793cc + 546b242 commit e6d0cb7

File tree

3 files changed

+210
-29
lines changed

3 files changed

+210
-29
lines changed

src/lib/api/board.ts

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,8 @@ type Filter = {
88
};
99

1010
type ArticleQuery = {
11-
boardId?: number | number[];
12-
topicId?: number;
13-
username?: string;
14-
query?: string;
15-
ordering?: string;
16-
page?: number;
17-
pageSize?: number;
11+
boardId?: number | number[]; topicId?: number; username?: string;
12+
query?: string; ordering?: string; page?: number; pageSize?: number;
1813
filter?: Filter;
1914
};
2015

@@ -50,29 +45,38 @@ function buildArticleParams(params: ArticleQuery): Record<string, QueryValue> {
5045
}
5146

5247
//게시판 리스트 가져오기
53-
export const fetchBoardList = () =>
54-
http.get('boards/').then(({ data }) => data);
48+
export const fetchBoardList = async () => {
49+
const { data } = await http.get('boards/');
50+
return data;
51+
};
5552

5653
//게시판 그룹 정보 가져오기
57-
export const fetchBoardGroups = () =>
58-
http.get('board_groups/').then(({ data }) => data);
54+
export const fetchBoardGroups = async () => {
55+
const { data } = await http.get('board_groups/');
56+
return data;
57+
};
5958

6059
//일반 게시글 목록 조회
61-
export const fetchArticles = (params: ArticleQuery = {}) =>
62-
http.get(`articles/?${queryBuilder(buildArticleParams(params))}`).then(({ data }) => data);
60+
export const fetchArticles = async (params: ArticleQuery = {}) => {
61+
const { data } = await http.get(`articles/?${queryBuilder(buildArticleParams(params))}`);
62+
return data;
63+
};
6364

6465
//추천 게시글 (top) 목록 조회
65-
export const fetchTopArticles = (params: ArticleQuery = {}) =>
66-
http.get(`articles/top/?${queryBuilder(buildArticleParams(params))}`).then(({ data }) => data);
66+
export const fetchTopArticles = async (params: ArticleQuery = {}) => {
67+
const { data } = await http.get(`articles/top/?${queryBuilder(buildArticleParams(params))}`);
68+
return data;
69+
};
6770

6871
//Scrap 목록 조회
69-
export const fetchArchives = (params: { query?: string; page?: number; pageSize?: number } = {}) => {
72+
export const fetchArchives = async (params: { query?: string; page?: number; pageSize?: number } = {}) => {
7073
const context: Record<string, QueryValue> = {};
7174
if (params.query) context.main_search__contains = params.query;
7275
if (params.page) context.page = params.page;
7376
if (params.pageSize) context.page_size = params.pageSize;
7477

75-
return http.get(`scraps/?${queryBuilder(context)}`).then(({ data }) => data);
78+
const { data } = await http.get(`scraps/?${queryBuilder(context)}`);
79+
return data;
7680
};
7781

7882
// Todo : parent_article type issue 해결하기
@@ -87,13 +91,14 @@ export const fetchArchivedPosts = async (params?: Parameters<typeof fetchArchive
8791
};
8892

8993
//최근 본 게시글 조회
90-
export const fetchRecentViewedPosts = (params: { query?: string; page?: number; pageSize?: number } = {}) => {
94+
export const fetchRecentViewedPosts = async (params: { query?: string; page?: number; pageSize?: number } = {}) => {
9195
const context: Record<string, QueryValue> = {};
9296
if (params.query) context.main_search__contains = params.query;
9397
if (params.page) context.page = params.page;
9498
if (params.pageSize) context.page_size = params.pageSize;
9599

96-
return http.get(`articles/recent/?${queryBuilder(context)}`).then(({ data }) => data);
100+
const { data } = await http.get(`articles/recent/?${queryBuilder(context)}`);
101+
return data;
97102
};
98103

99104
// Todo : 주석 달기
@@ -105,7 +110,7 @@ type BoardQuery = {
105110
order?: string;
106111
};
107112

108-
function buildBoardQuery({ boardId, ...params }: BoardQuery, status = 3) {
113+
async function buildBoardQuery({ boardId, ...params }: BoardQuery, status = 3) {
109114
const context: Record<string, QueryValue> = {
110115
school_response_status: status,
111116
};
@@ -115,24 +120,27 @@ function buildBoardQuery({ boardId, ...params }: BoardQuery, status = 3) {
115120
if (params.pageSize) context.page_size = params.pageSize;
116121
if (params.order) context.order = params.order;
117122

118-
return http.get(`board/${boardId}?${queryBuilder(context)}`).then(({ data }) => data);
123+
const { data } = await http.get(`board/${boardId}?${queryBuilder(context)}`);
124+
return data;
119125
}
120126

121-
export const fetchAnsweredPostinTimeOrder = (params: BoardQuery) =>
127+
export const fetchAnsweredPostinTimeOrder = async (params: BoardQuery) =>
122128
buildBoardQuery(params);
123129

124-
export const fetchUnansweredPostinTimeOrder = (params: BoardQuery) =>
130+
export const fetchUnansweredPostinTimeOrder = async (params: BoardQuery) =>
125131
buildBoardQuery(params);
126132

127-
export const fetchAnsweredPostinPositiveOrder = (params: BoardQuery) =>
133+
export const fetchAnsweredPostinPositiveOrder = async (params: BoardQuery) =>
128134
buildBoardQuery({ ...params, order: 'article__positive_vote_count' });
129135

130-
export const fetchUnansweredPostinPositiveOrder = (params: BoardQuery) =>
136+
export const fetchUnansweredPostinPositiveOrder = async (params: BoardQuery) =>
131137
buildBoardQuery({ ...params, order: 'article__positive_vote_count' });
132138

133-
export const fetchAllPostinPositiveOrder = (params: BoardQuery) =>
139+
export const fetchAllPostinPositiveOrder = async (params: BoardQuery) =>
134140
buildBoardQuery({ ...params, order: 'article__positive_vote_count' });
135141

136142
//신고 목록 조회
137-
export const fetchReports = () =>
138-
http.get('reports/').then(({ data }) => data);
143+
export const fetchReports = async () => {
144+
const { data } = await http.get('reports/');
145+
return data;
146+
};

src/lib/api/post.ts

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import http from '@/lib/api/http';
2+
import { queryBuilder } from '@/lib/utils/queryBuilder';
3+
4+
type VoteAction = 'vote_cancel' | 'vote_negative' | 'vote_positive';
5+
6+
// 게시글 단건 조회 (context에 vote action을 넣으면 해당 액션 경로 호출)
7+
export const fetchPost = async ({
8+
postId,
9+
context,
10+
}: {
11+
postId: number;
12+
context?: VoteAction;
13+
}) => {
14+
const url = context
15+
? `articles/${postId}/${context}/`
16+
: `articles/${postId}/`;
17+
const { data } = await http.get(url);
18+
return data;
19+
};
20+
21+
// 게시글 생성
22+
export const createPost = async ({
23+
boardId,
24+
newArticle,
25+
}: {
26+
boardId: number;
27+
newArticle: Record<string, unknown>;
28+
}) => {
29+
const { data } = await http.post('articles/', {
30+
...newArticle,
31+
parent_board: boardId,
32+
});
33+
return data;
34+
};
35+
36+
// 게시글 수정
37+
export const updatePost = async ({
38+
postId,
39+
newArticle,
40+
}: {
41+
postId: number;
42+
newArticle: Record<string, unknown>;
43+
}) => {
44+
const { data } = await http.put(`articles/${postId}/`, {
45+
...newArticle,
46+
});
47+
return data;
48+
};
49+
50+
// 게시글 스크랩
51+
export const archivePost = async (postId: number) => {
52+
const { data } = await http.post('scraps/', { parent_article: postId });
53+
return data;
54+
};
55+
56+
// 스크랩 해제
57+
export const unarchivePost = async (scrapId: number) => {
58+
const { data } = await http.delete(`scraps/${scrapId}/`);
59+
return data;
60+
};
61+
62+
// 게시글 신고
63+
export const reportPost = async (
64+
postId: number,
65+
typeReport: string,
66+
reasonReport: string
67+
) => {
68+
const { data } = await http.post('reports/', {
69+
parent_article: postId,
70+
type: typeReport,
71+
content: reasonReport,
72+
});
73+
return data;
74+
};
75+
76+
// 게시글 삭제
77+
export const deletePost = async (postId: number) => {
78+
const { data } = await http.delete(`articles/${postId}/`);
79+
return data;
80+
};
81+
82+
// 게시글 추천/비추천 (vote action은 별도 함수로 분리하는게 나을 수도 있지만, 필요시 context로 대체 가능)
83+
export const votePost = async (postId: number, action: VoteAction) => {
84+
const { data } = await http.post(`articles/${postId}/${action}/`);
85+
return data;
86+
};
87+
88+
// 댓글 단건 조회 (context에 vote action을 넣으면 해당 액션 경로 호출)
89+
export const fetchComment = async ({
90+
commentId,
91+
context,
92+
}: {
93+
commentId: number;
94+
context?: VoteAction;
95+
}) => {
96+
const url = context
97+
? `comments/${commentId}/${context}/`
98+
: `comments/${commentId}/`;
99+
const { data } = await http.get(url);
100+
return data;
101+
};
102+
103+
// 댓글 작성
104+
export const createComment = async (newComment: Record<string, unknown>) => {
105+
const { data } = await http.post('comments/', {
106+
...newComment,
107+
attachment: null,
108+
});
109+
return data;
110+
};
111+
112+
// 댓글 수정
113+
export const updateComment = async (
114+
commentId: number,
115+
newComment: Record<string, unknown>
116+
) => {
117+
const { data } = await http.patch(`comments/${commentId}/`, {
118+
...newComment,
119+
});
120+
return data;
121+
};
122+
123+
// 댓글 추천/비추천
124+
export const voteComment = async (commentId: number, action: VoteAction) => {
125+
const { data } = await http.post(`comments/${commentId}/${action}/`);
126+
return data;
127+
};
128+
129+
// 댓글 신고
130+
export const reportComment = async (
131+
commentId: number,
132+
typeReport: string,
133+
reasonReport: string
134+
) => {
135+
const { data } = await http.post('reports/', {
136+
parent_comment: commentId,
137+
type: typeReport,
138+
content: reasonReport,
139+
});
140+
return data;
141+
};
142+
143+
// 댓글 삭제
144+
export const deleteComment = async (commentId: number) => {
145+
const { data } = await http.delete(`comments/${commentId}/`);
146+
return data;
147+
};
148+
149+
// 파일 업로드 (단일/다중)
150+
export const uploadAttachments = async (attachments: File | File[]) => {
151+
const generateFormData = (file: File) => {
152+
const formData = new FormData();
153+
formData.append('file', file);
154+
return formData;
155+
};
156+
157+
const httpOptions = {
158+
headers: {
159+
'Content-Type': 'multipart/form-data',
160+
},
161+
};
162+
163+
// @TODO: File type인지 체크하기
164+
if (Array.isArray(attachments)) {
165+
return Promise.all(
166+
attachments.map((attachment) =>
167+
http.post('attachments/', generateFormData(attachment), httpOptions)
168+
)
169+
);
170+
}
171+
172+
return http.post('attachments/', generateFormData(attachments), httpOptions);
173+
};

src/lib/api/user.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import http from "./http";
1+
import http from "@/lib/api/http";
22
import { queryBuilder } from "../utils/queryBuilder";
33

44
//type QueryValue = string | number | boolean | null | undefined;

0 commit comments

Comments
 (0)