CalPal
-Managing Calories for Health Conscious People
-Login successful!
--
User Information
- --
Hi, {{ fname }} {{ lname }}!
-- -
Email: {{ email }}
-Password: {{ "*" * password|length }}
-Password: {{ password }}
- -diff --git a/README.md b/README.md index e28029e..c2b9bb7 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,4 @@ python app.py All parts of CalPal are free to use and abuse under the open-source MIT license. ## Acknowledgement -CalPal was created by [Nhat Nguyen](https://github.com/nguyen-nhat), [Jackson Truong](https://github.com/), and [Albert Ong](https://github.com/). +CalPal was created by [Nhat Nguyen](https://github.com/nguyen-nhat), [Jackson Truong](https://github.com/), and [Albert Ong](https://github.com/Albert-C-Ong). diff --git a/database/database.xlsx b/database/database.xlsx deleted file mode 100644 index b8ad6d1..0000000 Binary files a/database/database.xlsx and /dev/null differ diff --git a/database/exercise_database.xlsx b/database/exercise_database.xlsx new file mode 100644 index 0000000..71a1afd Binary files /dev/null and b/database/exercise_database.xlsx differ diff --git a/database/food_database.xlsx b/database/food_database.xlsx new file mode 100644 index 0000000..c38b433 Binary files /dev/null and b/database/food_database.xlsx differ diff --git a/database/template.xlsx b/database/template.xlsx deleted file mode 100644 index 428a972..0000000 Binary files a/database/template.xlsx and /dev/null differ diff --git a/database/user_database.xlsx b/database/user_database.xlsx new file mode 100644 index 0000000..aaa6e2f Binary files /dev/null and b/database/user_database.xlsx differ diff --git a/database/user_database_template.xlsx b/database/user_database_template.xlsx new file mode 100644 index 0000000..419b123 Binary files /dev/null and b/database/user_database_template.xlsx differ diff --git a/master.css b/master.css new file mode 100644 index 0000000..e323455 --- /dev/null +++ b/master.css @@ -0,0 +1,291 @@ + +/* + * CalPal: A calorie tracking app. + * Written by Nhat Nguyen and Albert Ong. + * CMPE 131 + * Revision: 15.11.2018 + * + * master.css + * The master stylesheet. Used in base.html +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + border: 0; + color: #FFEF9F; + font: inherit; + font-size: 100%; + margin: 0; + padding: 0; + vertical-align: baseline; +} + +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +body { + color: #FFEF9F; + font-family: sans-serif; + height: 100%; + margin: 0; + background-image: linear-gradient(to right, #B02635, #F97C21); + background-attachment: fixed; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +.main, .form-container .center, .form-container .success, .form-container .failure { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +html, body, form { + height: 100%; + width: 100%; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +} + +body { + margin: 1.5% 0% 1.5% 0%; +} + +.main { + min-height: inherit; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: inherit; +} + +.form-wrapper { + margin: 0 auto; + height: 100%; + width: 80%; +} + +.form-container { + border-radius: 5px; + background-color: #fba56730; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + padding: 2.5% 0% 2.5% 0%; + text-align: center; + width: 580px; +} + +.form-container h1 { + font-size: 32px; + font-weight: 700; + margin: 0px 0px 10px 0px; +} + +.form-container h2 { + font-style: italic; + font-size: 18px; + margin-bottom: 25px; +} + +.form-container .form-header p { + color: #FFEF9F; + font-size: 14px; + margin-bottom: 15px; +} + +.form-container a { + text-decoration: none; + color: black; + -webkit-transition: 0.25s; + transition: 0.25s; +} + +.form-container p a { + border-radius: 3px; + color: #FFEF9F; + font-weight: Bold; +} + +.form-container a:hover { + color: #F97C21; +} + +.form-container b { + font-weight: bolder; +} + +/* Styles the success message in the form container. */ +.form-container .success { + background-color: #FF882B; + border-radius: 2px; + color: white; + height: 40px; + margin: 15px 0px 10px 0px; +} + +/* Styles the failure message in the form container. */ +.form-container .failure { + border-radius: 2px; + background-color: #FF882B; + color: white; + height: 40px; + margin: 15px 0px 10px 0px; +} + +form button[type="submit"], +form input[type="email"], +form input[type="number"], +form input[type="password"], +form input[type="text"], +form select, +form select[type="gender"] { + margin-bottom: 10px; + padding-left: 4px; + border: 1px solid #f0f0f0; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + height: 40px; + border-radius: 3px; + outline: none; + -webkit-transition: 0.25s; + transition: 0.25s; +} + +form input[type="text"]:hover, form input[type="email"]:hover, form input[type="password"]:hover { + padding-left: 10px; +} + +form input[type="text"]:focus, form input[type="email"]:focus, form input[type="password"]:focus { + border-color: #f76c00; +} + +form input::-webkit-input-placeholder { + color: #d9d9d9; + padding-left: 2px; +} + +form input:-ms-input-placeholder { + color: #d9d9d9; + padding-left: 2px; +} + +form input::-ms-input-placeholder { + color: #d9d9d9; + padding-left: 2px; +} + +form input::placeholder { + color: #d9d9d9; + padding-left: 2px; +} + +/* Styles the login button. */ +form button[type="submit"] { + margin: 20px 0px 40px 0px; + background-color: #FF882B; + border-radius: 3px; + border: none; + color: white; + font-weight: bolder; + font-size: 1.15em; + cursor: pointer; +} + +form button[type="submit"]:hover { + background-color: #f76c00; +} + +form button[type="submit"]:focus { + background-color: #FFEF9F; + padding-top: 5px; +} + +form .input-label { + padding: 10px 0px 25px 0px; +} + +/* Styles all the labels within the form tag. */ +form label { + color: #FFEF9F; + display: block; + float: left; +} + +/* Styles the text that goes to the left of certain input fields. + * Such as the height and calorie goal. + */ +label .input-text { + color: red; +} + +form span { + float: right; + color: #FFEF9F; +} + +form .divider { + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +/* Controls the width of the name input fields. */ +form .divider-size { + width: 46%; +} + +/* Controls the width of the birthday input fields. */ +form. birthday-size { + width: 30%; +} + +/* Controls the styling of the CalPal logo. */ +.CalPal-logo{ + margin: 0% 0% 3% 0%; +} + +/* A shortened width used for the weight abd calorie goal inputs. */ +form .shortened-width { + width: 80%; +} diff --git a/project/app.py b/project/app.py index 349ba87..1f505e4 100644 --- a/project/app.py +++ b/project/app.py @@ -1,9 +1,24 @@ -# TODO Reseach G package +#!/usr/bin/python3 +""" +CalPal: A calorie tracking app. +Written by Nhat Nguyen and Albert Ong. +CMPE 131 +Revision: 02.12.2018 -# This is where the python flask code occupies +app.py +This is where the python flask code occupies +""" -from flask import Flask, render_template, redirect, url_for, request, Blueprint, session -from modules.reader import checkLogin, checkEmail, getDatabase, userCreation +from calendar import month_name +from datetime import datetime + +from flask import * +from modules.module import * +from modules.reader import * +from modules.FoodReader import (getFoodDatabase, + getFoodCalories) +from modules.ExerciseReader import (getExerciseDatabase, + getExerciseCalories) app = Flask(__name__) app.config["SECRET_KEY"] = "secret_key" @@ -13,63 +28,428 @@ # Redirects to the login page @main.route("/") def index(): - return redirect(url_for('main.login')) + session["calorie_food_list"] = [] + session["calorie_exercise_list"] = [] + session["count_food_calorie"] = 0 + session["count_exercise_calorie"] = 0 + + # Retrieves the list of exercises and foods. + session["food_list"] = getFoodDatabase()[1] + session["exercise_list"] = getExerciseDatabase()[0] + + return redirect(url_for('main.login')) + # User login page @main.route("/login") def login(): - return render_template("login.html") + session["calorie_food_list"] = [] + session["calorie_exercise_list"] = [] + session["count_food_calorie"] = 0 + session["count_exercise_calorie"] = 0 + + # Retrieves the list of exercises and foods. + session["food_list"] = getFoodDatabase()[1] + session["exercise_list"] = getExerciseDatabase()[0] + + return render_template("login.html") + # Handles the login page logic @main.route("/login", methods=["GET", "POST"]) def login_redirect(): - # Stores login user information - session["email"] = request.form["email"] - session["password"] = request.form["password"] - # If user information matches the information in the database, continue to application - if checkLogin(session['email'], session['password']): - return redirect(url_for('main.dashboard')) - else: - return render_template("login.html", loginFailure=True) + # Stores login user information + email_input = request.form["email"] + password_input = request.form["password"] + + # Attempts to retrieve the user's data. + try: + user_data = getUserData(email_input) + + # Returns displays an error message is the email is not currently registered. + except IndexError: + return render_template("login.html", unusedEmail = True) + + # If user information matches the information in the database, continue to application + if checkLogin(email_input, password_input): + + # Assigns the remaining as attributes to session. + for var_index, var_name in enumerate(("fname", + "lname", + "email", + "password", + "gender", + "birth-day", + "birth-month", + "birth-year", + "height", + "weight", + "calorie-goal")): + session[var_name] = user_data[var_index] + + # Loads the dashboard page. + return redirect(url_for('main.dashboard')) + + # Otherwise loads the login page with a login failure message. + else: + return render_template("login.html", loginFailure=True) -# User signin page -@main.route("/signup") -def signup(): - return render_template("signup.html") -# BUG Keeps name of previous user who signed up # If the user is sucessfully created -@main.route("/success") +@main.route("/login/success") def signup_success(): - return render_template("login.html", userCreation=True) - -# Handles the sign up page logic -@main.route("/signup", methods=["GET", "POST"]) -def signup_redirect(): - # Stores signup user information - session["fname"] = request.form["fname"] - session["lname"] = request.form["lname"] - session["email"] = request.form["email"] - session["password"] = request.form["password"] - - # If email is unique, create the user in the database + return render_template("login.html", userCreation=True) + + +# The first user signup page. +@main.route("/signup_page_1") +def signup_page_1(): + return render_template("signup_page_1.html") + + +# The first user signup page redirect. +@main.route("/signup_page_1", methods=["GET", "POST"]) +def signup_page_1_redirect(): + + # Uses a for loop to access the user's inputted + # first name, last name, email, and password. + for var_name in ("fname", "lname", "email", "password"): + session[var_name] = request.form[var_name] + + # Redirects to the second signup page if the inputted email is + # not already in the database. if not checkEmail(session["email"]): - userCreation(session["fname"], session["lname"], session["email"], session["password"]) - return redirect(url_for('main.signup_success')) + return redirect(url_for("main.signup_page_2")) + + # Otherwise, reloads the page will a failure message. else: - return render_template("signup.html", loginFailure=True) + return render_template("signup_page_1.html", loginFailure=True) + + +# The second user signup page. +@main.route("/signup_page_2") +def signup_page_2(): + return render_template("signup_page_2.html") + + +# The sign up button for the second user signup page. +@main.route("/signup_page_2", methods=["GET", "POST"]) +def signup_page_2_buttons(): + + # Retrieves the name of the action. + # This value will either be BACK or SIGN UP. + action_name = request.form.get("action") + + # Returns to the first sign up page if the back button was pressed. + if action_name == "BACK": + return redirect(url_for("main.signup_page_1")) + + # Creates a new user if the sign up button was pressed. + elif action_name == "SIGN UP": + + # Retrieves the user's height in feet and inches and converts + # them to integers. + height_feet = int(request.form["height-feet"]) + height_inches = int(request.form["height-inches"]) + + # Sums the total height in inches and converts it into a string. + total_height = str(mergeHeight(height_feet, height_inches)) + # Uses a for loop to iterate through every piece of user information. + for var_name in ("gender", + "birth-day", + "birth-month", + "birth-year", + "height", + "weight", + "calorie-goal"): + + # For the case of birth month... + if var_name == "birth-month": + + # Retrieves the name of the user's birth month. + month_name = request.form[var_name] + + # Converts the the user's birth month to its + # corresponing number. + month_num = monthNameToNumber(month_name) + + # Assigns the month number as an attribute. + session[var_name] = month_num + + # The assigned variable for height is different than other + # attributes because the total height was calculated previously + # in total inches. + elif var_name == "height": + session[var_name] = total_height + + # Creates an attribute using the name of the variable + else: + session[var_name] = request.form[var_name] + + # Creates a new user based on the user's inputted data. + createUser([session["fname"], + session["lname"], + session["email"], + session["password"], + session["gender"], + session["birth-day"], + session["birth-month"], + session["birth-year"], + session["height"], + session["weight"], + session["calorie-goal"]]) + + # Returns to the login page and displays a success message. + return redirect(url_for("main.signup_success")) -# TODO: Finish the dashboard page -# User dashboard page -@main.route("/app") +# User dashboard page. +@main.route("/dashboard") def dashboard(): - return render_template("app.html", fname=session['fname'], lname=session['lname'], email=session['email'], password=session['password']) + + # Attempts to retrieve the first name, last name, email, and + # password of the user. + + # Retrieves the current date. + current_date = datetime.today() + + # Extracts the day, month, and year into strings. + current_day = str(current_date.day) + current_month = month_name[current_date.month] + current_year = str(current_date.year) + + # Formats the current date into a sentence. + formatted_date = " ".join(["Today is", current_month, current_day + ",", current_year + "."]) + + session["foratted_date"] = formatted_date + + # Retrieves the list of exercises and foods. + food_list = getFoodDatabase()[1] + exercise_list = getExerciseDatabase()[0] + + return render_template("dashboard.html", + fname = session["fname"], + lname = session["lname"], + formatted_date = formatted_date, + exercise_list = exercise_list, + food_list = food_list, + total_calories = 0, + met_calorie_goal = False) + + +# Controls the buttons for the dashboard page. +@main.route("/dashboard", methods=["GET", "POST"]) +def dashboard_buttons(): + + # Retrieves the name of the action. + # This value will either be SUBMIT, EXIT, or UPDATE INFO. + action_name = request.form.get("action") + + # If the update info button was pressed... + if action_name == "UPDATE INFO": + + # Redirects to the update user info page. + return redirect(url_for("main.update_user_info")) + + # If the exit button was pressed... + elif action_name == "EXIT": + + # Clears all the data for the session. + session.clear() + + # Redirects to the login page. + return redirect(url_for("main.login")) + + + # If the sumbit foods button was pressed... + elif action_name == "SUBMIT_FOODS": + + # Retrieves the name of the food and the number of ounces consumed. + food = request.form["food"] + ounce = request.form["ounce"] + + calorie_food_list = session["calorie_food_list"] + count_food_calorie = 0 + + # Calculated the number of calories gained. + calories = getFoodCalories(food, float(ounce)) + + if (calories >= 0): + calorie_food_list.append([food, calories]) + session["calorie_food_list"] = calorie_food_list + + for calories in calorie_food_list: + count_food_calorie = count_food_calorie + int(calories[1]) + session["count_food_calorie"] = count_food_calorie + + # Calculates the difference between the number of calories gained + # and the number of calories burned. + total_calories = session["count_food_calorie"] - session["count_exercise_calorie"] + + # Calculates whether the user has met their calorie goal. + met_calorie_goal = metCalorieGoal(total_calories, session["calorie-goal"]) + + return render_template("dashboard.html", + fname = session["fname"], + lname = session["lname"], + formatted_date = session["foratted_date"], + food_list = session["food_list"], + exercise_list = session["exercise_list"], + calorie_food_list = session["calorie_food_list"], + calorie_exercise_list = session["calorie_exercise_list"], + total_calories = int(total_calories), + met_calorie_goal = met_calorie_goal) + # If the sumbit exercise button was pressed... + elif action_name == "SUBMIT_EXERCISE": + exercise = request.form["exercise"] + minute = request.form["minute"] + + calorie_exercise_list = session["calorie_exercise_list"] + count_exercise_calorie = 0 + + calories = getExerciseCalories(exercise, float(minute), session["weight"]) + if (calories >= 0): + calorie_exercise_list.append([exercise, calories]) + session["calorie_exercise_list"] = calorie_exercise_list + + for calories in calorie_exercise_list: + count_exercise_calorie = count_exercise_calorie + int(calories[1]) + session["count_exercise_calorie"] = count_exercise_calorie + + # Calculates the difference between the number of calories gained + # and the number of calories burned. + total_calories = session["count_food_calorie"] - session["count_exercise_calorie"] + + # Calculates whether the user has met their calorie goal. + met_calorie_goal = metCalorieGoal(total_calories, session["calorie-goal"]) + + return render_template("dashboard.html", + fname = session["fname"], + lname = session["lname"], + formatted_date = session["foratted_date"], + food_list = session["food_list"], + exercise_list = session["exercise_list"], + calorie_food_list = session["calorie_food_list"], + calorie_exercise_list = session["calorie_exercise_list"], + total_calories = int(total_calories), + met_calorie_goal = met_calorie_goal) + + +# The update user info page. +@main.route("/dashboard/update_user_info") +def update_user_info(updateSuccess = False, usedEmail = False): + + # Calculates the user's height in both feet and inches. + split_height = splitHeight(int(session["height"])) + height_feet = split_height[0] + height_inches = split_height[1] + + return render_template("update_user_info.html", + fname = session["fname"], + lname = session["lname"], + email = session["email"], + password = session["password"], + gender = session["gender"], + birth_day = session["birth-day"], + birth_month = session["birth-month"], + birth_year = session["birth-year"], + height_feet = height_feet, + height_inches = height_inches, + weight = session["weight"], + calorie_goal = session["calorie-goal"], + updateSuccess = updateSuccess, + usedEmail = usedEmail) + + +# Controls the buttons for the update user info page. +@main.route("/dashboard/update_user_info", methods=["GET", "POST"]) +def update_user_info_buttons(): + + # Retrieves the name of the action. + # This value will either be BACK or UPDATE. + action_name = request.form.get("action") + + # Redirects to the app page if the back button was pressed. + if action_name == "BACK": + return redirect(url_for("main.dashboard")) + + # If the update info button was pressed... + elif action_name == "UPDATE": + + # Retrieves the inputted email. + new_email = request.form["email"] + + # Checks if the inputted email is either unused in the current database + # or is the user's current email. + viable_email = (not checkEmail(new_email)) or \ + (new_email == session["email"]) + + # If the inputted email was viable... + if viable_email: + + # Retrieves all the new inputted values. + new_fname = request.form["fname"] + new_lname = request.form["lname"] + new_password = request.form["password"] + new_gender = request.form["gender"] + new_birth_day = request.form["birth-day"] + new_birth_month = monthNameToNumber(request.form["birth-month"]) # Converts month name to number. + new_birth_year = request.form["birth-year"] + new_height_feet = int(request.form["height-feet"]) + new_height_inches = int(request.form["height-inches"]) + new_weight = request.form["weight"] + new_calorie_goal = request.form["calorie-goal"] + + # Calculates the new, total height. + new_total_height = mergeHeight(new_height_feet, new_height_inches) + + # A list of the new user data. + new_user_data = [new_fname, + new_lname, + new_email, + new_password, + new_gender, + new_birth_day, + new_birth_month, + new_birth_year, + new_total_height, + new_weight, + new_calorie_goal] + + # Writes the new data to database.xlsx. + writeNewUserData(session["email"], new_user_data) + + # Assigns the new data as attributes to session. + for var_index, var_name in enumerate(("fname", + "lname", + "email", + "password", + "gender", + "birth-day", + "birth-month", + "birth-year", + "height", + "weight", + "calorie-goal")): + session[var_name] = new_user_data[var_index] + + # Reloads the same page except with an update successful message. + return update_user_info(updateSuccess = True) + + # Displays an error message is the email is already used. + else: + return update_user_info(usedEmail = True) + app.register_blueprint(main) + +#======================================================================= + if __name__ == "__main__": app.run(debug=True) + + diff --git a/project/modules/DatabaseReader.py b/project/modules/DatabaseReader.py new file mode 100644 index 0000000..68c3bbd --- /dev/null +++ b/project/modules/DatabaseReader.py @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +""" +CalPal: A calorie tracking app. +Written by Nhat Nguyen and Albert Ong. +CMPE 131 +Revision: 30.11.2018 + +DatabaseReader.py +""" + +import pandas as pd + + +def getDatabase(database_path, columns): + """ + Returns a database given the path to the database file and a list + of the names of the columns + """ + # Create a Pandas dataframe from the excel file + df = pd.read_excel(database_path, sheet_name="Sheet1") + + # A list that will store all the values in the database. + # This will be the final output. + database = [] + + # Uses a for loop to iterate each column of the database. + for column_name in columns: + + # Retrieves the database column. + database_column = convert(df[column_name]) + + # Appends the column to the final output. + database.append(database_column) + + # Returns the final output. + return database + + +def convert(df_column): + """ + Converts a DataFrame column to list + """ + data_list = [] + + for element in df_column: + data_list.append(element) + + return data_list diff --git a/project/modules/ExerciseReader.py b/project/modules/ExerciseReader.py new file mode 100644 index 0000000..a1f17f2 --- /dev/null +++ b/project/modules/ExerciseReader.py @@ -0,0 +1,68 @@ +#!/usr/bin/python3 +""" +CalPal: A calorie tracking app. +Written by Nhat Nguyen and Albert Ong. +CMPE 131 +Revision: 01.12.2018 +ExerciseReader.py +Reads data from exercise_database.xlsx +""" + +# Imports from DatabaseReader depending on whether or not the function +# is being run from ExerciseReader.py or app.py +if __name__ == "__main__": + from DatabaseReader import getDatabase +else: + from modules.DatabaseReader import getDatabase + + +def getExerciseDatabase(): + """ + Returns the entire exercise database. + """ + exercise_database_columns = ("Exercise Name", "Calories per minute") + return getDatabase(getExerciseDatabasePath(), exercise_database_columns) + + +def getExerciseDatabasePath(): + """ + Returns the path of the exercise database depending on whether or not this + file is being run on reader.py or app.py. + """ + if __name__ == "__main__": + database_path = "../../database/exercise_database.xlsx" + else: + database_path = "../database/exercise_database.xlsx" + + return database_path + + +def getExerciseCalories(exercise_name, minutes, weight): + """ + Calculates the number of calories burned given an exercise name, + the number of minutes exercising, and the user's weight. + """ + # Retrieves the exercise and calories per minute columns from + # exercise_databast.xlsx + exercise_column = getExerciseDatabase()[0] + calorie_column = getExerciseDatabase()[1] + + # Retrieves the index associated with the exercise name. + exercise_index = exercise_column.index(exercise_name) + + # Retrieves the calories per minute of the given exercise. + calories_per_minute = calorie_column[exercise_index] + + # Calculates the number of calories burned, which is the + # # of minutes exercising * # of calories per minute * the user's weight + calories_burned = minutes * calories_per_minute * weight + + # Returns the number of calories burned. + return calories_burned + + +#======================================================================= + + +if __name__ == "__main__": + pass \ No newline at end of file diff --git a/project/modules/FoodReader.py b/project/modules/FoodReader.py new file mode 100644 index 0000000..fd2b1d0 --- /dev/null +++ b/project/modules/FoodReader.py @@ -0,0 +1,70 @@ +#!/usr/bin/python3 +""" +CalPal: A calorie tracking app. +Written by Nhat Nguyen and Albert Ong. +CMPE 131 +Revision: 30.11.2018 + +FoodReader.py +Reads data from food_database.xlsx +""" + +# Imports from DatabaseReader depending on whether or not the function +# is being run from FoodReader.py or app.py +if __name__ == "__main__": + from DatabaseReader import getDatabase +else: + from modules.DatabaseReader import getDatabase + + +def getFoodDatabase(): + """ + Returns the entire food database. + """ + food_database_columns = ("Category", "Food name", "Calories per oz") + return getDatabase(getFoodDatabasePath(), food_database_columns) + + +def getFoodDatabasePath(): + """ + Returns the path of the food database depending on whether or not \ + this file is being run on reader.py or app.py. + """ + if __name__ == "__main__": + database_path = "../../database/food_database.xlsx" + else: + database_path = "../database/food_database.xlsx" + + return database_path + + +def getFoodCalories(food, ounces): + """ + Calclates the number of calories gained given a food name and + the number of ounces consumed. + """ + + # Retrieves the food and calories per ounce columns from + # food_database.xlsx + food_column = getFoodDatabase()[1] + calorie_column = getFoodDatabase()[2] + + # Retrieves the index associated with the given food name. + food_index = food_column.index(food) + + # Retrieves the number of calories per ounce for the given food name. + calories_per_ounce = calorie_column[food_index] + + # Calculated the number of calories gained, which is the + # # of ounces consumed * # of calories per ounce + calories_gained = ounces * calories_per_ounce + + # Returns the # of calories gained. + return calories_gained + + +#======================================================================= + + +if __name__ == "__main__": + print(getFoodCalories("Bagel", 12.5)) diff --git a/project/modules/database.py b/project/modules/database.py new file mode 100644 index 0000000..eea754e --- /dev/null +++ b/project/modules/database.py @@ -0,0 +1,138 @@ +# Import pandas +import pandas as pd + +# Create a Pandas dataframe from the excel file +df = pd.read_excel('../../database/database.xlsx', sheet_name='Sheet1') + +print(df) +print() +print(df['First Name']) + +print(df['Last Name']) +print(df['Email']) +print(df['Password']) + +print() + +print(df.columns) +print(df.index) + +print() +# First Name +print('COLUMN:', df.columns[0]) +print('TYPE:', type(df.columns[0])) +print('First Name' == df.columns[0]) + + +print() +# Prints the columns +for i in df.columns: + print(i) + +print() +print() + +# Print John +# print("NAME", df['First Name'][0]) + +print() +# print(df['Email'] == 'tim@apple.com') +print() +# print(df['Email'].index('tim@apple.com')) +print("DEBUG:", df['Email'].index) + +print() +print('INDEX:', df.loc[df['Email'] == 'tim@apple.com'].index[0]) +# print('INDEX:', df.loc[df['Email'] == 'jasmine@apple.com'].index[0]) +print() +# Checks if email is in email values +print('tim@apple.com' in df['Email'].values) + +print() +# print(df['']) + +def checkLogin(email, password): + ''' + Validates the user email and password. + + Args: + email (str): The email from the submitted form. + password (str): The password from the submitted form. + + Returns: + bool: True when the email and password matches the database, False otherwise. + ''' + + # Checks if email is in email database + if (email in df['Email'].values): + # Checks if email and password matches the database + index = df.loc[df['Email'] == email].index[0] + if ((df['Email'][index] == email) and (df['Password'][index] == password)): + return True + return False + +def userInformation(email): + ''' + Gets the user information in a dictionary. + + Args: + email (str): The email from the submitted form. + + Returns: + userInformation (dict): User information such as first name, last name, and email. + ''' + + userInformation = {} + userInformation['First Name'] = df['First Name'][df.loc[df['Email'] == email].index[0]] + userInformation['Last Name'] = df['Last Name'][df.loc[df['Email'] == email].index[0]] + userInformation['Email'] = email + return userInformation + + +print('Login Validation:', checkLogin('tim@apple.com', 'apple')) +print('Login Validation:', checkLogin('tim@apple.comm', 'apple')) +print('Login Validation:', checkLogin('tim@apple.com', '123')) + +userInformation('tim@apple.com') + +pizza = {} +pizza['apple'] = 'apple1' +print(type(pizza)) + + + AREA myData, DATA, READWRITE + +x DCD B0000000 +y DCD 20000000 +z DCD 0 + +AREA myCode, CODE, READONLY +EXPORT __main +ALIGN +ENTRY +__main PROC + +Create X +LDR r4, = x +LDR r0, [r4] +, # 1 + +Create Y +LDR r4, = y +LDR r1, [r4] +, # 1 + +SUB r3, r0, r1 + +LDR r4, = z +STR r3, [r4] + + +STOP B STOP +ENDP +END + + + + + diff --git a/project/modules/module.py b/project/modules/module.py index 0c9979c..0e58a77 100644 --- a/project/modules/module.py +++ b/project/modules/module.py @@ -1,121 +1,108 @@ -# Python module checks if the pass user information matches with the database - -# Import pandas -import pandas as pd - -# Convert DataFrame column to list -def convert(df_column): - list = [] - for element in df_column: - list.append(element) - return list - -# Checks if the email exist in the database -def checkEmail(email): - if email in list_email: - return(True) - else: - return(False) - -# Checks if the email match the password -def checkPassword(email, password): - if password == dict_email_password[email]: - return(True) - else: - return(False) - -# Checks form information with the database -def checkLogin(email, password): - if checkEmail(email): - return(checkPassword(email, password)) - else: - return(False) - -# Create users: If email is unique, add user to the database -def userCreation(fname, lname, email, password): - if checkEmail(email) == True: - return False - else: - list_fname.append(fname) - list_lname.append(lname) - list_email.append(email) - list_password.append(password) - - # Create a Pandas dataframe from the data. - df = pd.DataFrame({'First Name': list_fname, 'Last Name': list_lname, - 'Email': list_email, 'Password': list_password}) - - # Create a Pandas Excel writer using XlsxWriter as the engine. - writer = pd.ExcelWriter('../../database/database.xlsx', engine='xlsxwriter') - - # Convert the dataframe to an XlsxWriter Excel object. - df.to_excel(writer, sheet_name='Sheet1') - - # Close the Pandas Excel writer and output the Excel file. - writer.save() - - dict_email_password = {} - for i in range(len(list_email)): - dict_email_password[list_email[i]] = list_password[i] - - return True - - -def refreshDatabase(): - # Create a Pandas dataframe from the excel file - df = pd.read_excel('../../database/database.xlsx', sheet_name='Sheet1') - - # Save columns as list - list_fname = convert(df['First Name']) - list_lname = convert(df['Last Name']) - list_email = convert(df['Email']) - list_password = convert(df['Password']) - - # Create a dictionary (KEY email: VALUE password) for user information - dict_email_password = {} - for i in range(len(list_email)): - dict_email_password[list_email[i]] = list_password[i] - - -def getDatabase(): - list = [] - list.append(list_fname) - list.append(list_lname) - list.append(list_email) - list.append(list_password) - return(list) - -# Create a Pandas dataframe from the excel file -df = pd.read_excel('../../database/database.xlsx', sheet_name='Sheet1') - -# Save columns as list -list_fname = convert(df['First Name']) -list_lname = convert(df['Last Name']) -list_email = convert(df['Email']) -list_password = convert(df['Password']) - -# Create a dictionary (KEY email: VALUE password) for user information -dict_email_password = {} -for i in range(len(list_email)): - dict_email_password[list_email[i]] = list_password[i] - - -if __name__ == '__main__': - print() - print() - - fname = 'Jasmine' - lname = 'Mai' - email = 'jasmine@gmail.com' - password = 'Cat2' - - for i in range(10000): - fname = str(i) - lname = str(i) - email = str(i) + '@gmail.com' - password = str(i) - userCreation(fname, lname, email, password) - - print("AFTER:", list_email) - - print("DONE") +#!/usr/bin/python3 +""" +CalPal: A calorie tracking app. +Written by Nhat Nguyen and Albert Ong. +CMPE 131 +Revision: 02.12.2018 + +module.py +A Python module for extraneous functions and variables. +""" + +from calendar import month_name + + +def monthNameToNumber(month_name): + """ + Takes the name of a month and returns its corresponding number. + """ + + # A dictionary that converts a month name to its + # corresponding number. + month_name_to_number = \ + {"January" : 1, + "February" : 2, + "March" : 3, + "April" : 4, + "May" : 5, + "June" : 6, + "July" : 7, + "August" : 8, + "September" : 9, + "October" : 10, + "November" : 11, + "December" : 12, } + + return month_name_to_number[month_name] + + +def monthNumberToName(month_number): + """ + Takes a number between 1 and 12, represented as a string, + and returns the corresponing month name. + """ + month_index = int(month_number) + return month_name[month_index] + + +def mergeHeight(feet, inches): + """ + Takes two integer values, feet and inches, and calculates + the total height in inches. + """ + return (feet * 12) + inches + + +def splitHeight(total_height): + """ + Takes a single integer value, the total height in inches, and + returns a tuple of integers representing the total height + in terms of feet and inches. + + Example: + splitHeight(68) = (5, 8) + """ + feet = total_height // 12 + inches = total_height % 12 + + return (feet, inches) + + +def metCalorieGoal(calorie_difference, calorie_goal): + """ + Returns whether a given calorie goal has been met given + a calorie difference and a calorie goal. + """ + + # The calorie goal is multiplied by negative one because + # it represents the number of calories lost. + calorie_goal_neg = calorie_goal * -1 + + # Returns whether or not the calorie difference is less + # than or equal to the negative calorie goal. + return calorie_difference <= calorie_goal_neg + + +#======================================================================= + +if __name__ == "__main__": + + # The total height in inches. + total_height = 68 + print("total_height = ", total_height, "inches\n") + + # Splits the total height into feet and inches. + split_height = splitHeight(total_height) + feet = split_height[0] + inches = split_height[1] + + # Prints the total height represented in feet and inches. + print("splitHeight(total_height) = ", feet, "feet", inches, "inches") + + # Merges the feet and inches into inches. + # This values will be the same as total_height. + merged_height = mergeHeight(feet, inches) + print("mergeHeight(feet, inches) = ", merged_height, "inches") + + + diff --git a/project/modules/reader.py b/project/modules/reader.py index e61c1b6..b40d0d1 100644 --- a/project/modules/reader.py +++ b/project/modules/reader.py @@ -1,112 +1,315 @@ -# Python module checks if the pass user information matches with the database +#!/usr/bin/python3 +""" +CalPal: A calorie tracking app. +Written by Nhat Nguyen and Albert Ong. +CMPE 131 +Last Revised by Nhat Nguyen: 24.27.2018 + +reader.py +A Python module checks if the pass user information +matches with the database. + +TODO: Optimize the reading and writing database +""" # Import pandas import pandas as pd -# Convert DataFrame column to list + def convert(df_column): - list = [] + """ + Converts a DataFrame column to list + """ + data_list = [] + for element in df_column: - list.append(element) - return list + data_list.append(element) + + return data_list + -# Checks if the email exist in the database def checkEmail(email): - if email in list_email: - return(True) - else: - return(False) + """ + Checks if a given email is currently in the database. + """ + email_list = getUserDatabase()[2] + + return email in email_list -# Checks if the email match the password -def checkPassword(email, password): - if password == dict_email_password[email]: - return(True) - else: - return(False) -# Checks form information with the database def checkLogin(email, password): - if checkEmail(email): - return(checkPassword(email, password)) - else: - return(False) + """ + Validates the user email and password. -# Create users: If email is unique, add user to the database -def userCreation(fname, lname, email, password): - if checkEmail(email): - return False + Args: + email (str): The email from the submitted form. + password (str): The password from the submitted form. + + Returns: + bool: True when the email and password matches the database, False otherwise. + """ + + # Retrieves the entire user database. + database = getUserDatabase() + + # Retrieves the list of emilas and passwords. + email_list = database[2] + password_list = database[3] + + # Checks if the inputted email exists in the database. + if email in email_list: + + # Gets the index associated with the row of the user's data. + user_index = email_list.index(email) + + # Returns True if the inputted email and password match + if email_list[user_index] == email and password_list[user_index] == password: + return True + + # Returns False if the email is not in the database. else: - list_fname.append(fname) - list_lname.append(lname) - list_email.append(email) - list_password.append(password) + return False + + +def getUserData(email): + """ + A function that returns a user's data given the user's email. + This is specifically used in login_redirect. + + Returns a list of strings + """ + + # Retrieves the datafile. + datafile = pd.read_excel(getUserDatabasePath(), sheet_name="Sheet1") + + # Retrieves the index associated with the user's email. + index = datafile.loc[datafile["Email"] == email].index[0] + + # A list that will eventually store all of ther user's data. + user_data = [] + + # Iterates though ever list in the database. + for data_list in getUserDatabase(): + + # When integers are read, they're actually read as int64 types. + # This converts them to conventional ints. + try: + add_data = int(data_list[index]) + except ValueError: + add_data = data_list[index] + + # Adds the piece of data to user_data. + user_data.append(add_data) + + # Returns the user's data. + return user_data + + +def createUser(new_user_data): + """ + Creates a new users if the inputted email is unique. + + new_user_data is formatted: + [fname, + lname, + email, + password, + gender, + birth_day, + birth_month, + birth_year, + height, weight, + calorie_goal] + """ + + # Retrieves the inputted email. + email = new_user_data[2] + + # Only creates a new user if the email is not currently + # in the database. + if not checkEmail(email): + + # Adds the email and password to a dictionary. + password = new_user_data[3] dict_email_password[email] = password - # Create a Pandas dataframe from the data. - df = pd.DataFrame({'First Name': list_fname, 'Last Name': list_lname, - 'Email': list_email, 'Password': list_password}) + # A list that will eventually become the new database. + new_database = [] + + # Iterates through every column in the database. + for index, column in enumerate(getUserDatabase()): + + # Appends the new user data to the column. + column.append(new_user_data[index]) + + # Appends the column, now with the new user data added, to + # the new database. + new_database.append(column) + + # Writes the new database to user_database.xlsx + writeToUserDatabase(new_database) + +def writeNewUserData(old_email, new_user_data): + """ + Writes a set of new user data to user_database.xlsx. + """ + # Retrieves the datafile. + datafile = pd.read_excel(getUserDatabasePath(), sheet_name="Sheet1") + + # Retrieves the index associated with the user's previous email. + user_index = datafile.loc[datafile["Email"] == old_email].index[0] + + # A list that will eventually store the updated user batabase. + updated_database = [] + + # Iterates through every column in the database. + for data_index, column in enumerate(getUserDatabase()): + + # Replaces the value in the column at the given user's index + # with the new user data. + column[user_index] = new_user_data[data_index] + + # Adds the column to the updated database. + updated_database.append(column) + + # Writes the updated database to user_database.xlsx. + writeToUserDatabase(updated_database) + + +def getDatabase(database_path, columns): + """ + Returns a database given the path to the database file and a list + of the names of the columns + """ + # Create a Pandas dataframe from the excel file + df = pd.read_excel(database_path, sheet_name="Sheet1") + + # A list that will store all the values in the database. + # This will be the final output. + database = [] + + # Uses a for loop to iterate each column of the database. + for column_name in columns: + + # Retrieves the database column. + database_column = convert(df[column_name]) + + # Appends the column to the final output. + database.append(database_column) + + # Returns the final output. + return database + + +def getUserDatabase(): + """ + Returns the entire user database. + """ + user_data_columns = ("First Name", + "Last Name", + "Email", + "Password", + "Gender", + "Birth-day", + "Birth-month", + "Birth-year", + "Height", + "Weight", + "Calorie goal") + + return getDatabase(getUserDatabasePath(), user_data_columns) + + +def writeToUserDatabase(new_database): + """ + Takes a list of columns and writes the columns to user_database.xlsx + + This function is used in both createUser and writeNewUserData. + """ + + # A dictionary that will store the column names as keys + # and a list of data as values. + dataframe_dict = {} + + # Uses a for loop to interate through each column name + for column_index, column_name in enumerate(("First Name", + "Last Name", + "Email", + "Password", + "Gender", + "Birth-day", + "Birth-month", + "Birth-year", + "Height", + "Weight", + "Calorie goal")): + + # Assigns the column name to the list in the new database. + dataframe_dict[column_name] = new_database[column_index] + + # Creates a Pandas dataframe from the data. + df = pd.DataFrame(dataframe_dict) + # Create a Pandas Excel writer using XlsxWriter as the engine. - writer = pd.ExcelWriter('../database/database.xlsx', engine='xlsxwriter') + writer = pd.ExcelWriter(getUserDatabasePath(), engine="xlsxwriter") # Convert the dataframe to an XlsxWriter Excel object. df.to_excel(writer, sheet_name='Sheet1') # Close the Pandas Excel writer and output the Excel file. writer.save() + - return True - - -def refreshDatabase(): - # Create a Pandas dataframe from the excel file - df = pd.read_excel('../database/database.xlsx', sheet_name='Sheet1') - - # Save columns as list - list_fname = convert(df['First Name']) - list_lname = convert(df['Last Name']) - list_email = convert(df['Email']) - list_password = convert(df['Password']) +def getUserDatabasePath(): + """ + Returns the path of the user database depending on whether or not this + file is being run on reader.py or app.py. + """ + if __name__ == "__main__": + database_path = "../../database/user_database.xlsx" + else: + database_path = "../database/user_database.xlsx" + + return database_path + - # Create a dictionary (KEY email: VALUE password) for user information - dict_email_password = {} - for i in range(len(list_email)): - dict_email_password[list_email[i]] = list_password[i] +#======================================================================= -def getDatabase(): - list = [] - list.append(list_fname) - list.append(list_lname) - list.append(list_email) - list.append(list_password) - return(list) # Create a Pandas dataframe from the excel file -df = pd.read_excel('../database/database.xlsx', sheet_name='Sheet1') +df = pd.read_excel(getUserDatabasePath(), sheet_name="Sheet1") # Save columns as list -list_fname = convert(df['First Name']) -list_lname = convert(df['Last Name']) -list_email = convert(df['Email']) -list_password = convert(df['Password']) +list_fname = convert(df["First Name"]) +list_lname = convert(df["Last Name"]) +list_email = convert(df["Email"]) +list_password = convert(df["Password"]) +list_gender = convert(df["Gender"]) +list_birth_day = convert(df["Birth-day"]) +list_birth_month = convert(df["Birth-month"]) +list_birth_year = convert(df["Birth-year"]) +list_height = convert(df["Height"]) +list_weight = convert(df["Weight"]) +list_calorie_goal = convert(df["Calorie goal"]) # Create a dictionary (KEY email: VALUE password) for user information dict_email_password = {} for i in range(len(list_email)): - dict_email_password[list_email[i]] = list_password[i] - - -if __name__ == '__main__': - print() - - print("BEFORE:", list_email) + dict_email_password[list_email[i]] = list_password[i] - fname = 'Jasmine' - lname = 'Mai' - email = 'jasmine@gmail.com' - password = 'Cat2' - print("USER CREATED:", userCreation(fname, lname, email, password)) - print("AFTER:", list_email) +if __name__ == "__main__": - print("DONE") + fname = "John" + lname = "Doe" + email = "john.doe@gmail.com" + password = "testing" + gender = "Female" + birth_day = 1 + birth_month = 12 + birth_year = 1998 + height = 70 + + print(getUserData("jasmine@gmail.com")) + diff --git a/project/static/CalPal_Let's_get_to_know_you!.png b/project/static/CalPal_Let's_get_to_know_you!.png new file mode 100644 index 0000000..602812b Binary files /dev/null and b/project/static/CalPal_Let's_get_to_know_you!.png differ diff --git a/project/static/CalPal_User_info.png b/project/static/CalPal_User_info.png new file mode 100644 index 0000000..b66d94c Binary files /dev/null and b/project/static/CalPal_User_info.png differ diff --git a/project/static/CalPal_logo_opaque.png b/project/static/CalPal_logo_opaque.png new file mode 100644 index 0000000..ece5ca9 Binary files /dev/null and b/project/static/CalPal_logo_opaque.png differ diff --git a/project/static/dashboard.css b/project/static/dashboard.css new file mode 100644 index 0000000..d4052f5 --- /dev/null +++ b/project/static/dashboard.css @@ -0,0 +1,111 @@ + +/* + * CalPal: A calorie tracking app. + * Written by Nhat Nguyen and Albert Ong. + * CMPE 131 + * Revision: 02.12.2018 + * + * dashboard.css + * A stylesheet used specifically for dashboard.html +*/ + + +.dashboard { + margin-bottom: 150px; +} + +input[type='number'] { + -moz-appearance:textfield; +} + +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; +} + +#rectangle-box { + max-height: 200px; + overflow-y: scroll; + overflow-x: hidden; +} + +#rectangle { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0px 8% 0px 8%; + margin-bottom: 5px; + background: #ff882b; + width: 350px; + height: 40px; +} + +#rectangle p, #rectangle-e p { + color:white; + font-weight: bolder; +} + +#rectangle span { + color: red; + cursor: pointer; + position: relative; + right: 15px; + /* padding: 0px 8% 0px 0px; */ +} + +.form-container-dashboard { + margin-top: 4%; + border-radius: 5px; + background-color: #fba56730; + padding: 2.5% 0% 2.5% 0%; + text-align: center; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 1000px; +} + +#sidebyside { + display: flex; + position: relative; + right: 40px; +} + +#food, #exercise { + margin:20px; +} + +.dashboard-btn { + width:150px !important; +} + +.form-container-dashboard h1 { + font-size: 32px; + font-weight: 700; + margin: 10px 0px 10px 0px; +} + +.form-container-dashboard h2 { + font-size: 20px; + font-style: italic; + margin-bottom: 2px; +} + +.form-container-dashboard .success { + background-color: #ff882b; + border-radius: 2px; + color: white; + height: 40px; + font-size: 18px; + margin: auto; + text-align: center; + width: 50%; +} + +.form-container-dashboard .messages { + margin-top: 2em;; +} + +.form-container-dashboard .success p { + padding-top: 0.5em; +} + diff --git a/project/static/favicon.png b/project/static/favicon.png index aff3cbd..7d54be0 100644 Binary files a/project/static/favicon.png and b/project/static/favicon.png differ diff --git a/project/static/fitler.js b/project/static/fitler.js new file mode 100644 index 0000000..7b0f786 --- /dev/null +++ b/project/static/fitler.js @@ -0,0 +1,41 @@ +function filterF() { + var input, filter, ul, li, a, i; + input = document.getElementById('myFood'); + filter = input.value.toUpperCase(); + div = document.getElementById('myDropdownF'); + a = div.getElementsByTagName('a'); + for (i = 0; i < a.length; i++) { + if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) { + a[i].style.display = ''; + } else { + a[i].style.display = 'none'; + } + } +} + +function filterE() { + var input, filter, ul, li, a, i; + input = document.getElementById('myExercise'); + filter = input.value.toUpperCase(); + div = document.getElementById('myDropdown'); + a = div.getElementsByTagName('a'); + for (i = 0; i < a.length; i++) { + if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) { + a[i].style.display = ''; + } else { + a[i].style.display = 'none'; + } + } +} + +function filterFood(name) { + var input = document.getElementById('myFood'); + input.value = name; + filterF(); +} + +function filterExercise(name) { + var input = document.getElementById('myExercise'); + input.value = name; + filterE(); +} diff --git a/project/static/master.css b/project/static/master.css index 09cf3e5..8254c2a 100644 --- a/project/static/master.css +++ b/project/static/master.css @@ -1,3 +1,16 @@ +/* + * CalPal: A calorie tracking app. + * Written by Nhat Nguyen and Albert Ong. + * CMPE 131 + * Revision: 02.12.2018 + * + * master.css + * The master stylesheet. Used in base.html +*/ + +@import 'reset.css'; +@import 'dashboard.css'; + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -11,216 +24,385 @@ article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} - -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; + border: 0; + color: #ffef9f; + font: inherit; + font-size: 100%; + margin: 0; + padding: 0; + vertical-align: baseline; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; } body { - line-height: 1; + color: #ffef9f; + font-family: sans-serif; + height: 100%; + margin: 0px; + background-image: linear-gradient(to right, #b02635, #f97c21); + background-attachment: fixed; } -ol, ul { - list-style: none; +ol, +ul { + list-style: none; } -blockquote, q { - quotes: none; +blockquote, +q { + quotes: none; } -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; } table { - border-collapse: collapse; - border-spacing: 0; -} - -.main, .form-container .center, .form-container .success, .form-container .failure { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -html, body, form { - height: 100%; - width: 100%; + border-collapse: collapse; + border-spacing: 0; } -html, body { - min-height: 100%; - background-color: #f8f8f8; - background-attachment: fixed; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +.main, +.form-container .center, +.form-container .success, +.form-container .failure { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +html, +body, +form { + height: 100%; + width: 100%; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', + 'Helvetica Neue', sans-serif; } .main { - min-height: inherit; - -webkit-box-sizing: border-box; - box-sizing: border-box; - width: inherit; + min-height: inherit; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: inherit; } .form-wrapper { - margin: 0 auto; - height: 100%; - width: 70%; + margin: 0 auto; + height: 100%; + width: 80%; } .form-container { - border-radius: 5px; - -webkit-box-shadow: 0px 0px 50px 0px #e6e6e6; - box-shadow: 0px 0px 50px 0px #e6e6e6; - background-color: white; - -webkit-box-sizing: border-box; - box-sizing: border-box; - width: 580px; - text-align: center; - padding: 4% 0% 4% 0%; + margin-top: 4%; + border-radius: 5px; + background-color: #fba56730; + padding: 2.5% 0% 2.5% 0%; + text-align: center; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 580px; } .form-container h1 { - font-size: 32px; - font-weight: 700; - margin: 0px 0px 10px 0px; + font-size: 32px; + font-weight: 700; + margin: 0px 0px 10px 0px; } .form-container h2 { - font-style: italic; - font-size: 18px; - margin-bottom: 25px; + font-style: italic; + font-size: 18px; + margin-bottom: 25px; } .form-container .form-header p { - margin-bottom: 15px; - color: #646f79; - font-size: 14px; + color: #ffef9f; + font-size: 14px; + margin-bottom: 15px; } .form-container a { - text-decoration: none; - color: black; - -webkit-transition: 0.25s; - transition: 0.25s; + text-decoration: none; + color: black; + -webkit-transition: 0.25s; + transition: 0.25s; } .form-container p a { - color: #14aaf5; + border-radius: 3px; + color: #ffef9f; + font-weight: Bold; } .form-container a:hover { - color: #098ccd; + color: #f97c21; } .form-container b { - font-weight: bolder; + font-weight: bolder; } +/* Styles the success message in the form container. */ .form-container .success { - height: 40px; - margin: 15px 0px 10px 0px; - border-radius: 2px; - color: #4bc04e; - background-color: #ecffec; + background-color: #ff882b; + border-radius: 2px; + color: white; + height: 40px; + margin: 15px 0px 10px 0px; } +/* Styles the failure message in the form container. */ .form-container .failure { - height: 40px; - margin: 15px 0px 10px 0px; - border-radius: 2px; - background-color: #ffedef; -} - -form input[type="text"], form input[type="email"], form input[type="password"], form button[type="submit"] { - margin-bottom: 10px; - padding-left: 4px; - border: 1px solid #f0f0f0; - -webkit-box-sizing: border-box; - box-sizing: border-box; - width: 100%; - height: 40px; - border-radius: 3px; - outline: none; - -webkit-transition: 0.25s; - transition: 0.25s; + background-color: #ff882b; + border-radius: 2px; + color: white; + height: 40px; + margin: 15px 0px 10px 0px; +} + +/* Styles various input tags inside the form tag. */ +form button[type="submit"], +form input[type="email"], +form input[type="number"], +form input[type="password"], +form input[type="text"], +form datalist, +form input, +form select, +form select[type="gender"] { + background-color: white; + border: 1px solid #f0f0f0; + border-radius: 3px; + clear: left; + height: 40px; + margin-bottom: 10px; + outline: none; + padding-left: 4px; + transition: 0.25s; + -webkit-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: 0.25s; + width: 100%; } -form input[type="text"]:hover, form input[type="email"]:hover, form input[type="password"]:hover { - padding-left: 10px; +form input[type="text"]:hover, +form input[type="email"]:hover, +form input[type="password"]:hover { + padding-left: 10px; } -form input[type="text"]:focus, form input[type="email"]:focus, form input[type="password"]:focus { - border-color: #098ccd; +form input[type="text"]:focus, +form input[type="email"]:focus, +form input[type="password"]:focus { + border-color: #f76c00; } form input::-webkit-input-placeholder { - color: #d9d9d9; - padding-left: 2px; + color: #d9d9d9; + padding-left: 2px; } form input:-ms-input-placeholder { - color: #d9d9d9; - padding-left: 2px; + color: #d9d9d9; + padding-left: 2px; } form input::-ms-input-placeholder { - color: #d9d9d9; - padding-left: 2px; + color: #d9d9d9; + padding-left: 2px; } form input::placeholder { - color: #d9d9d9; - padding-left: 2px; + color: #d9d9d9; + padding-left: 2px; } +/* Styles the sumbit buttons inside the form tag. */ form button[type="submit"] { - margin: 20px 0px 40px 0px; - background-color: #14aaf5; - border-radius: 3px; - border: none; - color: white; - font-weight: bolder; - cursor: pointer; + margin: 20px 0px 40px 0px; + background-color: #ff882b; + border-radius: 3px; + border: none; + color: white; + font-weight: bolder; + font-size: 1.15em; + cursor: pointer; } form button[type="submit"]:hover { - background-color: #098ccd; + background-color: #f76c00; } form button[type="submit"]:focus { - background-color: #087bb5; - padding-top: 5px; + background-color: #ffef9f; + padding-top: 5px; } +/* Styles the input labels within the form tag. */ form .input-label { - padding: 10px 0px 25px 0px; + padding: 10px 0px 25px 0px; +} + +/* Styles the height input labels within the form tag. */ +form .height-input-label { + padding: 10px 40px 25px 0px; } +/* Styles the weight and calorie goal input labels within the form tag. */ +form .weight-calorie-input-label { + padding: 10px 140px 25px 0px; +} + +/* Styles all the labels within the form tag. */ form label { - color: #646f79; - display: block; - float: left; + color: #ffef9f; + float: left; } form span { - float: right; - color: #FF5555; + float: right; + color: #ffef9f; +} + +form .divider { + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +/* Controls the width of divided input fields. */ +form .divider-size { + width: 45%; +} + +/* Controls the width of the birthday input fields. */ +form .birthday-size { + width: 30%; +} + +/* Controls the styling of the CalPal logo. */ +.CalPal-logo { + margin: 0% 0% 3% 0%; +} + +/* A shortened width used for the weight abd calorie goal inputs. */ +form .shortened-width { + width: 70%; +} + +/* Styles the text that goes to the right of input tags. */ +form .input-details-text { + margin: 8px 0px 0px 6px; +} + +form .height-input-width { + width: 80%; +} + +/* STUFF */ +.dropbtn { + background-color: #4caf50; + color: white; + padding: 16px; + font-size: 16px; + border: none; + cursor: pointer; +} + +.dropbtn:hover, +.dropbtn:focus { + background-color: #3e8e41; +} + +#myDropdownF, #myDropdown { + max-height: 200px; + width: 100%; + overflow-x: hidden; +} + +#myInput { + background-image: url('https://www.w3schools.com/css/searchicon.png'); + box-sizing: border-box; + background-position: 14px 12px; + background-repeat: no-repeat; + font-size: 16px; + padding: 14px 20px 12px 45px; + border: none; + border-bottom: 1px solid #ddd; + width: 400px; +} + +#ounce, #minute { + box-sizing: border-box; + font-size: 16px; + padding: 14px 20px 12px 20px; + border: none; + border-bottom: 1px solid #ddd; + width: 400px; +} + +.dropdown p { + margin: 10px 0px 5px 0px; +} + +#myInput:focus { + outline: 1px solid #ddd; +} + +.dropdown { + position: relative; + display: inline-block; + flex-direction: column; +} + +.dropdown-content { + background-color: #f6f6f6; + min-width: 230px; + overflow: auto; + border: 1px solid #ddd; + z-index: 1; +} + +.dropdown-content a { + color: black; + padding: 12px 16px; + text-decoration: none; + display: block; +} + +.dropdown a:hover { + background-color: #ddd; +} + +.show { + display: block; } -/*# sourceMappingURL=master.css.map */ \ No newline at end of file diff --git a/project/static/reset.css b/project/static/reset.css index d81f451..165b900 100644 --- a/project/static/reset.css +++ b/project/static/reset.css @@ -1,3 +1,9 @@ +* { + box-sizing: border-box; + border-style: dotted; + border-width: 1px; +} + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -45,5 +51,4 @@ q:before, q:after { table { border-collapse: collapse; border-spacing: 0; -} -/*# sourceMappingURL=reset.css.map */ \ No newline at end of file +} \ No newline at end of file diff --git a/project/templates/app.html b/project/templates/app.html deleted file mode 100644 index f437568..0000000 --- a/project/templates/app.html +++ /dev/null @@ -1,38 +0,0 @@ - -{% extends "base.html" %} -{% block content %} - -
Login successful!
-User Information
- -Hi, {{ fname }} {{ lname }}!
-Email: {{ email }}
-Password: {{ "*" * password|length }}
-Password: {{ password }}
- -