Skip to content

Commit 07782b5

Browse files
authored
Merge pull request #14 from CS3219-AY2425S1/ben/fix-missing-code
Fix minor bugs and add template code for individual question page
2 parents f4e572d + b29b6a0 commit 07782b5

File tree

3 files changed

+98
-36
lines changed

3 files changed

+98
-36
lines changed

apps/question-service/src/app/page.tsx

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
TableProps,
1515
Tabs,
1616
Tag,
17-
Modal
17+
Modal,
1818
} from "antd";
1919
import { Content } from "antd/es/layout/layout";
2020
import {
@@ -25,41 +25,58 @@ import {
2525
} from "@ant-design/icons";
2626
import "./styles.scss";
2727
import { useEffect, useState } from "react";
28-
import { DeleteQuestion as DeleteQuestionByDocref, GetQuestions, Question } from "./services/question";
28+
import {
29+
DeleteQuestion as DeleteQuestionByDocref,
30+
GetQuestions,
31+
Question,
32+
} from "./services/question";
2933
import {
3034
CategoriesOption,
3135
DifficultyOption,
3236
OrderOption,
33-
} from "./utils/SelectOptions";
37+
} from "../utils/SelectOptions";
38+
import Link from "next/link";
3439

3540
/**
3641
* defines the State of the page whe a user is deleing an object. Has 3 general states:
3742
* - {}: user is not deleting anything. The page's normal state
3843
* - {index: docref string, deleteConfirmed: false}: Modal popup asking whether to delete the question, pending user's decision to confirm or cancel
3944
* - {index: docref string, deleteConfirmed: true}: Currently deleting the question and reloading the database
4045
*/
41-
type DeletionStage = {} | {index: Question, deleteConfirmed: boolean}
46+
type DeletionStage = {} | { index: Question; deleteConfirmed: boolean };
4247

43-
function DeleteModal({isDeleting, questionTitle, okHandler, cancelHandler}: {questionTitle: string, okHandler: () => void, cancelHandler: () => void, isDeleting: boolean }) {
44-
const title: string = `Delete Question \"${questionTitle}\"?`
45-
const text: string = 'This action is irreversible(?)!'
48+
function DeleteModal({
49+
isDeleting,
50+
questionTitle,
51+
okHandler,
52+
cancelHandler,
53+
}: {
54+
questionTitle: string;
55+
okHandler: () => void;
56+
cancelHandler: () => void;
57+
isDeleting: boolean;
58+
}) {
59+
const title: string = `Delete Question \"${questionTitle}\"?`;
60+
const text: string = "This action is irreversible(?)!";
4661

47-
return <Modal
48-
open={true}
49-
title={title}
50-
onOk={okHandler}
51-
onCancel={cancelHandler}
52-
confirmLoading={isDeleting}
53-
okButtonProps={{danger: true}}
54-
cancelButtonProps={{disabled: isDeleting}}>
55-
<p>{text}</p>
56-
</Modal>
62+
return (
63+
<Modal
64+
open={true}
65+
title={title}
66+
onOk={okHandler}
67+
onCancel={cancelHandler}
68+
confirmLoading={isDeleting}
69+
okButtonProps={{ danger: true }}
70+
cancelButtonProps={{ disabled: isDeleting }}
71+
>
72+
<p>{text}</p>
73+
</Modal>
74+
);
5775
}
5876

5977
export default function Home() {
60-
6178
// State of Deletion
62-
const [deletionStage, setDeletionStage] = useState<DeletionStage>({})
79+
const [deletionStage, setDeletionStage] = useState<DeletionStage>({});
6380

6481
// Table States
6582
const [questions, setQuestions] = useState<Question[] | undefined>(undefined); // Store the questions
@@ -107,7 +124,13 @@ export default function Home() {
107124
setIsLoading(true);
108125
}
109126

110-
let data = await GetQuestions(currentPage, limit, sortBy, difficulty, delayedSearch);
127+
let data = await GetQuestions(
128+
currentPage,
129+
limit,
130+
sortBy,
131+
difficulty,
132+
delayedSearch
133+
);
111134
setQuestions(data.questions);
112135
setTotalCount(data.totalCount);
113136
setTotalPages(data.totalPages);
@@ -116,7 +139,18 @@ export default function Home() {
116139
setIsLoading(false);
117140
}
118141

119-
useEffect(() => {loadQuestions()}, [limit, currentPage, sortBy, difficulty, delayedSearch]);
142+
useEffect(() => {
143+
loadQuestions();
144+
}, [limit, currentPage, sortBy, difficulty, delayedSearch]);
145+
146+
// Delay the fetching of data only after user stops typing for awhile
147+
useEffect(() => {
148+
const timeout = setTimeout(() => {
149+
setDelayedSearch(search);
150+
setCurrentPage(1); // Reset the current page
151+
}, 800);
152+
return () => clearTimeout(timeout);
153+
}, [search]);
120154

121155
// Table column specification
122156
const columns: TableProps<Question>["columns"] = [
@@ -130,7 +164,16 @@ export default function Home() {
130164
title: "Title",
131165
dataIndex: "title",
132166
key: "title",
133-
render: (text: string) => <Button type="link">{text}</Button>, // TODO (Sean): Onclick links to the individual question page
167+
render: (text: string, question: Question) => (
168+
<Link
169+
href={{
170+
pathname: `/question/${question.id}`,
171+
query: { data: question.docRefId }, // the data
172+
}}
173+
>
174+
<Button type="link">{text}</Button>
175+
</Link>
176+
), // TODO (Sean): Onclick links to the individual question page
134177
},
135178
{
136179
title: "Categories",
@@ -145,14 +188,18 @@ export default function Home() {
145188
key: "complexity",
146189
render: (difficulty: string) => {
147190
let color = "";
148-
if (difficulty === "Easy") {
191+
if (difficulty === "easy") {
149192
color = "#2DB55D";
150-
} else if (difficulty === "Medium") {
193+
} else if (difficulty === "medium") {
151194
color = "orange";
152-
} else if (difficulty === "Hard") {
195+
} else if (difficulty === "hard") {
153196
color = "red";
154197
}
155-
return <div style={{ color }}>{difficulty}</div>;
198+
return (
199+
<div style={{ color }}>
200+
{difficulty.charAt(0).toUpperCase() + difficulty.slice(1)}
201+
</div>
202+
);
156203
},
157204
},
158205
{
@@ -169,8 +216,8 @@ export default function Home() {
169216
danger
170217
icon={<DeleteOutlined />}
171218
onClick={() => {
172-
setDeletionStage({index: question, deleteConfirmed: false})}
173-
}
219+
setDeletionStage({ index: question, deleteConfirmed: false });
220+
}}
174221
></Button>
175222
</div>
176223
),
@@ -219,7 +266,7 @@ export default function Home() {
219266
error("Cannot delete: questions does not exist");
220267
return;
221268
}
222-
269+
223270
setDeletionStage({ index: deletionStage.index, deleteConfirmed: true });
224271
await DeleteQuestionByDocref(deletionStage.index.docRefId);
225272
if (questions.length == 1 && currentPage > 1) {
@@ -230,13 +277,12 @@ export default function Home() {
230277
await loadQuestions();
231278
success("Question deleted successfully");
232279
} catch (err) {
233-
if (typeof err == 'string') {
280+
if (typeof err == "string") {
234281
error(err);
235282
}
236283
}
237284
}
238285
setDeletionStage({});
239-
240286
};
241287
return (
242288
<div>
@@ -333,11 +379,14 @@ export default function Home() {
333379
</div>
334380
</Content>
335381
</Layout>
336-
{("index" in deletionStage && questions != undefined) && <DeleteModal
337-
okHandler={confirmDeleteHandler}
338-
cancelHandler={() => setDeletionStage({})}
339-
questionTitle={deletionStage.index.title}
340-
isDeleting={deletionStage.deleteConfirmed}/>}
382+
{"index" in deletionStage && questions != undefined && (
383+
<DeleteModal
384+
okHandler={confirmDeleteHandler}
385+
cancelHandler={() => setDeletionStage({})}
386+
questionTitle={deletionStage.index.title}
387+
isDeleting={deletionStage.deleteConfirmed}
388+
/>
389+
)}
341390
</div>
342391
);
343392
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"use client";
2+
3+
import { useSearchParams } from "next/navigation";
4+
5+
const QuestionPage = (): JSX.Element => {
6+
const searchParams = useSearchParams();
7+
const docRefId = searchParams.get("data");
8+
9+
// TODO: use docRefId to fetch the data via the service function and display the data below
10+
return <div>Hello World! {docRefId}</div>;
11+
};
12+
13+
export default QuestionPage;
File renamed without changes.

0 commit comments

Comments
 (0)