Skip to content

Commit c2031d1

Browse files
committed
refactor question to use API
1 parent 80ca034 commit c2031d1

File tree

9 files changed

+196
-125
lines changed

9 files changed

+196
-125
lines changed

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@
2424
"ts-node": "^10.9.1",
2525
"typescript": "^5.2.2"
2626
}
27-
}
27+
}

backend/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
handleSignUp,
77
} from "./auth/auth.controller";
88
import { handleCreateUser, handleGetUser } from "./user/user.controller";
9+
import { handleGetQuestions } from "./question/question.controller";
910
const app = express();
1011
const port = 3001;
1112

@@ -19,7 +20,7 @@ app.get("/", (req, res) => {
1920
app.post("/signup", handleSignUp);
2021
app.post("/login", handleLogin);
2122
app.delete("/logout", handleLogout);
22-
23+
app.get("/questions", handleGetQuestions);
2324
app.post("/user", handleCreateUser);
2425
app.get("/user", handleGetUser);
2526

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { Request, Response } from "express";
2+
import { db } from "./question.service";
3+
import { getDocs, collection, deleteDoc, doc, addDoc, setDoc } from "firebase/firestore";
4+
export async function handleGetQuestions(req: Request, res: Response) {
5+
try {
6+
// console.log(req.query.email);
7+
// const { email } = req.query;
8+
console.log(`getting all questions`);
9+
const query = await getDocs(collection(db, "questions"));
10+
const result = await Promise.all(
11+
query.docs.map(async (d) => {
12+
const q = d.data();
13+
const examplesArray = await getExamples(d.id);
14+
15+
return {
16+
id: d.id,
17+
title: q.title,
18+
tags: q.tags,
19+
categories: q.categories,
20+
constraints: q.constraints,
21+
difficulty: q.difficulty,
22+
description: q.description,
23+
examples: examplesArray,
24+
};
25+
})
26+
);
27+
28+
if (result.length > 0) {
29+
res.status(200).send(result);
30+
} else {
31+
res.status(500).send("no questions");
32+
}
33+
} catch (error) {
34+
console.error(error);
35+
res.status(500).send(error);
36+
}
37+
}
38+
39+
const getExamples = async (id: string) => {
40+
const subCollRef = collection(db, "questions", id, "examples");
41+
42+
const examplesSnapshot = await getDocs(subCollRef);
43+
44+
const examplesResult = examplesSnapshot.docs.map((data) => {
45+
const exampleData = data.data();
46+
47+
return {
48+
text: exampleData.text,
49+
image: exampleData.img || "", // Use an empty string if image is missing
50+
};
51+
});
52+
// console.log(examplesSnapshot)
53+
return examplesResult;
54+
};
55+
56+
export async function handleDeleteQuestion(req: Request, res: Response) {
57+
const questionId = req.params.questionId
58+
try {
59+
const docRef = doc(db, "questions", questionId)
60+
const result = await deleteDoc(docRef);
61+
} catch (err) {
62+
console.log(`error when deleting question with id ${questionId}` + err)
63+
}
64+
65+
66+
}
67+
68+
export async function handleAddQuestion(req: Request, res: Response) {
69+
try {
70+
71+
const {qtitle, qtags, qcategories, qconstraints, qdifficulty, qdescription, qexamples} = req.body
72+
const docRef = await addDoc(collection(db, "questions"), {
73+
title: qtitle,
74+
tags: qtags,
75+
categories: qcategories,
76+
constraints: qconstraints,
77+
difficulty: qdifficulty,
78+
description: qdescription,
79+
});
80+
const exampleRef = collection(db, "questions", docRef.id, "examples")
81+
qexamples.map(() => {
82+
83+
})
84+
const addExample = setDoc(exampleRef, qexamples)
85+
86+
}
87+
}

backend/src/question/question.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ import { getFirestore } from "firebase/firestore";
33
import { firebaseConfig } from "../firebase/firebase.config";
44

55
initializeApp(firebaseConfig);
6-
const db = getFirestore();
6+
export const db = getFirestore();

frontend/package-lock.json

Lines changed: 0 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/src/api/questions/data.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import httpClient from "../axios/config";
2+
import { QuestionDTO } from "./dto";
3+
// import { AuthDTO } from "./dto";
4+
// import { UserCredential } from "firebase/auth";
5+
6+
// export const registerUser = (params: AuthDTO) =>
7+
// httpClient.post<UserCredential>("/signup", params);
8+
9+
// export const signIn = (params: AuthDTO) =>
10+
// httpClient.post<UserCredential>("/login", params);
11+
12+
// export const signOut = () => httpClient.delete("/logout");
13+
14+
export const getAllQuestions = () => httpClient.get("/questions");
15+
16+
export const addQuestion = (params: QuestionDTO) =>
17+
httpClient.post("/questions", params);
18+
19+
export const deleteQuestion = (params: string) =>
20+
httpClient.delete("/questions/:questionId");

frontend/src/api/questions/dto.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Example } from "../../data/data.context";
2+
3+
export interface QuestionDTO {
4+
title: string;
5+
tags: string[];
6+
categories: string;
7+
constraints: string;
8+
difficulty: string;
9+
description: string;
10+
examples: Example[];
11+
}

frontend/src/data/data.context.tsx

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
21
import { createContext, ReactNode, useContext, useMemo, useState } from "react";
32
import { db } from "../firebase/firebase";
43
import { collection, getDocs } from "firebase/firestore";
4+
import { getAllQuestions } from "../api/questions/data";
55

66
interface Response {
77
type: "success" | "error" | undefined;
@@ -17,20 +17,20 @@ interface Question {
1717
constraints: string[];
1818
difficulty: "Easy" | "Medium" | "Hard";
1919
description: string;
20-
examples: Example[]
20+
examples: Example[];
2121
}
2222

23-
interface Example {
24-
text: string
25-
image: string
23+
export interface Example {
24+
text: string;
25+
image: string;
2626
}
2727

2828
interface DataContextData {
2929
loading: boolean;
3030
response: Response;
3131
questions: Question[];
3232
getQuestions: () => void;
33-
getExamples: (id:string) => void
33+
// getExamples: (id: string) => void;
3434
}
3535

3636
interface DataContextProviderProps {
@@ -47,69 +47,18 @@ const DataContext = createContext<DataContextData>({
4747
response: emptyResponse,
4848
questions: [],
4949
getQuestions: () => undefined,
50-
getExamples: (id:string) => undefined
50+
// getExamples: (id: string) => undefined,
5151
});
5252

5353
export function DataContextProvider({ children }: DataContextProviderProps) {
5454
const [loading, setLoading] = useState(false);
5555
const [response, setResponse] = useState<Response>(emptyResponse);
5656
const [questions, setQuestions] = useState<Question[]>([]);
5757

58-
59-
const getExamples = async (id:string) => {
60-
const subCollRef = collection(db, "questions", id, "examples")
61-
62-
const examplesSnapshot = await getDocs(subCollRef);
63-
64-
const examplesResult = examplesSnapshot.docs.map((data) => {
65-
const exampleData = data.data();
66-
67-
return {
68-
69-
text: exampleData.text,
70-
image: exampleData.img || '', // Use an empty string if image is missing
71-
};
72-
73-
74-
75-
})
76-
// console.log(examplesSnapshot)
77-
return examplesResult;
78-
}
79-
80-
8158
const getQuestions = async () => {
8259
try {
8360
setLoading(true);
84-
// console.log("penis")
85-
const query = await getDocs(collection(db, "questions"));
86-
const result = await Promise.all(query.docs.map(async (d) => {
87-
const q = d.data();
88-
// const getExamples = async () => {
89-
// const examplesSnapshot = await getDocs(collection(db, "questions", q.id, "examples"));
90-
// console.log(examplesSnapshot)
91-
// const examplesResult = examplesSnapshot.docs.map((data) => {
92-
// const exampleData = data.data();
93-
// return {
94-
// text: exampleData.text,
95-
// image: exampleData.img || '', // Use an empty string if image is missing
96-
// };
97-
98-
const examplesArray = await getExamples(d.id)
99-
100-
101-
// const examplesArray = await getExamples();
102-
return {
103-
id: d.id,
104-
title: q.title,
105-
tags: q.tags,
106-
categories: q.categories,
107-
constraints: q.constraints,
108-
difficulty: q.difficulty,
109-
description: q.description,
110-
examples: examplesArray
111-
};
112-
}));
61+
const result = await (await getAllQuestions()).data;
11362
setLoading(false);
11463
setQuestions(result);
11564
setResponse({
@@ -122,19 +71,14 @@ export function DataContextProvider({ children }: DataContextProviderProps) {
12271
type: "error",
12372
message: e,
12473
});
125-
12674
}
127-
128-
12975
};
13076

13177
const dataContextProviderValue = useMemo(
132-
() => ({ loading, response, questions, getQuestions, getExamples }),
78+
() => ({ loading, response, questions, getQuestions }),
13379
//eslint-disable-next-line react-hooks/exhaustive-deps
13480
[loading, response, questions]
13581
);
136-
137-
13882

13983
return (
14084
<DataContext.Provider value={dataContextProviderValue}>
@@ -145,5 +89,4 @@ export function DataContextProvider({ children }: DataContextProviderProps) {
14589

14690
export const useData = () => {
14791
return useContext(DataContext);
148-
14992
};

0 commit comments

Comments
 (0)