Skip to content

Commit 9a0a23f

Browse files
authored
Merge pull request #13 from CS3219-AY2425S1/enhance-indiv-qn
Implemented proper AddQn Page, add Delete button on individual question page
2 parents bb289e5 + d252f09 commit 9a0a23f

File tree

14 files changed

+493
-153
lines changed

14 files changed

+493
-153
lines changed
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import { fetchQuestion } from '@/api/gateway';
1+
import { fetchQuestion } from "@/api/gateway";
22
import { Question as QnType, StatusBody, isError } from "@/api/structs";
3-
import styles from '@/style/question.module.css';
4-
import ErrorBlock from '@/components/shared/ErrorBlock';
5-
import React from 'react'
6-
import QuestionBlock from './question';
3+
import styles from "@/style/question.module.css";
4+
import ErrorBlock from "@/components/shared/ErrorBlock";
5+
import React from "react";
6+
import QuestionBlock from "./question";
77

88
type Props = {
99
params: {
10-
question: string
11-
}
12-
}
10+
question: string;
11+
};
12+
};
1313

1414
async function Question({ params }: Props) {
1515
const question = await fetchQuestion(params.question);
1616

1717
return (
1818
<div className={styles.wrapper}>
19-
{
20-
isError(question)
21-
? <ErrorBlock err={question as StatusBody}/>
22-
: <QuestionBlock question={question as QnType}/>
23-
}
19+
{isError(question) ? (
20+
<ErrorBlock err={question as StatusBody} />
21+
) : (
22+
<QuestionBlock question={question as QnType} />
23+
)}
2424
</div>
25-
)
25+
);
2626
}
2727

28-
export default Question;
28+
export default Question;
Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,114 @@
1-
import { Question, StatusBody, Difficulty } from "@/api/structs";
2-
import styles from '@/style/question.module.css';
1+
"use client";
2+
import { deleteQuestion } from "@/api/gateway";
3+
import { Question, Difficulty } from "@/api/structs";
4+
import Chip from "@/components/shared/Chip";
5+
import PeerprepButton from "@/components/shared/PeerprepButton";
6+
import styles from "@/style/question.module.css";
7+
import { useRouter } from "next/navigation";
38

49
interface Props {
5-
question : Question;
10+
question: Question;
611
}
712

8-
const difficultyColor = (diff: Difficulty) => {
9-
return (
10-
diff === Difficulty.Easy ? <p className={`${styles.title} ${styles.easy}`}>Easy</p>
11-
: diff === Difficulty.Medium ? <p className={`${styles.title} ${styles.med}`}>Med</p>
12-
: <p className={`${styles.title} ${styles.hard}`}>Hard</p>
13+
interface DifficultyChipProps {
14+
diff: Difficulty;
15+
}
16+
17+
function DifficultyChip({ diff }: DifficultyChipProps) {
18+
return diff === Difficulty.Easy ? (
19+
<Chip className={styles.easy}>Easy</Chip>
20+
) : diff === Difficulty.Medium ? (
21+
<Chip className={styles.med}>Med</Chip>
22+
) : (
23+
<Chip className={styles.hard}>Hard</Chip>
1324
);
1425
}
1526

1627
function QuestionBlock({ question }: Props) {
28+
const router = useRouter();
1729
const keys = question.test_cases ? Object.keys(question.test_cases) : [];
1830

1931
const createRow = (key: string) => (
2032
<tr key={key}>
2133
<td className={`${styles.table} ${styles.cell}`}>{key}</td>
22-
<td className={`${styles.table} ${styles.cell}`}>{question.test_cases[key]}</td>
34+
<td className={`${styles.table} ${styles.cell}`}>
35+
{question.test_cases[key]}
36+
</td>
2337
</tr>
2438
);
2539

40+
const handleDelete = async () => {
41+
if (
42+
confirm(
43+
`Are you sure you want to delete ${question.title}? (ID: ${question.id}) `
44+
)
45+
) {
46+
const status = await deleteQuestion(question);
47+
if (status.error) {
48+
alert(
49+
`Failed to delete question. Code ${status.status}: ${status.error}`
50+
);
51+
return;
52+
}
53+
console.log(`Successfully deleted the question.`);
54+
router.push("/questions");
55+
} else {
56+
console.log("Deletion cancelled.");
57+
}
58+
};
59+
2660
return (
2761
<>
2862
<div className={styles.qn_container}>
2963
<div className={styles.title_wrapper}>
30-
<h1 className={styles.title}>Q{question.id}: {question.title}</h1>
31-
{difficultyColor(question.difficulty)}
64+
<div className={styles.label_wrapper}>
65+
<h1 className={styles.title}>
66+
Q{question.id}: {question.title}
67+
</h1>
68+
<DifficultyChip diff={question.difficulty} />
69+
</div>
70+
<PeerprepButton
71+
className={` ${styles.button}`}
72+
onClick={handleDelete}
73+
>
74+
Delete
75+
</PeerprepButton>
76+
</div>
77+
<div className={styles.label_wrapper}>
78+
<p>Categories: </p>
79+
{question.categories.length == 0 ? (
80+
<p>No categories listed.</p>
81+
) : (
82+
question.categories.map((elem, idx) => <p key={idx}>{elem}</p>)
83+
)}
3284
</div>
33-
<br/>
3485
<p>{question.description}</p>
35-
<br/>
86+
<br />
3687
{question.test_cases && (
3788
<table className={styles.table}>
3889
<tbody>
3990
<tr>
40-
<th className={`${styles.table} ${styles.header} ${styles.input}`}>Input</th>
41-
<th className={`${styles.table} ${styles.header} ${styles.output}`}>Expected Output</th>
91+
<th
92+
className={`${styles.table} ${styles.header} ${styles.input}`}
93+
>
94+
Input
95+
</th>
96+
<th
97+
className={`${styles.table} ${styles.header} ${styles.output}`}
98+
>
99+
Expected Output
100+
</th>
42101
</tr>
43102
{keys.map(createRow)}
44103
</tbody>
45104
</table>
46105
)}
47106
</div>
48107
<form className={styles.editor_container}>
49-
<textarea className={styles.code_editor}/>
108+
<textarea className={styles.code_editor} />
50109
</form>
51110
</>
52111
);
53112
}
54113

55-
export default QuestionBlock;
114+
export default QuestionBlock;

0 commit comments

Comments
 (0)