Skip to content

Commit 62ba1e4

Browse files
Create New Problem Backend
1 parent 65d0459 commit 62ba1e4

File tree

3 files changed

+163
-2
lines changed

3 files changed

+163
-2
lines changed

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

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@ import {
2929
DeleteQuestion as DeleteQuestionByDocref,
3030
GetQuestions,
3131
Question,
32+
CreateQuestion,
33+
NewQuestion
3234
} from "./services/question";
3335
import {
3436
CategoriesOption,
3537
DifficultyOption,
3638
OrderOption,
3739
} from "../utils/SelectOptions";
3840
import Link from "next/link";
41+
import TextArea from "antd/es/input/TextArea";
3942

4043
/**
4144
* defines the State of the page whe a user is deleing an object. Has 3 general states:
@@ -98,6 +101,51 @@ export default function Home() {
98101
// Message States
99102
const [messageApi, contextHolder] = message.useMessage();
100103

104+
// States for Create New Problem Modal
105+
const [isNewProblemModalOpen, setIsNewProblemModelOpen] = useState(false);
106+
const [newProblemCategories, setNewProblemCategories] = useState<string[]>([]);
107+
const [newProblemDifficulty, setNewProblemDifficulty] = useState<string[]>([]); // Store the selected difficulty level
108+
109+
const [newTitle, setNewTitle] = useState('sampleTitle');
110+
const [newDescription, setNewDescription] = useState('sampleDescription');
111+
const [newCategories, setNewCategories] = useState<string[]>(['Algorithms']);
112+
const [newComplexity, setNewComplexity] = useState(1);
113+
const [newProblemError, setNewProblemError] = useState<string | null>(null);
114+
115+
const handleCreateQuestion = async () => {
116+
const newQuestion: NewQuestion = {
117+
newTitle,
118+
newDescription,
119+
newCategories,
120+
newComplexity,
121+
// Add assets and testCases if needed
122+
};
123+
try {
124+
const createdQuestion: Question = await CreateQuestion(newQuestion);
125+
console.log("Question created successfully:", createdQuestion);
126+
// Reset form or update UI as needed
127+
} catch (err: any) {
128+
setNewProblemError(err.message);
129+
}
130+
};
131+
132+
const showNewProblemModal = () => {
133+
setIsNewProblemModelOpen(true);
134+
};
135+
136+
const handleNewProblemSubmit = () => {
137+
setIsNewProblemModelOpen(false);
138+
};
139+
140+
const handleNewProblemReturn = () => {
141+
setIsNewProblemModelOpen(false);
142+
};
143+
144+
// Handler for change in multi-select categories option
145+
const handleNewProblemCategoriesChange = (value: string[]) => {
146+
setNewProblemCategories(value);
147+
};
148+
101149
const success = (message: string) => {
102150
messageApi.open({
103151
type: "success",
@@ -174,7 +222,7 @@ export default function Home() {
174222
>
175223
<Button type="link">{text}</Button>
176224
</Link>
177-
), // TODO (Sean): Onclick links to the individual question page
225+
),
178226
},
179227
{
180228
title: "Categories",
@@ -210,6 +258,7 @@ export default function Home() {
210258
render: (_: number, question: Question) => (
211259
<div>
212260
{/* TODO (Sean): Include Logic to handle retrieving of editable data here and display in a modal component */}
261+
213262
<Button className="edit-button" icon={<EditOutlined />}></Button>
214263
{/* TODO (Ryan): Include Pop-up confirmation for delete when clicked and link to delete API --> can also explore success notification or look into react-toast*/}
215264
<Button
@@ -296,9 +345,71 @@ export default function Home() {
296345
<div className="content-title">Problems</div>
297346
<div className="create-button">
298347
{/* TODO (Sean): Launch a popup modal that links to the backend api to create a new entry in db, --> look into success/error notification/react toast */}
299-
<Button type="primary" icon={<PlusCircleOutlined />}>
348+
<Button type="primary" icon={<PlusCircleOutlined />} onClick={showNewProblemModal}>
300349
Create New Problem
301350
</Button>
351+
<Modal
352+
353+
title="Create New Problem"
354+
open={isNewProblemModalOpen}
355+
onOk={handleNewProblemSubmit}
356+
onCancel={handleNewProblemReturn}
357+
// footer={[
358+
// <Button key="back" onClick={handleNewProblemReturn}>
359+
// Return
360+
// </Button>,
361+
// <Button key="submit" type="primary" onClick={handleNewProblemSubmit}>
362+
// Submit
363+
// </Button>,
364+
// ]}
365+
>
366+
<input
367+
type="text"
368+
placeholder="Title"
369+
value={newTitle}
370+
onChange={(e) => setNewTitle(e.target.value)}
371+
/>
372+
{/* Add other input fields for description, categories, complexity, etc. */}
373+
<button onClick={handleCreateQuestion}>Create Question</button>
374+
375+
</Modal>
376+
{/* <Modal
377+
title="Create New Problem"
378+
open={isNewProblemModalOpen}
379+
onOk={handleNewProblemSubmit}
380+
onCancel={handleNewProblemReturn}
381+
footer={[
382+
<Button key="back" onClick={handleNewProblemReturn}>
383+
Return
384+
</Button>,
385+
<Button key="submit" type="primary" onClick={handleNewProblemSubmit}>
386+
Submit
387+
</Button>,
388+
]}
389+
>
390+
<TextArea className="create-title" placeholder="Problem Title" rows={1} maxLength={1}></TextArea>
391+
<Select
392+
allowClear
393+
placeholder="Difficulty"
394+
onChange={(value: string[]) => {
395+
setNewProblemDifficulty(value);
396+
}}
397+
options={DifficultyOption}
398+
className="new-problem-difficulty-select"
399+
value={newProblemDifficulty}
400+
/>
401+
<Select
402+
mode="multiple"
403+
allowClear
404+
placeholder="Categories"
405+
onChange={handleNewProblemCategoriesChange}
406+
options={CategoriesOption}
407+
className="new-problem-categories-multi-select"
408+
value={newProblemCategories}
409+
/>
410+
<TextArea className="create-description" placeholder="Description"></TextArea>
411+
<TextArea className="create-problem-id" placeholder="Problem ID"></TextArea>
412+
</Modal> */}
302413
</div>
303414
</div>
304415
{/* TODO (Ben/Ryan): Include and link search & filter parameters */}

apps/question-service/src/app/services/question.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ export interface QuestionListResponse {
2121
questions: Question[];
2222
}
2323

24+
export interface NewQuestion {
25+
newTitle: string;
26+
newDescription: string;
27+
newCategories: string[];
28+
newComplexity: string;
29+
}
30+
2431
// GET request to fetch all the questions (TODO: Ben --> Fetch with filtering/sorting etc)
2532
export const GetQuestions = async (
2633
currentPage?: number,
@@ -80,8 +87,42 @@ export const GetSingleQuestion = async (docRef: string): Promise<Question> => {
8087
return data;
8188
};
8289

90+
// Upload single question (TODO: Sean)
91+
export const CreateQuestion = async (question: NewQuestion): Promise<Question> => {
92+
try {
93+
const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}questions`, {
94+
method: "POST",
95+
headers: {
96+
'Content-Type': 'application/json',
97+
},
98+
body: JSON.stringify(question),
99+
});
100+
101+
if (!response.ok) {
102+
// Attempt to parse error message from server
103+
let errorMessage = `Error creating question: ${response.status} ${response.statusText}`;
104+
try {
105+
const errorData = await response.json();
106+
if (errorData && errorData.error) {
107+
errorMessage = `Error creating question: ${errorData.error}`;
108+
}
109+
} catch (e) {
110+
// If response is not JSON, keep the default error message
111+
}
112+
throw new Error(errorMessage);
113+
}
114+
115+
const createdQuestion: Question = await response.json();
116+
return createdQuestion;
117+
} catch (error) {
118+
console.error("CreateQuestion failed:", error);
119+
throw error;
120+
}
121+
};
122+
83123
// Update single question (TODO: Sean)
84124

125+
85126
// Delete single question (TODO: Ryan)
86127
export async function DeleteQuestion(docRef: String): Promise<void> {
87128
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}questions/${docRef}`, {

apps/question-service/src/app/styles.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,12 @@
5353
.order-select {
5454
width: 100%;
5555
}
56+
57+
.create-title,
58+
.new-problem-categories-multi-select,
59+
.new-problem-difficulty-select,
60+
.create-description,
61+
.create-problem-id {
62+
width: 100%;
63+
margin: 5px;
64+
}

0 commit comments

Comments
 (0)