Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
78 changes: 17 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,26 @@
# Getting Started with Create React App
## Programming challenge 2023
---
## Topic
This project is about building a user-friendly virtual-assistant application to help senior citizens easily enter their groceries into a shopping list. The main functions implemented in this project including:
- Application lets user “log in” by entering their name
- Application shows a shopping list for the user
- Application provides a way to add one or more items to their shopping list through textual entry and through narration
- Application should match items added by user to an item database
- Application allows users to print or share their list

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## How to run the code

## Available Scripts
- The list of the top-level dependencies I mainly used in this project could be seen in the "requirements.txt" file. I have also created a venv environment in backend folder with all the dependecies needed for flask. Since the node_modules which contains all the external libraries and dependencies of ReactJs is too large, I did not commit it to GitHub.

In the project directory, you can run:
- In this project, I applied ReactJS for front end and Flask for simulating backend API. The database I used to store data is MySQL. Before running the code, please change the MySQL link inside App.py to your username and password.

### `npm start`

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
- The database schema is designed in initial_db.py under backend folder and the data inserted into the database is designed in add_data.py folder. Before run the code, you need to first run "create database shoplistapp" command in MySQL and then run "initial_db.py" and "add_data.py".

The page will reload when you make changes.\
You may also see any lint errors in the console.

### `npm test`
- The ReactJS is running on port 3000 and the Flask is running on port 8000. To run the code, run "yarn start" or "npm start" under the repository and run python3 App.py under the backend folder.

Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.

### `npm run build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.

### `npm run eject`

**Note: this is a one-way operation. Once you `eject`, you can't go back!**

If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.

You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.

## Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).

### Code Splitting

This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)

### Analyzing the Bundle Size

This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)

### Making a Progressive Web App

This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)

### Advanced Configuration

This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)

### Deployment

This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)

### `npm run build` fails to minify

This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
## Implementation
- I have recorded a video which showing all the functions implemented in this project for your reference.
Here is the Google Drive link of the video: https://drive.google.com/file/d/1ntrTR0dRLRxm-a1Hnqu0RjAD0Rju924E/view?usp=sharing
167 changes: 167 additions & 0 deletions backend/App.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
from flask import Flask, request, jsonify, make_response, session, redirect, url_for, render_template
from flask_bcrypt import Bcrypt
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS, cross_origin
from initial_db import db, user, item, user_item
import secrets
from flask_session import Session
import redis
from flask_login import login_required

app = Flask(__name__)
app.config['SECRET_KEY'] = secrets.token_hex(16)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:55af5587f@localhost/shoplistapp'
app.config['SESSION_TYPE'] = "redis"
app.config['SESSION_PERMANENT'] = False
app.config['SESSION_USER_SIGNER'] = True
app.config['SESSION_REDIS'] = redis.from_url("redis://127.0.0.1:6379")
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_EHCO'] = True

bcrypt = Bcrypt(app)
CORS(app, supports_credentials=True)
server_session = Session(app)
db.init_app(app)

with app.app_context():
db.create_all()


@app.route("/")
def first_page():
return "Hello world"


@app.route("/signup", methods=["POST"])
def signup():
username = request.json["username"]
password = request.json["password"]
email = request.json["email"]

user_exists = user.query.filter_by(username = username).first() is not None

if user_exists:
return jsonify({"error": "username already exists"}), 409

hashed_password = bcrypt.generate_password_hash(password)
new_user = user(username = username, password=hashed_password, email = email)
db.session.add(new_user)
db.session.commit()

session["userid"] = new_user.userid

return jsonify({
"userid": new_user.userid,
"username": new_user.username,
"email": new_user.email
})



@app.route("/login", methods=['POST'])
def login():
username = request.json["username"]
password = request.json["password"]

user_name = user.query.filter_by(username=username).first()

if user_name is None:
return jsonify({"error": "username or password incorrect"}), 401

if not bcrypt.check_password_hash(user_name.password, password):
return jsonify({"error": "username or password incorrect"}), 401

session["userid"] = user_name.userid

return jsonify({
"userid": user_name.userid,
"username": user_name.username,
"email": user_name.email
})

@app.route("/logout", methods=["POST"])
def logout_user():
session.pop("userid")
return "200"

@app.route("/me", methods=['GET'])
def get_current_user():
user_id = session.get("userid")
if not user_id:
return jsonify({"error": "Unauthorized"}), 401
user_me = user.query.filter_by(userid = user_id).first()

return jsonify({
"userid": user_me.userid,
"email": user_me.email,
"username": user_me.username
})


@app.route("/mecart", methods=['GET'])
def mecart():
user_id = session.get("userid")
if user_id is None:
return jsonify({"error": "Unauthorized"}), 401

cart_item = (
item.query
.join(user_item, item.itemid == user_item.comitemid)
.filter(user_item.comuserid == user_id)
.all()
)
user_cart = []
for items in cart_item:
info = {
"itemid": items.itemid,
"itemname": items.itemname,
"price": items.price,
"imagepath": items.imagepath,
"description": items.description,
"stock": items.stock,
"alternative": items.alternative,
"store_email": items.store_email
}
user_cart.append(info)
return jsonify({"cart_items": user_cart}), 200


@app.route("/addcart", methods=['POST'])
def addcart():
data = request.json
item_id = data.get("itemid")

user_id = session.get("userid")
if user_id is None:
return jsonify({"error": "Unauthorized"}), 401

useritem = user_item(comuserid=user_id, comitemid=item_id)
db.session.add(useritem)
db.session.commit()

return jsonify({"message": "Item added to cart successfully"})


@app.route("/showitems", methods=['GET'])
def showitems():
show_items = item.query.all()

item_list = []
for show_item in show_items:
item_info = {
"itemid": show_item.itemid,
"itemname": show_item.itemname,
"price": show_item.price,
"imagepath": show_item.imagepath,
"description": show_item.description,
"stock": show_item.stock,
"alternative": show_item.alternative,
"store_email": show_item.store_email
}
item_list.append(item_info)

return jsonify({"show_items": item_list})


if __name__ == '__main__':
app.run(port=8000,debug=True)
Binary file added backend/__pycache__/initial_db.cpython-38.pyc
Binary file not shown.
39 changes: 39 additions & 0 deletions backend/add_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from initial_db import user, item, user_item

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:55af5587f@localhost/shoplistapp'
db = SQLAlchemy(app)
db.init_app(app)

import bcrypt

if __name__ == '__main__':
# Insert data into the User table

password_user1 = "123".encode("utf-8")
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password_user1, salt)
new_user_1 = user(userid = 1, username = "Eva", password = hashed_password, email = "eva@usc.edu")
new_item_1 = item(itemid = 1, itemname = "chips", price = 2.99, imagepath = "/itemimage/chips.png", description = "Chips in orignal flavor", stock = True, alternative = "cookies, popcorn", store_email = "hmart@gamil.com")
new_item_2 = item(itemid = 2, itemname = "cookies", price = 1.99, imagepath = "/itemimage/cookies.png", stock = True, alternative = "chips, popcorn", store_email = "hmart@gamil.com")
new_item_3 = item(itemid = 3, itemname = "popcorn", price = 5.99, imagepath = "/itemimage/popcorn.png", description = "spicy popcorn", stock = False, alternative = "cookies, chips", store_email = "hmart@gamil.com")
new_item_4 = item(itemid = 4, itemname = "coke", price = 0.99, imagepath = "/itemimage/coke.png", description = "200ml", stock = True, alternative = "lemonade", store_email = "hmart@gamil.com")
new_item_5 = item(itemid = 5, itemname = "lemonade", price = 1.50, imagepath = "/itemimage/lemonade.png", description = "500ml", stock = False, alternative = "coke", store_email = "target@gamil.com")
new_item_6 = item(itemid = 6, itemname = "laundry_detergent", price = 12.99, imagepath = "../item_image/laundry.png", description = "1000ml", stock = True, store_email = "target@gamil.com")
new_user_item_1 = user_item(comuserid = 1, comitemid = 2)
new_user_item_2 = user_item(comuserid = 1, comitemid = 6)

db.session.add(new_user_1)
db.session.add(new_item_1)
db.session.add(new_item_2)
db.session.add(new_item_3)
db.session.add(new_item_4)
db.session.add(new_item_5)
db.session.add(new_item_6)
db.session.add(new_user_item_1)
db.session.add(new_user_item_2)

db.session.commit()

35 changes: 35 additions & 0 deletions backend/initial_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:55af5587f@localhost/shoplistapp'
db = SQLAlchemy(app)

class user(db.Model, UserMixin):
userid = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(345), unique=True)
password = db.Column(db.String(80), nullable=False)

class item(db.Model):
itemid = db.Column(db.Integer, primary_key=True)
itemname = db.Column(db.String(255), nullable=False)
price = db.Column(db.Float, nullable=False)
imagepath = db.Column(db.String(255))
description = db.Column(db.String(255))
stock = db.Column(db.Boolean, nullable=False)
alternative = db.Column(db.String(255))
store_email = db.Column(db.String(255), nullable=False)

class user_item(db.Model):
comid = db.Column(db.Integer, primary_key=True)
comuserid = db.Column(db.Integer, db.ForeignKey('user.userid'))
comitemid = db.Column(db.Integer, db.ForeignKey('item.itemid'))

forw_user_id = db.relationship('user', foreign_keys=[comuserid], backref='back_user_id')
forw_item_id = db.relationship('item', foreign_keys=[comitemid], backref='back_item_id')


with app.app_context():
db.create_all()
Loading