Skip to content

Commit 5307cc3

Browse files
authored
Merge pull request #70 from hastagAB/edit/edu
Add Education POST and PUT Endpoints with File Upload Support
2 parents b605484 + ba98e85 commit 5307cc3

File tree

5 files changed

+218
-38
lines changed

5 files changed

+218
-38
lines changed

app.py

+77-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Flask Application for Resume Management
33
"""
4+
45
import os
56
import logging
67

@@ -10,7 +11,13 @@
1011
from werkzeug.utils import secure_filename
1112
from flask import Flask, jsonify, request, send_from_directory
1213
from models import Experience, Education, Skill, UserInformation
13-
from helpers import validate_fields, validate_phone_number, load_data, save_data, generate_id
14+
from helpers import (
15+
validate_fields,
16+
validate_phone_number,
17+
load_data,
18+
save_data,
19+
generate_id,
20+
)
1421

1522

1623
spell = SpellChecker()
@@ -26,7 +33,8 @@
2633
CORS(app)
2734
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
2835

29-
data = load_data('data/data.json')
36+
data = load_data("data/data.json")
37+
3038

3139
def reset_data():
3240
"""
@@ -61,7 +69,7 @@ def reset_data():
6169
]
6270

6371

64-
#reset_data()
72+
# reset_data()
6573

6674

6775
def allowed_file(filename):
@@ -157,7 +165,7 @@ def experience():
157165
logo_filename = filename
158166

159167
# Create new experience
160-
new_id = generate_id(data, 'experience')
168+
new_id = generate_id(data, "experience")
161169

162170
# Create new experience
163171
new_experience = Experience(
@@ -170,9 +178,12 @@ def experience():
170178
new_id,
171179
)
172180
data["experience"].append(new_experience)
173-
save_data('data/data.json', data)
181+
save_data("data/data.json", data)
174182
new_experience_index = len(data["experience"]) - 1
175-
return jsonify({"message": "New experience created", "id": new_experience_index}), 201
183+
return (
184+
jsonify({"message": "New experience created", "id": new_experience_index}),
185+
201,
186+
)
176187

177188
return 400
178189

@@ -191,15 +202,20 @@ def delete_experience(index):
191202
@app.route("/resume/education", methods=["GET", "POST"])
192203
def education():
193204
"""
194-
Handle education requests for GET and POST methods
205+
Handle education requests for GET and POST methods.
206+
POST: Add a new education entry with optional file upload.
195207
"""
196208
if request.method == "GET":
197209
return jsonify([edu.__dict__ for edu in data["education"]]), 200
198210

199211
if request.method == "POST":
200-
request_body = request.get_json()
212+
if request.content_type.startswith('multipart/form-data'):
213+
request_body = request.form
214+
else:
215+
request_body = request.get_json()
216+
201217
if not request_body:
202-
return jsonify({"error": "Request must be JSON"}), 400
218+
return jsonify({"error": "Request must be JSON or include form data"}), 400
203219

204220
required_fields = {
205221
"course": str,
@@ -219,21 +235,28 @@ def education():
219235
"invalid_fields": invalid_fields
220236
}), 400
221237

238+
logo_filename = DEFAULT_LOGO
239+
if "logo" in request.files:
240+
logo_file = request.files["logo"]
241+
if logo_file and allowed_file(logo_file.filename):
242+
filename = secure_filename(logo_file.filename)
243+
logo_file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
244+
logo_filename = filename
245+
222246
new_id = generate_id(data, 'education')
223247

224-
# Create new education entry
225248
new_education = Education(
226249
request_body["course"],
227250
request_body["school"],
228251
request_body["start_date"],
229252
request_body["end_date"],
230253
request_body["grade"],
231-
DEFAULT_LOGO,
254+
logo_filename,
232255
new_id
233256
)
234257
data["education"].append(new_education)
235258
save_data('data/data.json', data)
236-
new_education_index = new_id - 1
259+
new_education_index = len(data["education"]) - 1
237260
return jsonify({"message": "New education created", "id": new_education_index}), 201
238261

239262
return 400
@@ -270,6 +293,42 @@ def delete_education(index):
270293
return jsonify({"error": "Education entry not found"}), 404
271294

272295

296+
@app.route("/resume/education/<int:index>", methods=["PUT"])
297+
def update_education(index):
298+
"""
299+
Update education entry by index.
300+
Supports updating both text fields and file upload for logo.
301+
"""
302+
if 0 <= index < len(data["education"]):
303+
if request.content_type.startswith('multipart/form-data'):
304+
request_body = request.form
305+
else:
306+
request_body = request.get_json()
307+
308+
if not request_body:
309+
return jsonify({"error": "Request must be JSON or include form data"}), 400
310+
311+
edu = data["education"][index]
312+
313+
edu.course = request_body.get("course", edu.course)
314+
edu.school = request_body.get("school", edu.school)
315+
edu.start_date = request_body.get("start_date", edu.start_date)
316+
edu.end_date = request_body.get("end_date", edu.end_date)
317+
edu.grade = request_body.get("grade", edu.grade)
318+
319+
if "logo" in request.files:
320+
logo_file = request.files["logo"]
321+
if logo_file and allowed_file(logo_file.filename):
322+
filename = secure_filename(logo_file.filename)
323+
logo_file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
324+
edu.logo = filename
325+
326+
save_data('data/data.json', data)
327+
return jsonify({"message": "Education entry updated", "id": index}), 200
328+
329+
return jsonify({"error": "Education entry not found"}), 404
330+
331+
273332
@app.route("/resume/skill", methods=["GET", "POST"])
274333
def skill():
275334
"""
@@ -319,8 +378,11 @@ def skill():
319378
)
320379
data["skill"].append(new_skill)
321380

322-
save_data('data/data.json', data)
323-
return jsonify({"message": "New skill created", "id": len(data["skill"]) - 1}), 201
381+
save_data("data/data.json", data)
382+
return (
383+
jsonify({"message": "New skill created", "id": len(data["skill"]) - 1}),
384+
201,
385+
)
324386

325387
return 400
326388

@@ -356,7 +418,7 @@ def delete_skill(index):
356418
if 0 <= index < len(data["skill"]):
357419
removed_skill = data["skill"].pop(index)
358420
logging.info("Skill deleted: %s", removed_skill.name)
359-
save_data('data/data.json', data)
421+
save_data("data/data.json", data)
360422
return jsonify({"message": "Skill successfully deleted"}), 200
361423
return jsonify({"error": "Skill not found"}), 404
362424

data/data.json

+27
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,33 @@
7373
"grade": "86%",
7474
"logo": "default.jpg",
7575
"id": 3
76+
},
77+
{
78+
"course": "Engineering",
79+
"school": "NYU",
80+
"start_date": "October 2022",
81+
"end_date": "August 2024",
82+
"grade": "86%",
83+
"logo": "default.jpg",
84+
"id": 4
85+
},
86+
{
87+
"course": "Computer Science",
88+
"school": "University of Awesome",
89+
"start_date": "2020",
90+
"end_date": "2024",
91+
"grade": "A",
92+
"logo": "test-logo.jpg",
93+
"id": 5
94+
},
95+
{
96+
"course": "Updated Engineering",
97+
"school": "Updated NYU",
98+
"start_date": "October 2023",
99+
"end_date": "August 2025",
100+
"grade": "90%",
101+
"logo": "updated-logo.jpg",
102+
"id": 6
76103
}
77104
],
78105
"skill": [],

0 commit comments

Comments
 (0)