Skip to content

Commit 8451c3e

Browse files
committed
Merge branch 'development' of https://github.com/guanquann/cs3219-ay2425s1-project-g28 into admin-question-view
2 parents 1f411f3 + 4f60321 commit 8451c3e

File tree

11 files changed

+812
-27
lines changed

11 files changed

+812
-27
lines changed

backend/question-service/src/controllers/questionController.ts

Lines changed: 123 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ import {
55
DUPLICATE_QUESTION_RESPONSE_MESSAGE,
66
QN_DESC_EXCEED_CHAR_LIMIT_RESPONSE_MESSAGE,
77
QN_DESC_CHAR_LIMIT,
8-
QN_NOT_FOUND,
9-
QN_DELETED,
10-
SERVER_ERROR,
8+
QN_CREATED_MESSAGE,
9+
QN_NOT_FOUND_MESSAGE,
10+
QN_DELETED_MESSAGE,
11+
SERVER_ERROR_MESSAGE,
12+
QN_RETRIEVED_MESSAGE,
13+
PAGE_LIMIT_REQUIRED_MESSAGE,
14+
PAGE_LIMIT_INCORRECT_FORMAT_MESSAGE,
15+
CATEGORIES_NOT_FOUND_MESSAGE,
16+
CATEGORIES_RETRIEVED_MESSAGE,
1117
} from "../utils/constants.ts";
1218

1319
import { upload } from "../../config/multer";
@@ -45,11 +51,11 @@ export const createQuestion = async (
4551
await newQuestion.save();
4652

4753
res.status(201).json({
48-
message: "Question created successfully",
54+
message: QN_CREATED_MESSAGE,
4955
question: newQuestion,
5056
});
5157
} catch (error) {
52-
res.status(500).json({ message: SERVER_ERROR, error });
58+
res.status(500).json({ message: SERVER_ERROR_MESSAGE, error });
5359
}
5460
};
5561

@@ -92,7 +98,7 @@ export const updateQuestion = async (
9298

9399
const currentQuestion = await Question.findById(id);
94100
if (!currentQuestion) {
95-
res.status(404).json({ message: QN_NOT_FOUND });
101+
res.status(404).json({ message: QN_NOT_FOUND_MESSAGE });
96102
return;
97103
}
98104

@@ -120,7 +126,7 @@ export const updateQuestion = async (
120126
question: updatedQuestion,
121127
});
122128
} catch (error) {
123-
res.status(500).json({ message: SERVER_ERROR, error });
129+
res.status(500).json({ message: SERVER_ERROR_MESSAGE, error });
124130
}
125131
};
126132

@@ -132,13 +138,120 @@ export const deleteQuestion = async (
132138
const { id } = req.params;
133139
const currentQuestion = await Question.findById(id);
134140
if (!currentQuestion) {
135-
res.status(400).json({ message: QN_NOT_FOUND });
141+
res.status(404).json({ message: QN_NOT_FOUND_MESSAGE });
136142
return;
137143
}
138144

139145
await Question.findByIdAndDelete(id);
140-
res.status(200).json({ message: QN_DELETED });
146+
res.status(200).json({ message: QN_DELETED_MESSAGE });
141147
} catch (error) {
142-
res.status(500).json({ message: SERVER_ERROR, error });
148+
res.status(500).json({ message: SERVER_ERROR_MESSAGE, error });
149+
}
150+
};
151+
152+
interface QnListSearchFilterParams {
153+
page: string;
154+
qnLimit: string;
155+
title?: string;
156+
complexities?: string | string[];
157+
categories?: string | string[];
158+
}
159+
160+
export const readQuestionsList = async (
161+
req: Request<unknown, unknown, unknown, QnListSearchFilterParams>,
162+
res: Response,
163+
): Promise<void> => {
164+
try {
165+
const { page, qnLimit, title, complexities, categories } = req.query;
166+
167+
if (!page || !qnLimit) {
168+
res.status(400).json({ message: PAGE_LIMIT_REQUIRED_MESSAGE });
169+
return;
170+
}
171+
172+
const pageInt = parseInt(page, 10);
173+
const qnLimitInt = parseInt(qnLimit, 10);
174+
175+
if (pageInt < 1 || qnLimitInt < 1) {
176+
res.status(400).json({ message: PAGE_LIMIT_INCORRECT_FORMAT_MESSAGE });
177+
return;
178+
}
179+
180+
const query: any = {};
181+
182+
if (title) {
183+
query.title = { $regex: new RegExp(title, "i") };
184+
}
185+
186+
if (complexities) {
187+
query.complexity = {
188+
$in: Array.isArray(complexities) ? complexities : [complexities],
189+
};
190+
}
191+
192+
if (categories) {
193+
query.category = {
194+
$in: Array.isArray(categories) ? categories : [categories],
195+
};
196+
}
197+
198+
const filteredTotalQuestions = await Question.countDocuments(query);
199+
if (filteredTotalQuestions == 0) {
200+
res.status(404).json({ message: QN_NOT_FOUND_MESSAGE });
201+
return;
202+
}
203+
204+
const filteredQuestions = await Question.find(query)
205+
.skip((pageInt - 1) * qnLimitInt)
206+
.limit(qnLimitInt);
207+
208+
res.status(200).json({
209+
message: QN_RETRIEVED_MESSAGE,
210+
totalQns: filteredTotalQuestions,
211+
questions: filteredQuestions,
212+
});
213+
} catch (error) {
214+
res.status(500).json({ message: SERVER_ERROR_MESSAGE, error });
215+
}
216+
};
217+
218+
export const readQuestionIndiv = async (
219+
req: Request,
220+
res: Response,
221+
): Promise<void> => {
222+
try {
223+
const { id } = req.params;
224+
225+
const questionDetails = await Question.findById(id);
226+
if (!questionDetails) {
227+
res.status(404).json({ message: QN_NOT_FOUND_MESSAGE });
228+
return;
229+
}
230+
231+
res.status(200).json({
232+
message: QN_RETRIEVED_MESSAGE,
233+
question: questionDetails,
234+
});
235+
} catch (error) {
236+
res.status(500).json({ message: SERVER_ERROR_MESSAGE, error });
237+
}
238+
};
239+
240+
export const readCategories = async (
241+
req: Request,
242+
res: Response,
243+
): Promise<void> => {
244+
try {
245+
const uniqueCats = await Question.distinct("category");
246+
if (!uniqueCats || uniqueCats.length == 0) {
247+
res.status(404).json({ message: CATEGORIES_NOT_FOUND_MESSAGE });
248+
}
249+
250+
res.status(200).json({
251+
message: CATEGORIES_RETRIEVED_MESSAGE,
252+
categories: uniqueCats,
253+
});
254+
} catch (error) {
255+
res.status(500).json({ message: SERVER_ERROR_MESSAGE, error });
143256
}
144257
};

backend/question-service/src/routes/questionRoutes.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import {
44
deleteQuestion,
55
createImageLink,
66
updateQuestion,
7+
readQuestionsList,
8+
readQuestionIndiv,
9+
readCategories,
710
} from "../controllers/questionController.ts";
811

912
const router = express.Router();
@@ -14,6 +17,12 @@ router.post("/questions/images", createImageLink);
1417

1518
router.put("/questions/:id", updateQuestion);
1619

20+
router.get("/questions/categories", readCategories);
21+
22+
router.get("/questions", readQuestionsList);
23+
24+
router.get("/questions/:id", readQuestionIndiv);
25+
1726
router.delete("/questions/:id", deleteQuestion);
1827

1928
export default router;

backend/question-service/src/utils/constants.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,23 @@ export const QN_DESC_EXCEED_CHAR_LIMIT_RESPONSE_MESSAGE =
66
export const DUPLICATE_QUESTION_RESPONSE_MESSAGE =
77
"Duplicate question: A question with the same title already exists.";
88

9-
export const QN_NOT_FOUND = "Question not found.";
9+
export const QN_CREATED_MESSAGE = "Question created successfully.";
1010

11-
export const QN_DELETED = "Question deleted successfully.";
11+
export const QN_NOT_FOUND_MESSAGE = "Question not found.";
1212

13-
export const SERVER_ERROR = "Server error.";
13+
export const QN_DELETED_MESSAGE = "Question deleted successfully.";
14+
15+
export const SERVER_ERROR_MESSAGE = "Server error.";
16+
17+
export const QN_RETRIEVED_MESSAGE = "Question retrieved successfully.";
18+
19+
export const PAGE_LIMIT_REQUIRED_MESSAGE =
20+
"Page number and question limit per page should be provided.";
21+
22+
export const PAGE_LIMIT_INCORRECT_FORMAT_MESSAGE =
23+
"Page number and question limit per page should be positive integers.";
24+
25+
export const CATEGORIES_NOT_FOUND_MESSAGE = "No categories found.";
26+
27+
export const CATEGORIES_RETRIEVED_MESSAGE =
28+
"Categories retrieved successfully.";

0 commit comments

Comments
 (0)