Skip to content

Commit 3fbaf1e

Browse files
committed
feature/2-implement-endpoint
1 parent ff183af commit 3fbaf1e

File tree

5 files changed

+235
-111
lines changed

5 files changed

+235
-111
lines changed

backend/flaskr/__init__.py

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import os
2-
from flask import Flask, request, abort, jsonify
2+
from flask import Flask, request, abort, jsonify, Response
33
from flask_sqlalchemy import SQLAlchemy
44
from flask_cors import CORS
55
import random
6+
from sqlalchemy import delete
67

7-
from models import setup_db, Question, Category
8+
from models import db, setup_db, Question, Category
89

910
QUESTIONS_PER_PAGE = 10
1011

@@ -46,13 +47,12 @@ def get_categories():
4647
start = (page - 1) * 10
4748
end = start + 10
4849

49-
categories = Category.query.all()
50-
formatted_categories = [category.format() for category in categories]
50+
categories = get_all_formatted_category()
5151

5252
return jsonify({
5353
'success': True,
54-
'categories': formatted_categories[start:end],
55-
'total_categories': len(formatted_categories)
54+
'categories': categories[start:end],
55+
'total_categories': len(categories)
5656
})
5757

5858
"""
@@ -67,15 +67,14 @@ def get_categories():
6767
ten questions per page and pagination at the bottom of the screen for three pages.
6868
Clicking on the page numbers should update the questions.
6969
"""
70-
@app.route('/questions')
70+
@app.route('/questions', methods=['GET'])
7171
def get_questions():
7272
# Implement pagination
7373
page = request.args.get('page', 1, type=int)
7474
start = (page - 1) * 10
7575
end = start + 10
7676

77-
categories = Category.query.all()
78-
formatted_categories = [category.format() for category in categories]
77+
categories = get_all_formatted_category()
7978

8079
questions = Question.query.all()
8180
formatted_questions = [question.format() for question in questions]
@@ -84,7 +83,7 @@ def get_questions():
8483
'success': True,
8584
'questions': formatted_questions[start:end],
8685
'total_questions': len(formatted_questions),
87-
'categories': formatted_categories,
86+
'categories': categories
8887
})
8988

9089
"""
@@ -94,6 +93,32 @@ def get_questions():
9493
TEST: When you click the trash icon next to a question, the question will be removed.
9594
This removal will persist in the database and when you refresh the page.
9695
"""
96+
@app.route('/questions/<int:id>', methods=['DELETE'])
97+
def delete_question(id):
98+
id_question = int(id)
99+
100+
try:
101+
question = Question.query.filter(Question.id == id_question).one_or_none()
102+
103+
if question is None:
104+
handle_error(404, 'Error: question not found')
105+
106+
db.session.delete(question)
107+
db.session.commit()
108+
except:
109+
handle_error(422, 'An error occurred!')
110+
111+
return jsonify({
112+
'success': True,
113+
'message': "deleted successfully"
114+
})
115+
116+
# return jsonify({
117+
# 'success': True,
118+
# 'deleted': id_question,
119+
# 'question': current_questions,
120+
# 'total_question': len(current_questions)
121+
# })
97122

98123
"""
99124
@TODO:
@@ -105,6 +130,24 @@ def get_questions():
105130
the form will clear and the question will appear at the end of the last page
106131
of the questions list in the "List" tab.
107132
"""
133+
@app.route('/questions', methods=['POST'])
134+
def create_question():
135+
body = request.get_json()
136+
new_question = body.get('question', None)
137+
new_answer = body.get('answer', None)
138+
new_difficulty = body.get('difficulty', None)
139+
new_category = body.get('category', None)
140+
141+
try:
142+
question = Question(question=new_question, answer=new_answer, category=int(new_category), difficulty=int(new_difficulty))
143+
question.insert()
144+
except:
145+
handle_error(422, 'An error occurred!')
146+
147+
return({
148+
'success': True,
149+
'message': 'Create successfully!'
150+
})
108151

109152
"""
110153
@TODO:
@@ -116,6 +159,22 @@ def get_questions():
116159
only question that include that string within their question.
117160
Try using the word "title" to start.
118161
"""
162+
@app.route('/questions/search', methods=['POST'])
163+
def search_questions():
164+
page = request.args.get('page', 1, type=int)
165+
start = (page - 1) * 10
166+
end = start + 10
167+
168+
body = request.get_json()
169+
key_word = body['searchTerm']
170+
questions = db.session.query(Question).filter(Question.question.ilike(f'%{key_word}%')).all()
171+
formatted_questions = [question.format() for question in questions]
172+
173+
return jsonify({
174+
'success': True,
175+
'questions': formatted_questions[start:end],
176+
'total_questions': len(formatted_questions),
177+
})
119178

120179
"""
121180
@TODO:
@@ -125,6 +184,25 @@ def get_questions():
125184
categories in the left column will cause only questions of that
126185
category to be shown.
127186
"""
187+
@app.route("/categories/<int:id>/questions")
188+
def get_all_question(id):
189+
# Implement pagination
190+
page = request.args.get('page', 1, type=int)
191+
start = (page - 1) * 10
192+
end = start + 10
193+
194+
id_category = int(id)
195+
categories = Category.query.filter_by(id=id_category).all()
196+
formatted_categories = [category.format() for category in categories]
197+
questions = Question.query.filter_by(category=id_category).all()
198+
formatted_questions = [question.format() for question in questions]
199+
200+
return jsonify({
201+
'success': True,
202+
'questions': formatted_questions[start:end],
203+
'total_questions': len(formatted_questions),
204+
'currentCategory': formatted_categories[0]
205+
})
128206

129207
"""
130208
@TODO:
@@ -137,12 +215,46 @@ def get_questions():
137215
one question at a time is displayed, the user is allowed to answer
138216
and shown whether they were correct or not.
139217
"""
218+
@app.route("/quizzes", methods=['POST'])
219+
def get_question_to_play():
220+
data = request.get_json()
221+
previous_questions = data.get('previous_questions')
222+
quiz_category = data.get('quiz_category')
223+
result = None
224+
questions = []
225+
226+
# get all questions
227+
if quiz_category['id'] is 0:
228+
questions = Question.query.all()
229+
else:
230+
questions = Question.query.filter_by(category=quiz_category['id']).all()
231+
232+
format_questions = [question.format() for question in questions]
233+
if len(format_questions) != 0:
234+
if len(previous_questions) is 0:
235+
result = format_questions[0]
236+
else:
237+
data = [question for question in format_questions if question['id'] not in previous_questions]
238+
if len(data) != 0:
239+
result = data[0]
240+
241+
return jsonify({
242+
'question': result
243+
})
140244

141245
"""
142246
@TODO:
143247
Create error handlers for all expected errors
144248
including 404 and 422.
145249
"""
250+
def handle_error(code, message):
251+
error_message = ({'message': message})
252+
abort(Response(error_message, code))
253+
254+
def get_all_formatted_category():
255+
categories = Category.query.all()
256+
formatted_categories = [category.format() for category in categories]
257+
return formatted_categories
146258

147259
return app
148260

frontend/src/components/FormView.js

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,52 @@
1-
import React, { Component } from 'react';
2-
import $ from 'jquery';
3-
import '../stylesheets/FormView.css';
1+
import React, { Component } from "react";
2+
import $ from "jquery";
3+
import "../stylesheets/FormView.css";
44

55
class FormView extends Component {
66
constructor(props) {
77
super();
88
this.state = {
9-
question: '',
10-
answer: '',
9+
question: "",
10+
answer: "",
1111
difficulty: 1,
1212
category: 1,
13-
categories: {},
13+
categories: [],
1414
};
1515
}
1616

1717
componentDidMount() {
1818
$.ajax({
1919
url: `/categories`, //TODO: update request URL
20-
type: 'GET',
20+
type: "GET",
2121
success: (result) => {
22+
console.log(result);
2223
this.setState({ categories: result.categories });
2324
return;
2425
},
2526
error: (error) => {
26-
alert('Unable to load categories. Please try your request again');
27+
alert("Unable to load categories. Please try your request again");
2728
return;
2829
},
2930
});
3031
}
3132

3233
submitQuestion = (event) => {
34+
if (
35+
!this.state.question ||
36+
!this.state.answer ||
37+
!this.state.question.trim() ||
38+
!this.state.answer.trim()
39+
) {
40+
alert("The question or answer is invalid!");
41+
return;
42+
}
43+
3344
event.preventDefault();
3445
$.ajax({
35-
url: '/questions', //TODO: update request URL
36-
type: 'POST',
37-
dataType: 'json',
38-
contentType: 'application/json',
46+
url: "/questions", //TODO: update request URL
47+
type: "POST",
48+
dataType: "json",
49+
contentType: "application/json",
3950
data: JSON.stringify({
4051
question: this.state.question,
4152
answer: this.state.answer,
@@ -47,11 +58,11 @@ class FormView extends Component {
4758
},
4859
crossDomain: true,
4960
success: (result) => {
50-
document.getElementById('add-question-form').reset();
61+
document.getElementById("add-question-form").reset();
5162
return;
5263
},
5364
error: (error) => {
54-
alert('Unable to add question. Please try your request again');
65+
alert("Unable to add question. Please try your request again");
5566
return;
5667
},
5768
});
@@ -63,44 +74,44 @@ class FormView extends Component {
6374

6475
render() {
6576
return (
66-
<div id='add-form'>
77+
<div id="add-form">
6778
<h2>Add a New Trivia Question</h2>
6879
<form
69-
className='form-view'
70-
id='add-question-form'
80+
className="form-view"
81+
id="add-question-form"
7182
onSubmit={this.submitQuestion}
7283
>
7384
<label>
7485
Question
75-
<input type='text' name='question' onChange={this.handleChange} />
86+
<input type="text" name="question" onChange={this.handleChange} />
7687
</label>
7788
<label>
7889
Answer
79-
<input type='text' name='answer' onChange={this.handleChange} />
90+
<input type="text" name="answer" onChange={this.handleChange} />
8091
</label>
8192
<label>
8293
Difficulty
83-
<select name='difficulty' onChange={this.handleChange}>
84-
<option value='1'>1</option>
85-
<option value='2'>2</option>
86-
<option value='3'>3</option>
87-
<option value='4'>4</option>
88-
<option value='5'>5</option>
94+
<select name="difficulty" onChange={this.handleChange}>
95+
<option value="1">1</option>
96+
<option value="2">2</option>
97+
<option value="3">3</option>
98+
<option value="4">4</option>
99+
<option value="5">5</option>
89100
</select>
90101
</label>
91102
<label>
92103
Category
93-
<select name='category' onChange={this.handleChange}>
94-
{Object.keys(this.state.categories).map((id) => {
104+
<select name="category" onChange={this.handleChange}>
105+
{this.state.categories.map((category) => {
95106
return (
96-
<option key={id} value={id}>
97-
{this.state.categories[id]}
107+
<option key={category.id} value={category.id}>
108+
{category.type}
98109
</option>
99110
);
100111
})}
101112
</select>
102113
</label>
103-
<input type='submit' className='button' value='Submit' />
114+
<input type="submit" className="button" value="Submit" />
104115
</form>
105116
</div>
106117
);

0 commit comments

Comments
 (0)