Skip to content

Commit 710229b

Browse files
committed
Add delete button to QuestionCard
Add delete/get all questions to gateway TODO: Refresh page on delete (might need to refactor QuestionList) Partially resolves #8
1 parent 4575fde commit 710229b

File tree

4 files changed

+81
-25
lines changed

4 files changed

+81
-25
lines changed

peerprep/api/gateway.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,45 @@ export async function addQuestion(body: QuestionFullBody): Promise<StatusBody> {
8181
return { error: err.message, status: 0 };
8282
}
8383
}
84+
85+
export async function deleteQuestion(question: Question): Promise<StatusBody> {
86+
try {
87+
const response = await fetch(
88+
`${process.env.NEXT_PUBLIC_QUESTION_SERVICE}/questions/delete/${question.id}`,
89+
{
90+
method: "DELETE",
91+
headers: {
92+
"Content-type": "application/json; charset=UTF-8",
93+
},
94+
}
95+
);
96+
if (response.ok) {
97+
return {
98+
status: response.status,
99+
};
100+
}
101+
return {
102+
error: (await response.json())["Error deleting question: "],
103+
status: response.status,
104+
};
105+
} catch (err: any) {
106+
return { error: err.message, status: 0 };
107+
}
108+
}
109+
110+
export async function getAllQuestions(): Promise<Question[] | StatusBody> {
111+
try {
112+
const response = await fetch(
113+
`${process.env.NEXT_PUBLIC_QUESTION_SERVICE}/questions`
114+
);
115+
if (!response.ok) {
116+
return {
117+
error: await response.text(),
118+
status: response.status,
119+
};
120+
}
121+
return (await response.json()) as Question[];
122+
} catch (err: any) {
123+
return { error: err.message, status: 400 };
124+
}
125+
}

peerprep/api/structs.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export interface StatusBody {
2929
error?: string;
3030
}
3131

32-
export function isError(obj: Question | StatusBody): obj is StatusBody {
32+
export function isError(
33+
obj: Question[] | Question | StatusBody
34+
): obj is StatusBody {
3335
return (obj as StatusBody).status !== undefined;
3436
}

peerprep/components/questionpage/QuestionCard.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
"use client";
2+
import { deleteQuestion } from "@/api/gateway";
23
import React from "react";
34
import { Question, Difficulty } from "@/api/structs";
45
import PeerprepButton from "../shared/PeerprepButton";
56
import { useRouter } from "next/navigation";
67
import styles from "@/style/questionCard.module.css";
8+
import QuestionList from "./QuestionList";
79

810
type QuestionCardProps = {
911
question: Question;
1012
};
1113

1214
const QuestionCard: React.FC<QuestionCardProps> = ({ question }) => {
1315
const router = useRouter();
16+
const handleDelete = async () => {
17+
if (
18+
confirm(
19+
`Are you sure you want to delete ${question.title}? (ID: ${question.id}) `
20+
)
21+
) {
22+
const status = await deleteQuestion(question);
23+
if (status.error) {
24+
console.log("Failed to delete question.");
25+
console.log(`Code ${status.status}: ${status.error}`);
26+
return;
27+
}
28+
console.log(`Successfully deleted the question.`);
29+
} else {
30+
console.log("Deletion cancelled.");
31+
}
32+
};
1433

1534
const getDifficultyColor = (difficulty: Difficulty) => {
1635
switch (difficulty) {
@@ -55,12 +74,7 @@ const QuestionCard: React.FC<QuestionCardProps> = ({ question }) => {
5574
<PeerprepButton onClick={() => router.push(`questions/${question.id}`)}>
5675
View
5776
</PeerprepButton>
58-
<PeerprepButton
59-
// no functionality here yet
60-
onClick={() => console.log(`Deleting question ${question.id}`)}
61-
>
62-
Delete
63-
</PeerprepButton>
77+
<PeerprepButton onClick={handleDelete}>Delete</PeerprepButton>
6478
</div>
6579
</div>
6680
);

peerprep/components/questionpage/QuestionList.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"use client";
2+
import { getAllQuestions } from "@/api/gateway";
23
import React, { useEffect, useState } from "react";
34
import QuestionCard from "./QuestionCard";
4-
import { Question, StatusBody, Difficulty } from "@/api/structs";
5+
import { Question, StatusBody, Difficulty, isError } from "@/api/structs";
56
import PeerprepDropdown from "../shared/PeerprepDropdown";
67
import PeerprepSearchBar from "../shared/PeerprepSearchBar";
78

@@ -12,29 +13,26 @@ const QuestionList: React.FC = () => {
1213
Difficulty[0]
1314
);
1415
const [categoryFilter, setCategoryFilter] = useState<string>("all");
15-
// will prolly have to search by name later
1616
const [searchFilter, setSearchFilter] = useState<string>("");
1717
const [categories, setCategories] = useState<string[]>(["all"]);
1818

1919
useEffect(() => {
2020
const fetchQuestions = async () => {
21-
try {
22-
const response = await fetch(
23-
`${process.env.NEXT_PUBLIC_QUESTION_SERVICE}/questions`
24-
);
25-
const data: Question[] = await response.json();
26-
setQuestions(data);
27-
28-
// get all present categories in all qns
29-
const uniqueCategories = Array.from(
30-
new Set(data.flatMap((question) => question.categories))
31-
);
32-
setCategories(["all", ...uniqueCategories]);
33-
} catch (error) {
34-
console.error("Error fetching questions:", error);
35-
} finally {
36-
setLoading(false);
21+
const data = await getAllQuestions();
22+
// uh
23+
if (isError(data)) {
24+
// should also reflect the error
25+
return;
3726
}
27+
28+
setLoading(false);
29+
setQuestions(data);
30+
31+
// get all present categories in all qns
32+
const uniqueCategories = Array.from(
33+
new Set(data.flatMap((question) => question.categories))
34+
);
35+
setCategories(["all", ...uniqueCategories]);
3836
};
3937

4038
fetchQuestions();

0 commit comments

Comments
 (0)