From eea09332fd88b9c0f741c2f61fd3abeb9a351029 Mon Sep 17 00:00:00 2001 From: Ishav Sohal Date: Fri, 24 Nov 2023 14:50:02 -0500 Subject: [PATCH 01/20] implemented backend of energy metric feature --- backend/app.py | 2 + backend/models/energy.py | 98 ++++++++++++++++++++++++++ backend/models/user.py | 14 +++- backend/mongodb_api/carbon_track_db.py | 1 + backend/routes/energy.py | 55 +++++++++++++++ 5 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 backend/models/energy.py create mode 100644 backend/routes/energy.py diff --git a/backend/app.py b/backend/app.py index 4e82788..e7c7327 100644 --- a/backend/app.py +++ b/backend/app.py @@ -7,6 +7,7 @@ from routes.transportation import transportation_service from utils.customJSONEncoder import CustomJSONProvider from routes.food import food_service +from routes.energy import energy_service app = Flask(__name__) @@ -16,6 +17,7 @@ app.register_blueprint(users, url_prefix="/users") app.register_blueprint(transportation_service, url_prefix="/transportation") app.register_blueprint(food_service, url_prefix="/food") +app.register_blueprint(energy_service, url_prefix="/energy") CORS(app) diff --git a/backend/models/energy.py b/backend/models/energy.py new file mode 100644 index 0000000..244cde3 --- /dev/null +++ b/backend/models/energy.py @@ -0,0 +1,98 @@ +""" +Energy Model +""" + +from __future__ import annotations +import json +from datetime import datetime +from models.abstract_db_model import DB_MODEL +from bson import ObjectId +from bson import json_util + +class EnergyEntry(DB_MODEL): + oid: ObjectId + user_id: ObjectId + heating_oil: int # measured in L of fuel + natural_gas: int # measured in m3 of gas + electricity: int # measured in kWh + province: str + household: int + carbon_emissions: float # measured in kgs of CO2 + date: datetime + + def __init__(self, oid: ObjectId, user_id: ObjectId, heating_oil: int, natural_gas: int, province: str, + household: int, electricity: int, carbon_emissions: float, date: datetime) -> None: + super().__init__(oid) + self.user_id = ObjectId(user_id) + self.heating_oil = heating_oil + self.natural_gas = natural_gas + self.electricity = electricity + self.province = province + self.household = household + self.carbon_emissions = carbon_emissions + self.date = date + + def to_json(self, for_mongodb: bool = False) -> json: + res = { + '_id': self.oid, + 'user_id': self.user_id, + 'heating_oil': self.heating_oil, + 'natural_gas': self.natural_gas, + 'electricity': self.electricity, + 'province': self.province, + 'household': self.household, + 'carbon_emissions': self.calculate_carbon_emissions(), + 'date': self.date + } + if for_mongodb: + return res + return json.loads(json_util.dumps(res)) + + @staticmethod + def from_json(doc: json) -> EnergyEntry: + return EnergyEntry( + oid=ObjectId(doc["_id"]), + user_id=doc['user_id'], + heating_oil=doc["heating_oil"], + natural_gas=doc["natural_gas"], + electricity=doc["electricity"], + province=doc["province"], + household=doc["household"], + carbon_emissions=doc["carbon_emissions"], + date=doc["date"] + ) + + def calculate_carbon_emissions(self) -> float: + heating_oil_carbon_emissions = self.heating_oil * 2.753 + natural_gas_carbon_emissions = self.natural_gas * 1.96 + + if self.province == "British Colombia": + electricity_carbon_emissions = (self.electricity * 0.015)/self.household + elif self.province == "Alberta": + electricity_carbon_emissions = (self.electricity * 0.54)/self.household + elif self.province == "Saskatchewan": + electricity_carbon_emissions = (self.electricity * 0.73)/self.household + elif self.province == "Manitoba": + electricity_carbon_emissions = (self.electricity * 0.002)/self.household + elif self.province == "Ontario": + electricity_carbon_emissions = (self.electricity * 0.03)/self.household + elif self.province == "Quebec": + electricity_carbon_emissions = (self.electricity * 0.0017)/self.household + elif self.province == "New Brunswick": + electricity_carbon_emissions = (self.electricity * 0.3)/self.household + elif self.province == "Nova Scotia": + electricity_carbon_emissions = (self.electricity * 0.69)/self.household + elif self.province == "PEI": + electricity_carbon_emissions = (self.electricity * 0.3)/self.household + elif self.province == "Newfoundland and Labrador": + electricity_carbon_emissions = (self.electricity * 0.017)/self.household + elif self.province == "Yukon": + electricity_carbon_emissions = (self.electricity * 0.08)/self.household + elif self.province == "Nortwest Territories": + electricity_carbon_emissions = (self.electricity * 0.17)/self.household + else: # self.province == "Nunavut" + electricity_carbon_emissions = (self.electricity * 0.84)/self.household + return sum([heating_oil_carbon_emissions, natural_gas_carbon_emissions, electricity_carbon_emissions]) + + def __repr__(self) -> str: + return f'Energy ID: {self.oid.__str__()}' diff --git a/backend/models/user.py b/backend/models/user.py index 4167c7e..298474d 100644 --- a/backend/models/user.py +++ b/backend/models/user.py @@ -15,14 +15,18 @@ class User(DB_MODEL): badges: list[str] friends: list[str] score: int + province: str + household: int - def __init__(self, oid: ObjectId, full_name: str, email: str, badges: list[str], friends: list[str], score:int) -> None: + def __init__(self, oid: ObjectId, full_name: str, email: str, badges: list[str], friends: list[str], score:int, province:str, household:int) -> None: super().__init__(oid) self.full_name = str(full_name) self.email = str(email) self.badges = badges self.friends = friends self.score = score + self.province = province + self.household = household def to_json(self) -> json: res = { @@ -31,7 +35,9 @@ def to_json(self) -> json: 'email': self.email, 'badges': self.badges, 'friends': self.friends, - 'score': self.score + 'score': self.score, + 'province': self.province, + 'household': self.household } return res @@ -43,7 +49,9 @@ def from_json(doc: json) -> User: email=doc["email"], badges=doc["badges"], friends=doc["friends"], - score=doc["score"] + score=doc["score"], + province=doc["province"], + household=doc["household"] ) def __repr__(self) -> str: diff --git a/backend/mongodb_api/carbon_track_db.py b/backend/mongodb_api/carbon_track_db.py index b5105ce..906451d 100644 --- a/backend/mongodb_api/carbon_track_db.py +++ b/backend/mongodb_api/carbon_track_db.py @@ -14,3 +14,4 @@ class CarbonTrackDB: users_coll: Collection = carbonTrackDB.get_collection("users") transportation_coll: Collection = carbonTrackDB.get_collection("transportation") food_coll: Collection = carbonTrackDB.get_collection("food") + energy_coll: Collection = carbonTrackDB.get_collection("energy") diff --git a/backend/routes/energy.py b/backend/routes/energy.py new file mode 100644 index 0000000..2989446 --- /dev/null +++ b/backend/routes/energy.py @@ -0,0 +1,55 @@ +# Python Imports +from datetime import datetime +from bson import ObjectId +from flask import Blueprint, Response, jsonify, request + +from models.energy import EnergyEntry +from mongodb_api.carbon_track_db import CarbonTrackDB +from routes import carbon_auth +from utils.metric_resets import weekly_metric_reset, get_1_day_range + +energy_service = Blueprint('/energy', __name__) + + +@energy_service.route("/energy/", methods=['GET']) +@carbon_auth.auth.login_required +def get_energy(oid: str) -> Response: + query = {"_id": ObjectId(oid)} + item = CarbonTrackDB.energy_coll.find_one(query) + item = EnergyEntry.from_json(item).to_json() + return jsonify({'energy': item}) + + +@energy_service.route("/get_energy_metric_for_today/", methods=['GET']) +@carbon_auth.auth.login_required +def get_energy_metric_for_today(user_id: str) -> Response: + start_of_day, end_of_day = get_1_day_range(datetime.now()) + query = {"user_id": ObjectId(user_id), "date": {"$gte": start_of_day, "$lte": end_of_day}} + item = CarbonTrackDB.energy_coll.find_one(query) + if item is None: + create_energy(ObjectId(user_id)) + return get_energy_metric_for_today(user_id=user_id) + else: + item = EnergyEntry.from_json(item).to_json() + return jsonify({'energy': item}) + + +@carbon_auth.auth.login_required +def create_energy(user_id: ObjectId) -> Response: + energy = EnergyEntry(oid=ObjectId(), user_id=user_id, heating_oil = 0, natural_gas = 0, province = "Ontario", + household = 4, electricity = 0, carbon_emissions=0.0, date=weekly_metric_reset(datetime.today())) + energy = energy.to_json(for_mongodb=True) + inserted_id = CarbonTrackDB.energy_coll.insert_one(energy).inserted_id + energy = EnergyEntry.from_json(CarbonTrackDB.energy_coll.find_one({"_id": inserted_id})).to_json() + return energy + + +@energy_service.route("/energy/", methods=["PATCH"]) +@carbon_auth.auth.login_required +def update_energy(oid: str) -> Response: + query = {"_id": ObjectId(oid)} + energy = EnergyEntry.from_json(request.get_json()['energy']).to_json(for_mongodb=True) + CarbonTrackDB.energy_coll.update_one(query, {'$set': energy}) + item = CarbonTrackDB.energy_coll.find_one(query) + item = EnergyEntry.from_json(item).to_json() + return jsonify({'updated_energy': item}) From c0fbaeedfef137c5f3c7951a4af21bcc1d3fe8fa Mon Sep 17 00:00:00 2001 From: Ishav Sohal Date: Sun, 26 Nov 2023 22:52:41 -0500 Subject: [PATCH 02/20] added additional user attributes, fixed postman collection and energy endpoint --- backend/models/energy.py | 3 +- backend/models/user.py | 11 +- .../postman/Backend.postman_collection.json | 317 +++++++++++++++++- backend/routes/energy.py | 15 +- backend/routes/users.py | 17 +- 5 files changed, 338 insertions(+), 25 deletions(-) diff --git a/backend/models/energy.py b/backend/models/energy.py index 244cde3..d982562 100644 --- a/backend/models/energy.py +++ b/backend/models/energy.py @@ -9,6 +9,7 @@ from bson import ObjectId from bson import json_util + class EnergyEntry(DB_MODEL): oid: ObjectId user_id: ObjectId @@ -66,7 +67,7 @@ def calculate_carbon_emissions(self) -> float: heating_oil_carbon_emissions = self.heating_oil * 2.753 natural_gas_carbon_emissions = self.natural_gas * 1.96 - if self.province == "British Colombia": + if self.province == "British Columbia": electricity_carbon_emissions = (self.electricity * 0.015)/self.household elif self.province == "Alberta": electricity_carbon_emissions = (self.electricity * 0.54)/self.household diff --git a/backend/models/user.py b/backend/models/user.py index 298474d..146064a 100644 --- a/backend/models/user.py +++ b/backend/models/user.py @@ -17,8 +17,9 @@ class User(DB_MODEL): score: int province: str household: int + fuel_efficiency: float - def __init__(self, oid: ObjectId, full_name: str, email: str, badges: list[str], friends: list[str], score:int, province:str, household:int) -> None: + def __init__(self, oid: ObjectId, full_name: str, email: str, badges: list[str], friends: list[str], score:int, province:str, household:int, fuel_efficiency: float) -> None: super().__init__(oid) self.full_name = str(full_name) self.email = str(email) @@ -27,6 +28,7 @@ def __init__(self, oid: ObjectId, full_name: str, email: str, badges: list[str], self.score = score self.province = province self.household = household + self.fuel_efficiency = fuel_efficiency def to_json(self) -> json: res = { @@ -37,7 +39,8 @@ def to_json(self) -> json: 'friends': self.friends, 'score': self.score, 'province': self.province, - 'household': self.household + 'household': self.household, + 'fuel_efficiency': self.fuel_efficiency } return res @@ -51,8 +54,10 @@ def from_json(doc: json) -> User: friends=doc["friends"], score=doc["score"], province=doc["province"], - household=doc["household"] + household=doc["household"], + fuel_efficiency=doc["fuel_efficiency"] ) + def __repr__(self) -> str: return f'User ID: {self.oid.__str__()}' diff --git a/backend/postman/Backend.postman_collection.json b/backend/postman/Backend.postman_collection.json index 9137e24..2e1efde 100644 --- a/backend/postman/Backend.postman_collection.json +++ b/backend/postman/Backend.postman_collection.json @@ -10,7 +10,7 @@ "name": "Users", "item": [ { - "name": "Get User", + "name": "Get User by Email", "protocolProfileBehavior": { "disableBodyPruning": true }, @@ -37,14 +37,55 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/users/user_email/yazan@gmail.com", + "raw": "{{LocalBaseURL}}/users/user_email/abc@armoush.com", "host": [ "{{LocalBaseURL}}" ], "path": [ "users", "user_email", - "yazan@gmail.com" + "abc@armoush.com" + ] + } + }, + "response": [] + }, + { + "name": "Get User", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LocalBaseURL}}/users/user/651cf22c1d4f7834e2303a85", + "host": [ + "{{LocalBaseURL}}" + ], + "path": [ + "users", + "user", + "651cf22c1d4f7834e2303a85" ] } }, @@ -67,7 +108,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"user\": {\n \"_id\": \"651cf22c1d4f7834e2303a85\",\n \"full_name\": \"Adam\",\n \"email\": \"adam#armoush.com\",\n \"badges\": [],\n \"friends\": [],\n \"score\": 0\n }\n}", + "raw": "{\n \"user\": {\n \"_id\": \"651cf22c1d4f7834e2303a99\",\n \"full_name\": \"abc\",\n \"email\": \"abc@armoush.com\",\n \"badges\": [],\n \"friends\": [\"Ishav\", \"Yazan\"],\n \"score\": 434343,\n \"province\": \"British Columbia\",\n \"household\": 4,\n \"fuel_efficiency\": 32323.0\n\n }\n}", "options": { "raw": { "language": "json" @@ -104,7 +145,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"user\": {\n \"_id\": \"651cf22c1d4f7834e2303a85\",\n \"full_name\": \"Adam\",\n \"email\": \"adam#armoush.com\",\n \"badges\": [],\n \"friends\": [],\n \"score\": 0\n }\n}", + "raw": "{\n \"user\": {\n \"_id\": \"651cf22c1d4f7834e2303a85\",\n \"full_name\": \"Ishav\",\n \"email\": \"ishav@armoush.com\",\n \"badges\": [\"Badge 1\", \"Badge 2\"],\n \"friends\": [],\n \"score\": 323232,\n \"province\": \"British Columbia\",\n \"household\": 4,\n \"fuel_efficiency\": 4\n }\n}", "options": { "raw": { "language": "json" @@ -112,13 +153,14 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/users/user", + "raw": "{{LocalBaseURL}}/users/user/651cf22c1d4f7834e2303a85", "host": [ "{{LocalBaseURL}}" ], "path": [ "users", - "user" + "user", + "651cf22c1d4f7834e2303a85" ] } }, @@ -130,7 +172,7 @@ "name": "Transportation", "item": [ { - "name": "Get Transportation", + "name": "Get Current Transportation", "protocolProfileBehavior": { "disableBodyPruning": true }, @@ -165,13 +207,15 @@ "transportation", "transportation", "655d5c7d123217b52115b046" + "get_transportation_metric_for_today", + "655151e8875bab2e6811b8b8" ] } }, "response": [] }, { - "name": "Get Current Transportation", + "name": "Get Transportation", "protocolProfileBehavior": { "disableBodyPruning": true }, @@ -257,6 +301,135 @@ } ] }, + { + "name": "Food", + "item": [ + { + "name": "Get Current Food", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LocalBaseURL}}/food/get_food_metric_for_today/655151e8875bab2e6811b8b8", + "host": [ + "{{LocalBaseURL}}" + ], + "path": [ + "food", + "get_food_metric_for_today", + "655151e8875bab2e6811b8b8" + "transportation", + "transportation", + "651cf22c1d4f7834e2303a44" + ] + } + }, + "response": [] + }, + { + "name": "Get Food", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LocalBaseURL}}/food/food/6559599c7228677f5bc26d34", + "host": [ + "{{LocalBaseURL}}" + ], + "path": [ + "food", + "food", + "6559599c7228677f5bc26d34" + ] + } + }, + "response": [] + }, + { + "name": "Update Food", + "name": "Update Transportation", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", + "type": "string" + } + ] + }, + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"food\": {\n \"_id\": \"6559599c7228677f5bc26d34\",\n \"beef\": 22,\n \"carbon_emissions\": 0.0,\n \"cheese\": 2,\n \"chicken\": 22,\n \"date\": {\n \"$date\": \"2023-11-12T00:00:00Z\"\n },\n \"fish\": 22,\n \"food_waste\": 12,\n \"lamb\": 11,\n \"milk\": 22,\n \"pork\": 12,\n \"user_id\": \"655151e8875bab2e6811b8b8\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LocalBaseURL}}/food/food/6559599c7228677f5bc26d34", + "host": [ + "{{LocalBaseURL}}" + ], + "path": [ + "food", + "food", + "6559599c7228677f5bc26d34" + ] + } + }, + "response": [] + } + ] + }, { "name": "Food", "item": [ @@ -380,6 +553,131 @@ }, "response": [] } + ] + }, + { + "name": "Energy", + "item": [ + { + "name": "Get Current Energy", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LocalBaseURL}}/energy/get_energy_metric_for_today/651cf22c1d4f7834e2303a85", + "host": [ + "{{LocalBaseURL}}" + ], + "path": [ + "energy", + "get_energy_metric_for_today", + "651cf22c1d4f7834e2303a85" + ] + } + }, + "response": [] + }, + { + "name": "Get Energy", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LocalBaseURL}}/energy/energy/656411820133aef67f385412", + "host": [ + "{{LocalBaseURL}}" + ], + "path": [ + "energy", + "energy", + "656411820133aef67f385412" + ] + } + }, + "response": [] + }, + { + "name": "Update Energy", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", + "type": "string" + } + ] + }, + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"energy\": {\n \"_id\": \"656411820133aef67f385412\",\n \"carbon_emissions\": 0.0,\n \"date\": {\n \"$date\": \"2023-11-26T00:00:00Z\"\n },\n \"electricity\": 33,\n \"heating_oil\": 22,\n \"household\": 4,\n \"natural_gas\": 333,\n \"province\": \"British Columbia\",\n \"user_id\": \"651cf22c1d4f7834e2303a85\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{LocalBaseURL}}/energy/energy/656411820133aef67f385412", + "host": [ + "{{LocalBaseURL}}" + ], + "path": [ + "energy", + "energy", + "656411820133aef67f385412" + ] + } + }, + "response": [] + } ], "event": [ { @@ -455,3 +753,4 @@ } ] } + diff --git a/backend/routes/energy.py b/backend/routes/energy.py index 2989446..6e8e0ac 100644 --- a/backend/routes/energy.py +++ b/backend/routes/energy.py @@ -5,14 +5,14 @@ from models.energy import EnergyEntry from mongodb_api.carbon_track_db import CarbonTrackDB -from routes import carbon_auth +from routes import carbon_auth, users from utils.metric_resets import weekly_metric_reset, get_1_day_range energy_service = Blueprint('/energy', __name__) @energy_service.route("/energy/", methods=['GET']) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def get_energy(oid: str) -> Response: query = {"_id": ObjectId(oid)} item = CarbonTrackDB.energy_coll.find_one(query) @@ -21,7 +21,7 @@ def get_energy(oid: str) -> Response: @energy_service.route("/get_energy_metric_for_today/", methods=['GET']) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def get_energy_metric_for_today(user_id: str) -> Response: start_of_day, end_of_day = get_1_day_range(datetime.now()) query = {"user_id": ObjectId(user_id), "date": {"$gte": start_of_day, "$lte": end_of_day}} @@ -34,10 +34,11 @@ def get_energy_metric_for_today(user_id: str) -> Response: return jsonify({'energy': item}) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def create_energy(user_id: ObjectId) -> Response: - energy = EnergyEntry(oid=ObjectId(), user_id=user_id, heating_oil = 0, natural_gas = 0, province = "Ontario", - household = 4, electricity = 0, carbon_emissions=0.0, date=weekly_metric_reset(datetime.today())) + user = users.get_user_obj(user_id) + energy = EnergyEntry(oid=ObjectId(), user_id=user_id, heating_oil = 0, natural_gas = 0, province = user.province, + household = user.household, electricity = 0, carbon_emissions=0.0, date=weekly_metric_reset(datetime.today())) energy = energy.to_json(for_mongodb=True) inserted_id = CarbonTrackDB.energy_coll.insert_one(energy).inserted_id energy = EnergyEntry.from_json(CarbonTrackDB.energy_coll.find_one({"_id": inserted_id})).to_json() @@ -45,7 +46,7 @@ def create_energy(user_id: ObjectId) -> Response: @energy_service.route("/energy/", methods=["PATCH"]) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def update_energy(oid: str) -> Response: query = {"_id": ObjectId(oid)} energy = EnergyEntry.from_json(request.get_json()['energy']).to_json(for_mongodb=True) diff --git a/backend/routes/users.py b/backend/routes/users.py index f9c0890..4c7bdb2 100644 --- a/backend/routes/users.py +++ b/backend/routes/users.py @@ -9,8 +9,15 @@ users = Blueprint('/users', __name__) +#@carbon_auth.auth.login_required +def get_user_obj(user_id: ObjectId) -> User: + query = {"_id": user_id} + item = CarbonTrackDB.users_coll.find_one(query) + item = User.from_json(item) + return item + @users.route("/user/", methods=['GET']) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def get_user(user_id: str) -> Response: query = {"_id": ObjectId(user_id)} item = CarbonTrackDB.users_coll.find_one(query) @@ -19,7 +26,7 @@ def get_user(user_id: str) -> Response: @users.route("/user_email/", methods=['GET']) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def get_user_by_email(user_email: str) -> Response: query = {"email": user_email} item = CarbonTrackDB.users_coll.find_one(query) @@ -28,7 +35,7 @@ def get_user_by_email(user_email: str) -> Response: @users.route("/user", methods=['PUT']) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def create_user() -> Response: res: dict = request.get_json()['user'] user = User.from_json(res) @@ -45,7 +52,7 @@ def create_user() -> Response: @users.route("/user/", methods=['DELETE']) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def delete_user(user_id: str) -> Response: query = {"_id": ObjectId(user_id)} item = CarbonTrackDB.users_coll.find_one(query) @@ -55,7 +62,7 @@ def delete_user(user_id: str) -> Response: @users.route("user/", methods=["PATCH"]) -@carbon_auth.auth.login_required +#@carbon_auth.auth.login_required def update_user(user_id: str) -> Response: query = {"_id": ObjectId(user_id)} user = User.from_json(request.get_json()['user']).to_json() From b5827003c852ea9e70dbea2ff4193dcb9d469d02 Mon Sep 17 00:00:00 2001 From: Ishav Sohal Date: Sun, 26 Nov 2023 22:55:20 -0500 Subject: [PATCH 03/20] uncommented authentication checks --- backend/routes/energy.py | 8 ++++---- backend/routes/users.py | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/routes/energy.py b/backend/routes/energy.py index 6e8e0ac..98b4030 100644 --- a/backend/routes/energy.py +++ b/backend/routes/energy.py @@ -12,7 +12,7 @@ @energy_service.route("/energy/", methods=['GET']) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def get_energy(oid: str) -> Response: query = {"_id": ObjectId(oid)} item = CarbonTrackDB.energy_coll.find_one(query) @@ -21,7 +21,7 @@ def get_energy(oid: str) -> Response: @energy_service.route("/get_energy_metric_for_today/", methods=['GET']) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def get_energy_metric_for_today(user_id: str) -> Response: start_of_day, end_of_day = get_1_day_range(datetime.now()) query = {"user_id": ObjectId(user_id), "date": {"$gte": start_of_day, "$lte": end_of_day}} @@ -34,7 +34,7 @@ def get_energy_metric_for_today(user_id: str) -> Response: return jsonify({'energy': item}) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def create_energy(user_id: ObjectId) -> Response: user = users.get_user_obj(user_id) energy = EnergyEntry(oid=ObjectId(), user_id=user_id, heating_oil = 0, natural_gas = 0, province = user.province, @@ -46,7 +46,7 @@ def create_energy(user_id: ObjectId) -> Response: @energy_service.route("/energy/", methods=["PATCH"]) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def update_energy(oid: str) -> Response: query = {"_id": ObjectId(oid)} energy = EnergyEntry.from_json(request.get_json()['energy']).to_json(for_mongodb=True) diff --git a/backend/routes/users.py b/backend/routes/users.py index 4c7bdb2..15a37df 100644 --- a/backend/routes/users.py +++ b/backend/routes/users.py @@ -9,7 +9,7 @@ users = Blueprint('/users', __name__) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def get_user_obj(user_id: ObjectId) -> User: query = {"_id": user_id} item = CarbonTrackDB.users_coll.find_one(query) @@ -17,7 +17,7 @@ def get_user_obj(user_id: ObjectId) -> User: return item @users.route("/user/", methods=['GET']) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def get_user(user_id: str) -> Response: query = {"_id": ObjectId(user_id)} item = CarbonTrackDB.users_coll.find_one(query) @@ -26,7 +26,7 @@ def get_user(user_id: str) -> Response: @users.route("/user_email/", methods=['GET']) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def get_user_by_email(user_email: str) -> Response: query = {"email": user_email} item = CarbonTrackDB.users_coll.find_one(query) @@ -35,7 +35,7 @@ def get_user_by_email(user_email: str) -> Response: @users.route("/user", methods=['PUT']) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def create_user() -> Response: res: dict = request.get_json()['user'] user = User.from_json(res) @@ -52,7 +52,7 @@ def create_user() -> Response: @users.route("/user/", methods=['DELETE']) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def delete_user(user_id: str) -> Response: query = {"_id": ObjectId(user_id)} item = CarbonTrackDB.users_coll.find_one(query) @@ -62,7 +62,7 @@ def delete_user(user_id: str) -> Response: @users.route("user/", methods=["PATCH"]) -#@carbon_auth.auth.login_required +@carbon_auth.auth.login_required def update_user(user_id: str) -> Response: query = {"_id": ObjectId(user_id)} user = User.from_json(request.get_json()['user']).to_json() From 2c25823848950a8a0784342e4608699a1ef01148 Mon Sep 17 00:00:00 2001 From: Ishav Sohal Date: Sun, 26 Nov 2023 23:19:12 -0500 Subject: [PATCH 04/20] added frontend endpoints for energy metric --- frontend/src/APIs/EnergyAPI.ts | 40 ++++++++++++++++++++++++++++++++++ frontend/src/models/Energy.ts | 13 +++++++++++ 2 files changed, 53 insertions(+) create mode 100644 frontend/src/APIs/EnergyAPI.ts create mode 100644 frontend/src/models/Energy.ts diff --git a/frontend/src/APIs/EnergyAPI.ts b/frontend/src/APIs/EnergyAPI.ts new file mode 100644 index 0000000..4e2ab40 --- /dev/null +++ b/frontend/src/APIs/EnergyAPI.ts @@ -0,0 +1,40 @@ +import FLASK_HTTPS from './FLASK_API'; +import type ObjectID from 'bson-objectid'; +import type { Energy } from '../models/Energy'; + +const routeName = '/energy'; + +export const getEnergy = async (energyID: ObjectID): Promise => { + try { + const res = await FLASK_HTTPS.get(routeName + '/energy/' + energyID.str); + return res.data.energy as Energy; + } catch (error) { + console.error('Error fetching energy from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } +}; + +export const getEnergyMetricForToday = async (userID: ObjectID): Promise => { + try { + const res = await FLASK_HTTPS.get(routeName + '/get_energy_metric_for_today/' + userID.str); + return res.data.energy as Energy; + } catch (error) { + console.error('Error fetching energy from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } +}; + +export const updateEnergy = async (energy: Energy): Promise => { + try { + const res = await FLASK_HTTPS.patch(routeName + '/energy/' + energy._id.str, { + energy, + }); + return res.data.energy as Energy; + } catch (error) { + console.error('Error fetching energy from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } +}; diff --git a/frontend/src/models/Energy.ts b/frontend/src/models/Energy.ts new file mode 100644 index 0000000..1db2045 --- /dev/null +++ b/frontend/src/models/Energy.ts @@ -0,0 +1,13 @@ +import type ObjectID from 'bson-objectid'; + +export interface Energy { + _id: ObjectID; + user_id: ObjectID; + heating_oil: number; + natural_gas: number; + electricity: number; + province: string; + household: number; + carbon_emissions: number; + date: Date; +} From ebedfee75e442374bdfae82821800b264e6c147f Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 13:21:13 -0500 Subject: [PATCH 05/20] Added Abstract Carbon Model --- backend/models/abstract_carbon_model.py | 81 +++++++++++++++++++++++++ backend/models/abstract_db_model.py | 2 +- backend/models/energy.py | 60 +++++++++--------- backend/models/food.py | 36 +++++------ backend/models/transportation.py | 65 +++----------------- backend/models/user.py | 4 +- 6 files changed, 134 insertions(+), 114 deletions(-) create mode 100644 backend/models/abstract_carbon_model.py diff --git a/backend/models/abstract_carbon_model.py b/backend/models/abstract_carbon_model.py new file mode 100644 index 0000000..bc7f24d --- /dev/null +++ b/backend/models/abstract_carbon_model.py @@ -0,0 +1,81 @@ +""" +Carbon Model + +All classes that store carbon usage must inherit from this abstract class +""" +from __future__ import annotations +import json +from datetime import datetime, timezone +from typing import Union + +from bson import ObjectId +from models.abstract_db_model import DB_MODEL + + +class CARBON_MODEL(DB_MODEL): + + oid: ObjectId + user_id: ObjectId + carbon_emissions: int + date: datetime + + def __init__(self, oid: ObjectId, user_id: ObjectId, carbon_emissions: int, date: Union[str, datetime]) -> None: + super().__init__(oid) + self.user_id = ObjectId(user_id) + self.carbon_emissions = carbon_emissions + if isinstance(date, datetime): + self.date = date + else: + self.date = datetime.fromisoformat(date) + + def to_json(self) -> json: + raise NotImplementedError + + @staticmethod + def from_json(doc: json) -> CARBON_MODEL: + raise NotImplementedError + + def calculate_carbon_emissions(self) -> int: + raise NotImplementedError + + @staticmethod + def get_monthly_view(start: datetime, end: datetime, + carbonEntries: list[CARBON_MODEL]) -> list[dict[str, Union[list[float], str]]]: + monthly_data = [] + + # Make start date offset-aware (assuming UTC for simplicity) + start = start.replace(tzinfo=timezone.utc) + + current_month = start + while current_month <= end: + # Add the current month to the list + monthly_data.append({ + "month": current_month.strftime("%B"), + "year": current_month.strftime("%Y"), + "data": [0, 0, 0, 0] + }) + + # Move to the next month + if current_month.month == 12: + current_month = datetime(current_month.year + 1, 1, 1, tzinfo=timezone.utc) + else: + current_month = datetime(current_month.year, current_month.month + 1, 1, tzinfo=timezone.utc) + + for carbon_entry in carbonEntries: + for monthly_entry in monthly_data: + if carbon_entry.date.strftime("%B") == monthly_entry["month"] \ + and carbon_entry.date.strftime("%Y") == monthly_entry["year"]: + if carbon_entry.date.day < 7: + monthly_entry["data"][0] = carbon_entry.calculate_carbon_emissions() + elif carbon_entry.date.day < 14: + monthly_entry["data"][1] = carbon_entry.calculate_carbon_emissions() + elif carbon_entry.date.day < 21: + monthly_entry["data"][2] = carbon_entry.calculate_carbon_emissions() + elif carbon_entry.date.day < 28: + monthly_entry["data"][3] += carbon_entry.calculate_carbon_emissions() + else: # If a Month has 5 sunday, we add them to the fourth week + monthly_entry["data"][3] += carbon_entry.calculate_carbon_emissions() / 4 + return monthly_data + + def __repr__(self) -> str: + raise NotImplementedError diff --git a/backend/models/abstract_db_model.py b/backend/models/abstract_db_model.py index 9cf7859..50dfe19 100644 --- a/backend/models/abstract_db_model.py +++ b/backend/models/abstract_db_model.py @@ -1,7 +1,7 @@ """ DB Model -All class that are storable in the db must inherit from this abstract class +All classes that are storable in the db must inherit from this abstract class """ from __future__ import annotations import json diff --git a/backend/models/energy.py b/backend/models/energy.py index d982562..49e9b08 100644 --- a/backend/models/energy.py +++ b/backend/models/energy.py @@ -3,38 +3,35 @@ """ from __future__ import annotations +from typing import Union import json from datetime import datetime -from models.abstract_db_model import DB_MODEL +from models.abstract_carbon_model import CARBON_MODEL from bson import ObjectId -from bson import json_util -class EnergyEntry(DB_MODEL): +class EnergyEntry(CARBON_MODEL): oid: ObjectId user_id: ObjectId - heating_oil: int # measured in L of fuel - natural_gas: int # measured in m3 of gas - electricity: int # measured in kWh + carbon_emissions: int # measured in kgs of CO2 + date: datetime + heating_oil: int # measured in L of fuel + natural_gas: int # measured in m3 of gas + electricity: int # measured in kWh province: str household: int - carbon_emissions: float # measured in kgs of CO2 - date: datetime - def __init__(self, oid: ObjectId, user_id: ObjectId, heating_oil: int, natural_gas: int, province: str, - household: int, electricity: int, carbon_emissions: float, date: datetime) -> None: - super().__init__(oid) - self.user_id = ObjectId(user_id) + def __init__(self, oid: ObjectId, user_id: ObjectId, carbon_emissions: int, date: Union[str, datetime], + heating_oil: int, natural_gas: int, province: str, household: int, electricity: int) -> None: + super().__init__(oid, user_id, carbon_emissions, date) self.heating_oil = heating_oil self.natural_gas = natural_gas self.electricity = electricity self.province = province self.household = household - self.carbon_emissions = carbon_emissions - self.date = date - def to_json(self, for_mongodb: bool = False) -> json: - res = { + def to_json(self) -> json: + return { '_id': self.oid, 'user_id': self.user_id, 'heating_oil': self.heating_oil, @@ -45,9 +42,6 @@ def to_json(self, for_mongodb: bool = False) -> json: 'carbon_emissions': self.calculate_carbon_emissions(), 'date': self.date } - if for_mongodb: - return res - return json.loads(json_util.dumps(res)) @staticmethod def from_json(doc: json) -> EnergyEntry: @@ -68,31 +62,31 @@ def calculate_carbon_emissions(self) -> float: natural_gas_carbon_emissions = self.natural_gas * 1.96 if self.province == "British Columbia": - electricity_carbon_emissions = (self.electricity * 0.015)/self.household + electricity_carbon_emissions = (self.electricity * 0.015) / self.household elif self.province == "Alberta": - electricity_carbon_emissions = (self.electricity * 0.54)/self.household + electricity_carbon_emissions = (self.electricity * 0.54) / self.household elif self.province == "Saskatchewan": - electricity_carbon_emissions = (self.electricity * 0.73)/self.household + electricity_carbon_emissions = (self.electricity * 0.73) / self.household elif self.province == "Manitoba": - electricity_carbon_emissions = (self.electricity * 0.002)/self.household + electricity_carbon_emissions = (self.electricity * 0.002) / self.household elif self.province == "Ontario": - electricity_carbon_emissions = (self.electricity * 0.03)/self.household + electricity_carbon_emissions = (self.electricity * 0.03) / self.household elif self.province == "Quebec": - electricity_carbon_emissions = (self.electricity * 0.0017)/self.household + electricity_carbon_emissions = (self.electricity * 0.0017) / self.household elif self.province == "New Brunswick": - electricity_carbon_emissions = (self.electricity * 0.3)/self.household + electricity_carbon_emissions = (self.electricity * 0.3) / self.household elif self.province == "Nova Scotia": - electricity_carbon_emissions = (self.electricity * 0.69)/self.household + electricity_carbon_emissions = (self.electricity * 0.69) / self.household elif self.province == "PEI": - electricity_carbon_emissions = (self.electricity * 0.3)/self.household + electricity_carbon_emissions = (self.electricity * 0.3) / self.household elif self.province == "Newfoundland and Labrador": - electricity_carbon_emissions = (self.electricity * 0.017)/self.household + electricity_carbon_emissions = (self.electricity * 0.017) / self.household elif self.province == "Yukon": - electricity_carbon_emissions = (self.electricity * 0.08)/self.household + electricity_carbon_emissions = (self.electricity * 0.08) / self.household elif self.province == "Nortwest Territories": - electricity_carbon_emissions = (self.electricity * 0.17)/self.household - else: # self.province == "Nunavut" - electricity_carbon_emissions = (self.electricity * 0.84)/self.household + electricity_carbon_emissions = (self.electricity * 0.17) / self.household + else: # self.province == "Nunavut" + electricity_carbon_emissions = (self.electricity * 0.84) / self.household return sum([heating_oil_carbon_emissions, natural_gas_carbon_emissions, electricity_carbon_emissions]) def __repr__(self) -> str: diff --git a/backend/models/food.py b/backend/models/food.py index 4bdeafe..b7123f9 100644 --- a/backend/models/food.py +++ b/backend/models/food.py @@ -3,16 +3,18 @@ """ from __future__ import annotations +from typing import Union import json from datetime import datetime -from models.abstract_db_model import DB_MODEL +from models.abstract_carbon_model import CARBON_MODEL from bson import ObjectId -from bson import json_util -class FoodEntry(DB_MODEL): +class FoodEntry(CARBON_MODEL): oid: ObjectId user_id: ObjectId + carbon_emissions: int + date: datetime beef: int lamb: int pork: int @@ -21,15 +23,12 @@ class FoodEntry(DB_MODEL): cheese: int milk: int food_waste: int - carbon_emissions: float - date: datetime # food measurements in # of 100g servings - def __init__(self, oid: ObjectId, user_id: ObjectId, beef: int, lamb: int, pork: int, - chicken: int, fish: int, cheese: int, milk: int, food_waste: int, carbon_emissions: float, - date: datetime) -> None: - super().__init__(oid) - self.user_id = ObjectId(user_id) + def __init__(self, oid: ObjectId, user_id: ObjectId, carbon_emissions: int, date: Union[str, datetime], + beef: int, lamb: int, pork: int, chicken: int, fish: int, cheese: int, milk: int, + food_waste: int) -> None: + super().__init__(oid, user_id, carbon_emissions, date) self.beef = beef self.lamb = lamb self.pork = pork @@ -38,27 +37,22 @@ def __init__(self, oid: ObjectId, user_id: ObjectId, beef: int, lamb: int, pork: self.cheese = cheese self.milk = milk self.food_waste = food_waste - self.carbon_emissions = carbon_emissions - self.date = date - def to_json(self, for_mongodb: bool = False) -> json: - res = { + def to_json(self) -> json: + return { '_id': self.oid, 'user_id': self.user_id, 'beef': self.beef, 'lamb': self.lamb, 'pork': self.pork, - 'chicken': self.chicken, + 'chicken': self.chicken, 'fish': self.fish, - 'cheese': self.cheese, + 'cheese': self.cheese, 'milk': self.milk, - 'food_waste': self.food_waste, + 'food_waste': self.food_waste, 'carbon_emissions': self.calculate_carbon_emissions(), 'date': self.date } - if for_mongodb: - return res - return json.loads(json_util.dumps(res)) @staticmethod def from_json(doc: json) -> FoodEntry: @@ -87,7 +81,7 @@ def calculate_carbon_emissions(self) -> float: milk_carbon_emissions = self.milk * 0.8 food_waste_carbon_emissions = self.food_waste * 0.25 return sum([beef_carbon_emissions, lamb_carbon_emissions, pork_carbon_emissions, - chicken_carbon_emissions, fish_carbon_emissions, cheese_carbon_emissions, + chicken_carbon_emissions, fish_carbon_emissions, cheese_carbon_emissions, milk_carbon_emissions, food_waste_carbon_emissions]) def __repr__(self) -> str: diff --git a/backend/models/transportation.py b/backend/models/transportation.py index 2b03cd2..f91c55a 100644 --- a/backend/models/transportation.py +++ b/backend/models/transportation.py @@ -5,39 +5,33 @@ from __future__ import annotations from typing import Union import json -from datetime import datetime, timezone -from models.abstract_db_model import DB_MODEL +from datetime import datetime +from models.abstract_carbon_model import CARBON_MODEL from bson import ObjectId -class TransportationEntry(DB_MODEL): +class TransportationEntry(CARBON_MODEL): oid: ObjectId user_id: ObjectId + carbon_emissions: int + date: datetime bus: int train: int motorbike: int electric_car: int gasoline_car: int - carbon_emissions: int - date: datetime - def __init__(self, oid: ObjectId, user_id: ObjectId, bus: int, train: int, motorbike: int, - electric_car: int, gasoline_car: int, carbon_emissions: int, date: Union[str, datetime]) -> None: - super().__init__(oid) - self.user_id = ObjectId(user_id) + def __init__(self, oid: ObjectId, user_id: ObjectId, carbon_emissions: int, date: Union[str, datetime], + bus: int, train: int, motorbike: int, electric_car: int, gasoline_car: int) -> None: + super().__init__(oid, user_id, carbon_emissions, date) self.bus = bus self.train = train self.motorbike = motorbike self.electric_car = electric_car self.gasoline_car = gasoline_car - self.carbon_emissions = carbon_emissions - if isinstance(date, datetime): - self.date = date - else: - self.date = datetime.fromisoformat(date) def to_json(self) -> json: - res = { + return { "_id": self.oid, "user_id": self.user_id, "bus": self.bus, @@ -48,7 +42,6 @@ def to_json(self) -> json: "carbon_emissions": self.calculate_carbon_emissions(), "date": self.date } - return res @staticmethod def from_json(doc: json) -> TransportationEntry: @@ -73,45 +66,5 @@ def calculate_carbon_emissions(self) -> int: return int(sum([bus_carbon_emissions, train_carbon_emissions, motorbike_carbon_emissions, electric_car_carbon_emissions, gasoline_car_carbon_emissions])) - @staticmethod - def get_monthly_view(start: datetime, end: datetime, - transportationEntries: list[TransportationEntry]) -> list[dict[str, Union[list[float], str]]]: - monthly_data = [] - - # Make start date offset-aware (assuming UTC for simplicity) - start = start.replace(tzinfo=timezone.utc) - - current_month = start - while current_month <= end: - # Add the current month to the list - monthly_data.append({ - "month": current_month.strftime("%B"), - "year": current_month.strftime("%Y"), - "data": [0, 0, 0, 0] - }) - - # Move to the next month - if current_month.month == 12: - current_month = datetime(current_month.year + 1, 1, 1, tzinfo=timezone.utc) - else: - current_month = datetime(current_month.year, current_month.month + 1, 1, tzinfo=timezone.utc) - - for transportation_entry in transportationEntries: - for monthly_entry in monthly_data: - if transportation_entry.date.strftime("%B") == monthly_entry["month"] \ - and transportation_entry.date.strftime("%Y") == monthly_entry["year"]: - if transportation_entry.date.day < 7: - monthly_entry["data"][0] = transportation_entry.calculate_carbon_emissions() - elif transportation_entry.date.day < 14: - monthly_entry["data"][1] = transportation_entry.calculate_carbon_emissions() - elif transportation_entry.date.day < 21: - monthly_entry["data"][2] = transportation_entry.calculate_carbon_emissions() - elif transportation_entry.date.day < 28: - monthly_entry["data"][3] += transportation_entry.calculate_carbon_emissions() - else: # If a Month has 5 sunday, we add them to the fourth week - monthly_entry["data"][3] += transportation_entry.calculate_carbon_emissions() / 4 - - return monthly_data - def __repr__(self) -> str: return f"Transportation ID: {self.oid.__str__()}" diff --git a/backend/models/user.py b/backend/models/user.py index 146064a..1f384f2 100644 --- a/backend/models/user.py +++ b/backend/models/user.py @@ -31,7 +31,7 @@ def __init__(self, oid: ObjectId, full_name: str, email: str, badges: list[str], self.fuel_efficiency = fuel_efficiency def to_json(self) -> json: - res = { + return { '_id': self.oid, 'full_name': self.full_name, 'email': self.email, @@ -42,7 +42,6 @@ def to_json(self) -> json: 'household': self.household, 'fuel_efficiency': self.fuel_efficiency } - return res @staticmethod def from_json(doc: json) -> User: @@ -57,7 +56,6 @@ def from_json(doc: json) -> User: household=doc["household"], fuel_efficiency=doc["fuel_efficiency"] ) - def __repr__(self) -> str: return f'User ID: {self.oid.__str__()}' From b2ac1815dbd3568c40dd2540c61d33c14697d1c6 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 13:22:08 -0500 Subject: [PATCH 06/20] Removed User Duplicate Method --- backend/routes/users.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/backend/routes/users.py b/backend/routes/users.py index 15a37df..f9c0890 100644 --- a/backend/routes/users.py +++ b/backend/routes/users.py @@ -9,13 +9,6 @@ users = Blueprint('/users', __name__) -@carbon_auth.auth.login_required -def get_user_obj(user_id: ObjectId) -> User: - query = {"_id": user_id} - item = CarbonTrackDB.users_coll.find_one(query) - item = User.from_json(item) - return item - @users.route("/user/", methods=['GET']) @carbon_auth.auth.login_required def get_user(user_id: str) -> Response: From 814bb3b0f968bf2f55afead81bbd15fbe49bf09b Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 13:40:17 -0500 Subject: [PATCH 07/20] Updated Routes --- backend/routes/energy.py | 52 ++++++++++++++++++++------- backend/routes/food.py | 60 ++++++++++++++++++++------------ backend/routes/transportation.py | 11 +++--- 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/backend/routes/energy.py b/backend/routes/energy.py index 98b4030..168d728 100644 --- a/backend/routes/energy.py +++ b/backend/routes/energy.py @@ -1,12 +1,14 @@ # Python Imports from datetime import datetime +import flask from bson import ObjectId from flask import Blueprint, Response, jsonify, request - from models.energy import EnergyEntry +from models.user import User from mongodb_api.carbon_track_db import CarbonTrackDB from routes import carbon_auth, users -from utils.metric_resets import weekly_metric_reset, get_1_day_range +from utils.FirebaseAPI import FirebaseAPI +from utils.metric_resets import weekly_metric_reset energy_service = Blueprint('/energy', __name__) @@ -20,15 +22,36 @@ def get_energy(oid: str) -> Response: return jsonify({'energy': item}) -@energy_service.route("/get_energy_metric_for_today/", methods=['GET']) +@energy_service.route("/get_energy_entries_for_user_using_data_range", methods=['POST']) +@carbon_auth.auth.login_required +def get_energy_entries_for_user_using_date_range() -> Response: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + data = request.get_json() + start = datetime.fromisoformat(data.get('start')) + end = datetime.fromisoformat(data.get('end')) + # Validate that both start and end dates are provided + if not start or not end: + return jsonify({'error': 'Both start and end dates are required'}) + + query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} + items = list(CarbonTrackDB.energy_coll.find(query)) + energy_items: list[EnergyEntry] = [EnergyEntry.from_json(item) for item in items] + json_items = [item.to_json() for item in energy_items] + return jsonify({ + 'energyEntries': json_items, + 'monthlyData': EnergyEntry.get_monthly_view(start, end, energy_items) + }) + + +@energy_service.route("/get_energy_metric_for_today", methods=['GET']) @carbon_auth.auth.login_required -def get_energy_metric_for_today(user_id: str) -> Response: - start_of_day, end_of_day = get_1_day_range(datetime.now()) - query = {"user_id": ObjectId(user_id), "date": {"$gte": start_of_day, "$lte": end_of_day}} +def get_energy_metric_for_today() -> Response: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} item = CarbonTrackDB.energy_coll.find_one(query) if item is None: - create_energy(ObjectId(user_id)) - return get_energy_metric_for_today(user_id=user_id) + create_energy(ObjectId(user.oid)) + return get_energy_metric_for_today() else: item = EnergyEntry.from_json(item).to_json() return jsonify({'energy': item}) @@ -36,10 +59,10 @@ def get_energy_metric_for_today(user_id: str) -> Response: @carbon_auth.auth.login_required def create_energy(user_id: ObjectId) -> Response: - user = users.get_user_obj(user_id) - energy = EnergyEntry(oid=ObjectId(), user_id=user_id, heating_oil = 0, natural_gas = 0, province = user.province, - household = user.household, electricity = 0, carbon_emissions=0.0, date=weekly_metric_reset(datetime.today())) - energy = energy.to_json(for_mongodb=True) + user = User.from_json(CarbonTrackDB.users_coll.find_one({'_id'})) + energy = EnergyEntry(oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), + heating_oil=0, natural_gas=0, province=user.province, household=user.household, electricity=0) + energy = energy.to_json() inserted_id = CarbonTrackDB.energy_coll.insert_one(energy).inserted_id energy = EnergyEntry.from_json(CarbonTrackDB.energy_coll.find_one({"_id": inserted_id})).to_json() return energy @@ -49,7 +72,10 @@ def create_energy(user_id: ObjectId) -> Response: @carbon_auth.auth.login_required def update_energy(oid: str) -> Response: query = {"_id": ObjectId(oid)} - energy = EnergyEntry.from_json(request.get_json()['energy']).to_json(for_mongodb=True) + energy = EnergyEntry.from_json(request.get_json()['energy']).to_json() + del energy['_id'] + del energy['date'] + del energy['user_id'] CarbonTrackDB.energy_coll.update_one(query, {'$set': energy}) item = CarbonTrackDB.energy_coll.find_one(query) item = EnergyEntry.from_json(item).to_json() diff --git a/backend/routes/food.py b/backend/routes/food.py index f93379e..f718e44 100644 --- a/backend/routes/food.py +++ b/backend/routes/food.py @@ -1,12 +1,15 @@ # Python Imports from datetime import datetime + +import flask from bson import ObjectId from flask import Blueprint, Response, jsonify, request from models.food import FoodEntry from mongodb_api.carbon_track_db import CarbonTrackDB from routes import carbon_auth -from utils.metric_resets import weekly_metric_reset, get_1_day_range +from utils.FirebaseAPI import FirebaseAPI +from utils.metric_resets import weekly_metric_reset food_service = Blueprint('/food', __name__) @@ -20,15 +23,36 @@ def get_food(oid: str) -> Response: return jsonify({'food': item}) -@food_service.route("/get_food_metric_for_today/", methods=['GET']) +@food_service.route("/get_food_entries_for_user_using_data_range", methods=['POST']) +@carbon_auth.auth.login_required +def get_food_entries_for_user_using_date_range() -> Response: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + data = request.get_json() + start = datetime.fromisoformat(data.get('start')) + end = datetime.fromisoformat(data.get('end')) + # Validate that both start and end dates are provided + if not start or not end: + return jsonify({'error': 'Both start and end dates are required'}) + + query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} + items = list(CarbonTrackDB.food_coll.find(query)) + food_items: list[FoodEntry] = [FoodEntry.from_json(item) for item in items] + json_items = [item.to_json() for item in food_items] + return jsonify({ + 'foodEntries': json_items, + 'monthlyData': FoodEntry.get_monthly_view(start, end, food_items) + }) + + +@food_service.route("/get_food_metric_for_today/", methods=['GET']) @carbon_auth.auth.login_required -def get_food_metric_for_today(user_id: str) -> Response: - start_of_day, end_of_day = get_1_day_range(datetime.now()) - query = {"user_id": ObjectId(user_id), "date": {"$gte": start_of_day, "$lte": end_of_day}} +def get_food_metric_for_today() -> Response: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} item = CarbonTrackDB.food_coll.find_one(query) if item is None: - create_food(ObjectId(user_id)) - return get_food_metric_for_today(user_id=user_id) + create_food(ObjectId(user.oid)) + return get_food_metric_for_today() else: item = FoodEntry.from_json(item).to_json() return jsonify({'food': item}) @@ -37,20 +61,9 @@ def get_food_metric_for_today(user_id: str) -> Response: @carbon_auth.auth.login_required def create_food(user_id: ObjectId) -> Response: food = FoodEntry( - oid=ObjectId(), - user_id=user_id, - beef=0, - lamb=0, - pork=0, - chicken=0, - fish=0, - cheese=0, - milk=0, - food_waste=0, - carbon_emissions=0.0, - date=weekly_metric_reset(datetime.today())) - - food = food.to_json(for_mongodb=True) + oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), + beef=0, lamb=0, pork=0, chicken=0, fish=0, cheese=0, milk=0, food_waste=0) + food = food.to_json() inserted_id = CarbonTrackDB.food_coll.insert_one(food).inserted_id food = FoodEntry.from_json(CarbonTrackDB.food_coll.find_one({"_id": inserted_id})).to_json() return food @@ -60,7 +73,10 @@ def create_food(user_id: ObjectId) -> Response: @carbon_auth.auth.login_required def update_food(oid: str) -> Response: query = {"_id": ObjectId(oid)} - food = FoodEntry.from_json(request.get_json()['food']).to_json(for_mongodb=True) + food = FoodEntry.from_json(request.get_json()['food']).to_json() + del food['_id'] + del food['date'] + del food['user_id'] CarbonTrackDB.food_coll.update_one(query, {'$set': food}) item = CarbonTrackDB.food_coll.find_one(query) item = FoodEntry.from_json(item).to_json() diff --git a/backend/routes/transportation.py b/backend/routes/transportation.py index 491701b..5337461 100644 --- a/backend/routes/transportation.py +++ b/backend/routes/transportation.py @@ -3,7 +3,6 @@ from bson import ObjectId from flask import Blueprint, Response, jsonify, request import flask - from models.transportation import TransportationEntry from mongodb_api.carbon_track_db import CarbonTrackDB from routes import carbon_auth @@ -14,7 +13,7 @@ @transportation_service.route("/transportation/", methods=['GET']) -# @carbon_auth.auth.login_required +@carbon_auth.auth.login_required def get_transportation(oid: str) -> Response: query = {"_id": ObjectId(oid)} item = CarbonTrackDB.transportation_coll.find_one(query) @@ -22,9 +21,9 @@ def get_transportation(oid: str) -> Response: return jsonify({"transportation": item}) -@transportation_service.route("/get_transportations_entries_for_user_using_data_range", methods=['POST']) +@transportation_service.route("/get_transportation_entries_for_user_using_data_range", methods=['POST']) @carbon_auth.auth.login_required -def get_transportations_entries_for_user_using_date_range() -> Response: +def get_transportation_entries_for_user_using_date_range() -> Response: user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) data = request.get_json() start = datetime.fromisoformat(data.get('start')) @@ -59,8 +58,8 @@ def get_transportation_metric_for_today() -> Response: @carbon_auth.auth.login_required def create_transportation(user_id: ObjectId) -> Response: - transportation = TransportationEntry(oid=ObjectId(), user_id=user_id, bus=0, train=0, motorbike=0, electric_car=0, - gasoline_car=0, carbon_emissions=0, date=weekly_metric_reset(datetime.today())) + transportation = TransportationEntry(oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), + bus=0, train=0, motorbike=0, electric_car=0, gasoline_car=0) transportation = transportation.to_json() inserted_id = CarbonTrackDB.transportation_coll.insert_one(transportation).inserted_id transportation = TransportationEntry.from_json(CarbonTrackDB.transportation_coll.find_one({"_id": inserted_id})).to_json() From c6b20aacbba0392117f32eadd880d6562559926e Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 13:46:26 -0500 Subject: [PATCH 08/20] Added npm run dev command --- .github/workflows/checks.yml | 1 + frontend/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 5b16256..fa44bcb 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -16,6 +16,7 @@ jobs: run: | cd frontend npm install + npm run dev - name: Check linting run: | diff --git a/frontend/package.json b/frontend/package.json index 680f1da..fa750c1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,6 +4,7 @@ "main": "node_modules/expo/AppEntry.js", "scripts": { "start": "expo start", + "dev": "npx expo start --tunnel", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web", From e3060ae410bd7a1e73b57ad2f0986b20d8956e3b Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 13:47:12 -0500 Subject: [PATCH 09/20] Updated Routes --- backend/routes/energy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/routes/energy.py b/backend/routes/energy.py index 168d728..ab9d316 100644 --- a/backend/routes/energy.py +++ b/backend/routes/energy.py @@ -6,7 +6,7 @@ from models.energy import EnergyEntry from models.user import User from mongodb_api.carbon_track_db import CarbonTrackDB -from routes import carbon_auth, users +from routes import carbon_auth from utils.FirebaseAPI import FirebaseAPI from utils.metric_resets import weekly_metric_reset From a243d711eaf27e33ababab557ad7a7e5fc71cc37 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 16:11:07 -0500 Subject: [PATCH 10/20] Updated Routes to Handle Errors --- backend/app.py | 17 +++++ backend/routes/energy.py | 106 +++++++++++++++------------ backend/routes/food.py | 106 +++++++++++++++------------ backend/routes/transportation.py | 104 +++++++++++++++----------- backend/routes/users.py | 83 ++++++++++++--------- backend/utils/carbon_track_errors.py | 5 ++ 6 files changed, 253 insertions(+), 168 deletions(-) create mode 100644 backend/utils/carbon_track_errors.py diff --git a/backend/app.py b/backend/app.py index e7c7327..286624e 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1,6 +1,7 @@ # Python Imports from flask import Flask, Response, jsonify, render_template from flask_cors import CORS +from werkzeug.exceptions import HTTPException # Imports from routes.users import users @@ -32,6 +33,22 @@ def test_google() -> str: return render_template('index.html') +# Error handler for 400 Bad Request errors +@app.errorhandler(400) +def bad_request(error: HTTPException): + response = jsonify({"error": "Bad Request", "message": error.description}) + response.status_code = error.code + return response + + +# Error handler for 404 Not Found errors +@app.errorhandler(404) +def not_found(error: HTTPException): + response = jsonify({"error": error.name, "message": error.description}) + response.status_code = error.code + return response + + if __name__ == '__main__': app.run(host='0.0.0.0', port=6050, debug=True, threaded=False) diff --git a/backend/routes/energy.py b/backend/routes/energy.py index ab9d316..03c30c2 100644 --- a/backend/routes/energy.py +++ b/backend/routes/energy.py @@ -2,12 +2,13 @@ from datetime import datetime import flask from bson import ObjectId -from flask import Blueprint, Response, jsonify, request +from flask import Blueprint, Response, abort, jsonify, request from models.energy import EnergyEntry from models.user import User from mongodb_api.carbon_track_db import CarbonTrackDB from routes import carbon_auth from utils.FirebaseAPI import FirebaseAPI +from utils.carbon_track_errors import CarbonTrackError from utils.metric_resets import weekly_metric_reset energy_service = Blueprint('/energy', __name__) @@ -16,67 +17,82 @@ @energy_service.route("/energy/", methods=['GET']) @carbon_auth.auth.login_required def get_energy(oid: str) -> Response: - query = {"_id": ObjectId(oid)} - item = CarbonTrackDB.energy_coll.find_one(query) - item = EnergyEntry.from_json(item).to_json() - return jsonify({'energy': item}) + try: + query = {"_id": ObjectId(oid)} + item = CarbonTrackDB.energy_coll.find_one(query) + item = EnergyEntry.from_json(item).to_json() + return jsonify({'energy': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @energy_service.route("/get_energy_entries_for_user_using_data_range", methods=['POST']) @carbon_auth.auth.login_required def get_energy_entries_for_user_using_date_range() -> Response: - user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) - data = request.get_json() - start = datetime.fromisoformat(data.get('start')) - end = datetime.fromisoformat(data.get('end')) - # Validate that both start and end dates are provided - if not start or not end: - return jsonify({'error': 'Both start and end dates are required'}) + try: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + data = request.get_json() + start = datetime.fromisoformat(data.get('start')) + end = datetime.fromisoformat(data.get('end')) + # Validate that both start and end dates are provided + if not start or not end: + return jsonify({'error': 'Both start and end dates are required'}) - query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} - items = list(CarbonTrackDB.energy_coll.find(query)) - energy_items: list[EnergyEntry] = [EnergyEntry.from_json(item) for item in items] - json_items = [item.to_json() for item in energy_items] - return jsonify({ - 'energyEntries': json_items, - 'monthlyData': EnergyEntry.get_monthly_view(start, end, energy_items) - }) + query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} + items = list(CarbonTrackDB.energy_coll.find(query)) + energy_items: list[EnergyEntry] = [EnergyEntry.from_json(item) for item in items] + json_items = [item.to_json() for item in energy_items] + return jsonify({ + 'energyEntries': json_items, + 'monthlyData': EnergyEntry.get_monthly_view(start, end, energy_items) + }) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @energy_service.route("/get_energy_metric_for_today", methods=['GET']) @carbon_auth.auth.login_required def get_energy_metric_for_today() -> Response: - user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) - query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} - item = CarbonTrackDB.energy_coll.find_one(query) - if item is None: - create_energy(ObjectId(user.oid)) - return get_energy_metric_for_today() - else: - item = EnergyEntry.from_json(item).to_json() - return jsonify({'energy': item}) + try: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} + item = CarbonTrackDB.energy_coll.find_one(query) + if item is None: + create_energy(ObjectId(user.oid)) + return get_energy_metric_for_today() + else: + item = EnergyEntry.from_json(item).to_json() + return jsonify({'energy': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @carbon_auth.auth.login_required def create_energy(user_id: ObjectId) -> Response: - user = User.from_json(CarbonTrackDB.users_coll.find_one({'_id'})) - energy = EnergyEntry(oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), - heating_oil=0, natural_gas=0, province=user.province, household=user.household, electricity=0) - energy = energy.to_json() - inserted_id = CarbonTrackDB.energy_coll.insert_one(energy).inserted_id - energy = EnergyEntry.from_json(CarbonTrackDB.energy_coll.find_one({"_id": inserted_id})).to_json() - return energy + try: + user = User.from_json(CarbonTrackDB.users_coll.find_one({'_id'})) + energy = EnergyEntry(oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), + heating_oil=0, natural_gas=0, province=user.province, household=user.household, electricity=0) + energy = energy.to_json() + inserted_id = CarbonTrackDB.energy_coll.insert_one(energy).inserted_id + energy = EnergyEntry.from_json(CarbonTrackDB.energy_coll.find_one({"_id": inserted_id})).to_json() + return energy + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @energy_service.route("/energy/", methods=["PATCH"]) @carbon_auth.auth.login_required def update_energy(oid: str) -> Response: - query = {"_id": ObjectId(oid)} - energy = EnergyEntry.from_json(request.get_json()['energy']).to_json() - del energy['_id'] - del energy['date'] - del energy['user_id'] - CarbonTrackDB.energy_coll.update_one(query, {'$set': energy}) - item = CarbonTrackDB.energy_coll.find_one(query) - item = EnergyEntry.from_json(item).to_json() - return jsonify({'updated_energy': item}) + try: + query = {"_id": ObjectId(oid)} + energy = EnergyEntry.from_json(request.get_json()['energy']).to_json() + del energy['_id'] + del energy['date'] + del energy['user_id'] + CarbonTrackDB.energy_coll.update_one(query, {'$set': energy}) + item = CarbonTrackDB.energy_coll.find_one(query) + item = EnergyEntry.from_json(item).to_json() + return jsonify({'updated_energy': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") diff --git a/backend/routes/food.py b/backend/routes/food.py index f718e44..a7807cb 100644 --- a/backend/routes/food.py +++ b/backend/routes/food.py @@ -3,12 +3,13 @@ import flask from bson import ObjectId -from flask import Blueprint, Response, jsonify, request +from flask import Blueprint, Response, abort, jsonify, request from models.food import FoodEntry from mongodb_api.carbon_track_db import CarbonTrackDB from routes import carbon_auth from utils.FirebaseAPI import FirebaseAPI +from utils.carbon_track_errors import CarbonTrackError from utils.metric_resets import weekly_metric_reset food_service = Blueprint('/food', __name__) @@ -17,67 +18,82 @@ @food_service.route("/food/", methods=['GET']) @carbon_auth.auth.login_required def get_food(oid: str) -> Response: - query = {"_id": ObjectId(oid)} - item = CarbonTrackDB.food_coll.find_one(query) - item = FoodEntry.from_json(item).to_json() - return jsonify({'food': item}) + try: + query = {"_id": ObjectId(oid)} + item = CarbonTrackDB.food_coll.find_one(query) + item = FoodEntry.from_json(item).to_json() + return jsonify({'food': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @food_service.route("/get_food_entries_for_user_using_data_range", methods=['POST']) @carbon_auth.auth.login_required def get_food_entries_for_user_using_date_range() -> Response: - user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) - data = request.get_json() - start = datetime.fromisoformat(data.get('start')) - end = datetime.fromisoformat(data.get('end')) - # Validate that both start and end dates are provided - if not start or not end: - return jsonify({'error': 'Both start and end dates are required'}) + try: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + data = request.get_json() + start = datetime.fromisoformat(data.get('start')) + end = datetime.fromisoformat(data.get('end')) + # Validate that both start and end dates are provided + if not start or not end: + return jsonify({'error': 'Both start and end dates are required'}) - query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} - items = list(CarbonTrackDB.food_coll.find(query)) - food_items: list[FoodEntry] = [FoodEntry.from_json(item) for item in items] - json_items = [item.to_json() for item in food_items] - return jsonify({ - 'foodEntries': json_items, - 'monthlyData': FoodEntry.get_monthly_view(start, end, food_items) - }) + query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} + items = list(CarbonTrackDB.food_coll.find(query)) + food_items: list[FoodEntry] = [FoodEntry.from_json(item) for item in items] + json_items = [item.to_json() for item in food_items] + return jsonify({ + 'foodEntries': json_items, + 'monthlyData': FoodEntry.get_monthly_view(start, end, food_items) + }) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @food_service.route("/get_food_metric_for_today/", methods=['GET']) @carbon_auth.auth.login_required def get_food_metric_for_today() -> Response: - user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) - query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} - item = CarbonTrackDB.food_coll.find_one(query) - if item is None: - create_food(ObjectId(user.oid)) - return get_food_metric_for_today() - else: - item = FoodEntry.from_json(item).to_json() - return jsonify({'food': item}) + try: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} + item = CarbonTrackDB.food_coll.find_one(query) + if item is None: + create_food(ObjectId(user.oid)) + return get_food_metric_for_today() + else: + item = FoodEntry.from_json(item).to_json() + return jsonify({'food': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @carbon_auth.auth.login_required def create_food(user_id: ObjectId) -> Response: - food = FoodEntry( - oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), - beef=0, lamb=0, pork=0, chicken=0, fish=0, cheese=0, milk=0, food_waste=0) - food = food.to_json() - inserted_id = CarbonTrackDB.food_coll.insert_one(food).inserted_id - food = FoodEntry.from_json(CarbonTrackDB.food_coll.find_one({"_id": inserted_id})).to_json() - return food + try: + food = FoodEntry( + oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), + beef=0, lamb=0, pork=0, chicken=0, fish=0, cheese=0, milk=0, food_waste=0) + food = food.to_json() + inserted_id = CarbonTrackDB.food_coll.insert_one(food).inserted_id + food = FoodEntry.from_json(CarbonTrackDB.food_coll.find_one({"_id": inserted_id})).to_json() + return food + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @food_service.route("/food/", methods=["PATCH"]) @carbon_auth.auth.login_required def update_food(oid: str) -> Response: - query = {"_id": ObjectId(oid)} - food = FoodEntry.from_json(request.get_json()['food']).to_json() - del food['_id'] - del food['date'] - del food['user_id'] - CarbonTrackDB.food_coll.update_one(query, {'$set': food}) - item = CarbonTrackDB.food_coll.find_one(query) - item = FoodEntry.from_json(item).to_json() - return jsonify({'updated_food': item}) + try: + query = {"_id": ObjectId(oid)} + food = FoodEntry.from_json(request.get_json()['food']).to_json() + del food['_id'] + del food['date'] + del food['user_id'] + CarbonTrackDB.food_coll.update_one(query, {'$set': food}) + item = CarbonTrackDB.food_coll.find_one(query) + item = FoodEntry.from_json(item).to_json() + return jsonify({'updated_food': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") diff --git a/backend/routes/transportation.py b/backend/routes/transportation.py index 5337461..6255181 100644 --- a/backend/routes/transportation.py +++ b/backend/routes/transportation.py @@ -1,11 +1,12 @@ # Python Imports from datetime import datetime from bson import ObjectId -from flask import Blueprint, Response, jsonify, request +from flask import Blueprint, Response, abort, jsonify, request import flask from models.transportation import TransportationEntry from mongodb_api.carbon_track_db import CarbonTrackDB from routes import carbon_auth +from utils.carbon_track_errors import CarbonTrackError from utils.metric_resets import weekly_metric_reset from utils.FirebaseAPI import FirebaseAPI @@ -15,66 +16,81 @@ @transportation_service.route("/transportation/", methods=['GET']) @carbon_auth.auth.login_required def get_transportation(oid: str) -> Response: - query = {"_id": ObjectId(oid)} - item = CarbonTrackDB.transportation_coll.find_one(query) - item = TransportationEntry.from_json(item).to_json() - return jsonify({"transportation": item}) + try: + query = {"_id": ObjectId(oid)} + item = CarbonTrackDB.transportation_coll.find_one(query) + item = TransportationEntry.from_json(item).to_json() + return jsonify({"transportation": item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @transportation_service.route("/get_transportation_entries_for_user_using_data_range", methods=['POST']) @carbon_auth.auth.login_required def get_transportation_entries_for_user_using_date_range() -> Response: - user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) - data = request.get_json() - start = datetime.fromisoformat(data.get('start')) - end = datetime.fromisoformat(data.get('end')) - # Validate that both start and end dates are provided - if not start or not end: - return jsonify({'error': 'Both start and end dates are required'}) + try: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + data = request.get_json() + start = datetime.fromisoformat(data.get('start')) + end = datetime.fromisoformat(data.get('end')) + # Validate that both start and end dates are provided + if not start or not end: + return jsonify({'error': 'Both start and end dates are required'}) - query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} - items = list(CarbonTrackDB.transportation_coll.find(query)) - transportation_items: list[TransportationEntry] = [TransportationEntry.from_json(item) for item in items] - json_items = [item.to_json() for item in transportation_items] - return jsonify({ - 'transportationEntries': json_items, - 'monthlyData': TransportationEntry.get_monthly_view(start, end, transportation_items) - }) + query = {"user_id": ObjectId(user.oid), "date": {"$gte": start, "$lte": end}} + items = list(CarbonTrackDB.transportation_coll.find(query)) + transportation_items: list[TransportationEntry] = [TransportationEntry.from_json(item) for item in items] + json_items = [item.to_json() for item in transportation_items] + return jsonify({ + 'transportationEntries': json_items, + 'monthlyData': TransportationEntry.get_monthly_view(start, end, transportation_items) + }) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @transportation_service.route("/get_transportation_metric_for_today", methods=['GET']) @carbon_auth.auth.login_required def get_transportation_metric_for_today() -> Response: - user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) - query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} - item = CarbonTrackDB.transportation_coll.find_one(query) - if item is None: - create_transportation(ObjectId(user.oid)) - return get_transportation_metric_for_today() - else: - item = TransportationEntry.from_json(item).to_json() - return jsonify({'transportation': item}) + try: + user = FirebaseAPI.get_user(flask.request.headers.get('Authorization').split()[1]) + query = {"user_id": ObjectId(user.oid), "date": weekly_metric_reset(datetime.now())} + item = CarbonTrackDB.transportation_coll.find_one(query) + if item is None: + create_transportation(ObjectId(user.oid)) + return get_transportation_metric_for_today() + else: + item = TransportationEntry.from_json(item).to_json() + return jsonify({'transportation': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @carbon_auth.auth.login_required def create_transportation(user_id: ObjectId) -> Response: - transportation = TransportationEntry(oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), - bus=0, train=0, motorbike=0, electric_car=0, gasoline_car=0) - transportation = transportation.to_json() - inserted_id = CarbonTrackDB.transportation_coll.insert_one(transportation).inserted_id - transportation = TransportationEntry.from_json(CarbonTrackDB.transportation_coll.find_one({"_id": inserted_id})).to_json() - return transportation + try: + transportation = TransportationEntry(oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), + bus=0, train=0, motorbike=0, electric_car=0, gasoline_car=0) + transportation = transportation.to_json() + inserted_id = CarbonTrackDB.transportation_coll.insert_one(transportation).inserted_id + transportation = TransportationEntry.from_json(CarbonTrackDB.transportation_coll.find_one({"_id": inserted_id})).to_json() + return transportation + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @transportation_service.route("/transportation/", methods=["PATCH"]) @carbon_auth.auth.login_required def update_transportation(oid: str) -> Response: - query = {"_id": ObjectId(oid)} - transportation: dict = TransportationEntry.from_json(request.get_json()['transportation']).to_json() - del transportation['_id'] - del transportation['date'] - del transportation['user_id'] - CarbonTrackDB.transportation_coll.update_one(query, {'$set': transportation}) - item = CarbonTrackDB.transportation_coll.find_one(query) - item = TransportationEntry.from_json(item).to_json() - return jsonify({'updated_transportation': item}) + try: + query = {"_id": ObjectId(oid)} + transportation: dict = TransportationEntry.from_json(request.get_json()['transportation']).to_json() + del transportation['_id'] + del transportation['date'] + del transportation['user_id'] + CarbonTrackDB.transportation_coll.update_one(query, {'$set': transportation}) + item = CarbonTrackDB.transportation_coll.find_one(query) + item = TransportationEntry.from_json(item).to_json() + return jsonify({'updated_transportation': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") diff --git a/backend/routes/users.py b/backend/routes/users.py index f9c0890..e090fbf 100644 --- a/backend/routes/users.py +++ b/backend/routes/users.py @@ -1,68 +1,83 @@ # Python Imports from bson import ObjectId -from flask import Blueprint, Response, jsonify, request - +from flask import Blueprint, Response, abort, jsonify, request from models.user import User from mongodb_api.carbon_track_db import CarbonTrackDB from routes import carbon_auth +from utils.carbon_track_errors import CarbonTrackError users = Blueprint('/users', __name__) @users.route("/user/", methods=['GET']) -@carbon_auth.auth.login_required +# @carbon_auth.auth.login_required def get_user(user_id: str) -> Response: - query = {"_id": ObjectId(user_id)} - item = CarbonTrackDB.users_coll.find_one(query) - item = User.from_json(item).to_json() - return jsonify({'user': item}) + try: + query = {"_id": ObjectId(user_id)} + item = CarbonTrackDB.users_coll.find_one(query) + item = User.from_json(item).to_json() + return jsonify({'user': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @users.route("/user_email/", methods=['GET']) @carbon_auth.auth.login_required def get_user_by_email(user_email: str) -> Response: - query = {"email": user_email} - item = CarbonTrackDB.users_coll.find_one(query) - item = User.from_json(item).to_json() - return jsonify({'user': item}) + try: + query = {"email": user_email} + item = CarbonTrackDB.users_coll.find_one(query) + item = User.from_json(item).to_json() + return jsonify({'user': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @users.route("/user", methods=['PUT']) @carbon_auth.auth.login_required def create_user() -> Response: - res: dict = request.get_json()['user'] - user = User.from_json(res) + try: + res: dict = request.get_json()['user'] + user = User.from_json(res) - query = {"email": user.email.lower()} - item = CarbonTrackDB.users_coll.find_one(query) - if item is None: - user = user.to_json() - inserted_id = CarbonTrackDB.users_coll.insert_one(user).inserted_id - user = User.from_json(CarbonTrackDB.users_coll.find_one({"_id": inserted_id})).to_json() - return jsonify({'user': user}) - else: - return jsonify({'error': 'User Already Exits With Same Email, Please Log In'}) + query = {"email": user.email.lower()} + item = CarbonTrackDB.users_coll.find_one(query) + if item is None: + user = user.to_json() + inserted_id = CarbonTrackDB.users_coll.insert_one(user).inserted_id + user = User.from_json(CarbonTrackDB.users_coll.find_one({"_id": inserted_id})).to_json() + return jsonify({'user': user}) + else: + abort(code=400, description="User Already Exits With Same Email, Please Log In") + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @users.route("/user/", methods=['DELETE']) @carbon_auth.auth.login_required def delete_user(user_id: str) -> Response: - query = {"_id": ObjectId(user_id)} - item = CarbonTrackDB.users_coll.find_one(query) - item = User.from_json(item).to_json() - CarbonTrackDB.users_coll.delete_one(query) - return jsonify({'deleted user': item}) + try: + query = {"_id": ObjectId(user_id)} + item = CarbonTrackDB.users_coll.find_one(query) + item = User.from_json(item).to_json() + CarbonTrackDB.users_coll.delete_one(query) + return jsonify({'deleted user': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") @users.route("user/", methods=["PATCH"]) @carbon_auth.auth.login_required def update_user(user_id: str) -> Response: - query = {"_id": ObjectId(user_id)} - user = User.from_json(request.get_json()['user']).to_json() - del user['_id'] - CarbonTrackDB.users_coll.update_one(query, {'$set': user}) - item = CarbonTrackDB.users_coll.find_one(query) - item = User.from_json(item).to_json() - return jsonify({'updated_user': item}) + try: + query = {"_id": ObjectId(user_id)} + user = User.from_json(request.get_json()['user']).to_json() + del user['_id'] + CarbonTrackDB.users_coll.update_one(query, {'$set': user}) + item = CarbonTrackDB.users_coll.find_one(query) + item = User.from_json(item).to_json() + return jsonify({'updated_user': item}) + except CarbonTrackError as e: + abort(code=400, description=f"{e}") diff --git a/backend/utils/carbon_track_errors.py b/backend/utils/carbon_track_errors.py new file mode 100644 index 0000000..1d9e487 --- /dev/null +++ b/backend/utils/carbon_track_errors.py @@ -0,0 +1,5 @@ +"""Exceptions raised by Carbon Track.""" +from __future__ import annotations + + +CarbonTrackError = Exception From 429105ff564e48fa2877cd24c1ae714e1ae3f4f7 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 16:12:33 -0500 Subject: [PATCH 11/20] Added Auth Error Handling --- .github/workflows/checks.yml | 1 - frontend/src/APIs/FLASK_API.tsx | 2 +- frontend/src/APIs/TransportationAPI.ts | 4 ++-- frontend/src/screens/login.tsx | 15 +++++++++++++-- frontend/src/screens/signup.tsx | 3 +++ frontend/src/screens/transportationHistory.tsx | 2 +- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index fa44bcb..5b16256 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -16,7 +16,6 @@ jobs: run: | cd frontend npm install - npm run dev - name: Check linting run: | diff --git a/frontend/src/APIs/FLASK_API.tsx b/frontend/src/APIs/FLASK_API.tsx index 6342285..a21008f 100644 --- a/frontend/src/APIs/FLASK_API.tsx +++ b/frontend/src/APIs/FLASK_API.tsx @@ -1,6 +1,6 @@ import axios from "axios"; import firebaseService from "../utilities/firebase"; -const FLASK_LOCAL_ADDRESS: string = "http://10.0.0.72:6050"; +const FLASK_LOCAL_ADDRESS: string = "http://10.0.10.10:6050"; // Function to get the Firebase authentication token const getFirebaseAuthToken = async (): Promise => { diff --git a/frontend/src/APIs/TransportationAPI.ts b/frontend/src/APIs/TransportationAPI.ts index b9a2610..447a4b7 100644 --- a/frontend/src/APIs/TransportationAPI.ts +++ b/frontend/src/APIs/TransportationAPI.ts @@ -17,9 +17,9 @@ export const TransportationAPI = { } }, - getTransportationsEntriesForUserUsingDataRange: async (start: Date, end: Date) => { + getTransportationEntriesForUserUsingDataRange: async (start: Date, end: Date) => { try { - const res = await FLASK_HTTPS.post(routeName + '/get_transportations_entries_for_user_using_data_range', { + const res = await FLASK_HTTPS.post(routeName + '/get_transportations_entrie_for_user_using_data_range', { start, end }); diff --git a/frontend/src/screens/login.tsx b/frontend/src/screens/login.tsx index bc87142..a9053e9 100644 --- a/frontend/src/screens/login.tsx +++ b/frontend/src/screens/login.tsx @@ -8,6 +8,7 @@ import Colors from '../../assets/colorConstants'; import { Formik } from 'formik'; import * as Yup from 'yup'; import FormTextField from '../components/forms/formTextField'; +import { UsersAPI } from '../APIs/UsersAPI'; export type StackNavigation = StackNavigationProp; @@ -26,8 +27,18 @@ export default function LogInScreen(): JSX.Element { const handleLogIn = async (fields: ILogInFields): Promise => { const { email, password } = fields; try { - await firebaseService.signInUser(email, password); - navigation.navigate('DashBoard'); + await firebaseService.signInUser(email, password).then(async () => { + await UsersAPI.GetLoggedInUser().then((res) => { + if (res != null) { + navigation.navigate('DashBoard'); + } else { + console.warn('User was not logged in: ' + res); + } + }).catch((err) => { + console.warn('User was not logged in: ' + err); + }); + }); + } catch (error) { alert('Incorrect Email or password'); } diff --git a/frontend/src/screens/signup.tsx b/frontend/src/screens/signup.tsx index db261fe..65eb169 100644 --- a/frontend/src/screens/signup.tsx +++ b/frontend/src/screens/signup.tsx @@ -55,6 +55,9 @@ export default function SignUp(): JSX.Element { badges: [], friends: [], score: 0, + province: '', + household: 0, + fuel_efficiency: 0 }).then((res): void => { console.log(res) if (typeof res === 'string') { diff --git a/frontend/src/screens/transportationHistory.tsx b/frontend/src/screens/transportationHistory.tsx index b9a96e6..05d26cd 100644 --- a/frontend/src/screens/transportationHistory.tsx +++ b/frontend/src/screens/transportationHistory.tsx @@ -37,7 +37,7 @@ export default function TransportationHistory(): JSX.Element { }); useEffect(() => { - void TransportationAPI.getTransportationsEntriesForUserUsingDataRange( + void TransportationAPI.getTransportationEntriesForUserUsingDataRange( startDate, endDate).then((res) => { if (res != null) { if (res.monthlyData != null) { From 1b7d476fe818aa8cb05c0888325b53e86f221a98 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 16:14:24 -0500 Subject: [PATCH 12/20] Updated Models --- frontend/src/models/Energy.ts | 18 +++++++++--------- frontend/src/models/Food.ts | 24 ++++++++++++------------ frontend/src/models/Transportation.ts | 4 ++-- frontend/src/models/User.ts | 3 +++ 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/frontend/src/models/Energy.ts b/frontend/src/models/Energy.ts index 1db2045..1406b6e 100644 --- a/frontend/src/models/Energy.ts +++ b/frontend/src/models/Energy.ts @@ -1,13 +1,13 @@ import type ObjectID from 'bson-objectid'; export interface Energy { - _id: ObjectID; - user_id: ObjectID; - heating_oil: number; - natural_gas: number; - electricity: number; - province: string; - household: number; - carbon_emissions: number; - date: Date; + _id: ObjectID + user_id: ObjectID + carbon_emissions: number + date: Date + heating_oil: number + natural_gas: number + electricity: number + province: string + household: number } diff --git a/frontend/src/models/Food.ts b/frontend/src/models/Food.ts index b3f4261..818efd2 100644 --- a/frontend/src/models/Food.ts +++ b/frontend/src/models/Food.ts @@ -1,16 +1,16 @@ import type ObjectID from 'bson-objectid'; export interface Food { - _id: ObjectID; - user_id: ObjectID; - beef: number; - lamb: number; - pork: number; - chicken: number; - fish: number; - cheese: number; - milk: number; - food_waste: number; - carbon_emissions: number; - date: Date; + _id: ObjectID + user_id: ObjectID + carbon_emissions: number + date: Date + beef: number + lamb: number + pork: number + chicken: number + fish: number + cheese: number + milk: number + food_waste: number } diff --git a/frontend/src/models/Transportation.ts b/frontend/src/models/Transportation.ts index 94fe1fd..176b21b 100644 --- a/frontend/src/models/Transportation.ts +++ b/frontend/src/models/Transportation.ts @@ -4,13 +4,13 @@ import { type ObjectId } from "mongodb"; export interface TransportationEntry { _id: ObjectId user_id: ObjectId + carbon_emissions: number + date: Date bus: number train: number motorbike: number electric_car: number gasoline_car: number - carbon_emissions: number - date: Date } export interface MonthlyEntry { diff --git a/frontend/src/models/User.ts b/frontend/src/models/User.ts index 0dc8ca6..8d194cc 100644 --- a/frontend/src/models/User.ts +++ b/frontend/src/models/User.ts @@ -8,6 +8,9 @@ export interface User { badges: string[] friends: ObjectId[] score: number + province: string + household: number + fuel_efficiency: number } From 3831e02dcb54d9f9804d716154a36365656597db Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 18:09:20 -0500 Subject: [PATCH 13/20] Added Token Grabber --- backend/app.py | 8 +- backend/routes/ct_firebase_service.py | 18 ++++ backend/routes/energy.py | 2 +- backend/routes/food.py | 2 +- backend/routes/transportation.py | 2 +- backend/templates/google_login.html | 122 ++++++++++++++++++++++++++ backend/templates/index.html | 46 ---------- backend/utils/FirebaseAPI.py | 9 +- 8 files changed, 147 insertions(+), 62 deletions(-) create mode 100644 backend/routes/ct_firebase_service.py create mode 100644 backend/templates/google_login.html delete mode 100644 backend/templates/index.html diff --git a/backend/app.py b/backend/app.py index 286624e..af85f85 100644 --- a/backend/app.py +++ b/backend/app.py @@ -3,6 +3,7 @@ from flask_cors import CORS from werkzeug.exceptions import HTTPException +from routes.ct_firebase_service import ct_firebase_service # Imports from routes.users import users from routes.transportation import transportation_service @@ -19,6 +20,7 @@ app.register_blueprint(transportation_service, url_prefix="/transportation") app.register_blueprint(food_service, url_prefix="/food") app.register_blueprint(energy_service, url_prefix="/energy") +app.register_blueprint(ct_firebase_service, url_prefix="/f") CORS(app) @@ -27,12 +29,6 @@ def home() -> Response: return jsonify('Carbon Track APP BACKEND API :: UNAUTHORIZED ACCESS') -# This is just for testing -@app.route("/google") -def test_google() -> str: - return render_template('index.html') - - # Error handler for 400 Bad Request errors @app.errorhandler(400) def bad_request(error: HTTPException): diff --git a/backend/routes/ct_firebase_service.py b/backend/routes/ct_firebase_service.py new file mode 100644 index 0000000..f80586d --- /dev/null +++ b/backend/routes/ct_firebase_service.py @@ -0,0 +1,18 @@ +# Python Imports +from bson import ObjectId +from flask import Blueprint, Response, abort, jsonify, render_template, request +from models.user import User +from mongodb_api.carbon_track_db import CarbonTrackDB +from routes import carbon_auth +from utils.FirebaseAPI import FirebaseAPI +from utils.carbon_track_errors import CarbonTrackError + +ct_firebase_service = Blueprint('/f', __name__) + + +# This is just for testing +@ct_firebase_service.route("/google") +def test_login_with_google() -> str: + return render_template('google_login.html') + + diff --git a/backend/routes/energy.py b/backend/routes/energy.py index 03c30c2..0b7e659 100644 --- a/backend/routes/energy.py +++ b/backend/routes/energy.py @@ -93,6 +93,6 @@ def update_energy(oid: str) -> Response: CarbonTrackDB.energy_coll.update_one(query, {'$set': energy}) item = CarbonTrackDB.energy_coll.find_one(query) item = EnergyEntry.from_json(item).to_json() - return jsonify({'updated_energy': item}) + return jsonify({'energy': item}) except CarbonTrackError as e: abort(code=400, description=f"{e}") diff --git a/backend/routes/food.py b/backend/routes/food.py index a7807cb..9075c58 100644 --- a/backend/routes/food.py +++ b/backend/routes/food.py @@ -94,6 +94,6 @@ def update_food(oid: str) -> Response: CarbonTrackDB.food_coll.update_one(query, {'$set': food}) item = CarbonTrackDB.food_coll.find_one(query) item = FoodEntry.from_json(item).to_json() - return jsonify({'updated_food': item}) + return jsonify({'food': item}) except CarbonTrackError as e: abort(code=400, description=f"{e}") diff --git a/backend/routes/transportation.py b/backend/routes/transportation.py index 6255181..4a9b505 100644 --- a/backend/routes/transportation.py +++ b/backend/routes/transportation.py @@ -91,6 +91,6 @@ def update_transportation(oid: str) -> Response: CarbonTrackDB.transportation_coll.update_one(query, {'$set': transportation}) item = CarbonTrackDB.transportation_coll.find_one(query) item = TransportationEntry.from_json(item).to_json() - return jsonify({'updated_transportation': item}) + return jsonify({'transportation': item}) except CarbonTrackError as e: abort(code=400, description=f"{e}") diff --git a/backend/templates/google_login.html b/backend/templates/google_login.html new file mode 100644 index 0000000..2ec3e6c --- /dev/null +++ b/backend/templates/google_login.html @@ -0,0 +1,122 @@ + + + + + Login with Firebase + + + + + +

Login with Firebase

+ + + + + diff --git a/backend/templates/index.html b/backend/templates/index.html deleted file mode 100644 index 35b8a5c..0000000 --- a/backend/templates/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - Login with Firebase - - - -

Login with Firebase

- - diff --git a/backend/utils/FirebaseAPI.py b/backend/utils/FirebaseAPI.py index 57479e1..b545706 100644 --- a/backend/utils/FirebaseAPI.py +++ b/backend/utils/FirebaseAPI.py @@ -2,6 +2,8 @@ from pprint import pprint import firebase_admin from firebase_admin import credentials, auth +from firebase_admin.auth import UserRecord + from models.user import User from mongodb_api.carbon_track_db import CarbonTrackDB @@ -25,10 +27,3 @@ def get_user(id_token: str) -> Optional[User]: item = CarbonTrackDB.users_coll.find_one(query) item = User.from_json(item) return item - - -if __name__ == "__main__": - d = FirebaseAPI.verify_google_token( - "eyJhbGciOiJSUzI1NiIsImtpZCI6ImE2YzYzNTNmMmEzZWMxMjg2NTA1MzBkMTVmNmM0Y2Y0NTcxYTQ1NTciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vY2FyYm9uLXRyYWNrLXN5c3RlbSIsImF1ZCI6ImNhcmJvbi10cmFjay1zeXN0ZW0iLCJhdXRoX3RpbWUiOjE3MDA2NzU5NzksInVzZXJfaWQiOiJ3UFVEaEFiM0Q5ZHpoeDJXa1RBZlBLbnhGSG0xIiwic3ViIjoid1BVRGhBYjNEOWR6aHgyV2tUQWZQS254RkhtMSIsImlhdCI6MTcwMDY3NTk3OSwiZXhwIjoxNzAwNjc5NTc5LCJlbWFpbCI6InlhemFuQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJ5YXphbkBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.MRTtHwIK-sShrOUSOTq0yJvjj2svkH3X5T2Zb2hP-KzUYxXLWTRDVUtbBxCJMghqCccTm0jYVNEEd-9i4KteCbJmSLDNbqXR0qO2797fsyo0LU9YpjRyk6-NV6CpHSSMIXeuOcdgXCo65yh_aVlS-tZJg5QU5Av0RtCxHG2szIAz-gqQMuwMxi5iHSCRns67NrxrTdO-BT_lazZo5L3huiyDnE-AGGgprQQcL1I4DMRYRwkEwDLrXoM6GNIylIur0rlVWQxUlOQvUEDhOW8YenpwPm0xuVe78yWxPMFj4aMwgoe6DotMW-HfGv5jSz6baZSHg0yfsEwbtH-iUL88uQ" - ) - pprint(d) From 21ca9b3c3e3cd7a53f2c342af6bc85e053362921 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 18:09:39 -0500 Subject: [PATCH 14/20] Updated Frontend to be up-to-date --- frontend/src/APIs/EnergyAPI.ts | 85 +++++++++++++++----------- frontend/src/APIs/FoodAPI.ts | 45 +++++++++----- frontend/src/APIs/TransportationAPI.ts | 2 +- frontend/src/models/Energy.ts | 13 +++- frontend/src/models/Food.ts | 13 +++- 5 files changed, 106 insertions(+), 52 deletions(-) diff --git a/frontend/src/APIs/EnergyAPI.ts b/frontend/src/APIs/EnergyAPI.ts index 4e2ab40..c54c226 100644 --- a/frontend/src/APIs/EnergyAPI.ts +++ b/frontend/src/APIs/EnergyAPI.ts @@ -1,40 +1,57 @@ import FLASK_HTTPS from './FLASK_API'; -import type ObjectID from 'bson-objectid'; -import type { Energy } from '../models/Energy'; +import type { EnergyEntry, EnergyRes } from '../models/Energy'; +import { type ObjectId } from 'mongodb'; const routeName = '/energy'; -export const getEnergy = async (energyID: ObjectID): Promise => { - try { - const res = await FLASK_HTTPS.get(routeName + '/energy/' + energyID.str); - return res.data.energy as Energy; - } catch (error) { - console.error('Error fetching energy from Flask BE: ', error); - console.error('Temp tip: have you started the backend?: '); - return undefined; - } -}; - -export const getEnergyMetricForToday = async (userID: ObjectID): Promise => { - try { - const res = await FLASK_HTTPS.get(routeName + '/get_energy_metric_for_today/' + userID.str); - return res.data.energy as Energy; - } catch (error) { - console.error('Error fetching energy from Flask BE: ', error); - console.error('Temp tip: have you started the backend?: '); - return undefined; - } -}; +export const EnergyAPI = { -export const updateEnergy = async (energy: Energy): Promise => { - try { - const res = await FLASK_HTTPS.patch(routeName + '/energy/' + energy._id.str, { - energy, - }); - return res.data.energy as Energy; - } catch (error) { - console.error('Error fetching energy from Flask BE: ', error); - console.error('Temp tip: have you started the backend?: '); - return undefined; + getEnergy: async (energyID: ObjectId) => { + try { + const res = await FLASK_HTTPS.get(routeName + '/energy/' + energyID.toHexString()); + return res.data.energy as EnergyEntry; + } catch (error) { + console.error('Error fetching energy from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } + }, + + getEnergyEntriesForUserUsingDataRange: async (start: Date, end: Date) => { + try { + const res = await FLASK_HTTPS.post(routeName + '/get_energy_entries_for_user_using_data_range', { + start, + end + }); + return res.data as EnergyRes; + } catch (error) { + console.error('Error fetching energy from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } + }, + + getEnergyMetricForToday: async (): Promise => { + try { + const res = await FLASK_HTTPS.get(routeName + '/get_energy_metric_for_today'); + return res.data.energy as EnergyEntry; + } catch (error) { + console.error('Error fetching energy from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } + }, + + updateEnergy: async (energy: EnergyEntry): Promise => { + try { + const res = await FLASK_HTTPS.patch(routeName + '/energy/' + energy._id.toString(), { + energy, + }); + return res.data.energy as EnergyEntry; + } catch (error) { + console.error('Error fetching energy from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } } -}; +} \ No newline at end of file diff --git a/frontend/src/APIs/FoodAPI.ts b/frontend/src/APIs/FoodAPI.ts index 69ecb02..d1a4017 100644 --- a/frontend/src/APIs/FoodAPI.ts +++ b/frontend/src/APIs/FoodAPI.ts @@ -1,42 +1,57 @@ import FLASK_HTTPS from './FLASK_API'; -import type ObjectID from 'bson-objectid'; -import type { Food } from '../models/Food'; +import type { FoodEntry, FoodRes } from '../models/Food'; +import { type ObjectId } from 'mongodb'; const routeName = '/food'; export const FoodAPI = { - getFood: async (foodID: ObjectID) => { + + getFood: async (foodID: ObjectId) => { try { - const res = await FLASK_HTTPS.get(routeName + '/food/' + foodID.str); - return res.data.food as Food; + const res = await FLASK_HTTPS.get(routeName + '/food/' + foodID.toHexString()); + return res.data.food as FoodEntry; } catch (error) { console.error('Error fetching food from Flask BE: ', error); console.error('Temp tip: have you started the backend?: '); return undefined; } }, - - getFoodMetricForToday: async (userID: ObjectID): Promise => { + + getFoodEntriesForUserUsingDataRange: async (start: Date, end: Date) => { try { - const res = await FLASK_HTTPS.get(routeName + '/get_food_metric_for_today/' + userID.str); - return res.data.food as Food; + const res = await FLASK_HTTPS.post(routeName + '/get_food_entries_for_user_using_data_range', { + start, + end + }); + return res.data as FoodRes; } catch (error) { console.error('Error fetching food from Flask BE: ', error); console.error('Temp tip: have you started the backend?: '); return undefined; } }, - - updateFood: async (food: Food): Promise => { + + getFoodMetricForToday: async (): Promise => { + try { + const res = await FLASK_HTTPS.get(routeName + '/get_food_metric_for_today'); + return res.data.food as FoodEntry; + } catch (error) { + console.error('Error fetching food from Flask BE: ', error); + console.error('Temp tip: have you started the backend?: '); + return undefined; + } + }, + + updateFood: async (food: FoodEntry): Promise => { try { - const res = await FLASK_HTTPS.patch(routeName + '/food/' + food._id.str, { + const res = await FLASK_HTTPS.patch(routeName + '/food/' + food._id.toString(), { food, }); - return res.data.food as Food; + return res.data.food as FoodEntry; } catch (error) { console.error('Error fetching food from Flask BE: ', error); console.error('Temp tip: have you started the backend?: '); return undefined; } - }, -}; + } +} \ No newline at end of file diff --git a/frontend/src/APIs/TransportationAPI.ts b/frontend/src/APIs/TransportationAPI.ts index 447a4b7..ad865ab 100644 --- a/frontend/src/APIs/TransportationAPI.ts +++ b/frontend/src/APIs/TransportationAPI.ts @@ -19,7 +19,7 @@ export const TransportationAPI = { getTransportationEntriesForUserUsingDataRange: async (start: Date, end: Date) => { try { - const res = await FLASK_HTTPS.post(routeName + '/get_transportations_entrie_for_user_using_data_range', { + const res = await FLASK_HTTPS.post(routeName + '/get_transportation_entries_for_user_using_data_range', { start, end }); diff --git a/frontend/src/models/Energy.ts b/frontend/src/models/Energy.ts index 1406b6e..6b2863c 100644 --- a/frontend/src/models/Energy.ts +++ b/frontend/src/models/Energy.ts @@ -1,6 +1,6 @@ import type ObjectID from 'bson-objectid'; -export interface Energy { +export interface EnergyEntry { _id: ObjectID user_id: ObjectID carbon_emissions: number @@ -11,3 +11,14 @@ export interface Energy { province: string household: number } + +export interface MonthlyEntry { + 'data': number[] + 'month': string + 'year': string +} + +export interface EnergyRes { + energyEntries: EnergyEntry[] + monthlyData: MonthlyEntry[] +} diff --git a/frontend/src/models/Food.ts b/frontend/src/models/Food.ts index 818efd2..4f82682 100644 --- a/frontend/src/models/Food.ts +++ b/frontend/src/models/Food.ts @@ -1,6 +1,6 @@ import type ObjectID from 'bson-objectid'; -export interface Food { +export interface FoodEntry { _id: ObjectID user_id: ObjectID carbon_emissions: number @@ -14,3 +14,14 @@ export interface Food { milk: number food_waste: number } + +export interface MonthlyEntry { + 'data': number[] + 'month': string + 'year': string +} + +export interface FoodRes { + foodEntries: FoodEntry[] + monthlyData: MonthlyEntry[] +} From 292a6e7db82227026897ac7aaf6652e5f7d11208 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 19:20:12 -0500 Subject: [PATCH 15/20] Refactored A lot of code --- backend/models/energy.py | 5 +- backend/routes/energy.py | 2 +- backend/routes/food.py | 2 +- backend/routes/users.py | 5 +- backend/utils/FirebaseAPI.py | 2 + frontend/src/components/appNavigation.tsx | 27 +- frontend/src/models/Energy.ts | 6 +- frontend/src/models/Food.ts | 6 +- frontend/src/screens/Energy/energy.tsx | 181 +++++++++++ .../src/screens/Energy/energyEntryEdit.tsx | 277 ++++++++++++++++ .../src/screens/{ => Energy}/energyForum.tsx | 4 +- frontend/src/screens/Food/foodEntryEdit.tsx | 304 ++++++++++++++++++ frontend/src/screens/{ => Food}/foodForum.tsx | 6 +- .../src/screens/{ => Food}/foodHistory.tsx | 62 +++- .../transportationEntryEdit.tsx | 8 +- .../transportationForum.tsx | 6 +- .../transportationHistory.tsx | 10 +- frontend/src/screens/dashboard.tsx | 47 ++- 18 files changed, 909 insertions(+), 51 deletions(-) create mode 100644 frontend/src/screens/Energy/energy.tsx create mode 100644 frontend/src/screens/Energy/energyEntryEdit.tsx rename frontend/src/screens/{ => Energy}/energyForum.tsx (98%) create mode 100644 frontend/src/screens/Food/foodEntryEdit.tsx rename frontend/src/screens/{ => Food}/foodForum.tsx (97%) rename frontend/src/screens/{ => Food}/foodHistory.tsx (66%) rename frontend/src/screens/{ => Transportation}/transportationEntryEdit.tsx (97%) rename frontend/src/screens/{ => Transportation}/transportationForum.tsx (98%) rename frontend/src/screens/{ => Transportation}/transportationHistory.tsx (95%) diff --git a/backend/models/energy.py b/backend/models/energy.py index 49e9b08..ab3a104 100644 --- a/backend/models/energy.py +++ b/backend/models/energy.py @@ -61,6 +61,9 @@ def calculate_carbon_emissions(self) -> float: heating_oil_carbon_emissions = self.heating_oil * 2.753 natural_gas_carbon_emissions = self.natural_gas * 1.96 + if self.household < 1: + self.household = 1 + if self.province == "British Columbia": electricity_carbon_emissions = (self.electricity * 0.015) / self.household elif self.province == "Alberta": @@ -83,7 +86,7 @@ def calculate_carbon_emissions(self) -> float: electricity_carbon_emissions = (self.electricity * 0.017) / self.household elif self.province == "Yukon": electricity_carbon_emissions = (self.electricity * 0.08) / self.household - elif self.province == "Nortwest Territories": + elif self.province == "Northwest Territories": electricity_carbon_emissions = (self.electricity * 0.17) / self.household else: # self.province == "Nunavut" electricity_carbon_emissions = (self.electricity * 0.84) / self.household diff --git a/backend/routes/energy.py b/backend/routes/energy.py index 0b7e659..0901c1c 100644 --- a/backend/routes/energy.py +++ b/backend/routes/energy.py @@ -70,7 +70,7 @@ def get_energy_metric_for_today() -> Response: @carbon_auth.auth.login_required def create_energy(user_id: ObjectId) -> Response: try: - user = User.from_json(CarbonTrackDB.users_coll.find_one({'_id'})) + user = User.from_json(CarbonTrackDB.users_coll.find_one({'_id': user_id})) energy = EnergyEntry(oid=ObjectId(), user_id=user_id, carbon_emissions=0, date=weekly_metric_reset(datetime.today()), heating_oil=0, natural_gas=0, province=user.province, household=user.household, electricity=0) energy = energy.to_json() diff --git a/backend/routes/food.py b/backend/routes/food.py index 9075c58..460d3b4 100644 --- a/backend/routes/food.py +++ b/backend/routes/food.py @@ -51,7 +51,7 @@ def get_food_entries_for_user_using_date_range() -> Response: abort(code=400, description=f"{e}") -@food_service.route("/get_food_metric_for_today/", methods=['GET']) +@food_service.route("/get_food_metric_for_today", methods=['GET']) @carbon_auth.auth.login_required def get_food_metric_for_today() -> Response: try: diff --git a/backend/routes/users.py b/backend/routes/users.py index e090fbf..3b2e737 100644 --- a/backend/routes/users.py +++ b/backend/routes/users.py @@ -10,7 +10,7 @@ @users.route("/user/", methods=['GET']) -# @carbon_auth.auth.login_required +@carbon_auth.auth.login_required def get_user(user_id: str) -> Response: try: query = {"_id": ObjectId(user_id)} @@ -73,10 +73,11 @@ def update_user(user_id: str) -> Response: query = {"_id": ObjectId(user_id)} user = User.from_json(request.get_json()['user']).to_json() del user['_id'] + del user['email'] CarbonTrackDB.users_coll.update_one(query, {'$set': user}) item = CarbonTrackDB.users_coll.find_one(query) item = User.from_json(item).to_json() - return jsonify({'updated_user': item}) + return jsonify({'user': item}) except CarbonTrackError as e: abort(code=400, description=f"{e}") diff --git a/backend/utils/FirebaseAPI.py b/backend/utils/FirebaseAPI.py index b545706..367002a 100644 --- a/backend/utils/FirebaseAPI.py +++ b/backend/utils/FirebaseAPI.py @@ -14,7 +14,9 @@ class FirebaseAPI: @staticmethod def verify_google_token(id_token: str) -> Optional[dict]: + # print("Yazan") # print(id_token) + id_token="eyJhbGciOiJSUzI1NiIsImtpZCI6IjBiYmQyOTllODU2MmU3MmYyZThkN2YwMTliYTdiZjAxMWFlZjU1Y2EiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vY2FyYm9uLXRyYWNrLXN5c3RlbSIsImF1ZCI6ImNhcmJvbi10cmFjay1zeXN0ZW0iLCJhdXRoX3RpbWUiOjE3MDExMjc0NTAsInVzZXJfaWQiOiJ3UFVEaEFiM0Q5ZHpoeDJXa1RBZlBLbnhGSG0xIiwic3ViIjoid1BVRGhBYjNEOWR6aHgyV2tUQWZQS254RkhtMSIsImlhdCI6MTcwMTEyNzQ1MCwiZXhwIjoxNzAxMTMxMDUwLCJlbWFpbCI6InlhemFuQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJ5YXphbkBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.YcyzOeOgXiurm2W8lw2YwvIL2Pfweezu2ASK_RK3MuVRUw2Z1AXwWTJyDbjioYfaXS2GwurtJ3u-q7TqPlL4MmTwb5G09F7cmbNBvbEBQTtOhK9TmyNlMcGV0Gtkaf3J7xebL4qcwQ9aI_lZ1MGS9tMYn8gwArxIVs8nNPxkSFUicrj_buf3Jan6kNMfVIQOOUg9cqocn3VoxInAI9fjbxyliZ7LDF3rNBzBNsXQoOJ6UlHqEcd_Up2oLGsEm3HnIArtPzn4V_BNcmkaZh2cx28KDUjUPpTVHdWguEPUkA_CFhDTYdts7ReisAQviKTkhIxDkCGsUtllWU0Q4fTNcg" return auth.verify_id_token( id_token=id_token, check_revoked=True ) diff --git a/frontend/src/components/appNavigation.tsx b/frontend/src/components/appNavigation.tsx index bb8afc8..5291c03 100644 --- a/frontend/src/components/appNavigation.tsx +++ b/frontend/src/components/appNavigation.tsx @@ -7,12 +7,15 @@ import LogInScreen from '../screens/login'; import SignUpScreen from '../screens/signup'; import DashBoardScreen from '../screens/dashboard'; import Forum from '../screens/forum'; -import FoodForum from '../screens/foodForum'; -import EnergyForum from '../screens/energyForum'; -import TransportationForum from '../screens/transportationForum'; -import TransportationEntryEdit from '../screens/transportationEntryEdit'; -import FoodHistory from '../screens/foodHistory'; -import TransportationHistory from '../screens/transportationHistory'; +import FoodForum from '../screens/Food/foodForum'; +import EnergyForum from '../screens/Energy/energyForum'; +import TransportationForum from '../screens/Transportation/transportationForum'; +import TransportationEntryEdit from '../screens/Transportation/transportationEntryEdit'; +import FoodHistory from '../screens/Food/foodHistory'; +import TransportationHistory from '../screens/Transportation/transportationHistory'; +import EnergyHistory from '../screens/Energy/energy'; +import EnergyEntryEdit from '../screens/Energy/energyEntryEdit'; +import FoodEntryEdit from '../screens/Food/foodEntryEdit'; const Stack = createNativeStackNavigator(); @@ -25,12 +28,18 @@ const AppNavigation = (): JSX.Element => { - - + - + + + + + + + + ); diff --git a/frontend/src/models/Energy.ts b/frontend/src/models/Energy.ts index 6b2863c..1017396 100644 --- a/frontend/src/models/Energy.ts +++ b/frontend/src/models/Energy.ts @@ -1,8 +1,8 @@ -import type ObjectID from 'bson-objectid'; +import { type ObjectId } from "mongodb" export interface EnergyEntry { - _id: ObjectID - user_id: ObjectID + _id: ObjectId + user_id: ObjectId carbon_emissions: number date: Date heating_oil: number diff --git a/frontend/src/models/Food.ts b/frontend/src/models/Food.ts index 4f82682..e18a7fc 100644 --- a/frontend/src/models/Food.ts +++ b/frontend/src/models/Food.ts @@ -1,8 +1,8 @@ -import type ObjectID from 'bson-objectid'; +import { type ObjectId } from 'mongodb'; export interface FoodEntry { - _id: ObjectID - user_id: ObjectID + _id: ObjectId + user_id: ObjectId carbon_emissions: number date: Date beef: number diff --git a/frontend/src/screens/Energy/energy.tsx b/frontend/src/screens/Energy/energy.tsx new file mode 100644 index 0000000..c7a184f --- /dev/null +++ b/frontend/src/screens/Energy/energy.tsx @@ -0,0 +1,181 @@ +import React, { useEffect, useState } from 'react'; +import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, ScrollView } from 'react-native'; +import Colors from '../../../assets/colorConstants'; +import { useFonts } from 'expo-font'; +import { BarChart } from 'react-native-chart-kit'; +import { EnergyAPI } from '../../APIs/EnergyAPI'; +import { type EnergyEntry, type MonthlyEntry } from '../../models/Energy'; +import { useNavigation } from '@react-navigation/native'; +import { type StackNavigationProp } from '@react-navigation/stack'; +import { type RootStackParamList } from '../../components/types'; +import WidgetBox from '../../widgets/widgetBox'; +export type StackNavigation = StackNavigationProp; + + +export default function EnergyHistory(): JSX.Element { + + const [expandedStates, setExpandedStates] = useState(Array(100).fill(false)); + const [monthlyData, setMonthlyData] = useState(); + const [startDate] = useState(new Date(2023, 8, 1)); + const [endDate] = useState(new Date(2023, 11, 1)); + const navigation = useNavigation(); + const [energyEntry, setEnergyEntry] = useState(); + + const toggleExpanded = (index: number): void => { + const updatedStates = [...expandedStates]; + const currentState = updatedStates[index]; + + if (typeof currentState === 'boolean') { + updatedStates[index] = !currentState; + setExpandedStates(updatedStates); + } + }; + + const [loaded] = useFonts({ + Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + }); + + useEffect(() => { + void EnergyAPI.getEnergyEntriesForUserUsingDataRange( + startDate, endDate).then((res) => { + if (res != null) { + if (res.monthlyData != null) { + setMonthlyData(res.monthlyData) + } + } + }); + void EnergyAPI.getEnergyMetricForToday().then((res) => { + if (res != null) { + setEnergyEntry(res) + } + }); + }, [endDate, loaded, startDate, navigation]) + + if (!loaded || monthlyData === undefined || energyEntry === undefined) { + return <>; + } + + return ( + + + {monthlyData.map((chart, index) => ( + + toggleExpanded(index)} style={styles.tab}> + {chart.month} + + {Boolean(expandedStates[index]) && ( + + Emissions from energy in {chart.month} + + Colors.DARKLIMEGREEN, + labelColor: (opacity = 1) => Colors.DARKLIMEGREEN, + style: { + borderRadius: 16, + }, + propsForDots: { + r: '6', + strokeWidth: '2', + stroke: '#ffa726', + }, + }} + verticalLabelRotation={0} + showValuesOnTopOfBars + withInnerLines={false} + withHorizontalLabels={false} + /> + + + )} + + ))} + + + + { + navigation.navigate('EnergyEntryEdit'); + }} + > + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + backgroundColor: Colors.LIGHTFGREEN, + }, + scrollContainer: { + paddingTop: 60, + flex: 1, + paddingHorizontal: 30, + backgroundColor: Colors.LIGHTFGREEN, + }, + tab: { + backgroundColor: Colors.DARKGREEN, + padding: 25, + borderRadius: 10, + marginBottom: 20, + }, + tabTitle: { + fontSize: 18, + fontWeight: 'bold', + fontFamily: 'Montserrat', + color: Colors.WHITE, + textAlign: 'center', + }, + tabText: { + fontSize: 13, + fontWeight: '700', + fontFamily: 'Montserrat', + color: Colors.DARKLIMEGREEN, + }, + expandedContent: { + marginBottom: 20, + padding: 10, + backgroundColor: Colors.WHITE, + borderRadius: 5, + }, + chartContainer: { + overflow: 'hidden', + }, + chart: { + marginVertical: 8, + marginHorizontal: 8, + alignSelf: 'center', + marginLeft: -50, + }, + widgetContainer: { + padding: 10, + flexDirection: 'row', + }, + widgetBoarder: { + padding: 10, + } +}); diff --git a/frontend/src/screens/Energy/energyEntryEdit.tsx b/frontend/src/screens/Energy/energyEntryEdit.tsx new file mode 100644 index 0000000..762f0b6 --- /dev/null +++ b/frontend/src/screens/Energy/energyEntryEdit.tsx @@ -0,0 +1,277 @@ +import { + StyleSheet, + Text, + View, + TouchableOpacity, + ScrollView, + Modal, + Linking, +} from 'react-native'; +import * as React from 'react'; +import Icon from 'react-native-vector-icons/FontAwesome'; +import { useEffect, useState } from 'react'; +import { type StackNavigationProp } from '@react-navigation/stack'; +import { type RootStackParamList } from '../../components/types'; +import { useNavigation } from '@react-navigation/native'; +import { useFonts } from 'expo-font'; +import Colors from '../../../assets/colorConstants'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import Slider from '@react-native-community/slider'; +import { EnergyAPI } from '../../APIs/EnergyAPI'; +import { type EnergyEntry } from '../../models/Energy'; + +export type StackNavigation = StackNavigationProp; + +export default function EnergyEntryEdit(): JSX.Element { + interface SliderData { + id: number; + label: string; + minValue: number; + maxValue: number; + initialValue: number; + } + + const [energyEntry, setEnergyEntry] = useState(); + + const [slidersData, setSliderData] = useState([]); + + const [heatingOilUsage, setHeatingOilUsage] = useState(0); + const [naturalGasUsage, setNaturalGasUsage] = useState(0); + const [electricityUsage, setElectricityUsage] = useState(0); + const [householdUsage, setHouseholdUsage] = useState(0); + + const onSliderValueChange = (value: number, index: number): void => { + slidersData[index].initialValue = value + switch (index) { + case 0: + setHeatingOilUsage(value); + break; + case 1: + setNaturalGasUsage(value); + break; + case 2: + setElectricityUsage(value); + break; + case 3: + setHouseholdUsage(value); + break; + default: + break; + } + }; + + const openLink = async (url: string): Promise => { + const supported = await Linking.canOpenURL(url); + + if (supported) { + await Linking.openURL(url); + } else { + console.error('Cannot open the URL'); + } + }; + + const handleLinkPress = (): void => { + const url = 'https://fcr-ccc.nrcan-rncan.gc.ca/en'; + openLink(url).catch((error) => { + console.error('Error opening link:', error); + }); + }; + + const [loaded] = useFonts({ + Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + }); + + const navigation = useNavigation(); + + const [modalVisible, setModalVisible] = useState(false); + + const handleSurveySubmit = (): void => { + // Process survey responses, e.g., send them to a server + if (energyEntry != null) { + const newEntry: EnergyEntry = { + _id: energyEntry._id, + user_id: energyEntry.user_id, + carbon_emissions: energyEntry.carbon_emissions, + date: energyEntry.date, + heating_oil: heatingOilUsage, + natural_gas: naturalGasUsage, + electricity: electricityUsage, + province: energyEntry.province, + household: householdUsage + } + void EnergyAPI.updateEnergy(newEntry).then(() => { + navigation.navigate('EnergyHistory'); + }) + } + }; + + useEffect(() => { + if (energyEntry != null) { + setSliderData([ + { id: 1, label: 'Heating Oil', minValue: 0, maxValue: 800, initialValue: energyEntry.heating_oil }, + { id: 2, label: 'Natural Gas', minValue: 0, maxValue: 800, initialValue: energyEntry.natural_gas }, + { id: 3, label: 'Electricity', minValue: 0, maxValue: 800, initialValue: energyEntry.electricity }, + { id: 4, label: 'House Hold Members', minValue: 1, maxValue: 10, initialValue: energyEntry.household }, + ]) + setHeatingOilUsage(energyEntry.heating_oil); + setNaturalGasUsage(energyEntry.natural_gas); + setElectricityUsage(energyEntry.electricity); + setHouseholdUsage(energyEntry.household); + } + }, [energyEntry]) + + useEffect(() => { + void EnergyAPI.getEnergyMetricForToday().then((res) => { + if (res != null) { + setEnergyEntry(res) + } + }) + }, [loaded]) + + if (!loaded || slidersData.length === 0) { + return <>; + } + + return ( + + + Calculate your emissions from energy: + + + + + + If you don't know your vehicle's fuel efficiency, it's available + online{' '} + + here + + . Select the "combination" value under Comsumption in L/100km. The average + fuel consumption of non-plug-in hybrid personal vehicles in Canada is 8.9 L / 100 + km. + + setModalVisible(!modalVisible)} + > + + + + + + + + On average, how much distance do you travel using the following methods per week: + + + {slidersData.map((slider, index) => ( + + + {slider.label}: {slidersData[index].initialValue} km + + onSliderValueChange(value, index)} + /> + + {slider.minValue} + {slider.maxValue} + + {/* You can include additional components related to this slider here */} + + ))} + + + Save + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + backgroundColor: Colors.LIGHTFGREEN, + }, + labelContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + paddingHorizontal: 12, + }, + modalBackground: { + backgroundColor: Colors.BLACKTRANS, + flex: 1, + }, + modalContainer: { + backgroundColor: Colors.WHITE, + marginHorizontal: 50, + marginVertical: 180, + padding: 20, + borderRadius: 10, + flex: 1, + flexDirection: 'row', + }, + scrollContainer: { + paddingTop: 30, + flex: 1, + paddingHorizontal: 30, + backgroundColor: Colors.LIGHTFGREEN, + }, + label: { + fontSize: 15, + }, + header: { + color: Colors.DARKGREEN, + fontFamily: 'Montserrat', + fontSize: 25, + fontWeight: '700', + marginBottom: 50, + }, + question: { + fontFamily: 'Montserrat', + fontSize: 20, + fontWeight: '700', + color: Colors.DARKGREEN, + marginBottom: 20, + }, + buttoning: { + backgroundColor: Colors.DARKGREEN, + borderRadius: 10, + marginBottom: 70, + padding: 18, + }, + buttoningText: { + color: Colors.WHITE, + fontSize: 16, + fontWeight: '700', + textAlign: 'center', + }, + questionContainer: { + paddingBottom: 30, + }, + infoText: { + fontSize: 20, + color: Colors.DARKGREEN, + }, + linkText: { + color: Colors.BLUE, + }, + closeIcon: { + marginLeft: 'auto', + }, + silder: { + height: 50, + width: '100%', + }, +}); diff --git a/frontend/src/screens/energyForum.tsx b/frontend/src/screens/Energy/energyForum.tsx similarity index 98% rename from frontend/src/screens/energyForum.tsx rename to frontend/src/screens/Energy/energyForum.tsx index 0744e5f..40fb1b6 100644 --- a/frontend/src/screens/energyForum.tsx +++ b/frontend/src/screens/Energy/energyForum.tsx @@ -2,9 +2,9 @@ import { StyleSheet, Text, View, ScrollView, TouchableOpacity, TextInput } from import { Picker } from '@react-native-picker/picker'; import * as React from 'react'; import { type StackNavigationProp } from '@react-navigation/stack'; -import { type RootStackParamList } from '../components/types'; +import { type RootStackParamList } from '../../components/types'; import { useFonts } from 'expo-font'; -import Colors from '../../assets/colorConstants'; +import Colors from '../../../assets/colorConstants'; import { useState } from 'react'; import { useNavigation } from '@react-navigation/native'; import { SafeAreaView } from 'react-native-safe-area-context'; diff --git a/frontend/src/screens/Food/foodEntryEdit.tsx b/frontend/src/screens/Food/foodEntryEdit.tsx new file mode 100644 index 0000000..0b3067f --- /dev/null +++ b/frontend/src/screens/Food/foodEntryEdit.tsx @@ -0,0 +1,304 @@ +import { + StyleSheet, + Text, + View, + TouchableOpacity, + ScrollView, + Modal, + Linking, +} from 'react-native'; +import * as React from 'react'; +import Icon from 'react-native-vector-icons/FontAwesome'; +import { useEffect, useState } from 'react'; +import { type StackNavigationProp } from '@react-navigation/stack'; +import { type RootStackParamList } from '../../components/types'; +import { useNavigation } from '@react-navigation/native'; +import { useFonts } from 'expo-font'; +import Colors from '../../../assets/colorConstants'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import Slider from '@react-native-community/slider'; +import { FoodAPI } from '../../APIs/FoodAPI'; +import { type FoodEntry } from '../../models/Food'; + +export type StackNavigation = StackNavigationProp; + +export default function FoodEntryEdit(): JSX.Element { + interface SliderData { + id: number; + label: string; + minValue: number; + maxValue: number; + initialValue: number; + } + + const [foodEntry, setFoodEntry] = useState(); + + const [slidersData, setSliderData] = useState([]); + + const [beefConsumption, setBeefConsumption] = useState(0); + const [lambConsumption, setLambConsumption] = useState(0); + const [porkConsumption, setPorkConsumption] = useState(0); + const [chickenConsumption, setChickenConsumption] = useState(0); + const [fishConsumption, setFishConsumption] = useState(0); + const [cheeseConsumption, setCheeseConsumption] = useState(0); + const [milkConsumption, setMilkConsumption] = useState(0); + const [foodWaste, setFoodWaste] = useState(0); + + const onSliderValueChange = (value: number, index: number): void => { + slidersData[index].initialValue = value; + switch (index) { + case 0: + setBeefConsumption(value); + break; + case 1: + setLambConsumption(value); + break; + case 2: + setPorkConsumption(value); + break; + case 3: + setChickenConsumption(value); + break; + case 4: + setFishConsumption(value); + break; + case 5: + setCheeseConsumption(value); + break; + case 6: + setMilkConsumption(value); + break; + case 7: + setFoodWaste(value); + break; + default: + break; + } + }; + + const openLink = async (url: string): Promise => { + const supported = await Linking.canOpenURL(url); + + if (supported) { + await Linking.openURL(url); + } else { + console.error('Cannot open the URL'); + } + }; + + const handleLinkPress = (): void => { + const url = 'https://fcr-ccc.nrcan-rncan.gc.ca/en'; + openLink(url).catch((error) => { + console.error('Error opening link:', error); + }); + }; + + const [loaded] = useFonts({ + Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + }); + + const navigation = useNavigation(); + + const [modalVisible, setModalVisible] = useState(false); + + const handleSurveySubmit = (): void => { + // Process survey responses, e.g., send them to a server + if (foodEntry != null) { + const newEntry: FoodEntry = { + _id: foodEntry._id, + user_id: foodEntry.user_id, + carbon_emissions: foodEntry.carbon_emissions, + date: foodEntry.date, + beef: beefConsumption, + lamb: lambConsumption, + pork: porkConsumption, + chicken: chickenConsumption, + fish: fishConsumption, + cheese: cheeseConsumption, + milk: milkConsumption, + food_waste: foodWaste, + } + void FoodAPI.updateFood(newEntry).then(() => { + navigation.navigate('FoodHistory'); + }) + } + }; + + useEffect(() => { + if (foodEntry != null) { + setSliderData([ + { id: 1, label: 'Beef', minValue: 0, maxValue: 800, initialValue: foodEntry.beef }, + { id: 2, label: 'Lamb', minValue: 0, maxValue: 800, initialValue: foodEntry.lamb }, + { id: 3, label: 'Pork', minValue: 0, maxValue: 800, initialValue: foodEntry.pork }, + { id: 4, label: 'Chicken', minValue: 0, maxValue: 800, initialValue: foodEntry.chicken }, + { id: 5, label: 'Fish', minValue: 0, maxValue: 800, initialValue: foodEntry.fish }, + { id: 6, label: 'Cheese', minValue: 0, maxValue: 800, initialValue: foodEntry.cheese }, + { id: 7, label: 'Milk', minValue: 0, maxValue: 800, initialValue: foodEntry.milk }, + { id: 8, label: 'Food Waste', minValue: 0, maxValue: 800, initialValue: foodEntry.food_waste }, + ]); + setBeefConsumption(foodEntry.beef); + setLambConsumption(foodEntry.lamb); + setPorkConsumption(foodEntry.pork); + setChickenConsumption(foodEntry.chicken); + setFishConsumption(foodEntry.fish); + setCheeseConsumption(foodEntry.cheese); + setMilkConsumption(foodEntry.milk); + setFoodWaste(foodEntry.food_waste); + } + }, [foodEntry]); + + useEffect(() => { + void FoodAPI.getFoodMetricForToday().then((res) => { + if (res != null) { + setFoodEntry(res) + } + }) + }, [loaded]) + + if (!loaded || slidersData.length === 0) { + return <>; + } + + return ( + + + Calculate your emissions from food: + + + + + + If you don't know your vehicle's fuel efficiency, it's available + online{' '} + + here + + . Select the "combination" value under Comsumption in L/100km. The average + fuel consumption of non-plug-in hybrid personal vehicles in Canada is 8.9 L / 100 + km. + + setModalVisible(!modalVisible)} + > + + + + + + + + On average, how much distance do you travel using the following methods per week: + + + {slidersData.map((slider, index) => ( + + + {slider.label}: {slidersData[index].initialValue} km + + onSliderValueChange(value, index)} + /> + + {slider.minValue} + {slider.maxValue} + + {/* You can include additional components related to this slider here */} + + ))} + + + Save + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + backgroundColor: Colors.LIGHTFGREEN, + }, + labelContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + paddingHorizontal: 12, + }, + modalBackground: { + backgroundColor: Colors.BLACKTRANS, + flex: 1, + }, + modalContainer: { + backgroundColor: Colors.WHITE, + marginHorizontal: 50, + marginVertical: 180, + padding: 20, + borderRadius: 10, + flex: 1, + flexDirection: 'row', + }, + scrollContainer: { + paddingTop: 30, + flex: 1, + paddingHorizontal: 30, + backgroundColor: Colors.LIGHTFGREEN, + }, + label: { + fontSize: 15, + }, + header: { + color: Colors.DARKGREEN, + fontFamily: 'Montserrat', + fontSize: 25, + fontWeight: '700', + marginBottom: 50, + }, + question: { + fontFamily: 'Montserrat', + fontSize: 20, + fontWeight: '700', + color: Colors.DARKGREEN, + marginBottom: 20, + }, + buttoning: { + backgroundColor: Colors.DARKGREEN, + borderRadius: 10, + marginBottom: 70, + padding: 18, + }, + buttoningText: { + color: Colors.WHITE, + fontSize: 16, + fontWeight: '700', + textAlign: 'center', + }, + questionContainer: { + paddingBottom: 30, + }, + infoText: { + fontSize: 20, + color: Colors.DARKGREEN, + }, + linkText: { + color: Colors.BLUE, + }, + closeIcon: { + marginLeft: 'auto', + }, + silder: { + height: 50, + width: '100%', + }, +}); diff --git a/frontend/src/screens/foodForum.tsx b/frontend/src/screens/Food/foodForum.tsx similarity index 97% rename from frontend/src/screens/foodForum.tsx rename to frontend/src/screens/Food/foodForum.tsx index 6364f2c..cd84492 100644 --- a/frontend/src/screens/foodForum.tsx +++ b/frontend/src/screens/Food/foodForum.tsx @@ -1,12 +1,12 @@ import { StyleSheet, Text, View, ScrollView, TouchableOpacity, TextInput } from 'react-native'; import * as React from 'react'; import { type StackNavigationProp } from '@react-navigation/stack'; -import { type RootStackParamList } from '../components/types'; +import { type RootStackParamList } from '../../components/types'; import { useFonts } from 'expo-font'; -import Colors from '../../assets/colorConstants'; +import Colors from '../../../assets/colorConstants'; import { useState } from 'react'; import { useNavigation } from '@react-navigation/native'; -import foodSliderData from '../../assets/foodQuestions'; +import foodSliderData from '../../../assets/foodQuestions'; import { SafeAreaView } from 'react-native-safe-area-context'; import Slider from '@react-native-community/slider'; diff --git a/frontend/src/screens/foodHistory.tsx b/frontend/src/screens/Food/foodHistory.tsx similarity index 66% rename from frontend/src/screens/foodHistory.tsx rename to frontend/src/screens/Food/foodHistory.tsx index 0707cc7..5e2e62f 100644 --- a/frontend/src/screens/foodHistory.tsx +++ b/frontend/src/screens/Food/foodHistory.tsx @@ -1,17 +1,25 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, ScrollView } from 'react-native'; -import Colors from '../../assets/colorConstants'; +import Colors from '../../../assets/colorConstants'; import { useFonts } from 'expo-font'; import { BarChart } from 'react-native-chart-kit'; +import { FoodAPI } from '../../APIs/FoodAPI'; +import { type FoodEntry, type MonthlyEntry } from '../../models/Food'; +import { useNavigation } from '@react-navigation/native'; +import { type StackNavigationProp } from '@react-navigation/stack'; +import { type RootStackParamList } from '../../components/types'; +import WidgetBox from '../../widgets/widgetBox'; +export type StackNavigation = StackNavigationProp; + export default function FoodHistory(): JSX.Element { - const monthlyData = [ - { month: 'September', data: [20, 25, 30, 22] }, - { month: 'November', data: [18, 24, 16, 4] }, - // Add data for other months... - ]; - const [expandedStates, setExpandedStates] = useState(Array(monthlyData.length).fill(false)); + const [expandedStates, setExpandedStates] = useState(Array(100).fill(false)); + const [monthlyData, setMonthlyData] = useState(); + const [startDate] = useState(new Date(2023, 8, 1)); + const [endDate] = useState(new Date(2023, 11, 1)); + const navigation = useNavigation(); + const [foodEntry, setFoodEntry] = useState(); const toggleExpanded = (index: number): void => { const updatedStates = [...expandedStates]; @@ -27,7 +35,24 @@ export default function FoodHistory(): JSX.Element { Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), }); - if (!loaded) { + + useEffect(() => { + void FoodAPI.getFoodEntriesForUserUsingDataRange( + startDate, endDate).then((res) => { + if (res != null) { + if (res.monthlyData != null) { + setMonthlyData(res.monthlyData) + } + } + }); + void FoodAPI.getFoodMetricForToday().then((res) => { + if (res != null) { + setFoodEntry(res) + } + }); + }, [endDate, loaded, startDate, navigation]) + + if (!loaded || monthlyData === undefined || foodEntry === undefined) { return <>; } @@ -80,12 +105,22 @@ export default function FoodHistory(): JSX.Element { withHorizontalLabels={false} /> - {/* Add more content here */} )} ))} + + + { + navigation.navigate('FoodEntryEdit'); + }} + > + + + + ); } @@ -136,4 +171,11 @@ const styles = StyleSheet.create({ alignSelf: 'center', marginLeft: -50, }, + widgetContainer: { + padding: 10, + flexDirection: 'row', + }, + widgetBoarder: { + padding: 10, + } }); diff --git a/frontend/src/screens/transportationEntryEdit.tsx b/frontend/src/screens/Transportation/transportationEntryEdit.tsx similarity index 97% rename from frontend/src/screens/transportationEntryEdit.tsx rename to frontend/src/screens/Transportation/transportationEntryEdit.tsx index 28f3e76..f54d216 100644 --- a/frontend/src/screens/transportationEntryEdit.tsx +++ b/frontend/src/screens/Transportation/transportationEntryEdit.tsx @@ -11,14 +11,14 @@ import * as React from 'react'; import Icon from 'react-native-vector-icons/FontAwesome'; import { useEffect, useState } from 'react'; import { type StackNavigationProp } from '@react-navigation/stack'; -import { type RootStackParamList } from '../components/types'; +import { type RootStackParamList } from '../../components/types'; import { useNavigation } from '@react-navigation/native'; import { useFonts } from 'expo-font'; -import Colors from '../../assets/colorConstants'; +import Colors from '../../../assets/colorConstants'; import { SafeAreaView } from 'react-native-safe-area-context'; import Slider from '@react-native-community/slider'; -import { TransportationAPI } from '../APIs/TransportationAPI'; -import { type TransportationEntry } from '../models/Transportation'; +import { TransportationAPI } from '../../APIs/TransportationAPI'; +import { type TransportationEntry } from '../../models/Transportation'; export type StackNavigation = StackNavigationProp; diff --git a/frontend/src/screens/transportationForum.tsx b/frontend/src/screens/Transportation/transportationForum.tsx similarity index 98% rename from frontend/src/screens/transportationForum.tsx rename to frontend/src/screens/Transportation/transportationForum.tsx index 7201ba2..ff478a1 100644 --- a/frontend/src/screens/transportationForum.tsx +++ b/frontend/src/screens/Transportation/transportationForum.tsx @@ -13,11 +13,11 @@ import { import Icon from 'react-native-vector-icons/FontAwesome'; import { useState } from 'react'; import { type StackNavigationProp } from '@react-navigation/stack'; - import { type RootStackParamList } from '../components/types'; + import { type RootStackParamList } from '../../components/types'; import { useNavigation } from '@react-navigation/native'; import { useFonts } from 'expo-font'; - import Colors from '../../assets/colorConstants'; - import transportationQuestions from '../../assets/questions'; + import Colors from '../../../assets/colorConstants'; + import transportationQuestions from '../../../assets/questions'; import { SafeAreaView } from 'react-native-safe-area-context'; import Slider from '@react-native-community/slider'; diff --git a/frontend/src/screens/transportationHistory.tsx b/frontend/src/screens/Transportation/transportationHistory.tsx similarity index 95% rename from frontend/src/screens/transportationHistory.tsx rename to frontend/src/screens/Transportation/transportationHistory.tsx index 05d26cd..f133b7c 100644 --- a/frontend/src/screens/transportationHistory.tsx +++ b/frontend/src/screens/Transportation/transportationHistory.tsx @@ -1,14 +1,14 @@ import React, { useEffect, useState } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, ScrollView } from 'react-native'; -import Colors from '../../assets/colorConstants'; +import Colors from '../../../assets/colorConstants'; import { useFonts } from 'expo-font'; import { BarChart } from 'react-native-chart-kit'; -import { TransportationAPI } from '../APIs/TransportationAPI'; -import { type TransportationEntry, type MonthlyEntry } from '../models/Transportation'; +import { TransportationAPI } from '../../APIs/TransportationAPI'; +import { type TransportationEntry, type MonthlyEntry } from '../../models/Transportation'; import { useNavigation } from '@react-navigation/native'; import { type StackNavigationProp } from '@react-navigation/stack'; -import { type RootStackParamList } from '../components/types'; -import WidgetBox from '../widgets/widgetBox'; +import { type RootStackParamList } from '../../components/types'; +import WidgetBox from '../../widgets/widgetBox'; export type StackNavigation = StackNavigationProp; diff --git a/frontend/src/screens/dashboard.tsx b/frontend/src/screens/dashboard.tsx index 24d7483..973a8bb 100644 --- a/frontend/src/screens/dashboard.tsx +++ b/frontend/src/screens/dashboard.tsx @@ -11,11 +11,17 @@ import { type User } from '../models/User'; import { UsersAPI } from '../APIs/UsersAPI'; import { type TransportationEntry } from '../models/Transportation'; import { TransportationAPI } from '../APIs/TransportationAPI'; +import { type FoodEntry } from '../models/Food'; +import { type EnergyEntry } from '../models/Energy'; +import { FoodAPI } from '../APIs/FoodAPI'; +import { EnergyAPI } from '../APIs/EnergyAPI'; export type StackNavigation = StackNavigationProp; export default function DashBoardScreen(): JSX.Element { const [user, setUser] = useState(undefined); const [transportationEntry, setTransportationEntry] = useState(); + const [foodEntry, setFoodEntry] = useState(); + const [energyEntry, setEnergyEntry] = useState(); const [photoURL] = useState("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Default_pfp.svg/2048px-Default_pfp.svg.png"); const navigation = useNavigation(); @@ -36,9 +42,19 @@ export default function DashBoardScreen(): JSX.Element { setTransportationEntry(res) } }); + void FoodAPI.getFoodMetricForToday().then((res) => { + if (res != null) { + setFoodEntry(res) + } + }); + void EnergyAPI.getEnergyMetricForToday().then((res) => { + if (res != null) { + setEnergyEntry(res) + } + }); }, [loaded]); - if (!loaded || user === undefined || transportationEntry === undefined) { + if (!loaded || user === undefined || transportationEntry === undefined || foodEntry === undefined || energyEntry === undefined) { return <>; } @@ -61,25 +77,48 @@ export default function DashBoardScreen(): JSX.Element { + + { + navigation.navigate('TransportationHistory'); + }} + > + + + + { navigation.navigate('FoodHistory'); }} > - + + + { - navigation.navigate('TransportationHistory'); + navigation.navigate('EnergyHistory'); }} > - + + + + + + { + navigation.navigate('Settings'); + }} + > + + ); From 6b875838f008ce5bf4d453c823dad05c64d69ac4 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 19:21:28 -0500 Subject: [PATCH 16/20] Fixed Linting --- backend/app.py | 2 +- backend/routes/ct_firebase_service.py | 9 ++------- backend/utils/FirebaseAPI.py | 2 -- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/backend/app.py b/backend/app.py index af85f85..1de4a0d 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1,5 +1,5 @@ # Python Imports -from flask import Flask, Response, jsonify, render_template +from flask import Flask, Response, jsonify from flask_cors import CORS from werkzeug.exceptions import HTTPException diff --git a/backend/routes/ct_firebase_service.py b/backend/routes/ct_firebase_service.py index f80586d..9f220a7 100644 --- a/backend/routes/ct_firebase_service.py +++ b/backend/routes/ct_firebase_service.py @@ -1,11 +1,6 @@ # Python Imports -from bson import ObjectId -from flask import Blueprint, Response, abort, jsonify, render_template, request -from models.user import User -from mongodb_api.carbon_track_db import CarbonTrackDB -from routes import carbon_auth -from utils.FirebaseAPI import FirebaseAPI -from utils.carbon_track_errors import CarbonTrackError +from flask import Blueprint, render_template + ct_firebase_service = Blueprint('/f', __name__) diff --git a/backend/utils/FirebaseAPI.py b/backend/utils/FirebaseAPI.py index 367002a..f8b4418 100644 --- a/backend/utils/FirebaseAPI.py +++ b/backend/utils/FirebaseAPI.py @@ -1,8 +1,6 @@ from typing import Optional -from pprint import pprint import firebase_admin from firebase_admin import credentials, auth -from firebase_admin.auth import UserRecord from models.user import User from mongodb_api.carbon_track_db import CarbonTrackDB From 3e502aa686505f2f10b5b5c0321d9a84351df1c3 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 19:22:22 -0500 Subject: [PATCH 17/20] Update Backend.postman_collection.json --- .../postman/Backend.postman_collection.json | 359 ++++++------------ 1 file changed, 112 insertions(+), 247 deletions(-) diff --git a/backend/postman/Backend.postman_collection.json b/backend/postman/Backend.postman_collection.json index 2e1efde..f61fe52 100644 --- a/backend/postman/Backend.postman_collection.json +++ b/backend/postman/Backend.postman_collection.json @@ -1,30 +1,21 @@ { "info": { - "_postman_id": "4e6a6476-9f0c-4b6a-b021-a2ee98a764fc", + "_postman_id": "96af37c1-9d9e-43ba-9dcd-f25fcc13248e", "name": "Backend", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "30673965" + "_exporter_id": "25097543", + "_collection_link": "https://smartqrapp.postman.co/workspace/CarbonTrack~a09486ca-92c2-404d-9e10-1f18c1befa4a/collection/25097543-96af37c1-9d9e-43ba-9dcd-f25fcc13248e?action=share&source=collection_link&creator=25097543" }, "item": [ { "name": "Users", "item": [ { - "name": "Get User by Email", + "name": "Get User Via ID", "protocolProfileBehavior": { "disableBodyPruning": true }, "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "GET", "header": [], "body": { @@ -37,35 +28,25 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/users/user_email/abc@armoush.com", + "raw": "{{LocalBaseURL}}/users/user/65651db4f3369512431e5c4a", "host": [ "{{LocalBaseURL}}" ], "path": [ "users", - "user_email", - "abc@armoush.com" + "user", + "65651db4f3369512431e5c4a" ] } }, "response": [] }, { - "name": "Get User", + "name": "Get User Via Emai", "protocolProfileBehavior": { "disableBodyPruning": true }, "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "GET", "header": [], "body": { @@ -78,14 +59,14 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/users/user/651cf22c1d4f7834e2303a85", + "raw": "{{LocalBaseURL}}/users/user_email/yazan@gmail.com", "host": [ "{{LocalBaseURL}}" ], "path": [ "users", - "user", - "651cf22c1d4f7834e2303a85" + "user_email", + "yazan@gmail.com" ] } }, @@ -99,7 +80,7 @@ "bearer": [ { "key": "token", - "value": "\"eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTE3OTkzLCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MTc5OTMsImV4cCI6MTY5ODUyMTU5MywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.Q1b4XkYwuMzn1aGv3qHVu469hGrgUI8FMSrsru_CgVGxhBKTKsUaKExwRssakLEwcQ0u68OcmNQjBLbwP2SE99f61R0GQxuiyI5m5L1-OhTrbPRYcRYDEFBySmSQMgOFBmPik5JlMcWOz1LtLXzbnCR-epcSrxs8qUZ2_rfpeYaaJavRQuYBJmQo8FgJyPz-LQ2aa-2ileNipyyg7AXxqU0fgnTLSSvHzPqk6O-bSCci53QdY2w6n2vusEUpIea6i5XhIrfr0BkMXy8VIoJQ8RoIjdS-_CpTx-1aixDzOMQd-I-synRJN7-YZKV5E4yupIquNPjQmFFoGF5xGTEelA\"", + "value": "", "type": "string" } ] @@ -108,7 +89,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"user\": {\n \"_id\": \"651cf22c1d4f7834e2303a99\",\n \"full_name\": \"abc\",\n \"email\": \"abc@armoush.com\",\n \"badges\": [],\n \"friends\": [\"Ishav\", \"Yazan\"],\n \"score\": 434343,\n \"province\": \"British Columbia\",\n \"household\": 4,\n \"fuel_efficiency\": 32323.0\n\n }\n}", + "raw": "{\n \"user\": {\n \"_id\": \"651cf22c1d4f7834e2303a85\",\n \"full_name\": \"Adam\",\n \"email\": \"adam#armoush.com\",\n \"badges\": [],\n \"friends\": [],\n \"score\": 0\n }\n}", "options": { "raw": { "language": "json" @@ -131,21 +112,11 @@ { "name": "Update User", "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "\"eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTE3OTkzLCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MTc5OTMsImV4cCI6MTY5ODUyMTU5MywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.Q1b4XkYwuMzn1aGv3qHVu469hGrgUI8FMSrsru_CgVGxhBKTKsUaKExwRssakLEwcQ0u68OcmNQjBLbwP2SE99f61R0GQxuiyI5m5L1-OhTrbPRYcRYDEFBySmSQMgOFBmPik5JlMcWOz1LtLXzbnCR-epcSrxs8qUZ2_rfpeYaaJavRQuYBJmQo8FgJyPz-LQ2aa-2ileNipyyg7AXxqU0fgnTLSSvHzPqk6O-bSCci53QdY2w6n2vusEUpIea6i5XhIrfr0BkMXy8VIoJQ8RoIjdS-_CpTx-1aixDzOMQd-I-synRJN7-YZKV5E4yupIquNPjQmFFoGF5xGTEelA\"", - "type": "string" - } - ] - }, "method": "PATCH", "header": [], "body": { "mode": "raw", - "raw": "{\n \"user\": {\n \"_id\": \"651cf22c1d4f7834e2303a85\",\n \"full_name\": \"Ishav\",\n \"email\": \"ishav@armoush.com\",\n \"badges\": [\"Badge 1\", \"Badge 2\"],\n \"friends\": [],\n \"score\": 323232,\n \"province\": \"British Columbia\",\n \"household\": 4,\n \"fuel_efficiency\": 4\n }\n}", + "raw": "{\n \"user\": {\n \"_id\": \"65651db4f3369512431e5c4a\",\n \"full_name\": \"Yazan Armoush\",\n \"email\": \"yazan@gmail.com\",\n \"badges\": [],\n \"friends\": [],\n \"score\": 0,\n \"province\": \"\",\n \"household\": 0,\n \"fuel_efficiency\": 0\n }\n}", "options": { "raw": { "language": "json" @@ -153,14 +124,14 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/users/user/651cf22c1d4f7834e2303a85", + "raw": "{{LocalBaseURL}}/users/user/65651db4f3369512431e5c4a", "host": [ "{{LocalBaseURL}}" ], "path": [ "users", "user", - "651cf22c1d4f7834e2303a85" + "65651db4f3369512431e5c4a" ] } }, @@ -172,21 +143,11 @@ "name": "Transportation", "item": [ { - "name": "Get Current Transportation", + "name": "Get Transportation", "protocolProfileBehavior": { "disableBodyPruning": true }, "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "GET", "header": [], "body": { @@ -199,23 +160,21 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/transportation/transportation/655d5c7d123217b52115b046", + "raw": "{{LocalBaseURL}}/transportation/transportation/65651db5495a95751815af4e", "host": [ "{{LocalBaseURL}}" ], "path": [ "transportation", "transportation", - "655d5c7d123217b52115b046" - "get_transportation_metric_for_today", - "655151e8875bab2e6811b8b8" + "65651db5495a95751815af4e" ] } }, "response": [] }, { - "name": "Get Transportation", + "name": "Get Current Transportation", "protocolProfileBehavior": { "disableBodyPruning": true }, @@ -251,7 +210,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"start\": \"2023-01-01T00:00:00Z\",\n \"end\": \"2023-12-01T00:00:00Z\"\n}", + "raw": "{\n \"start\": \"2023-10-01T00:00:00Z\",\n \"end\": \"2023-12-01T00:00:00Z\"\n}", "options": { "raw": { "language": "json" @@ -259,13 +218,13 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/transportation/get_transportations_entries_for_user_using_data_range", + "raw": "{{LocalBaseURL}}/transportation/get_transportation_entries_for_user_using_data_range", "host": [ "{{LocalBaseURL}}" ], "path": [ "transportation", - "get_transportations_entries_for_user_using_data_range" + "get_transportation_entries_for_user_using_data_range" ] } }, @@ -278,7 +237,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"transportation\": {\n \"_id\": \"655d5c7d123217b52115b046\",\n \"bus\": 200,\n \"carbon_emissions\": 0.0,\n \"date\": \"2023-11-19T00:00:00Z\",\n \"electric_car\": 4000,\n \"gasoline_car\": 100,\n \"motorbike\": 0,\n \"train\": 0,\n \"user_id\": \"655151e8875bab2e6811b8b8\"\n }\n}", + "raw": "{\n \"transportation\": {\n \"_id\": \"65651db5495a95751815af4e\",\n \"user_id\": \"65651db4f3369512431e5c4a\",\n \"bus\": 200,\n \"train\": 0,\n \"motorbike\": 0,\n \"electric_car\": 4000,\n \"gasoline_car\": 100,\n \"carbon_emissions\": 1850,\n \"date\": \"2023-11-26T00:00:00\"\n }\n}", "options": { "raw": { "language": "json" @@ -286,40 +245,50 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/transportation/transportation/655d625a1df1b3b87663ba71", + "raw": "{{LocalBaseURL}}/transportation/transportation/65651db5495a95751815af4e", "host": [ "{{LocalBaseURL}}" ], "path": [ "transportation", "transportation", - "655d625a1df1b3b87663ba71" + "65651db5495a95751815af4e" ] } }, "response": [] } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Food", "item": [ { - "name": "Get Current Food", + "name": "Get Food", "protocolProfileBehavior": { "disableBodyPruning": true }, "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "GET", "header": [], "body": { @@ -332,38 +301,25 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/food/get_food_metric_for_today/655151e8875bab2e6811b8b8", + "raw": "{{LocalBaseURL}}/food/food/6565277a04aaad72e88b010d", "host": [ "{{LocalBaseURL}}" ], "path": [ "food", - "get_food_metric_for_today", - "655151e8875bab2e6811b8b8" - "transportation", - "transportation", - "651cf22c1d4f7834e2303a44" + "food", + "6565277a04aaad72e88b010d" ] } }, "response": [] }, { - "name": "Get Food", + "name": "Get Current Food", "protocolProfileBehavior": { "disableBodyPruning": true }, "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "GET", "header": [], "body": { @@ -376,38 +332,27 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/food/food/6559599c7228677f5bc26d34", + "raw": "{{LocalBaseURL}}/food/get_food_metric_for_today/", "host": [ "{{LocalBaseURL}}" ], "path": [ "food", - "food", - "6559599c7228677f5bc26d34" + "get_food_metric_for_today", + "" ] } }, "response": [] }, { - "name": "Update Food", - "name": "Update Transportation", + "name": "Date Range", "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, - "method": "PATCH", + "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "{\n \"food\": {\n \"_id\": \"6559599c7228677f5bc26d34\",\n \"beef\": 22,\n \"carbon_emissions\": 0.0,\n \"cheese\": 2,\n \"chicken\": 22,\n \"date\": {\n \"$date\": \"2023-11-12T00:00:00Z\"\n },\n \"fish\": 22,\n \"food_waste\": 12,\n \"lamb\": 11,\n \"milk\": 22,\n \"pork\": 12,\n \"user_id\": \"655151e8875bab2e6811b8b8\"\n }\n}", + "raw": "{\n \"start\": \"2023-10-01T00:00:00Z\",\n \"end\": \"2023-12-01T00:00:00Z\"\n}", "options": { "raw": { "language": "json" @@ -415,45 +360,26 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/food/food/6559599c7228677f5bc26d34", + "raw": "{{LocalBaseURL}}/food/get_food_entries_for_user_using_data_range", "host": [ "{{LocalBaseURL}}" ], "path": [ "food", - "food", - "6559599c7228677f5bc26d34" + "get_food_entries_for_user_using_data_range" ] } }, "response": [] - } - ] - }, - { - "name": "Food", - "item": [ + }, { - "name": "Get Current Food", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, + "name": "Update Transportation", "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, - "method": "GET", + "method": "PATCH", "header": [], "body": { "mode": "raw", - "raw": "", + "raw": "{\n \"food\": {\n \"_id\": \"6565277a04aaad72e88b010d\",\n \"user_id\": \"65651db4f3369512431e5c4a\",\n \"beef\": 0,\n \"lamb\": 0,\n \"pork\": 0,\n \"chicken\": 0,\n \"fish\": 10,\n \"cheese\": 0,\n \"milk\": 0,\n \"food_waste\": 0,\n \"carbon_emissions\": 0.0,\n \"date\": \"2023-11-26T00:00:00\"\n }\n}", "options": { "raw": { "language": "json" @@ -461,35 +387,50 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/food/get_food_metric_for_today/655151e8875bab2e6811b8b8", + "raw": "{{LocalBaseURL}}/food/food/6565277a04aaad72e88b010d", "host": [ "{{LocalBaseURL}}" ], "path": [ "food", - "get_food_metric_for_today", - "655151e8875bab2e6811b8b8" + "food", + "6565277a04aaad72e88b010d" ] } }, "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } }, { - "name": "Get Food", + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Energy", + "item": [ + { + "name": "Get Eenrgy", "protocolProfileBehavior": { "disableBodyPruning": true }, "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "GET", "header": [], "body": { @@ -502,78 +443,25 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/food/food/6559599c7228677f5bc26d34", + "raw": "{{LocalBaseURL}}/energy/energy/656529e46e7a0fc224b33573", "host": [ "{{LocalBaseURL}}" ], "path": [ - "food", - "food", - "6559599c7228677f5bc26d34" + "energy", + "energy", + "656529e46e7a0fc224b33573" ] } }, "response": [] }, - { - "name": "Update Food", - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, - "method": "PATCH", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"food\": {\n \"_id\": \"6559599c7228677f5bc26d34\",\n \"beef\": 22,\n \"carbon_emissions\": 0.0,\n \"cheese\": 2,\n \"chicken\": 22,\n \"date\": {\n \"$date\": \"2023-11-12T00:00:00Z\"\n },\n \"fish\": 22,\n \"food_waste\": 12,\n \"lamb\": 11,\n \"milk\": 22,\n \"pork\": 12,\n \"user_id\": \"655151e8875bab2e6811b8b8\"\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{LocalBaseURL}}/food/food/6559599c7228677f5bc26d34", - "host": [ - "{{LocalBaseURL}}" - ], - "path": [ - "food", - "food", - "6559599c7228677f5bc26d34" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "Energy", - "item": [ { "name": "Get Current Energy", "protocolProfileBehavior": { "disableBodyPruning": true }, "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "GET", "header": [], "body": { @@ -586,40 +474,26 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/energy/get_energy_metric_for_today/651cf22c1d4f7834e2303a85", + "raw": "{{LocalBaseURL}}/energy/get_energy_metric_for_today", "host": [ "{{LocalBaseURL}}" ], "path": [ "energy", - "get_energy_metric_for_today", - "651cf22c1d4f7834e2303a85" + "get_energy_metric_for_today" ] } }, "response": [] }, { - "name": "Get Energy", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, + "name": "Date Range", "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, - "method": "GET", + "method": "POST", "header": [], "body": { "mode": "raw", - "raw": "", + "raw": "{\n \"start\": \"2023-10-01T00:00:00Z\",\n \"end\": \"2023-12-01T00:00:00Z\"\n}", "options": { "raw": { "language": "json" @@ -627,14 +501,13 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/energy/energy/656411820133aef67f385412", + "raw": "{{LocalBaseURL}}/energy/get_energy_entries_for_user_using_data_range", "host": [ "{{LocalBaseURL}}" ], "path": [ "energy", - "energy", - "656411820133aef67f385412" + "get_energy_entries_for_user_using_data_range" ] } }, @@ -643,21 +516,11 @@ { "name": "Update Energy", "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBkMGU4NmJkNjQ3NDBjYWQyNDc1NjI4ZGEyZWM0OTZkZjUyYWRiNWQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiWWF6YW4gQXJtb3VzaCIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NKMThLbUhSTDY3d2NHNDZLNDhaVF9RN0RVbExyN25rOHhJQ2s1S0VNZExVRW9xPXM5Ni1jIiwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2NhcmJvbi10cmFjay1zeXN0ZW0iLCJhdWQiOiJjYXJib24tdHJhY2stc3lzdGVtIiwiYXV0aF90aW1lIjoxNjk4NTMwMzE3LCJ1c2VyX2lkIjoiUkZSbmdJVm1Bd1BHY0pxVFVPalZOeFB4SzVzMSIsInN1YiI6IlJGUm5nSVZtQXdQR2NKcVRVT2pWTnhQeEs1czEiLCJpYXQiOjE2OTg1MzAzMTcsImV4cCI6MTY5ODUzMzkxNywiZW1haWwiOiJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJnb29nbGUuY29tIjpbIjExNzEyOTg2MDYwMzg2MDUxODQwOCJdLCJlbWFpbCI6WyJ5YXphbi5hcm1vdXNoMUBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.D586V3FjImF4P46sjEw1VuwgHXY5VTHPPrQAzC1thWqe5rASSYqxPRtn53xCD8_mxAzNjPu5zmGLmuiW0AL3x8hs4KiB8jhGlcx_z32mfDOBqvhlqgJw6HEsQRj7kziPvD1gnTt0I4xVuculKFSY6gYeyoii6_A6fN4frqoR59qzb4iNDXnHaKovleUB9VWmzG1cLcvzSP1nXSvj8tNIR_e52yTPq9tpAf-hkzs_1dTS3a65canzVOW_F6plnX79TZJ5N9Wvm7669cX8v2qUb-e5gBkMnU2i70jjheacaXVuHx_cb-JIK12VpmrsVfJGSD_uwCfODHf140lfdr_okg", - "type": "string" - } - ] - }, "method": "PATCH", "header": [], "body": { "mode": "raw", - "raw": "{\n \"energy\": {\n \"_id\": \"656411820133aef67f385412\",\n \"carbon_emissions\": 0.0,\n \"date\": {\n \"$date\": \"2023-11-26T00:00:00Z\"\n },\n \"electricity\": 33,\n \"heating_oil\": 22,\n \"household\": 4,\n \"natural_gas\": 333,\n \"province\": \"British Columbia\",\n \"user_id\": \"651cf22c1d4f7834e2303a85\"\n }\n}", + "raw": "{\n \"energy\": {\n \"_id\": \"6565277a04aaad72e88b010d\",\n \"user_id\": \"65651db4f3369512431e5c4a\",\n \"heating_oil\": 0,\n \"natural_gas\": 0,\n \"electricity\": 500,\n \"province\": \"\",\n \"household\": 0,\n \"carbon_emissions\": 0.0,\n \"date\": \"2023-11-26T00:00:00\"\n }\n}", "options": { "raw": { "language": "json" @@ -665,14 +528,14 @@ } }, "url": { - "raw": "{{LocalBaseURL}}/energy/energy/656411820133aef67f385412", + "raw": "{{LocalBaseURL}}/energy/energy/656529e46e7a0fc224b33573", "host": [ "{{LocalBaseURL}}" ], "path": [ "energy", "energy", - "656411820133aef67f385412" + "656529e46e7a0fc224b33573" ] } }, @@ -706,9 +569,12 @@ "method": "GET", "header": [], "url": { - "raw": "{{LocalBaseURL}}", + "raw": "{{LocalBaseURL}}/", "host": [ "{{LocalBaseURL}}" + ], + "path": [ + "" ] } }, @@ -720,7 +586,7 @@ "bearer": [ { "key": "token", - "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBiYmQyOTllODU2MmU3MmYyZThkN2YwMTliYTdiZjAxMWFlZjU1Y2EiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vY2FyYm9uLXRyYWNrLXN5c3RlbSIsImF1ZCI6ImNhcmJvbi10cmFjay1zeXN0ZW0iLCJhdXRoX3RpbWUiOjE3MDA4NDg5NjgsInVzZXJfaWQiOiJ3UFVEaEFiM0Q5ZHpoeDJXa1RBZlBLbnhGSG0xIiwic3ViIjoid1BVRGhBYjNEOWR6aHgyV2tUQWZQS254RkhtMSIsImlhdCI6MTcwMDg0ODk2OCwiZXhwIjoxNzAwODUyNTY4LCJlbWFpbCI6InlhemFuQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJ5YXphbkBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.E1XaTAt-BQ6ub7AdOKV_BR8z533NJA-G9DhXI26rffCtZXj55SPpUSYd71t_jVZ2Q8RSZyrKdOkkbW9pwMKw0zUKRCWLpwS5bbWFUBvcX4qhmGiAO6-ZkHYrn9cJiHr6cToT3baPLCzIYuIFzuABjC4w3LZL4C_UQlWhfF2Qois_Qc7-XdNyNJ7e9n0bSlAlM8rOtbkIy0o4T1_9n1rVwM6hiH2ePGWTOjmjcGCSqichttqbYLIhB5NOTrhYXTuTtJtpV_wr2tdi2lDCFoMXGj8DaLVsq4URHJVf_U7JvWKUg50_8wlIZs9c6Px2ypSGIXEYEwUrjtOsIjRlPdPJDA", + "value": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBiYmQyOTllODU2MmU3MmYyZThkN2YwMTliYTdiZjAxMWFlZjU1Y2EiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vY2FyYm9uLXRyYWNrLXN5c3RlbSIsImF1ZCI6ImNhcmJvbi10cmFjay1zeXN0ZW0iLCJhdXRoX3RpbWUiOjE3MDExMjc0NTAsInVzZXJfaWQiOiJ3UFVEaEFiM0Q5ZHpoeDJXa1RBZlBLbnhGSG0xIiwic3ViIjoid1BVRGhBYjNEOWR6aHgyV2tUQWZQS254RkhtMSIsImlhdCI6MTcwMTEyNzQ1MCwiZXhwIjoxNzAxMTMxMDUwLCJlbWFpbCI6InlhemFuQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJ5YXphbkBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.YcyzOeOgXiurm2W8lw2YwvIL2Pfweezu2ASK_RK3MuVRUw2Z1AXwWTJyDbjioYfaXS2GwurtJ3u-q7TqPlL4MmTwb5G09F7cmbNBvbEBQTtOhK9TmyNlMcGV0Gtkaf3J7xebL4qcwQ9aI_lZ1MGS9tMYn8gwArxIVs8nNPxkSFUicrj_buf3Jan6kNMfVIQOOUg9cqocn3VoxInAI9fjbxyliZ7LDF3rNBzBNsXQoOJ6UlHqEcd_Up2oLGsEm3HnIArtPzn4V_BNcmkaZh2cx28KDUjUPpTVHdWguEPUkA_CFhDTYdts7ReisAQviKTkhIxDkCGsUtllWU0Q4fTNcg", "type": "string" } ] @@ -752,5 +618,4 @@ "type": "string" } ] -} - +} \ No newline at end of file From 4432c13fac57a7b804d58497a278c2cbf82908f9 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 19:29:50 -0500 Subject: [PATCH 18/20] Added Correct Paths --- frontend/src/components/appNavigation.tsx | 2 +- frontend/src/screens/Energy/energyEntryEdit.tsx | 4 ++-- frontend/src/screens/Energy/energyForum.tsx | 4 ++-- frontend/src/screens/Energy/{energy.tsx => energyHistory.tsx} | 4 ++-- frontend/src/screens/Food/foodEntryEdit.tsx | 4 ++-- frontend/src/screens/Food/foodForum.tsx | 4 ++-- frontend/src/screens/Food/foodHistory.tsx | 4 ++-- .../src/screens/Transportation/transportationEntryEdit.tsx | 4 ++-- frontend/src/screens/Transportation/transportationForum.tsx | 4 ++-- frontend/src/screens/Transportation/transportationHistory.tsx | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) rename frontend/src/screens/Energy/{energy.tsx => energyHistory.tsx} (97%) diff --git a/frontend/src/components/appNavigation.tsx b/frontend/src/components/appNavigation.tsx index 5291c03..e073247 100644 --- a/frontend/src/components/appNavigation.tsx +++ b/frontend/src/components/appNavigation.tsx @@ -13,7 +13,7 @@ import TransportationForum from '../screens/Transportation/transportationForum'; import TransportationEntryEdit from '../screens/Transportation/transportationEntryEdit'; import FoodHistory from '../screens/Food/foodHistory'; import TransportationHistory from '../screens/Transportation/transportationHistory'; -import EnergyHistory from '../screens/Energy/energy'; +import EnergyHistory from '../screens/Energy/energyHistory'; import EnergyEntryEdit from '../screens/Energy/energyEntryEdit'; import FoodEntryEdit from '../screens/Food/foodEntryEdit'; diff --git a/frontend/src/screens/Energy/energyEntryEdit.tsx b/frontend/src/screens/Energy/energyEntryEdit.tsx index 762f0b6..a52494a 100644 --- a/frontend/src/screens/Energy/energyEntryEdit.tsx +++ b/frontend/src/screens/Energy/energyEntryEdit.tsx @@ -78,8 +78,8 @@ export default function EnergyEntryEdit(): JSX.Element { }; const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); const navigation = useNavigation(); diff --git a/frontend/src/screens/Energy/energyForum.tsx b/frontend/src/screens/Energy/energyForum.tsx index 40fb1b6..9eb9d1d 100644 --- a/frontend/src/screens/Energy/energyForum.tsx +++ b/frontend/src/screens/Energy/energyForum.tsx @@ -13,8 +13,8 @@ export type StackNavigation = StackNavigationProp; export default function EnergyForum(): JSX.Element { const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); const navigation = useNavigation(); diff --git a/frontend/src/screens/Energy/energy.tsx b/frontend/src/screens/Energy/energyHistory.tsx similarity index 97% rename from frontend/src/screens/Energy/energy.tsx rename to frontend/src/screens/Energy/energyHistory.tsx index c7a184f..d1787ba 100644 --- a/frontend/src/screens/Energy/energy.tsx +++ b/frontend/src/screens/Energy/energyHistory.tsx @@ -32,8 +32,8 @@ export default function EnergyHistory(): JSX.Element { }; const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); useEffect(() => { diff --git a/frontend/src/screens/Food/foodEntryEdit.tsx b/frontend/src/screens/Food/foodEntryEdit.tsx index 0b3067f..b702092 100644 --- a/frontend/src/screens/Food/foodEntryEdit.tsx +++ b/frontend/src/screens/Food/foodEntryEdit.tsx @@ -94,8 +94,8 @@ export default function FoodEntryEdit(): JSX.Element { }; const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); const navigation = useNavigation(); diff --git a/frontend/src/screens/Food/foodForum.tsx b/frontend/src/screens/Food/foodForum.tsx index cd84492..4236804 100644 --- a/frontend/src/screens/Food/foodForum.tsx +++ b/frontend/src/screens/Food/foodForum.tsx @@ -14,8 +14,8 @@ export type StackNavigation = StackNavigationProp; export default function FoodForum(): JSX.Element { const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); const navigation = useNavigation(); diff --git a/frontend/src/screens/Food/foodHistory.tsx b/frontend/src/screens/Food/foodHistory.tsx index 5e2e62f..b13e306 100644 --- a/frontend/src/screens/Food/foodHistory.tsx +++ b/frontend/src/screens/Food/foodHistory.tsx @@ -32,8 +32,8 @@ export default function FoodHistory(): JSX.Element { }; const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); useEffect(() => { diff --git a/frontend/src/screens/Transportation/transportationEntryEdit.tsx b/frontend/src/screens/Transportation/transportationEntryEdit.tsx index f54d216..701b301 100644 --- a/frontend/src/screens/Transportation/transportationEntryEdit.tsx +++ b/frontend/src/screens/Transportation/transportationEntryEdit.tsx @@ -82,8 +82,8 @@ export default function TransportationEntryEdit(): JSX.Element { }; const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); const navigation = useNavigation(); diff --git a/frontend/src/screens/Transportation/transportationForum.tsx b/frontend/src/screens/Transportation/transportationForum.tsx index ff478a1..2ca7ea8 100644 --- a/frontend/src/screens/Transportation/transportationForum.tsx +++ b/frontend/src/screens/Transportation/transportationForum.tsx @@ -84,8 +84,8 @@ import { }; const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); const navigation = useNavigation(); diff --git a/frontend/src/screens/Transportation/transportationHistory.tsx b/frontend/src/screens/Transportation/transportationHistory.tsx index f133b7c..45ea689 100644 --- a/frontend/src/screens/Transportation/transportationHistory.tsx +++ b/frontend/src/screens/Transportation/transportationHistory.tsx @@ -32,8 +32,8 @@ export default function TransportationHistory(): JSX.Element { }; const [loaded] = useFonts({ - Montserrat: require('../../assets/fonts/MontserratThinRegular.ttf'), - Josefin: require('../../assets/fonts/JosefinSansThinRegular.ttf'), + Montserrat: require('../../../assets/fonts/MontserratThinRegular.ttf'), + Josefin: require('../../../assets/fonts/JosefinSansThinRegular.ttf'), }); useEffect(() => { From 3fceb28a86d8554bc1cb08cc1a2f142b45144416 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 19:37:23 -0500 Subject: [PATCH 19/20] Update FirebaseAPI.py --- backend/utils/FirebaseAPI.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/utils/FirebaseAPI.py b/backend/utils/FirebaseAPI.py index f8b4418..0c0b7a5 100644 --- a/backend/utils/FirebaseAPI.py +++ b/backend/utils/FirebaseAPI.py @@ -1,3 +1,4 @@ +# from typing import Optional from typing import Optional import firebase_admin from firebase_admin import credentials, auth @@ -12,9 +13,6 @@ class FirebaseAPI: @staticmethod def verify_google_token(id_token: str) -> Optional[dict]: - # print("Yazan") - # print(id_token) - id_token="eyJhbGciOiJSUzI1NiIsImtpZCI6IjBiYmQyOTllODU2MmU3MmYyZThkN2YwMTliYTdiZjAxMWFlZjU1Y2EiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vY2FyYm9uLXRyYWNrLXN5c3RlbSIsImF1ZCI6ImNhcmJvbi10cmFjay1zeXN0ZW0iLCJhdXRoX3RpbWUiOjE3MDExMjc0NTAsInVzZXJfaWQiOiJ3UFVEaEFiM0Q5ZHpoeDJXa1RBZlBLbnhGSG0xIiwic3ViIjoid1BVRGhBYjNEOWR6aHgyV2tUQWZQS254RkhtMSIsImlhdCI6MTcwMTEyNzQ1MCwiZXhwIjoxNzAxMTMxMDUwLCJlbWFpbCI6InlhemFuQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJ5YXphbkBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.YcyzOeOgXiurm2W8lw2YwvIL2Pfweezu2ASK_RK3MuVRUw2Z1AXwWTJyDbjioYfaXS2GwurtJ3u-q7TqPlL4MmTwb5G09F7cmbNBvbEBQTtOhK9TmyNlMcGV0Gtkaf3J7xebL4qcwQ9aI_lZ1MGS9tMYn8gwArxIVs8nNPxkSFUicrj_buf3Jan6kNMfVIQOOUg9cqocn3VoxInAI9fjbxyliZ7LDF3rNBzBNsXQoOJ6UlHqEcd_Up2oLGsEm3HnIArtPzn4V_BNcmkaZh2cx28KDUjUPpTVHdWguEPUkA_CFhDTYdts7ReisAQviKTkhIxDkCGsUtllWU0Q4fTNcg" return auth.verify_id_token( id_token=id_token, check_revoked=True ) From df776c56a7bdcb4fb06603997897d5739f323239 Mon Sep 17 00:00:00 2001 From: Yazan Armoush Date: Mon, 27 Nov 2023 19:39:10 -0500 Subject: [PATCH 20/20] Updated Frontend to be up-to-date --- backend/utils/FirebaseAPI.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/utils/FirebaseAPI.py b/backend/utils/FirebaseAPI.py index 0c0b7a5..2d18964 100644 --- a/backend/utils/FirebaseAPI.py +++ b/backend/utils/FirebaseAPI.py @@ -13,6 +13,7 @@ class FirebaseAPI: @staticmethod def verify_google_token(id_token: str) -> Optional[dict]: + print(id_token) return auth.verify_id_token( id_token=id_token, check_revoked=True )