base
1import json 2import bcrypt 3from flask_pymongo import PyMongo 4from flask import Flask, request, jsonify 5from flask_pymongo import PyMongo 6from pymongo import MongoClient 7import mongomock 8from datetime import datetime, timedelta, timezone 9from flask_jwt_extended import create_access_token,get_jwt,get_jwt_identity, \ 10 unset_jwt_cookies, jwt_required, JWTManager 11from datetime import datetime, timedelta 12from functools import reduce 13from bson import json_util 14from pymongo import MongoClient 15from flasgger import Swagger 16 17 18 19api = Flask(__name__) 20api.secret_key = 'secret' 21api.config["JWT_SECRET_KEY"] = "softwareEngineering" 22api.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=1) 23jwt = JWTManager(api) 24mongo = None 25 26Swagger(api) 27 28 29def setup_mongo_client(app): 30 global mongo 31 if app.config['TESTING']: 32 # Use mongomock for testing 33 app.mongo_client = mongomock.MongoClient() 34 mongo = app.mongo_client["test"] 35 else: 36 # Use a real MongoDB connection for production 37 app.mongo_client = MongoClient('localhost', 27017) 38 mongo = app.mongo_client["test"] 39 40# Call setup_mongo_client during normal (non-test) app initialization 41setup_mongo_client(api) 42 43@api.route('/token', methods=["POST"]) # pragma: no cover 44def create_token(): 45 """ 46 Create a new access token 47 48 --- 49 tags: 50 - Authentication 51 parameters: 52 - name: email 53 in: formData 54 type: string 55 required: true 56 description: User email 57 - name: password 58 in: formData 59 type: string 60 required: true 61 description: User password 62 responses: 63 200: 64 description: Login successful 65 401: 66 description: Invalid email or password 67 """ 68 email = request.json.get("email", None) 69 password = request.json.get("password", None) 70 user = mongo.user.find_one({"email": email}) 71 if (user is not None and (user["password"] == password)): 72 access_token = create_access_token(identity=email) 73 return jsonify({"message": "Login successful", "access_token":access_token}) 74 else: 75 print("Invalid email or password") 76 return jsonify({"message": "Invalid email or password"}),401 77 78@api.route("/google-login", methods=["POST"]) 79def google_login(): 80 email = request.json.get("email", None) 81 firstName = request.json.get("first_name", None) 82 lastName = request.json.get("last_name", None) 83 user = mongo.user.find_one({"email": email}) 84 if (user is None): 85 mongo.user.insert_one({"email": email, "first_name": firstName, "last_name": lastName}) 86 access_token = create_access_token(identity=email) 87 return jsonify({"message": "Login successful", "access_token":access_token}) 88 89 90 91@api.route("/register", methods=["POST"]) 92def register(): 93 """ 94 Register a new user 95 96 --- 97 tags: 98 - User Registration 99 parameters: 100 - name: email 101 in: formData 102 type: string 103 required: true 104 description: User email 105 - name: password 106 in: formData 107 type: string 108 required: true 109 description: User password 110 - name: firstName 111 in: formData 112 type: string 113 required: true 114 description: User's first name 115 - name: lastName 116 in: formData 117 type: string 118 required: true 119 description: User's last name 120 responses: 121 200: 122 description: Registration successful 123 409: 124 description: User already exists 125 500: 126 description: Registration failed 127 """ 128 129 email = request.json.get('email', None) 130 password = request.json.get('password', None) 131 first_name = request.json.get('firstName', None) 132 last_name = request.json.get('lastName', None) 133 new_document = { 134 "email": email, 135 "password": password, 136 "first_name": first_name, 137 "last_name": last_name, 138 } 139 query = { 140 "email": email, 141 } 142 try: 143 inserted = mongo.user.update_one(query, {"$set": new_document}, upsert=True) 144 if (inserted.upserted_id): 145 response = jsonify({"msg": "register successful"}) 146 else: 147 print("User already exists") 148 response = jsonify({"msg": "User already exists"}) 149 except Exception as e: 150 response = jsonify({"msg": "register failed"}) 151 152 return response 153 154@api.route("/logout", methods=["POST"]) 155def logout(): 156 """ 157 Logout the user and clear their session 158 159 --- 160 tags: 161 - User Logout 162 responses: 163 200: 164 description: Logout successful 165 """ 166 response = jsonify({"msg": "logout successful"}) 167 unset_jwt_cookies(response) 168 return response 169 170@api.route('/events', methods=['GET']) 171def get_events(): 172 """ 173 Retrieve a list of events 174 175 This endpoint retrieves a list of events from the database. 176 177 --- 178 tags: 179 - Events 180 responses: 181 200: 182 description: A list of events 183 schema: 184 type: array 185 items: 186 type: object 187 properties: 188 _id: 189 type: string 190 # Add more properties as needed 191 404: 192 description: No events found 193 """ 194 events_collection = mongo.events 195 events = list(events_collection.find({})) 196 for event in events: 197 event["_id"] = str(event["_id"]) # Convert ObjectId to string 198 return jsonify(events) 199 200@api.route('/is-enrolled', methods=['POST']) 201@jwt_required() 202def is_enrolled(): 203 """ 204 Check if the user is enrolled in an event 205 206 This endpoint checks if the authenticated user is enrolled in a specific event. 207 208 --- 209 tags: 210 - Events 211 parameters: 212 - in: body 213 name: data 214 description: Data containing the eventTitle 215 required: true 216 schema: 217 type: object 218 properties: 219 eventTitle: 220 type: string 221 example: 222 eventTitle: "Event Name" 223 security: 224 - JWT: [] 225 responses: 226 200: 227 description: Indicates whether the user is enrolled 228 schema: 229 type: object 230 properties: 231 isEnrolled: 232 type: boolean 233 401: 234 description: Unauthorized access 235 """ 236 237 data = request.json 238 eventTitle = data['eventTitle'] 239 current_user = get_jwt_identity() 240 enrollment = mongo.user.find_one({"email": current_user, "eventTitle": eventTitle}) 241 242 if enrollment: 243 return jsonify({"isEnrolled": True}) 244 else: 245 return jsonify({"isEnrolled": False}) 246 247 248@api.route('/enroll', methods=['POST']) # pragma: no cover 249@jwt_required() 250def enroll_event(): # pragma: no cover 251 """ 252 Enroll the user in an event 253 254 This endpoint allows an authenticated user to enroll in an event. 255 256 --- 257 tags: 258 - Events 259 parameters: 260 - in: body 261 name: data 262 description: Data containing the eventTitle 263 required: true 264 schema: 265 type: object 266 properties: 267 eventTitle: 268 type: string 269 example: 270 eventTitle: "Event Name" 271 security: 272 - JWT: [] 273 responses: 274 200: 275 description: User successfully enrolled in the event 276 schema: 277 type: object 278 properties: 279 status: 280 type: string 281 example: "Data saved successfully" 282 500: 283 description: An error occurred while enrolling the user 284 """ 285 data = request.get_json() # get data from POST request 286 current_user = get_jwt_identity() 287 try: 288 # Insert data into MongoDB 289 mongo.user.insert_one({ 290 "email": current_user, 291 "eventTitle": data['eventTitle'] 292 }) 293 response = {"status": "Data saved successfully"} 294 except Exception as e: 295 response = {"status": "Error", "message": str(e)} 296 297 return jsonify(response) 298 299@api.route('/unenroll', methods=['POST']) # pragma: no cover 300@jwt_required() 301def unenroll_event(): # pragma: no cover 302 """ 303 Unenroll the user from an event 304 305 This endpoint allows an authenticated user to unenroll from an event. 306 307 --- 308 tags: 309 - Events 310 parameters: 311 - in: body 312 name: data 313 description: Data containing the eventTitle 314 required: true 315 schema: 316 type: object 317 properties: 318 eventTitle: 319 type: string 320 example: 321 eventTitle: "Event Name" 322 security: 323 - JWT: [] 324 responses: 325 200: 326 description: User successfully unenrolled from the event 327 schema: 328 type: object 329 properties: 330 status: 331 type: string 332 example: "Data saved successfully" 333 500: 334 description: An error occurred while unenrolling the user 335 """ 336 data = request.get_json() # get data from POST request 337 current_user = get_jwt_identity() 338 try: 339 # Insert data into MongoDB 340 mongo.user.delete_one({ 341 "email": current_user, 342 "eventTitle": data['eventTitle'] 343 }) 344 response = {"status": "Data saved successfully"} 345 except Exception as e: 346 response = {"status": "Error", "message": str(e)} 347 348 return jsonify(response) 349 350@api.route('/profile') 351@jwt_required() 352def my_profile(): # pragma: no cover 353 """ 354 Retrieve user profile information 355 356 This endpoint allows an authenticated user to retrieve their profile information. 357 358 --- 359 tags: 360 - User 361 security: 362 - JWT: [] 363 responses: 364 200: 365 description: User profile information retrieved successfully 366 schema: 367 type: object 368 example: 369 { 370 "_id": "12345", 371 "email": "user@example.com", 372 "first_name": "John", 373 "last_name": "Doe", 374 "age": 30, 375 "weight": 70, 376 "height": 175 377 } 378 401: 379 description: Unauthorized. User must be logged in to access their profile. 380 404: 381 description: User profile not found. 382 500: 383 description: An error occurred while retrieving the user profile. 384 """ 385 current_user = get_jwt_identity() 386 profile = mongo.user.find_one({"email": current_user}) 387 return jsonify(json_util.dumps(profile)) 388 389@api.route('/caloriesConsumed',methods=["POST"]) 390@jwt_required() 391def addUserConsumedCalories(): # pragma: no cover 392 """ 393 Add consumed calories for a user 394 395 This endpoint allows an authenticated user to add consumed calories for a specific date. 396 397 --- 398 tags: 399 - User 400 security: 401 - JWT: [] 402 parameters: 403 - name: body 404 in: body 405 required: true 406 schema: 407 type: object 408 properties: 409 intakeDate: 410 type: string 411 format: date 412 description: The date for which calories are being recorded (e.g., "2023-10-17"). 413 intakeFoodItem: 414 type: string 415 description: The name of the food item. 416 intakeCalories: 417 type: integer 418 description: The number of calories consumed for the food item. 419 responses: 420 200: 421 description: Calories consumed data saved successfully. 422 schema: 423 type: object 424 example: 425 { 426 "status": "Data saved successfully" 427 } 428 401: 429 description: Unauthorized. User must be logged in to add consumed calories. 430 500: 431 description: An error occurred while saving consumed calories data. 432 """ 433 data = request.get_json() # get data from POST request 434 current_user = get_jwt_identity() 435 try: 436 # Insert data into MongoDB 437 mongo.user.update_one({'email': current_user, "consumedDate": data['intakeDate']}, {"$push": {"foodConsumed": {"item":data["intakeFoodItem"],"calories":data["intakeCalories"]}}}, upsert=True) 438 response = {"status": "Data saved successfully"} 439 statusCode = 200 440 except Exception as e: 441 response = {"status": "Error", "message": str(e)} 442 statusCode = 500 443 return jsonify(response),statusCode 444 445@api.route('/profileUpdate',methods=["POST"]) 446@jwt_required() 447def profileUpdate(): # pragma: no cover 448 """ 449 Update user profile 450 451 This endpoint allows an authenticated user to update their profile information. 452 453 --- 454 tags: 455 - User 456 security: 457 - JWT: [] 458 parameters: 459 - name: body 460 in: body 461 required: true 462 schema: 463 type: object 464 properties: 465 firstName: 466 type: string 467 description: The user's first name. 468 lastName: 469 type: string 470 description: The user's last name. 471 age: 472 type: integer 473 description: The user's age. 474 weight: 475 type: number 476 description: The user's weight. 477 height: 478 type: number 479 description: The user's height. 480 sex: 481 type: string 482 description: The user's sex. 483 responses: 484 200: 485 description: User profile updated successfully. 486 schema: 487 type: object 488 example: 489 { 490 "msg": "Update successful" 491 } 492 401: 493 description: Unauthorized. User must be logged in to update their profile. 494 500: 495 description: An error occurred while updating the user's profile. 496 """ 497 current_user = get_jwt_identity() 498 first_name = request.json.get('firstName', None) 499 last_name = request.json.get('lastName', None) 500 age = request.json.get('age', None) 501 weight = request.json.get('weight', None) 502 height = request.json.get('height', None) 503 sex = request.json.get('sex', None) 504 activityLevel = request.json.get('activityLevel', None) 505 bmi = (0.453*float(weight))/((0.3048*float(height))**2) 506 bmi = round(bmi,2) 507 tdee = calculate_tdee(height, weight, age, sex, activityLevel) 508 new_document = { 509 "first_name": first_name, 510 "last_name": last_name, 511 "age": age, 512 "weight": weight, 513 "height": height, 514 "sex": sex, 515 "bmi": bmi, 516 "target_calories": tdee, 517 } 518 query = { 519 "email": current_user, 520 } 521 try: 522 mongo.user.update_one(query, {"$set": new_document}, upsert=True) 523 response = jsonify({"msg": "update successful"}) 524 except Exception as e: 525 response = jsonify({"msg": "update failed"}) 526 527 return response 528 529@api.route('/goalsUpdate',methods=["POST"]) 530@jwt_required() 531def goalsUpdate(): # pragma: no cover 532 """ 533 Update user goals 534 535 This endpoint allows an authenticated user to update their fitness goals, such as target weight, target calories, and target goal. 536 537 --- 538 tags: 539 - User 540 security: 541 - JWT: [] 542 parameters: 543 - name: body 544 in: body 545 required: true 546 schema: 547 type: object 548 properties: 549 targetWeight: 550 type: number 551 description: The user's target weight goal. 552 targetCalories: 553 type: number 554 description: The user's target daily calorie intake goal. 555 activityLevel: 556 type: string 557 description: The user's activity level. 558 responses: 559 200: 560 description: User goals updated successfully. 561 schema: 562 type: object 563 example: 564 { 565 "msg": "Update successful" 566 } 567 401: 568 description: Unauthorized. User must be logged in to update their goals. 569 500: 570 description: An error occurred while updating the user's goals. 571 """ 572 current_user = get_jwt_identity() 573 targetWeight = request.json.get('targetWeight', None) 574 activityLevel = request.json.get('activityLevel', None) 575 576 new_document = { 577 "target_weight": targetWeight, 578 "activity_level": activityLevel 579 } 580 query = { 581 "email": current_user, 582 } 583 try: 584 profile = mongo.user.find_one(query) 585 tdee = calculate_tdee(profile["height"], profile["weight"], profile["age"], profile["sex"], activityLevel) 586 if tdee: 587 new_document["target_calories"] = tdee 588 mongo.user.update_one(query, {"$set": new_document}, upsert=True) 589 response = jsonify({"msg": "update successful"}) 590 except Exception as e: 591 response = jsonify({"msg": "update failed"}) 592 593 return response 594 595 596@api.route('/caloriesBurned',methods=["POST"]) 597@jwt_required() 598def addUserBurnedCalories(): # pragma: no cover 599 """ 600 Add user's burned calories 601 602 This endpoint allows an authenticated user to add information about calories burned on a specific date. 603 604 --- 605 tags: 606 - User 607 security: 608 - JWT: [] 609 parameters: 610 - name: body 611 in: body 612 required: true 613 schema: 614 type: object 615 properties: 616 burnoutDate: 617 type: string 618 format: date 619 description: The date on which calories were burned. 620 burntoutCalories: 621 type: number 622 description: The number of calories burned on the specified date. 623 responses: 624 200: 625 description: Calories burned data saved successfully. 626 schema: 627 type: object 628 example: 629 { 630 "status": "Data saved successfully" 631 } 632 401: 633 description: Unauthorized. User must be logged in to add burned calories data. 634 500: 635 description: An error occurred while saving the burned calories data. 636 """ 637 data = request.get_json() # get data from POST request 638 current_user = get_jwt_identity() 639 try: 640 # Insert data into MongoDB 641 mongo.user.update_one({'email': current_user, "consumedDate": data['burnoutDate']}, {"$inc": {"burntCalories": int(data["burntoutCalories"])}}, upsert=True) 642 response = {"status": "Data saved successfully"} 643 statusCode = 200 644 except Exception as e: 645 response = {"status": "Error", "message": str(e)} 646 statusCode = 500 647 return jsonify(response),statusCode 648 649@api.route('/createFood', methods=["POST"]) 650def createFood(): 651 """ 652 Create a custom food 653 654 This endpoint allows an authenticated user to create their custom food item with the amount of calories it has. 655 656 --- 657 tags: 658 - User 659 parameters: 660 - name: body 661 in: body 662 required: true 663 schema: 664 type: object 665 properties: 666 foodName: 667 type: string 668 format: food item name 669 description: The name of the food item being created. 670 calories: 671 type: number 672 description: The number of calories in the created food item. 673 responses: 674 200: 675 description: Food item created successfully 676 schema: 677 type: object 678 example: 679 { 680 "status": "Data saved successfully" 681 } 682 401: 683 description: Unauthorized. User must be logged in to create custom food. 684 500: 685 description: An error occurred while creating the custom food. 686 687 """ 688 data = request.get_json() # get data from POST request 689 foodName = data['foodName'] 690 calories = data['calories'] 691 try: 692 # Insert data into MongoDB 693 mongo.food.insert_one({'food': foodName, "calories": calories}) 694 response = {"status": "Data saved successfully"} 695 statusCode = 200 696 except Exception as e: 697 response = {"status": "Error", "message": str(e)} 698 statusCode = 500 699 return jsonify(response),statusCode 700 701@api.route('/createMeal', methods=["POST"]) 702@jwt_required() 703def createMeal(): 704 """ 705 Create a custom meal 706 707 This endpoint allows an authenticated user to create their own meals with different food items as the ingredients. 708 709 --- 710 tags: 711 - User 712 security: 713 - JWT: [] 714 parameters: 715 - name: body 716 in: body 717 required: true 718 schema: 719 type: object 720 properties: 721 mealName: 722 type: string 723 format: Meal name 724 description: The name of the meal item being created. 725 ingredients: 726 type: list 727 description: Is a list of the ingredients in the meal. 728 responses: 729 200: 730 description: Meal created successfully 731 schema: 732 type: object 733 example: 734 { 735 "status": "Data saved successfully" 736 } 737 401: 738 description: Unauthorized. User must be logged in to create custom meal. 739 500: 740 description: An error occurred while creating the custom meal. 741 742 """ 743 data = request.get_json() # get data from POST request 744 current_user = get_jwt_identity() 745 mealName = data['mealName'] 746 ingredients = data['ingredients'] 747 calories = 0 748 for item in ingredients: 749 food_item = mongo.food.find_one({"food": item}) 750 calories += int(food_item["calories"]) 751 try: 752 # Insert data into MongoDB 753 mongo.food.insert_one({'food': mealName, "calories": calories}) 754 mongo.user.insert_one({ 755 "email": current_user, 756 "meal_name": mealName, 757 "ingredients": ingredients, 758 "total_calories": calories 759 }) 760 response = {"status": "Data saved successfully"} 761 statusCode = 200 762 except Exception as e: 763 response = {"status": "Error", "message": str(e)} 764 statusCode = 500 765 return jsonify(response),statusCode 766 767@api.route('/weekHistory',methods=["POST"]) 768@jwt_required() 769def getWeekHistory(): # pragma: no cover 770 """ 771 Get user's weekly history 772 773 This endpoint allows an authenticated user to retrieve their food consumption and calories burned history for the past week. 774 775 --- 776 tags: 777 - User 778 security: 779 - JWT: [] 780 parameters: 781 - name: body 782 in: body 783 required: true 784 schema: 785 type: object 786 properties: 787 todayDate: 788 type: string 789 format: date 790 description: The date for the end of the week (today's date). 791 responses: 792 200: 793 description: Successfully retrieved the user's weekly history. 794 schema: 795 type: array 796 items: 797 type: object 798 properties: 799 dayIndex: 800 type: integer 801 description: Integer from 0 to 6 representing the day index. 802 date: 803 type: string 804 format: date 805 description: The date for each day in the week. 806 foodConsumed: 807 type: array 808 items: 809 type: object 810 properties: 811 item: 812 type: string 813 description: Food item name. 814 calories: 815 type: number 816 description: Calories consumed from the food item. 817 description: A list of dictionaries containing food items and their consumed calories. 818 caloriesConsumed: 819 type: number 820 description: The sum of all calories consumed for that day. 821 exceededDailyLimit: 822 type: boolean 823 description: Indicates whether the calories consumed exceeded the daily limit. 824 burntCalories: 825 type: number 826 description: Calories burned on that day. 827 example: 828 [ 829 { 830 "dayIndex": 0, 831 "date": "10/13/2023", 832 "foodConsumed": [ 833 { 834 "item": "Chicken Salad", 835 "calories": 500 836 }, 837 { 838 "item": "Onion Soup", 839 "calories": 300 840 }, 841 { 842 "item": "Potato Salad", 843 "calories": 500 844 }, 845 { 846 "item": "Cheese Burger", 847 "calories": 500 848 } 849 ], 850 "caloriesConsumed": 1800, 851 "exceededDailyLimit": false, 852 "burntCalories": 1200 853 }, 854 { 855 "dayIndex": 1, 856 "date": "10/12/2023", 857 "foodConsumed": [...], 858 "caloriesConsumed": ..., 859 "exceededDailyLimit": ..., 860 "burntCalories": ... 861 }, 862 ... 863 ] 864 401: 865 description: Unauthorized. User must be logged in to retrieve weekly history. 866 500: 867 description: An error occurred while retrieving the user's weekly history. 868 """ 869 data = request.get_json() # get data from POST request 870 current_user = get_jwt_identity() 871 todayDate = datetime.strptime(data["todayDate"],"%m/%d/%Y") 872 dates = [(todayDate-timedelta(days=x)).strftime("%m/%d/%Y") for x in range(7)] 873 calorieLimit = 1000 874 result = [] 875 try: 876 for index,dateToFind in enumerate(dates): 877 # Every day's res item should like this 878 # { 879 # dayIndex: 0, #Interger from 0-6 880 # date: "10/13/2023", #Date 0=today, 6=7th day ago from today 881 # foodConsumed: [ # A list of dicts, each dict contains a food item and its calories 882 # { 883 # item: "Chicken Salad", 884 # calories: 500, 885 # }, 886 # { 887 # item: "Onion Soup", 888 # calories: 300, 889 # }, 890 # { 891 # item: "Potato Salad", 892 # calories: 500, 893 # }, 894 # { 895 # item: "Cheese Burger", 896 # calories: 500, 897 # }, 898 # ], 899 # caloriesConsumed: 1800, # the sum of all calories consumed from above list 900 # exceededDailyLimit: false, # true or false based on whether caloriesConsumed is > limit user set 901 # burntCalories: 1200, # calories burnt out on that day 902 # } 903 res = {} 904 data = mongo.user.find_one({'email': current_user, "consumedDate": dateToFind}) 905 res["dayIndex"] = index 906 res["date"] = dateToFind 907 if data: 908 if "foodConsumed" in data: 909 res["foodConsumed"] = data["foodConsumed"] 910 res["caloriesConsumed"] = reduce(lambda a,b: a+b, [int(item["calories"]) for item in data["foodConsumed"]]) 911 res["exceededDailyLimit"] = res["caloriesConsumed"]>calorieLimit 912 if "burntCalories" in data: 913 res["burntCalories"] = data["burntCalories"] 914 if "foodConsumed" not in res: 915 res["foodConsumed"] = [] 916 if "caloriesConsumed" not in res: 917 res["caloriesConsumed"] = 0 918 if "burntCalories" not in res: 919 res["burntCalories"] = 0 920 if "exceededDailyLimit" not in res: 921 res["exceededDailyLimit"] = False 922 result.append(res) 923 response = result 924 statusCode = 200 925 except Exception as e: 926 response = {"status": "Error", "message": str(e)} 927 statusCode = 500 928 return jsonify(response),statusCode 929 930@api.route("/myMeals",methods=["GET"]) 931@jwt_required() 932def getMyMeals(): 933 """ 934 Get My Meals 935 936 This endpoint allows an authenticated user to retrieve the custom meals that they have created. 937 938 --- 939 tags: 940 - User 941 - Meals 942 security: 943 - JWT: [] 944 responses: 945 200: 946 description: Successfully retrieved the custom meals created by user 947 schema: 948 type: object 949 properties: 950 mealName: 951 type: string 952 description: Name of the custom meal 953 ingredients: 954 type: array 955 description: List of ingredients in the meal 956 example: 957 { 958 "mealName":"My meal", 959 "ingredients":["Eggs","Toast"], 960 } 961 401: 962 description: Unauthorized. User must be logged in to retrieve the food calorie mapping. 963 500: 964 description: An error occurred while retrieving the food calorie mapping. 965 """ 966 current_user = get_jwt_identity() 967 result = [] 968 try: 969 data = mongo.user.find({"email": current_user,"meal_name":{"$exists": True}}) 970 for meal in data: 971 cal_info = [] 972 for item in meal['ingredients']: 973 food_item = mongo.food.find_one({'food':item}) 974 cal_info.append({str(item):food_item['calories']}) 975 res={} 976 res['meal_name']=meal['meal_name'] 977 res['ingredients']=meal['ingredients'] 978 res['total_calories']=meal['total_calories'] 979 result.append(res) 980 response = result 981 statusCode = 200 982 except Exception as e: 983 response = {"status": "Error", "message": str(e)} 984 statusCode = 500 985 return jsonify(response),statusCode 986 987 988@api.route('/foodCalorieMapping',methods=["GET"]) 989@jwt_required() 990def getFoodCalorieMapping(): 991 """ 992 Get food calorie mapping 993 994 This endpoint allows an authenticated user to retrieve a mapping of food items to their respective calorie values. 995 996 --- 997 tags: 998 - Food 999 security: 1000 - JWT: [] 1001 responses: 1002 200: 1003 description: Successfully retrieved the food calorie mapping. 1004 schema: 1005 type: object 1006 properties: 1007 foodItem: 1008 type: integer 1009 description: Food item name. 1010 calories: 1011 type: number 1012 description: Calories associated with the food item. 1013 example: 1014 { 1015 "Potato": 50, 1016 "Acai": 20, 1017 "Cheeseburger": 80, 1018 ... 1019 } 1020 401: 1021 description: Unauthorized. User must be logged in to retrieve the food calorie mapping. 1022 500: 1023 description: An error occurred while retrieving the food calorie mapping. 1024 """ 1025 try: 1026 data = mongo.food.find() 1027 # Response should be in this format {foodItem: calories, foodItem: calories....} 1028 # For Example { Potato: 50, Acai: 20, Cheeseburger: 80 } 1029 response = {item["food"]:item["calories"] for item in data} 1030 statusCode = 200 1031 except Exception as e: 1032 response = {"status": "Error", "message": str(e)} 1033 statusCode = 500 1034 return jsonify(response),statusCode 1035 1036@api.route('/usersEvents',methods=["GET"]) 1037@jwt_required() 1038def getUserRegisteredEvents(): 1039 """ 1040 Get user's registered events 1041 1042 This endpoint allows an authenticated user to retrieve the events they are registered for. 1043 1044 --- 1045 tags: 1046 - Events 1047 security: 1048 - JWT: [] 1049 responses: 1050 200: 1051 description: Successfully retrieved the user's registered events. 1052 schema: 1053 type: array 1054 items: 1055 type: object 1056 properties: 1057 eventName: 1058 type: string 1059 description: Name of the event. 1060 date: 1061 type: string 1062 format: date 1063 description: Date of the event. 1064 example: 1065 [ 1066 { 1067 "eventName": "Yoga", 1068 "date": "2023-12-11" 1069 }, 1070 { 1071 "eventName": "Swimming", 1072 "date": "2023-11-10" 1073 }, 1074 ... 1075 ] 1076 401: 1077 description: Unauthorized. User must be logged in to retrieve their registered events. 1078 500: 1079 description: An error occurred while retrieving the user's registered events. 1080 """ 1081 try: 1082 # current_user = get_jwt_identity() 1083 current_user = get_jwt_identity() 1084 data = mongo.user.find({"email": current_user, "eventTitle":{"$exists": True}}) 1085 response = [] 1086 date="10/23/2023" 1087 for item in data: 1088 res = {"eventName": item["eventTitle"], "date": date} 1089 response.append(res) 1090 # Response should be in this format [{eventName: Yoga, date: "12/11/2023"},{eventName: Swimming, date: "11/10/2023"}] 1091 # For Example { Potato: 50, Acai: 20, Cheeseburger: 80 } 1092 statusCode = 200 1093 except Exception as e: 1094 response = {"status": "Error", "message": str(e)} 1095 statusCode = 500 1096 return jsonify(response),statusCode 1097 1098def calculate_tdee(height,weight,age,sex,activityLevel): 1099 if height and weight and age and sex and activityLevel: 1100 pass 1101 else: 1102 return None 1103 kg_weight = float(weight)*0.45359237 1104 cm_height = float(height)*30.48 1105 common_calc_for_male_female = (10*kg_weight) + (6.25*cm_height) - (5*int(age)) 1106 if sex == "Male": 1107 bmr = common_calc_for_male_female + 5 1108 else: 1109 bmr = common_calc_for_male_female - 161 1110 personal_activity_levels = {'Minimal': 1.2,'Light': 1.375, 'Moderate': 1.55, 'Heavy':1.725, 'Athlete': 1.9} 1111 tdee = int((bmr * personal_activity_levels[activityLevel])) 1112 return tdee
30def setup_mongo_client(app): 31 global mongo 32 if app.config['TESTING']: 33 # Use mongomock for testing 34 app.mongo_client = mongomock.MongoClient() 35 mongo = app.mongo_client["test"] 36 else: 37 # Use a real MongoDB connection for production 38 app.mongo_client = MongoClient('localhost', 27017) 39 mongo = app.mongo_client["test"]
44@api.route('/token', methods=["POST"]) # pragma: no cover 45def create_token(): 46 """ 47 Create a new access token 48 49 --- 50 tags: 51 - Authentication 52 parameters: 53 - name: email 54 in: formData 55 type: string 56 required: true 57 description: User email 58 - name: password 59 in: formData 60 type: string 61 required: true 62 description: User password 63 responses: 64 200: 65 description: Login successful 66 401: 67 description: Invalid email or password 68 """ 69 email = request.json.get("email", None) 70 password = request.json.get("password", None) 71 user = mongo.user.find_one({"email": email}) 72 if (user is not None and (user["password"] == password)): 73 access_token = create_access_token(identity=email) 74 return jsonify({"message": "Login successful", "access_token":access_token}) 75 else: 76 print("Invalid email or password") 77 return jsonify({"message": "Invalid email or password"}),401
Create a new access token
tags:
- Authentication parameters:
- name: email in: formData type: string required: true description: User email
- name: password in: formData type: string required: true description: User password responses: 200: description: Login successful 401: description: Invalid email or password
79@api.route("/google-login", methods=["POST"]) 80def google_login(): 81 email = request.json.get("email", None) 82 firstName = request.json.get("first_name", None) 83 lastName = request.json.get("last_name", None) 84 user = mongo.user.find_one({"email": email}) 85 if (user is None): 86 mongo.user.insert_one({"email": email, "first_name": firstName, "last_name": lastName}) 87 access_token = create_access_token(identity=email) 88 return jsonify({"message": "Login successful", "access_token":access_token})
92@api.route("/register", methods=["POST"]) 93def register(): 94 """ 95 Register a new user 96 97 --- 98 tags: 99 - User Registration 100 parameters: 101 - name: email 102 in: formData 103 type: string 104 required: true 105 description: User email 106 - name: password 107 in: formData 108 type: string 109 required: true 110 description: User password 111 - name: firstName 112 in: formData 113 type: string 114 required: true 115 description: User's first name 116 - name: lastName 117 in: formData 118 type: string 119 required: true 120 description: User's last name 121 responses: 122 200: 123 description: Registration successful 124 409: 125 description: User already exists 126 500: 127 description: Registration failed 128 """ 129 130 email = request.json.get('email', None) 131 password = request.json.get('password', None) 132 first_name = request.json.get('firstName', None) 133 last_name = request.json.get('lastName', None) 134 new_document = { 135 "email": email, 136 "password": password, 137 "first_name": first_name, 138 "last_name": last_name, 139 } 140 query = { 141 "email": email, 142 } 143 try: 144 inserted = mongo.user.update_one(query, {"$set": new_document}, upsert=True) 145 if (inserted.upserted_id): 146 response = jsonify({"msg": "register successful"}) 147 else: 148 print("User already exists") 149 response = jsonify({"msg": "User already exists"}) 150 except Exception as e: 151 response = jsonify({"msg": "register failed"}) 152 153 return response
Register a new user
tags:
- User Registration parameters:
- name: email in: formData type: string required: true description: User email
- name: password in: formData type: string required: true description: User password
- name: firstName in: formData type: string required: true description: User's first name
- name: lastName in: formData type: string required: true description: User's last name responses: 200: description: Registration successful 409: description: User already exists 500: description: Registration failed
155@api.route("/logout", methods=["POST"]) 156def logout(): 157 """ 158 Logout the user and clear their session 159 160 --- 161 tags: 162 - User Logout 163 responses: 164 200: 165 description: Logout successful 166 """ 167 response = jsonify({"msg": "logout successful"}) 168 unset_jwt_cookies(response) 169 return response
Logout the user and clear their session
tags:
- User Logout responses: 200: description: Logout successful
171@api.route('/events', methods=['GET']) 172def get_events(): 173 """ 174 Retrieve a list of events 175 176 This endpoint retrieves a list of events from the database. 177 178 --- 179 tags: 180 - Events 181 responses: 182 200: 183 description: A list of events 184 schema: 185 type: array 186 items: 187 type: object 188 properties: 189 _id: 190 type: string 191 # Add more properties as needed 192 404: 193 description: No events found 194 """ 195 events_collection = mongo.events 196 events = list(events_collection.find({})) 197 for event in events: 198 event["_id"] = str(event["_id"]) # Convert ObjectId to string 199 return jsonify(events)
Retrieve a list of events
This endpoint retrieves a list of events from the database.
tags:
- Events responses: 200: description: A list of events schema: type: array items: type: object properties: _id: type: string # Add more properties as needed 404: description: No events found
201@api.route('/is-enrolled', methods=['POST']) 202@jwt_required() 203def is_enrolled(): 204 """ 205 Check if the user is enrolled in an event 206 207 This endpoint checks if the authenticated user is enrolled in a specific event. 208 209 --- 210 tags: 211 - Events 212 parameters: 213 - in: body 214 name: data 215 description: Data containing the eventTitle 216 required: true 217 schema: 218 type: object 219 properties: 220 eventTitle: 221 type: string 222 example: 223 eventTitle: "Event Name" 224 security: 225 - JWT: [] 226 responses: 227 200: 228 description: Indicates whether the user is enrolled 229 schema: 230 type: object 231 properties: 232 isEnrolled: 233 type: boolean 234 401: 235 description: Unauthorized access 236 """ 237 238 data = request.json 239 eventTitle = data['eventTitle'] 240 current_user = get_jwt_identity() 241 enrollment = mongo.user.find_one({"email": current_user, "eventTitle": eventTitle}) 242 243 if enrollment: 244 return jsonify({"isEnrolled": True}) 245 else: 246 return jsonify({"isEnrolled": False})
Check if the user is enrolled in an event
This endpoint checks if the authenticated user is enrolled in a specific event.
tags:
- Events parameters:
- in: body name: data description: Data containing the eventTitle required: true schema: type: object properties: eventTitle: type: string example: eventTitle: "Event Name" security:
- JWT: [] responses: 200: description: Indicates whether the user is enrolled schema: type: object properties: isEnrolled: type: boolean 401: description: Unauthorized access
249@api.route('/enroll', methods=['POST']) # pragma: no cover 250@jwt_required() 251def enroll_event(): # pragma: no cover 252 """ 253 Enroll the user in an event 254 255 This endpoint allows an authenticated user to enroll in an event. 256 257 --- 258 tags: 259 - Events 260 parameters: 261 - in: body 262 name: data 263 description: Data containing the eventTitle 264 required: true 265 schema: 266 type: object 267 properties: 268 eventTitle: 269 type: string 270 example: 271 eventTitle: "Event Name" 272 security: 273 - JWT: [] 274 responses: 275 200: 276 description: User successfully enrolled in the event 277 schema: 278 type: object 279 properties: 280 status: 281 type: string 282 example: "Data saved successfully" 283 500: 284 description: An error occurred while enrolling the user 285 """ 286 data = request.get_json() # get data from POST request 287 current_user = get_jwt_identity() 288 try: 289 # Insert data into MongoDB 290 mongo.user.insert_one({ 291 "email": current_user, 292 "eventTitle": data['eventTitle'] 293 }) 294 response = {"status": "Data saved successfully"} 295 except Exception as e: 296 response = {"status": "Error", "message": str(e)} 297 298 return jsonify(response)
Enroll the user in an event
This endpoint allows an authenticated user to enroll in an event.
tags:
- Events parameters:
- in: body name: data description: Data containing the eventTitle required: true schema: type: object properties: eventTitle: type: string example: eventTitle: "Event Name" security:
- JWT: [] responses: 200: description: User successfully enrolled in the event schema: type: object properties: status: type: string example: "Data saved successfully" 500: description: An error occurred while enrolling the user
300@api.route('/unenroll', methods=['POST']) # pragma: no cover 301@jwt_required() 302def unenroll_event(): # pragma: no cover 303 """ 304 Unenroll the user from an event 305 306 This endpoint allows an authenticated user to unenroll from an event. 307 308 --- 309 tags: 310 - Events 311 parameters: 312 - in: body 313 name: data 314 description: Data containing the eventTitle 315 required: true 316 schema: 317 type: object 318 properties: 319 eventTitle: 320 type: string 321 example: 322 eventTitle: "Event Name" 323 security: 324 - JWT: [] 325 responses: 326 200: 327 description: User successfully unenrolled from the event 328 schema: 329 type: object 330 properties: 331 status: 332 type: string 333 example: "Data saved successfully" 334 500: 335 description: An error occurred while unenrolling the user 336 """ 337 data = request.get_json() # get data from POST request 338 current_user = get_jwt_identity() 339 try: 340 # Insert data into MongoDB 341 mongo.user.delete_one({ 342 "email": current_user, 343 "eventTitle": data['eventTitle'] 344 }) 345 response = {"status": "Data saved successfully"} 346 except Exception as e: 347 response = {"status": "Error", "message": str(e)} 348 349 return jsonify(response)
Unenroll the user from an event
This endpoint allows an authenticated user to unenroll from an event.
tags:
- Events parameters:
- in: body name: data description: Data containing the eventTitle required: true schema: type: object properties: eventTitle: type: string example: eventTitle: "Event Name" security:
- JWT: [] responses: 200: description: User successfully unenrolled from the event schema: type: object properties: status: type: string example: "Data saved successfully" 500: description: An error occurred while unenrolling the user
351@api.route('/profile') 352@jwt_required() 353def my_profile(): # pragma: no cover 354 """ 355 Retrieve user profile information 356 357 This endpoint allows an authenticated user to retrieve their profile information. 358 359 --- 360 tags: 361 - User 362 security: 363 - JWT: [] 364 responses: 365 200: 366 description: User profile information retrieved successfully 367 schema: 368 type: object 369 example: 370 { 371 "_id": "12345", 372 "email": "user@example.com", 373 "first_name": "John", 374 "last_name": "Doe", 375 "age": 30, 376 "weight": 70, 377 "height": 175 378 } 379 401: 380 description: Unauthorized. User must be logged in to access their profile. 381 404: 382 description: User profile not found. 383 500: 384 description: An error occurred while retrieving the user profile. 385 """ 386 current_user = get_jwt_identity() 387 profile = mongo.user.find_one({"email": current_user}) 388 return jsonify(json_util.dumps(profile))
Retrieve user profile information
This endpoint allows an authenticated user to retrieve their profile information.
tags:
- User security:
- JWT: [] responses: 200: description: User profile information retrieved successfully schema: type: object example: { "_id": "12345", "email": "user@example.com", "first_name": "John", "last_name": "Doe", "age": 30, "weight": 70, "height": 175 } 401: description: Unauthorized. User must be logged in to access their profile. 404: description: User profile not found. 500: description: An error occurred while retrieving the user profile.
390@api.route('/caloriesConsumed',methods=["POST"]) 391@jwt_required() 392def addUserConsumedCalories(): # pragma: no cover 393 """ 394 Add consumed calories for a user 395 396 This endpoint allows an authenticated user to add consumed calories for a specific date. 397 398 --- 399 tags: 400 - User 401 security: 402 - JWT: [] 403 parameters: 404 - name: body 405 in: body 406 required: true 407 schema: 408 type: object 409 properties: 410 intakeDate: 411 type: string 412 format: date 413 description: The date for which calories are being recorded (e.g., "2023-10-17"). 414 intakeFoodItem: 415 type: string 416 description: The name of the food item. 417 intakeCalories: 418 type: integer 419 description: The number of calories consumed for the food item. 420 responses: 421 200: 422 description: Calories consumed data saved successfully. 423 schema: 424 type: object 425 example: 426 { 427 "status": "Data saved successfully" 428 } 429 401: 430 description: Unauthorized. User must be logged in to add consumed calories. 431 500: 432 description: An error occurred while saving consumed calories data. 433 """ 434 data = request.get_json() # get data from POST request 435 current_user = get_jwt_identity() 436 try: 437 # Insert data into MongoDB 438 mongo.user.update_one({'email': current_user, "consumedDate": data['intakeDate']}, {"$push": {"foodConsumed": {"item":data["intakeFoodItem"],"calories":data["intakeCalories"]}}}, upsert=True) 439 response = {"status": "Data saved successfully"} 440 statusCode = 200 441 except Exception as e: 442 response = {"status": "Error", "message": str(e)} 443 statusCode = 500 444 return jsonify(response),statusCode
Add consumed calories for a user
This endpoint allows an authenticated user to add consumed calories for a specific date.
tags:
- User security:
- JWT: [] parameters:
- name: body in: body required: true schema: type: object properties: intakeDate: type: string format: date description: The date for which calories are being recorded (e.g., "2023-10-17"). intakeFoodItem: type: string description: The name of the food item. intakeCalories: type: integer description: The number of calories consumed for the food item. responses: 200: description: Calories consumed data saved successfully. schema: type: object example: { "status": "Data saved successfully" } 401: description: Unauthorized. User must be logged in to add consumed calories. 500: description: An error occurred while saving consumed calories data.
446@api.route('/profileUpdate',methods=["POST"]) 447@jwt_required() 448def profileUpdate(): # pragma: no cover 449 """ 450 Update user profile 451 452 This endpoint allows an authenticated user to update their profile information. 453 454 --- 455 tags: 456 - User 457 security: 458 - JWT: [] 459 parameters: 460 - name: body 461 in: body 462 required: true 463 schema: 464 type: object 465 properties: 466 firstName: 467 type: string 468 description: The user's first name. 469 lastName: 470 type: string 471 description: The user's last name. 472 age: 473 type: integer 474 description: The user's age. 475 weight: 476 type: number 477 description: The user's weight. 478 height: 479 type: number 480 description: The user's height. 481 sex: 482 type: string 483 description: The user's sex. 484 responses: 485 200: 486 description: User profile updated successfully. 487 schema: 488 type: object 489 example: 490 { 491 "msg": "Update successful" 492 } 493 401: 494 description: Unauthorized. User must be logged in to update their profile. 495 500: 496 description: An error occurred while updating the user's profile. 497 """ 498 current_user = get_jwt_identity() 499 first_name = request.json.get('firstName', None) 500 last_name = request.json.get('lastName', None) 501 age = request.json.get('age', None) 502 weight = request.json.get('weight', None) 503 height = request.json.get('height', None) 504 sex = request.json.get('sex', None) 505 activityLevel = request.json.get('activityLevel', None) 506 bmi = (0.453*float(weight))/((0.3048*float(height))**2) 507 bmi = round(bmi,2) 508 tdee = calculate_tdee(height, weight, age, sex, activityLevel) 509 new_document = { 510 "first_name": first_name, 511 "last_name": last_name, 512 "age": age, 513 "weight": weight, 514 "height": height, 515 "sex": sex, 516 "bmi": bmi, 517 "target_calories": tdee, 518 } 519 query = { 520 "email": current_user, 521 } 522 try: 523 mongo.user.update_one(query, {"$set": new_document}, upsert=True) 524 response = jsonify({"msg": "update successful"}) 525 except Exception as e: 526 response = jsonify({"msg": "update failed"}) 527 528 return response
Update user profile
This endpoint allows an authenticated user to update their profile information.
tags:
- User security:
- JWT: [] parameters:
- name: body in: body required: true schema: type: object properties: firstName: type: string description: The user's first name. lastName: type: string description: The user's last name. age: type: integer description: The user's age. weight: type: number description: The user's weight. height: type: number description: The user's height. sex: type: string description: The user's sex. responses: 200: description: User profile updated successfully. schema: type: object example: { "msg": "Update successful" } 401: description: Unauthorized. User must be logged in to update their profile. 500: description: An error occurred while updating the user's profile.
530@api.route('/goalsUpdate',methods=["POST"]) 531@jwt_required() 532def goalsUpdate(): # pragma: no cover 533 """ 534 Update user goals 535 536 This endpoint allows an authenticated user to update their fitness goals, such as target weight, target calories, and target goal. 537 538 --- 539 tags: 540 - User 541 security: 542 - JWT: [] 543 parameters: 544 - name: body 545 in: body 546 required: true 547 schema: 548 type: object 549 properties: 550 targetWeight: 551 type: number 552 description: The user's target weight goal. 553 targetCalories: 554 type: number 555 description: The user's target daily calorie intake goal. 556 activityLevel: 557 type: string 558 description: The user's activity level. 559 responses: 560 200: 561 description: User goals updated successfully. 562 schema: 563 type: object 564 example: 565 { 566 "msg": "Update successful" 567 } 568 401: 569 description: Unauthorized. User must be logged in to update their goals. 570 500: 571 description: An error occurred while updating the user's goals. 572 """ 573 current_user = get_jwt_identity() 574 targetWeight = request.json.get('targetWeight', None) 575 activityLevel = request.json.get('activityLevel', None) 576 577 new_document = { 578 "target_weight": targetWeight, 579 "activity_level": activityLevel 580 } 581 query = { 582 "email": current_user, 583 } 584 try: 585 profile = mongo.user.find_one(query) 586 tdee = calculate_tdee(profile["height"], profile["weight"], profile["age"], profile["sex"], activityLevel) 587 if tdee: 588 new_document["target_calories"] = tdee 589 mongo.user.update_one(query, {"$set": new_document}, upsert=True) 590 response = jsonify({"msg": "update successful"}) 591 except Exception as e: 592 response = jsonify({"msg": "update failed"}) 593 594 return response
Update user goals
This endpoint allows an authenticated user to update their fitness goals, such as target weight, target calories, and target goal.
tags:
- User security:
- JWT: [] parameters:
- name: body in: body required: true schema: type: object properties: targetWeight: type: number description: The user's target weight goal. targetCalories: type: number description: The user's target daily calorie intake goal. activityLevel: type: string description: The user's activity level. responses: 200: description: User goals updated successfully. schema: type: object example: { "msg": "Update successful" } 401: description: Unauthorized. User must be logged in to update their goals. 500: description: An error occurred while updating the user's goals.
597@api.route('/caloriesBurned',methods=["POST"]) 598@jwt_required() 599def addUserBurnedCalories(): # pragma: no cover 600 """ 601 Add user's burned calories 602 603 This endpoint allows an authenticated user to add information about calories burned on a specific date. 604 605 --- 606 tags: 607 - User 608 security: 609 - JWT: [] 610 parameters: 611 - name: body 612 in: body 613 required: true 614 schema: 615 type: object 616 properties: 617 burnoutDate: 618 type: string 619 format: date 620 description: The date on which calories were burned. 621 burntoutCalories: 622 type: number 623 description: The number of calories burned on the specified date. 624 responses: 625 200: 626 description: Calories burned data saved successfully. 627 schema: 628 type: object 629 example: 630 { 631 "status": "Data saved successfully" 632 } 633 401: 634 description: Unauthorized. User must be logged in to add burned calories data. 635 500: 636 description: An error occurred while saving the burned calories data. 637 """ 638 data = request.get_json() # get data from POST request 639 current_user = get_jwt_identity() 640 try: 641 # Insert data into MongoDB 642 mongo.user.update_one({'email': current_user, "consumedDate": data['burnoutDate']}, {"$inc": {"burntCalories": int(data["burntoutCalories"])}}, upsert=True) 643 response = {"status": "Data saved successfully"} 644 statusCode = 200 645 except Exception as e: 646 response = {"status": "Error", "message": str(e)} 647 statusCode = 500 648 return jsonify(response),statusCode
Add user's burned calories
This endpoint allows an authenticated user to add information about calories burned on a specific date.
tags:
- User security:
- JWT: [] parameters:
- name: body in: body required: true schema: type: object properties: burnoutDate: type: string format: date description: The date on which calories were burned. burntoutCalories: type: number description: The number of calories burned on the specified date. responses: 200: description: Calories burned data saved successfully. schema: type: object example: { "status": "Data saved successfully" } 401: description: Unauthorized. User must be logged in to add burned calories data. 500: description: An error occurred while saving the burned calories data.
650@api.route('/createFood', methods=["POST"]) 651def createFood(): 652 """ 653 Create a custom food 654 655 This endpoint allows an authenticated user to create their custom food item with the amount of calories it has. 656 657 --- 658 tags: 659 - User 660 parameters: 661 - name: body 662 in: body 663 required: true 664 schema: 665 type: object 666 properties: 667 foodName: 668 type: string 669 format: food item name 670 description: The name of the food item being created. 671 calories: 672 type: number 673 description: The number of calories in the created food item. 674 responses: 675 200: 676 description: Food item created successfully 677 schema: 678 type: object 679 example: 680 { 681 "status": "Data saved successfully" 682 } 683 401: 684 description: Unauthorized. User must be logged in to create custom food. 685 500: 686 description: An error occurred while creating the custom food. 687 688 """ 689 data = request.get_json() # get data from POST request 690 foodName = data['foodName'] 691 calories = data['calories'] 692 try: 693 # Insert data into MongoDB 694 mongo.food.insert_one({'food': foodName, "calories": calories}) 695 response = {"status": "Data saved successfully"} 696 statusCode = 200 697 except Exception as e: 698 response = {"status": "Error", "message": str(e)} 699 statusCode = 500 700 return jsonify(response),statusCode
Create a custom food
This endpoint allows an authenticated user to create their custom food item with the amount of calories it has.
tags:
- User parameters:
- name: body in: body required: true schema: type: object properties: foodName: type: string format: food item name description: The name of the food item being created. calories: type: number description: The number of calories in the created food item. responses: 200: description: Food item created successfully schema: type: object example: { "status": "Data saved successfully" } 401: description: Unauthorized. User must be logged in to create custom food. 500: description: An error occurred while creating the custom food.
702@api.route('/createMeal', methods=["POST"]) 703@jwt_required() 704def createMeal(): 705 """ 706 Create a custom meal 707 708 This endpoint allows an authenticated user to create their own meals with different food items as the ingredients. 709 710 --- 711 tags: 712 - User 713 security: 714 - JWT: [] 715 parameters: 716 - name: body 717 in: body 718 required: true 719 schema: 720 type: object 721 properties: 722 mealName: 723 type: string 724 format: Meal name 725 description: The name of the meal item being created. 726 ingredients: 727 type: list 728 description: Is a list of the ingredients in the meal. 729 responses: 730 200: 731 description: Meal created successfully 732 schema: 733 type: object 734 example: 735 { 736 "status": "Data saved successfully" 737 } 738 401: 739 description: Unauthorized. User must be logged in to create custom meal. 740 500: 741 description: An error occurred while creating the custom meal. 742 743 """ 744 data = request.get_json() # get data from POST request 745 current_user = get_jwt_identity() 746 mealName = data['mealName'] 747 ingredients = data['ingredients'] 748 calories = 0 749 for item in ingredients: 750 food_item = mongo.food.find_one({"food": item}) 751 calories += int(food_item["calories"]) 752 try: 753 # Insert data into MongoDB 754 mongo.food.insert_one({'food': mealName, "calories": calories}) 755 mongo.user.insert_one({ 756 "email": current_user, 757 "meal_name": mealName, 758 "ingredients": ingredients, 759 "total_calories": calories 760 }) 761 response = {"status": "Data saved successfully"} 762 statusCode = 200 763 except Exception as e: 764 response = {"status": "Error", "message": str(e)} 765 statusCode = 500 766 return jsonify(response),statusCode
Create a custom meal
This endpoint allows an authenticated user to create their own meals with different food items as the ingredients.
tags:
- User security:
- JWT: [] parameters:
- name: body in: body required: true schema: type: object properties: mealName: type: string format: Meal name description: The name of the meal item being created. ingredients: type: list description: Is a list of the ingredients in the meal. responses: 200: description: Meal created successfully schema: type: object example: { "status": "Data saved successfully" } 401: description: Unauthorized. User must be logged in to create custom meal. 500: description: An error occurred while creating the custom meal.
768@api.route('/weekHistory',methods=["POST"]) 769@jwt_required() 770def getWeekHistory(): # pragma: no cover 771 """ 772 Get user's weekly history 773 774 This endpoint allows an authenticated user to retrieve their food consumption and calories burned history for the past week. 775 776 --- 777 tags: 778 - User 779 security: 780 - JWT: [] 781 parameters: 782 - name: body 783 in: body 784 required: true 785 schema: 786 type: object 787 properties: 788 todayDate: 789 type: string 790 format: date 791 description: The date for the end of the week (today's date). 792 responses: 793 200: 794 description: Successfully retrieved the user's weekly history. 795 schema: 796 type: array 797 items: 798 type: object 799 properties: 800 dayIndex: 801 type: integer 802 description: Integer from 0 to 6 representing the day index. 803 date: 804 type: string 805 format: date 806 description: The date for each day in the week. 807 foodConsumed: 808 type: array 809 items: 810 type: object 811 properties: 812 item: 813 type: string 814 description: Food item name. 815 calories: 816 type: number 817 description: Calories consumed from the food item. 818 description: A list of dictionaries containing food items and their consumed calories. 819 caloriesConsumed: 820 type: number 821 description: The sum of all calories consumed for that day. 822 exceededDailyLimit: 823 type: boolean 824 description: Indicates whether the calories consumed exceeded the daily limit. 825 burntCalories: 826 type: number 827 description: Calories burned on that day. 828 example: 829 [ 830 { 831 "dayIndex": 0, 832 "date": "10/13/2023", 833 "foodConsumed": [ 834 { 835 "item": "Chicken Salad", 836 "calories": 500 837 }, 838 { 839 "item": "Onion Soup", 840 "calories": 300 841 }, 842 { 843 "item": "Potato Salad", 844 "calories": 500 845 }, 846 { 847 "item": "Cheese Burger", 848 "calories": 500 849 } 850 ], 851 "caloriesConsumed": 1800, 852 "exceededDailyLimit": false, 853 "burntCalories": 1200 854 }, 855 { 856 "dayIndex": 1, 857 "date": "10/12/2023", 858 "foodConsumed": [...], 859 "caloriesConsumed": ..., 860 "exceededDailyLimit": ..., 861 "burntCalories": ... 862 }, 863 ... 864 ] 865 401: 866 description: Unauthorized. User must be logged in to retrieve weekly history. 867 500: 868 description: An error occurred while retrieving the user's weekly history. 869 """ 870 data = request.get_json() # get data from POST request 871 current_user = get_jwt_identity() 872 todayDate = datetime.strptime(data["todayDate"],"%m/%d/%Y") 873 dates = [(todayDate-timedelta(days=x)).strftime("%m/%d/%Y") for x in range(7)] 874 calorieLimit = 1000 875 result = [] 876 try: 877 for index,dateToFind in enumerate(dates): 878 # Every day's res item should like this 879 # { 880 # dayIndex: 0, #Interger from 0-6 881 # date: "10/13/2023", #Date 0=today, 6=7th day ago from today 882 # foodConsumed: [ # A list of dicts, each dict contains a food item and its calories 883 # { 884 # item: "Chicken Salad", 885 # calories: 500, 886 # }, 887 # { 888 # item: "Onion Soup", 889 # calories: 300, 890 # }, 891 # { 892 # item: "Potato Salad", 893 # calories: 500, 894 # }, 895 # { 896 # item: "Cheese Burger", 897 # calories: 500, 898 # }, 899 # ], 900 # caloriesConsumed: 1800, # the sum of all calories consumed from above list 901 # exceededDailyLimit: false, # true or false based on whether caloriesConsumed is > limit user set 902 # burntCalories: 1200, # calories burnt out on that day 903 # } 904 res = {} 905 data = mongo.user.find_one({'email': current_user, "consumedDate": dateToFind}) 906 res["dayIndex"] = index 907 res["date"] = dateToFind 908 if data: 909 if "foodConsumed" in data: 910 res["foodConsumed"] = data["foodConsumed"] 911 res["caloriesConsumed"] = reduce(lambda a,b: a+b, [int(item["calories"]) for item in data["foodConsumed"]]) 912 res["exceededDailyLimit"] = res["caloriesConsumed"]>calorieLimit 913 if "burntCalories" in data: 914 res["burntCalories"] = data["burntCalories"] 915 if "foodConsumed" not in res: 916 res["foodConsumed"] = [] 917 if "caloriesConsumed" not in res: 918 res["caloriesConsumed"] = 0 919 if "burntCalories" not in res: 920 res["burntCalories"] = 0 921 if "exceededDailyLimit" not in res: 922 res["exceededDailyLimit"] = False 923 result.append(res) 924 response = result 925 statusCode = 200 926 except Exception as e: 927 response = {"status": "Error", "message": str(e)} 928 statusCode = 500 929 return jsonify(response),statusCode
Get user's weekly history
This endpoint allows an authenticated user to retrieve their food consumption and calories burned history for the past week.
tags:
- User security:
- JWT: [] parameters:
- name: body in: body required: true schema: type: object properties: todayDate: type: string format: date description: The date for the end of the week (today's date). responses: 200: description: Successfully retrieved the user's weekly history. schema: type: array items: type: object properties: dayIndex: type: integer description: Integer from 0 to 6 representing the day index. date: type: string format: date description: The date for each day in the week. foodConsumed: type: array items: type: object properties: item: type: string description: Food item name. calories: type: number description: Calories consumed from the food item. description: A list of dictionaries containing food items and their consumed calories. caloriesConsumed: type: number description: The sum of all calories consumed for that day. exceededDailyLimit: type: boolean description: Indicates whether the calories consumed exceeded the daily limit. burntCalories: type: number description: Calories burned on that day. example: [ { "dayIndex": 0, "date": "10/13/2023", "foodConsumed": [ { "item": "Chicken Salad", "calories": 500 }, { "item": "Onion Soup", "calories": 300 }, { "item": "Potato Salad", "calories": 500 }, { "item": "Cheese Burger", "calories": 500 } ], "caloriesConsumed": 1800, "exceededDailyLimit": false, "burntCalories": 1200 }, { "dayIndex": 1, "date": "10/12/2023", "foodConsumed": [...], "caloriesConsumed": ..., "exceededDailyLimit": ..., "burntCalories": ... }, ... ] 401: description: Unauthorized. User must be logged in to retrieve weekly history. 500: description: An error occurred while retrieving the user's weekly history.
931@api.route("/myMeals",methods=["GET"]) 932@jwt_required() 933def getMyMeals(): 934 """ 935 Get My Meals 936 937 This endpoint allows an authenticated user to retrieve the custom meals that they have created. 938 939 --- 940 tags: 941 - User 942 - Meals 943 security: 944 - JWT: [] 945 responses: 946 200: 947 description: Successfully retrieved the custom meals created by user 948 schema: 949 type: object 950 properties: 951 mealName: 952 type: string 953 description: Name of the custom meal 954 ingredients: 955 type: array 956 description: List of ingredients in the meal 957 example: 958 { 959 "mealName":"My meal", 960 "ingredients":["Eggs","Toast"], 961 } 962 401: 963 description: Unauthorized. User must be logged in to retrieve the food calorie mapping. 964 500: 965 description: An error occurred while retrieving the food calorie mapping. 966 """ 967 current_user = get_jwt_identity() 968 result = [] 969 try: 970 data = mongo.user.find({"email": current_user,"meal_name":{"$exists": True}}) 971 for meal in data: 972 cal_info = [] 973 for item in meal['ingredients']: 974 food_item = mongo.food.find_one({'food':item}) 975 cal_info.append({str(item):food_item['calories']}) 976 res={} 977 res['meal_name']=meal['meal_name'] 978 res['ingredients']=meal['ingredients'] 979 res['total_calories']=meal['total_calories'] 980 result.append(res) 981 response = result 982 statusCode = 200 983 except Exception as e: 984 response = {"status": "Error", "message": str(e)} 985 statusCode = 500 986 return jsonify(response),statusCode
Get My Meals
This endpoint allows an authenticated user to retrieve the custom meals that they have created.
tags:
- User
- Meals security:
- JWT: [] responses: 200: description: Successfully retrieved the custom meals created by user schema: type: object properties: mealName: type: string description: Name of the custom meal ingredients: type: array description: List of ingredients in the meal example: { "mealName":"My meal", "ingredients":["Eggs","Toast"], } 401: description: Unauthorized. User must be logged in to retrieve the food calorie mapping. 500: description: An error occurred while retrieving the food calorie mapping.
989@api.route('/foodCalorieMapping',methods=["GET"]) 990@jwt_required() 991def getFoodCalorieMapping(): 992 """ 993 Get food calorie mapping 994 995 This endpoint allows an authenticated user to retrieve a mapping of food items to their respective calorie values. 996 997 --- 998 tags: 999 - Food 1000 security: 1001 - JWT: [] 1002 responses: 1003 200: 1004 description: Successfully retrieved the food calorie mapping. 1005 schema: 1006 type: object 1007 properties: 1008 foodItem: 1009 type: integer 1010 description: Food item name. 1011 calories: 1012 type: number 1013 description: Calories associated with the food item. 1014 example: 1015 { 1016 "Potato": 50, 1017 "Acai": 20, 1018 "Cheeseburger": 80, 1019 ... 1020 } 1021 401: 1022 description: Unauthorized. User must be logged in to retrieve the food calorie mapping. 1023 500: 1024 description: An error occurred while retrieving the food calorie mapping. 1025 """ 1026 try: 1027 data = mongo.food.find() 1028 # Response should be in this format {foodItem: calories, foodItem: calories....} 1029 # For Example { Potato: 50, Acai: 20, Cheeseburger: 80 } 1030 response = {item["food"]:item["calories"] for item in data} 1031 statusCode = 200 1032 except Exception as e: 1033 response = {"status": "Error", "message": str(e)} 1034 statusCode = 500 1035 return jsonify(response),statusCode
Get food calorie mapping
This endpoint allows an authenticated user to retrieve a mapping of food items to their respective calorie values.
tags:
- Food security:
- JWT: [] responses: 200: description: Successfully retrieved the food calorie mapping. schema: type: object properties: foodItem: type: integer description: Food item name. calories: type: number description: Calories associated with the food item. example: { "Potato": 50, "Acai": 20, "Cheeseburger": 80, ... } 401: description: Unauthorized. User must be logged in to retrieve the food calorie mapping. 500: description: An error occurred while retrieving the food calorie mapping.
1037@api.route('/usersEvents',methods=["GET"]) 1038@jwt_required() 1039def getUserRegisteredEvents(): 1040 """ 1041 Get user's registered events 1042 1043 This endpoint allows an authenticated user to retrieve the events they are registered for. 1044 1045 --- 1046 tags: 1047 - Events 1048 security: 1049 - JWT: [] 1050 responses: 1051 200: 1052 description: Successfully retrieved the user's registered events. 1053 schema: 1054 type: array 1055 items: 1056 type: object 1057 properties: 1058 eventName: 1059 type: string 1060 description: Name of the event. 1061 date: 1062 type: string 1063 format: date 1064 description: Date of the event. 1065 example: 1066 [ 1067 { 1068 "eventName": "Yoga", 1069 "date": "2023-12-11" 1070 }, 1071 { 1072 "eventName": "Swimming", 1073 "date": "2023-11-10" 1074 }, 1075 ... 1076 ] 1077 401: 1078 description: Unauthorized. User must be logged in to retrieve their registered events. 1079 500: 1080 description: An error occurred while retrieving the user's registered events. 1081 """ 1082 try: 1083 # current_user = get_jwt_identity() 1084 current_user = get_jwt_identity() 1085 data = mongo.user.find({"email": current_user, "eventTitle":{"$exists": True}}) 1086 response = [] 1087 date="10/23/2023" 1088 for item in data: 1089 res = {"eventName": item["eventTitle"], "date": date} 1090 response.append(res) 1091 # Response should be in this format [{eventName: Yoga, date: "12/11/2023"},{eventName: Swimming, date: "11/10/2023"}] 1092 # For Example { Potato: 50, Acai: 20, Cheeseburger: 80 } 1093 statusCode = 200 1094 except Exception as e: 1095 response = {"status": "Error", "message": str(e)} 1096 statusCode = 500 1097 return jsonify(response),statusCode
Get user's registered events
This endpoint allows an authenticated user to retrieve the events they are registered for.
tags:
- Events security:
- JWT: [] responses: 200: description: Successfully retrieved the user's registered events. schema: type: array items: type: object properties: eventName: type: string description: Name of the event. date: type: string format: date description: Date of the event. example: [ { "eventName": "Yoga", "date": "2023-12-11" }, { "eventName": "Swimming", "date": "2023-11-10" }, ... ] 401: description: Unauthorized. User must be logged in to retrieve their registered events. 500: description: An error occurred while retrieving the user's registered events.
1099def calculate_tdee(height,weight,age,sex,activityLevel): 1100 if height and weight and age and sex and activityLevel: 1101 pass 1102 else: 1103 return None 1104 kg_weight = float(weight)*0.45359237 1105 cm_height = float(height)*30.48 1106 common_calc_for_male_female = (10*kg_weight) + (6.25*cm_height) - (5*int(age)) 1107 if sex == "Male": 1108 bmr = common_calc_for_male_female + 5 1109 else: 1110 bmr = common_calc_for_male_female - 161 1111 personal_activity_levels = {'Minimal': 1.2,'Light': 1.375, 'Moderate': 1.55, 'Heavy':1.725, 'Athlete': 1.9} 1112 tdee = int((bmr * personal_activity_levels[activityLevel])) 1113 return tdee