Skip to content

Commit ba06467

Browse files
committed
enable cors, intergrate frontend and backend, change dto strucutre, change question service
1 parent d51a264 commit ba06467

File tree

8 files changed

+197
-121
lines changed

8 files changed

+197
-121
lines changed

backend/question-service/src/dto/CreateQuestion.dto.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ enum Difficulty {
2626
}
2727

2828
export class CreateQuestionDto {
29+
@IsNotEmpty()
30+
@IsString()
31+
id: string;
32+
2933
@IsNotEmpty()
3034
@IsString()
3135
title: string;
@@ -39,7 +43,8 @@ export class CreateQuestionDto {
3943
message:
4044
'Category must be Algorithm, DynamicProgramming, Array, SQL, Heap, Recursion, Graph, Sorting',
4145
})
42-
categories: Category[];
46+
categories: Category;
47+
// categories: Category[];
4348

4449
@IsNotEmpty()
4550
@IsEnum(Difficulty, {
@@ -50,4 +55,4 @@ export class CreateQuestionDto {
5055
@IsNotEmpty()
5156
@IsString()
5257
link: string;
53-
}
58+
}

backend/question-service/src/main.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import { AppModule } from './app.module';
33

44
async function bootstrap() {
55
const app = await NestFactory.create(AppModule);
6+
app.enableCors({
7+
origin: '*',
8+
});
69
app.enableShutdownHooks();
710
await app.listen(3002);
8-
console.log(app.getHttpAdapter().getInstance()._router.stack);
11+
// console.log(app.getHttpAdapter().getInstance()._router.stack);
912
}
1013
bootstrap();

backend/question-service/src/questions/questions.controller.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ export class QuestionsController {
4141
@Param('id') id: string,
4242
@Body() UpdateQuestionDto: UpdateQuestionDto,
4343
) {
44-
const isValid = mongoose.Types.ObjectId.isValid(id);
45-
if (!isValid) throw new HttpException('Invalid ID', 400);
44+
// NEED TO CHANGE THIS, PREVIOUSLY ID IS THE AUTOMATICALLY GENERATED ID BY MONGODB, NOW IT IS SPECIFIED BY USER
45+
//
46+
// const isValid = mongoose.Types.ObjectId.isValid(id);
47+
// if (!isValid) throw new HttpException('Invalid ID', 400);
4648
const updateQuestion = await this.questionsService.updateQuestion(
4749
id,
4850
UpdateQuestionDto,
@@ -53,8 +55,11 @@ export class QuestionsController {
5355

5456
@Delete(':id')
5557
async deleteQuestion(@Param('id') id: string) {
56-
const isValid = mongoose.Types.ObjectId.isValid(id);
57-
if (!isValid) throw new HttpException('Invalid ID', 400);
58+
// NEED TO CHANGE THIS, PREVIOUSLY ID IS THE AUTOMATICALLY GENERATED ID BY MONGODB, NOW IT IS SPECIFIED BY USER
59+
//
60+
// const isValid = mongoose.Types.ObjectId.isValid(id);
61+
// if (!isValid) throw new HttpException('Invalid ID', 400);
62+
5863
const deletedUser = await this.questionsService.deleteQuestion(id);
5964
if (!deletedUser) throw new HttpException('Question not Found', 404);
6065
return;

backend/question-service/src/questions/questions.service.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ export class QuestionsService {
2424
return this.questionModel.findById(id);
2525
}
2626

27-
updateQuestion(id: string, updateUserDto: UpdateQuestionDto) {
28-
return this.questionModel.findByIdAndUpdate(id, updateUserDto, {
29-
new: true,
30-
});
27+
updateQuestion(id: string, updateQuestionDto: UpdateQuestionDto) {
28+
return this.questionModel
29+
.findOneAndUpdate({ id: id }, updateQuestionDto, {
30+
new: true,
31+
})
32+
.exec();
3133
}
3234

3335
deleteQuestion(id: string) {
34-
return this.questionModel.findByIdAndDelete(id);
36+
return this.questionModel.deleteOne({ id: id }).exec();
3537
}
3638
}

backend/question-service/src/schemas/Question.schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import mongoose from 'mongoose';
33

44
@Schema()
55
export class Question {
6-
@Prop({ unique: true })
6+
@Prop({ unique: true, required: true })
77
id: number;
88

99
@Prop({ unique: true, required: true })
@@ -22,4 +22,4 @@ export class Question {
2222
link: string;
2323
}
2424

25-
export const QuestionSchema = SchemaFactory.createForClass(Question)
25+
export const QuestionSchema = SchemaFactory.createForClass(Question);

backend/user-service/src/main.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { AppModule } from './app.module';
44
async function bootstrap() {
55
const app = await NestFactory.create(AppModule);
66
app.enableCors({
7-
origin: 'http://localhost:3000',
7+
origin: '*',
88
});
99
await app.listen(3001);
1010
}
11-
bootstrap();
11+
bootstrap();
Lines changed: 137 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,153 @@
1-
import axios from 'axios';
2-
import React, { useState } from 'react';
3-
import EditQuestionForm from './editquestionform';
1+
import axios from "axios";
2+
import React, { useState } from "react";
3+
import EditQuestionForm from "./editquestionform";
44

55
export interface Question {
6-
id: string;
7-
title: string;
8-
description: string;
9-
categories: string;
10-
complexity: string;
11-
link: string;
6+
id: string;
7+
title: string;
8+
description: string;
9+
categories: string;
10+
complexity: string;
11+
link: string;
1212
}
1313

1414
interface QuestionTableProps {
15-
searchTerm: string;
16-
category: string;
17-
complexity: string;
18-
questions: Question[];
19-
setQuestions: React.Dispatch<React.SetStateAction<Question[]>>;
15+
searchTerm: string;
16+
category: string;
17+
complexity: string;
18+
questions: Question[];
19+
setQuestions: React.Dispatch<React.SetStateAction<Question[]>>;
2020
}
2121

22-
const QuestionTable: React.FC<QuestionTableProps> = ({ searchTerm, category, complexity, questions, setQuestions }) => {
22+
const QuestionTable: React.FC<QuestionTableProps> = ({
23+
searchTerm,
24+
category,
25+
complexity,
26+
questions,
27+
setQuestions,
28+
}) => {
29+
const [editingQuestion, setEditingQuestion] = useState<Question | null>(null);
2330

24-
const [editingQuestion, setEditingQuestion] = useState<Question | null>(null);
25-
26-
const filteredQuestions = questions.filter((question) => {
27-
const matchesSearchTerm = question.title.toLowerCase().includes(searchTerm.toLowerCase());
28-
const matchesCategory = category ? question.categories.includes(category) : true;
29-
const matchesComplexity = complexity ? question.complexity === complexity : true;
30-
return matchesSearchTerm && matchesCategory && matchesComplexity;
31-
});
31+
const filteredQuestions = questions.filter((question) => {
32+
const matchesSearchTerm = question.title
33+
.toLowerCase()
34+
.includes(searchTerm.toLowerCase());
35+
const matchesCategory = category
36+
? question.categories.includes(category)
37+
: true;
38+
const matchesComplexity = complexity
39+
? question.complexity === complexity
40+
: true;
41+
return matchesSearchTerm && matchesCategory && matchesComplexity;
42+
});
3243

33-
const handleDelete = async(id: string) => {
34-
try {
35-
await axios.delete(`http://localhost:3000/questions/${id}`);
36-
setQuestions((prevQuestions) => prevQuestions.filter(question => question.id !== id));
37-
} catch (error) {
38-
alert('Error deleting question: ' + error);
39-
}
40-
setQuestions((prevQuestions) => prevQuestions.filter(question => question.id !== id));
41-
};
44+
const handleDelete = async (id: string) => {
45+
try {
46+
console.log("id is ", id);
47+
await axios.delete(`http://localhost:3002/questions/${id}`);
48+
setQuestions((prevQuestions) =>
49+
prevQuestions.filter((question) => question.id !== id)
50+
);
51+
} catch (error) {
52+
alert("Error deleting question: " + error);
53+
}
54+
setQuestions((prevQuestions) =>
55+
prevQuestions.filter((question) => question.id !== id)
56+
);
57+
};
4258

43-
const handleUpdate = async(updatedQuestion: Question) => {
44-
try {
45-
const response = await axios.patch(`http://localhost:3000/questions/${updatedQuestion.id}`, updatedQuestion);
46-
setQuestions((prevQuestions) =>
47-
prevQuestions.map(question => (question.id === updatedQuestion.id ? response.data : question))
48-
);
49-
} catch (error) {
50-
alert('Error updating question: ' + error);
51-
}
52-
};
59+
const handleUpdate = async (updatedQuestion: Question) => {
60+
try {
61+
console.log("updated question is ", updatedQuestion)
62+
const response = await axios.patch(
63+
`http://localhost:3002/questions/${updatedQuestion.id}`,
64+
updatedQuestion
65+
);
66+
setQuestions((prevQuestions) =>
67+
prevQuestions.map((question) =>
68+
question.id === updatedQuestion.id ? response.data : question
69+
)
70+
);
71+
} catch (error) {
72+
alert("Error updating question: " + error);
73+
}
74+
};
5375

54-
const closeEditForm = () => {
55-
setEditingQuestion(null);
56-
};
76+
const closeEditForm = () => {
77+
setEditingQuestion(null);
78+
};
5779

58-
return (
59-
<div className="bg-gray-800 text-white">
60-
<table className="min-w-full table-auto">
61-
<thead className="bg-gray-700">
62-
<tr>
63-
<th className="border px-4 py-2">ID</th>
64-
<th className="border px-4 py-2">Title</th>
65-
<th className="border px-4 py-2">Description</th>
66-
<th className="border px-4 py-2">Categories</th>
67-
<th className="border px-4 py-2">Complexity</th>
68-
<th className="border px-4 py-2">Link</th>
69-
<th className="border px-4 py-2">Actions</th>
70-
</tr>
71-
</thead>
72-
<tbody className="bg-gray-800">
73-
{filteredQuestions.map((question) => (
74-
<tr key={question.id}>
75-
<td className="border px-4 py-2">{question.id}</td>
76-
<td className="border px-4 py-2">{question.title}</td>
77-
<td className="border px-4 py-2">{question.description}</td>
78-
<td className="border px-4 py-2">{question.categories}</td>
79-
<td className="border px-4 py-2">{question.complexity}</td>
80-
<td className="border px-4 py-2">
81-
<a href={question.link} target="_blank" rel="noopener noreferrer" className="text-blue-500">
82-
View
83-
</a>
84-
</td>
85-
<td className="border px-4 py-2">
86-
<div className="flex space-x-2">
87-
<button onClick={() => handleDelete(question.id)} className="bg-red-500 text-white rounded px-2 py-1">
88-
Delete
89-
</button>
90-
<button onClick={() => setEditingQuestion(question)} className="bg-red-500 text-white rounded px-2 py-1">
91-
Edit
92-
</button>
93-
</div>
94-
</td>
95-
</tr>
96-
))}
97-
{filteredQuestions.length === 0 && (
98-
<tr>
99-
<td colSpan={7} className="border border-gray-300 px-4 py-2 text-center">
100-
No questions found.
101-
</td>
102-
</tr>
103-
)}
104-
</tbody>
105-
</table>
106-
{editingQuestion && (
107-
<EditQuestionForm
108-
question={editingQuestion}
109-
onUpdate={handleUpdate}
110-
onClose={closeEditForm}
111-
/>
112-
)}
80+
return (
81+
<div className="bg-gray-800 text-white">
82+
<table className="min-w-full table-auto">
83+
<thead className="bg-gray-700">
84+
<tr>
85+
<th className="border px-4 py-2">ID</th>
86+
<th className="border px-4 py-2">Title</th>
87+
<th className="border px-4 py-2">Description</th>
88+
<th className="border px-4 py-2">Categories</th>
89+
<th className="border px-4 py-2">Complexity</th>
90+
<th className="border px-4 py-2">Link</th>
91+
<th className="border px-4 py-2">Actions</th>
92+
</tr>
93+
</thead>
94+
<tbody className="bg-gray-800">
95+
{filteredQuestions.map((question) => (
96+
<tr key={question.id}>
97+
<td className="border px-4 py-2">{question.id}</td>
98+
<td className="border px-4 py-2">{question.title}</td>
99+
<td className="border px-4 py-2">{question.description}</td>
100+
<td className="border px-4 py-2">{question.categories}</td>
101+
<td className="border px-4 py-2">{question.complexity}</td>
102+
<td className="border px-4 py-2">
103+
<a
104+
href={question.link}
105+
target="_blank"
106+
rel="noopener noreferrer"
107+
className="text-blue-500"
108+
>
109+
View
110+
</a>
111+
</td>
112+
<td className="border px-4 py-2">
113+
<div className="flex space-x-2">
114+
<button
115+
onClick={() => handleDelete(question.id)}
116+
className="bg-red-500 text-white rounded px-2 py-1"
117+
>
118+
Delete
119+
</button>
120+
<button
121+
onClick={() => setEditingQuestion(question)}
122+
className="bg-red-500 text-white rounded px-2 py-1"
123+
>
124+
Edit
125+
</button>
126+
</div>
127+
</td>
128+
</tr>
129+
))}
130+
{filteredQuestions.length === 0 && (
131+
<tr>
132+
<td
133+
colSpan={7}
134+
className="border border-gray-300 px-4 py-2 text-center"
135+
>
136+
No questions found.
137+
</td>
138+
</tr>
139+
)}
140+
</tbody>
141+
</table>
142+
{editingQuestion && (
143+
<EditQuestionForm
144+
question={editingQuestion}
145+
onUpdate={handleUpdate}
146+
onClose={closeEditForm}
147+
/>
148+
)}
113149
</div>
114-
);
150+
);
115151
};
116152

117153
export default QuestionTable;

0 commit comments

Comments
 (0)