├── .gitignore ├── database.db ├── static ├── images │ ├── logo.png │ └── shoppingCart.png ├── uploads │ ├── storediagram.gif │ ├── WWW.YIFY-TORRENTS.COM.jpg │ ├── Untitled_by_Aaron_Burden.jpg │ ├── Untitled_by_Troy_Jarrell.jpg │ ├── Untitled_0026_by_Mike_Sinko.jpg │ ├── Untitled_7019_by_Mike_Sinko.jpg │ ├── Yellow_Jacket_by_Manuel_Frei.png │ ├── Kinkaku_Ji_by_Elizabeth_K_Joseph.jpg │ ├── Mountainous_View_by_Sven_Scheuermeier.jpg │ ├── The_Sky_Is_The_Limit_by_Kaushik_Panchal.jpg │ └── 17068-purple-planet-1366x768-fantasy-wallpaper.png ├── css │ ├── remove.css │ ├── home.css │ ├── productDescription.css │ ├── cart.css │ └── topStyle.css └── js │ ├── changePassword.js │ └── validateForm.js ├── Pipfile ├── templates ├── login.html ├── remove.html ├── add.html ├── changePassword.html ├── register.html ├── profileHome.html ├── cart.html ├── displayCategory.html ├── productDescription.html ├── home.html └── editProfile.html ├── README.md ├── database.py ├── LICENSE ├── Pipfile.lock └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | query.py 2 | -------------------------------------------------------------------------------- /database.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/database.db -------------------------------------------------------------------------------- /static/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/images/logo.png -------------------------------------------------------------------------------- /static/images/shoppingCart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/images/shoppingCart.png -------------------------------------------------------------------------------- /static/uploads/storediagram.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/storediagram.gif -------------------------------------------------------------------------------- /static/css/remove.css: -------------------------------------------------------------------------------- 1 | table { 2 | border-width: 10px; 3 | } 4 | 5 | #itemImage { 6 | height: 100px; 7 | width: 80px; 8 | } 9 | -------------------------------------------------------------------------------- /static/uploads/WWW.YIFY-TORRENTS.COM.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/WWW.YIFY-TORRENTS.COM.jpg -------------------------------------------------------------------------------- /static/uploads/Untitled_by_Aaron_Burden.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/Untitled_by_Aaron_Burden.jpg -------------------------------------------------------------------------------- /static/uploads/Untitled_by_Troy_Jarrell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/Untitled_by_Troy_Jarrell.jpg -------------------------------------------------------------------------------- /static/uploads/Untitled_0026_by_Mike_Sinko.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/Untitled_0026_by_Mike_Sinko.jpg -------------------------------------------------------------------------------- /static/uploads/Untitled_7019_by_Mike_Sinko.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/Untitled_7019_by_Mike_Sinko.jpg -------------------------------------------------------------------------------- /static/uploads/Yellow_Jacket_by_Manuel_Frei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/Yellow_Jacket_by_Manuel_Frei.png -------------------------------------------------------------------------------- /static/uploads/Kinkaku_Ji_by_Elizabeth_K_Joseph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/Kinkaku_Ji_by_Elizabeth_K_Joseph.jpg -------------------------------------------------------------------------------- /static/uploads/Mountainous_View_by_Sven_Scheuermeier.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/Mountainous_View_by_Sven_Scheuermeier.jpg -------------------------------------------------------------------------------- /static/uploads/The_Sky_Is_The_Limit_by_Kaushik_Panchal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/The_Sky_Is_The_Limit_by_Kaushik_Panchal.jpg -------------------------------------------------------------------------------- /static/uploads/17068-purple-planet-1366x768-fantasy-wallpaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshShah1997/Shopping-Cart/HEAD/static/uploads/17068-purple-planet-1366x768-fantasy-wallpaper.png -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | flask = "*" 8 | pysqlite3 = "*" 9 | 10 | [dev-packages] 11 | 12 | [requires] 13 | python_version = "3.8" 14 | -------------------------------------------------------------------------------- /static/js/changePassword.js: -------------------------------------------------------------------------------- 1 | function validate() { 2 | var pass = document.getElementById("newpassword").value; 3 | var cpass = document.getElementById("cpassword").value; 4 | if (pass == cpass) { 5 | return true; 6 | } else { 7 | alert("Passwords do not match!"); 8 | return false; 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /static/js/validateForm.js: -------------------------------------------------------------------------------- 1 | function validate() { 2 | var pass = document.getElementById("password").value; 3 | var cpass = document.getElementById("cpassword").value; 4 | if (pass == cpass) { 5 | return true; 6 | } else { 7 | alert("Passwords do not match"); 8 | return false; 9 | } 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | First flask app 4 | 5 | 6 |

{{error}}

7 |
8 |

Email:

9 |

Password:

10 |

11 | Register here 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /static/css/home.css: -------------------------------------------------------------------------------- 1 | 2 | #itemImage { 3 | height: 200px; 4 | width: 150px; 5 | } 6 | 7 | .display { 8 | margin-top: 20px; 9 | margin-left: 20px; 10 | margin-right: 20px; 11 | margin-bottom: 20px; 12 | } 13 | 14 | table { 15 | border-spacing: 20px; 16 | } 17 | 18 | #productName { 19 | text-align: center; 20 | font-weight: bold; 21 | } 22 | 23 | #productPrice { 24 | text-align: center; 25 | } 26 | 27 | .displayCategory ul li { 28 | font-size: 20px; 29 | } 30 | -------------------------------------------------------------------------------- /templates/remove.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Remove 5 | 6 | 7 | 8 | 9 | 10 | {% for i in range(6) %} 11 | 12 | {% for row in data %} 13 | 22 | {% endfor %} 23 | 24 | {% endfor %} 25 |
14 | 15 | {% if i == 4 %} 16 | 17 | {% else %} 18 | {{row[i]}} 19 | {% endif %} 20 | 21 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /static/css/productDescription.css: -------------------------------------------------------------------------------- 1 | #display { 2 | margin-top: 20px; 3 | margin-left: 20px; 4 | margin-right: 20px; 5 | margin-bottom: 20px; 6 | } 7 | 8 | #productImage { 9 | height: 250px; 10 | width: 200px; 11 | margin-left: 20px; 12 | margin-right: 20px; 13 | margin-top: 20px; 14 | margin-bottom: 20px; 15 | display: inline-block; 16 | float: left; 17 | } 18 | 19 | #productDescription { 20 | margin-left: 20px; 21 | margin-right: 20px; 22 | margin-top: 20px; 23 | margin-bottom: 20px; 24 | display: inline-block; 25 | font-size: 19px; 26 | } 27 | 28 | #descriptionTable td { 29 | width: 150px; 30 | } 31 | 32 | #addToCart { 33 | font-size: 20px; 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /templates/add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Admin 5 | 6 | 7 |

Add items

8 |
9 | Name:
10 | Price:
11 | Description:
12 | Image:
13 | Stock:
14 | Category:
19 | 20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /templates/changePassword.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Change Password 4 | 5 | 6 | 7 |

Change password

8 |

{{ msg }}

9 |
10 |

Old Password:

11 |

New Password:

12 |

Confirm Password:

13 | 14 |
15 | Go to Profile 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shopping Cart 2 | A simple E-commerce website using Flask. 3 | 4 | ## Dependencies ## 5 | 1. Python3 6 | 2. Flask 7 | 3. Sqlite 8 | 9 | ## How to run ## 10 | 1. Set up database by running database.py (Or you can reuse existing database included in the repo) 11 | 2. Run main.py 12 | 3. Enter localhost:5000 in the browser 13 | 14 | ## Pipenv instructions ## 15 | 1. Install pipenv (python3 -m pip install --user pipenv) 16 | 2. Install dependencies (pipenv install --dev) 17 | 3. Setup database (pipenv run python database.py) 18 | 4. Run the server (pipenv run python main.py) 19 | 5. Enter localhost:5000 in the browser 20 | 21 | ## Sample User ## 22 | Sample credentials present in existing database: 23 | Username - sample@example.com 24 | Password - sample 25 | 26 | -------------------------------------------------------------------------------- /database.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | #Open database 4 | conn = sqlite3.connect('database.db') 5 | 6 | #Create table 7 | conn.execute('''CREATE TABLE users 8 | (userId INTEGER PRIMARY KEY, 9 | password TEXT, 10 | email TEXT, 11 | firstName TEXT, 12 | lastName TEXT, 13 | address1 TEXT, 14 | address2 TEXT, 15 | zipcode TEXT, 16 | city TEXT, 17 | state TEXT, 18 | country TEXT, 19 | phone TEXT 20 | )''') 21 | 22 | conn.execute('''CREATE TABLE products 23 | (productId INTEGER PRIMARY KEY, 24 | name TEXT, 25 | price REAL, 26 | description TEXT, 27 | image TEXT, 28 | stock INTEGER, 29 | categoryId INTEGER, 30 | FOREIGN KEY(categoryId) REFERENCES categories(categoryId) 31 | )''') 32 | 33 | conn.execute('''CREATE TABLE kart 34 | (userId INTEGER, 35 | productId INTEGER, 36 | FOREIGN KEY(userId) REFERENCES users(userId), 37 | FOREIGN KEY(productId) REFERENCES products(productId) 38 | )''') 39 | 40 | conn.execute('''CREATE TABLE categories 41 | (categoryId INTEGER PRIMARY KEY, 42 | name TEXT 43 | )''') 44 | 45 | 46 | 47 | conn.close() 48 | 49 | -------------------------------------------------------------------------------- /static/css/cart.css: -------------------------------------------------------------------------------- 1 | #tableItems { 2 | margin-left: 20px; 3 | margin-right: 20px; 4 | margin-top: 20px; 5 | margin-bottom: 20px; 6 | } 7 | 8 | #itemImage { 9 | margin-left: 5px; 10 | margin-right: 5px; 11 | margin-top: 5px; 12 | margin-bottom: 5px; 13 | height: 100px; 14 | float: left; 15 | } 16 | 17 | #itemName { 18 | margin-left: 5px; 19 | margin-right: 5px; 20 | margin-top: 5px; 21 | margin-bottom: 5px; 22 | height: 100px; 23 | width: 200px; 24 | float: left; 25 | } 26 | 27 | #titleName { 28 | width: 200px; 29 | float: left; 30 | } 31 | 32 | #titlePrice { 33 | float: left; 34 | } 35 | 36 | #itemPrice { 37 | margin-left: 5px; 38 | margin-right: 5px; 39 | margin-top: 5px; 40 | margin-bottom: 5px; 41 | height: 100px; 42 | display: inline-block; 43 | } 44 | 45 | #image { 46 | height: 100px; 47 | width: 80px; 48 | } 49 | 50 | #seperator { 51 | margin: 0px; 52 | max-width: 400px; 53 | } 54 | 55 | #total { 56 | padding-left: 280px; 57 | } 58 | 59 | #itemNameTag { 60 | font-weight: bold; 61 | } 62 | 63 | #subtotal { 64 | font-weight: bold; 65 | font-size: 20px; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Harsh Shah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /templates/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Registration 4 | 6 | 7 | 8 |
9 |

Email:

10 | 11 |

Password:

12 | 13 |

Confirm Password:

14 | 15 |

First Name:

16 |

Last Name:

17 |

Address Line 1:

18 |

Address Line 2:

19 |

Zipcode:

20 |

City:

21 |

State:

22 |

Country:

23 |

Phone Number:

24 | 25 |

26 | 27 | Login here 28 |
29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /templates/profileHome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Profile Home 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | {% if not loggedIn %} 19 |
20 | Sign In 21 |
22 | {% else %} 23 | 32 | {% endif %} 33 |
34 | 35 | 36 | CART {{noOfItems}} 37 | 38 |
39 |
40 | 41 |
42 | View Profile
43 | Edit Profile
44 | Change password 45 |
46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /static/css/topStyle.css: -------------------------------------------------------------------------------- 1 | #logo { 2 | height: 40px; 3 | width: 50px; 4 | margin-left: 20px; 5 | margin-top: 10px; 6 | margin-bottom: 10px; 7 | margin-right: 20px; 8 | float: left; 9 | } 10 | 11 | #title { 12 | background-color: black; 13 | display: inline-block; 14 | width: 100%; 15 | } 16 | 17 | #searchBox { 18 | height: 20px; 19 | width: 800px; 20 | margin-left: 20px; 21 | margin-top: 20px; 22 | margin-bottom: 20px; 23 | margin-right: 20px; 24 | float: left; 25 | font-size: 1.5em; 26 | } 27 | 28 | #searchButton { 29 | height: 25px; 30 | margin-top: 20px; 31 | margin-bottom: 20px; 32 | margin-right: 20px; 33 | float: left; 34 | } 35 | 36 | .dropbtn { 37 | background-color: black; 38 | color: white; 39 | padding: 16px; 40 | font-size: 15px; 41 | border: none; 42 | cursor: pointer; 43 | } 44 | 45 | .dropdown { 46 | position: relative; 47 | float: left; 48 | } 49 | 50 | .dropdown-content { 51 | display: none; 52 | position: absolute; 53 | background-color: #f9f9f9; 54 | min-width: 160px; 55 | box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); 56 | } 57 | 58 | .dropdown-content a { 59 | font-size: 14px; 60 | color: black; 61 | padding: 12px 16px; 62 | text-decoration: none; 63 | display: block; 64 | } 65 | 66 | .dropdown-content a:hover {background-color: #f1f1f1} 67 | 68 | .dropdown:hover .dropdown-content { 69 | display: block; 70 | } 71 | 72 | .dropdown:hover .dropbtn { 73 | background-color: gray; 74 | } 75 | 76 | #signInButton { 77 | color: yellow; 78 | margin-top: 20px; 79 | margin-bottom: 20px; 80 | margin-left: 20px; 81 | margin-right: 20px; 82 | float: left; 83 | } 84 | #kart { 85 | color: white; 86 | margin-top: 20px; 87 | margin-bottom: 20px; 88 | margin-left: 20px; 89 | margin-right: 20px; 90 | float: left; 91 | } 92 | 93 | #cartIcon { 94 | height: 30px; 95 | width: 30px; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /templates/cart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Your Cart 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | {% if not loggedIn %} 19 |
20 | Sign In 21 |
22 | {% else %} 23 | 32 | {% endif %} 33 |
34 | 35 | 36 | CART {{noOfItems}} 37 | 38 |
39 |
40 |
41 |

Shopping Cart

42 |
43 | {% for row in products %} 44 |
45 |
46 |
47 | 48 |
49 |
50 | {{row[1]}}
51 | In stock
52 | Remove 53 |
54 |
55 | ${{row[2]}} 56 |
57 |
58 | {% endfor %} 59 |
60 |
61 | Subtotal : ${{totalPrice}} 62 |
63 |
64 |
65 | Proceed to checkout 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /templates/displayCategory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Category: {{categoryName}} 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | {% if not loggedIn %} 19 |
20 | Sign In 21 |
22 | {% else %} 23 | 32 | {% endif %} 33 |
34 | 35 | 36 | CART {{noOfItems}} 37 | 38 |
39 |
40 | 41 |
42 |

Showing all products of Category {{categoryName}}:

43 | {% for itemData in data %} 44 | 45 | 46 | {% for row in itemData %} 47 | 50 | {% endfor %} 51 | 52 | 53 | {% for row in itemData %} 54 | 59 | {% endfor %} 60 | 61 | 62 | {% for row in itemData %} 63 | 66 | {% endfor %} 67 | 68 |
48 | {{row[1]}} 49 |
55 | 56 | 57 | 58 |
64 | ${{row[2]}} 65 |
69 | {% endfor %} 70 |
71 | 72 | 73 | -------------------------------------------------------------------------------- /templates/productDescription.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Product Description 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | {% if not loggedIn %} 19 |
20 | Sign In 21 |
22 | {% else %} 23 | 32 | {% endif %} 33 |
34 | 35 | 36 | CART {{noOfItems}} 37 | 38 |
39 |
40 |
41 |
42 |

{{data[1]}}

43 |
44 |
45 | 46 |
47 | 48 |
49 |

Details

50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
Name{{data[1]}}
Price${{data[2]}}
Stock{{data[5]}}
64 |

Description

65 |

{{data[3]}}

66 |
67 |
68 | Add to Cart 69 |
70 |
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Welcome 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | {% if not loggedIn %} 19 |
20 | Sign In 21 |
22 | {% else %} 23 | 32 | {% endif %} 33 |
34 | 35 | 36 | CART {{noOfItems}} 37 | 38 |
39 |
40 |
41 |
42 |

Shop by Category:

43 | 48 |
49 |
50 |

Items

51 | {% for data in itemData %} 52 | 53 | 54 | {% for row in data %} 55 | 58 | {% endfor %} 59 | 60 | 61 | {% for row in data %} 62 | 67 | {% endfor %} 68 | 69 | 70 | {% for row in data %} 71 | 74 | {% endfor %} 75 | 76 |
56 | {{row[1]}} 57 |
63 | 64 | 65 | 66 |
72 | ${{row[2]}} 73 |
77 | {% endfor %} 78 |
79 |
80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /templates/editProfile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Edit Profile 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | {% if not loggedIn %} 19 |
20 | Sign In 21 |
22 | {% else %} 23 | 32 | {% endif %} 33 |
34 | 35 | 36 | CART {{noOfItems}} 37 | 38 |
39 |
40 | 41 |
42 |

Edit profile

43 |
44 |

Email:

45 |

First Name:

46 |

Last Name:

47 |

Address 1:

48 |

Address 2:

49 |

Zip Code:

50 |

City:

51 |

State:

52 |

Country:

53 |

Phone Number:

54 | 55 |
56 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "6b7af0fb986b8f9bf5f7e6fb2745fcd4c3a3fa2b1745868783aa57098eb1dd17" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.8" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "click": { 20 | "hashes": [ 21 | "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", 22 | "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb" 23 | ], 24 | "markers": "python_version >= '3.6'", 25 | "version": "==8.0.4" 26 | }, 27 | "flask": { 28 | "hashes": [ 29 | "sha256:59da8a3170004800a2837844bfa84d49b022550616070f7cb1a659682b2e7c9f", 30 | "sha256:e1120c228ca2f553b470df4a5fa927ab66258467526069981b3eb0a91902687d" 31 | ], 32 | "index": "pypi", 33 | "version": "==2.0.3" 34 | }, 35 | "itsdangerous": { 36 | "hashes": [ 37 | "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", 38 | "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" 39 | ], 40 | "markers": "python_version >= '3.7'", 41 | "version": "==2.1.2" 42 | }, 43 | "jinja2": { 44 | "hashes": [ 45 | "sha256:a2f09a92f358b96b5f6ca6ecb4502669c4acb55d8733bbb2b2c9c4af5564c605", 46 | "sha256:da424924c069a4013730d8dd010cbecac7e7bb752be388db3741688bffb48dc6" 47 | ], 48 | "markers": "python_version >= '3.7'", 49 | "version": "==3.1.0" 50 | }, 51 | "markupsafe": { 52 | "hashes": [ 53 | "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003", 54 | "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88", 55 | "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5", 56 | "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7", 57 | "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a", 58 | "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603", 59 | "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1", 60 | "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135", 61 | "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247", 62 | "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6", 63 | "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601", 64 | "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77", 65 | "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02", 66 | "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e", 67 | "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63", 68 | "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f", 69 | "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980", 70 | "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b", 71 | "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812", 72 | "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff", 73 | "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96", 74 | "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1", 75 | "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925", 76 | "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a", 77 | "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6", 78 | "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e", 79 | "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f", 80 | "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4", 81 | "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f", 82 | "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3", 83 | "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c", 84 | "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a", 85 | "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417", 86 | "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a", 87 | "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a", 88 | "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37", 89 | "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452", 90 | "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933", 91 | "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a", 92 | "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7" 93 | ], 94 | "markers": "python_version >= '3.7'", 95 | "version": "==2.1.1" 96 | }, 97 | "pysqlite3": { 98 | "hashes": [ 99 | "sha256:0352864898aa406beb762f4a620594c950a9a4430caab679bce574065698c8ac" 100 | ], 101 | "index": "pypi", 102 | "version": "==0.4.7" 103 | }, 104 | "werkzeug": { 105 | "hashes": [ 106 | "sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8", 107 | "sha256:b863f8ff057c522164b6067c9e28b041161b4be5ba4d0daceeaa50a163822d3c" 108 | ], 109 | "markers": "python_version >= '3.6'", 110 | "version": "==2.0.3" 111 | } 112 | }, 113 | "develop": {} 114 | } 115 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from flask import * 2 | import sqlite3, hashlib, os 3 | from werkzeug.utils import secure_filename 4 | 5 | app = Flask(__name__) 6 | app.secret_key = 'random string' 7 | UPLOAD_FOLDER = 'static/uploads' 8 | ALLOWED_EXTENSIONS = set(['jpeg', 'jpg', 'png', 'gif']) 9 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER 10 | 11 | def getLoginDetails(): 12 | with sqlite3.connect('database.db') as conn: 13 | cur = conn.cursor() 14 | if 'email' not in session: 15 | loggedIn = False 16 | firstName = '' 17 | noOfItems = 0 18 | else: 19 | loggedIn = True 20 | cur.execute("SELECT userId, firstName FROM users WHERE email = ?", (session['email'], )) 21 | userId, firstName = cur.fetchone() 22 | cur.execute("SELECT count(productId) FROM kart WHERE userId = ?", (userId, )) 23 | noOfItems = cur.fetchone()[0] 24 | conn.close() 25 | return (loggedIn, firstName, noOfItems) 26 | 27 | @app.route("/") 28 | def root(): 29 | loggedIn, firstName, noOfItems = getLoginDetails() 30 | with sqlite3.connect('database.db') as conn: 31 | cur = conn.cursor() 32 | cur.execute('SELECT productId, name, price, description, image, stock FROM products') 33 | itemData = cur.fetchall() 34 | cur.execute('SELECT categoryId, name FROM categories') 35 | categoryData = cur.fetchall() 36 | itemData = parse(itemData) 37 | return render_template('home.html', itemData=itemData, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems, categoryData=categoryData) 38 | 39 | @app.route("/add") 40 | def admin(): 41 | with sqlite3.connect('database.db') as conn: 42 | cur = conn.cursor() 43 | cur.execute("SELECT categoryId, name FROM categories") 44 | categories = cur.fetchall() 45 | conn.close() 46 | return render_template('add.html', categories=categories) 47 | 48 | @app.route("/addItem", methods=["GET", "POST"]) 49 | def addItem(): 50 | if request.method == "POST": 51 | name = request.form['name'] 52 | price = float(request.form['price']) 53 | description = request.form['description'] 54 | stock = int(request.form['stock']) 55 | categoryId = int(request.form['category']) 56 | 57 | #Uploading image procedure 58 | image = request.files['image'] 59 | if image and allowed_file(image.filename): 60 | filename = secure_filename(image.filename) 61 | image.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) 62 | imagename = filename 63 | with sqlite3.connect('database.db') as conn: 64 | try: 65 | cur = conn.cursor() 66 | cur.execute('''INSERT INTO products (name, price, description, image, stock, categoryId) VALUES (?, ?, ?, ?, ?, ?)''', (name, price, description, imagename, stock, categoryId)) 67 | conn.commit() 68 | msg="added successfully" 69 | except: 70 | msg="error occured" 71 | conn.rollback() 72 | conn.close() 73 | print(msg) 74 | return redirect(url_for('root')) 75 | 76 | @app.route("/remove") 77 | def remove(): 78 | with sqlite3.connect('database.db') as conn: 79 | cur = conn.cursor() 80 | cur.execute('SELECT productId, name, price, description, image, stock FROM products') 81 | data = cur.fetchall() 82 | conn.close() 83 | return render_template('remove.html', data=data) 84 | 85 | @app.route("/removeItem") 86 | def removeItem(): 87 | productId = request.args.get('productId') 88 | with sqlite3.connect('database.db') as conn: 89 | try: 90 | cur = conn.cursor() 91 | cur.execute('DELETE FROM products WHERE productID = ?', (productId, )) 92 | conn.commit() 93 | msg = "Deleted successsfully" 94 | except: 95 | conn.rollback() 96 | msg = "Error occured" 97 | conn.close() 98 | print(msg) 99 | return redirect(url_for('root')) 100 | 101 | @app.route("/displayCategory") 102 | def displayCategory(): 103 | loggedIn, firstName, noOfItems = getLoginDetails() 104 | categoryId = request.args.get("categoryId") 105 | with sqlite3.connect('database.db') as conn: 106 | cur = conn.cursor() 107 | cur.execute("SELECT products.productId, products.name, products.price, products.image, categories.name FROM products, categories WHERE products.categoryId = categories.categoryId AND categories.categoryId = ?", (categoryId, )) 108 | data = cur.fetchall() 109 | conn.close() 110 | categoryName = data[0][4] 111 | data = parse(data) 112 | return render_template('displayCategory.html', data=data, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems, categoryName=categoryName) 113 | 114 | @app.route("/account/profile") 115 | def profileHome(): 116 | if 'email' not in session: 117 | return redirect(url_for('root')) 118 | loggedIn, firstName, noOfItems = getLoginDetails() 119 | return render_template("profileHome.html", loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems) 120 | 121 | @app.route("/account/profile/edit") 122 | def editProfile(): 123 | if 'email' not in session: 124 | return redirect(url_for('root')) 125 | loggedIn, firstName, noOfItems = getLoginDetails() 126 | with sqlite3.connect('database.db') as conn: 127 | cur = conn.cursor() 128 | cur.execute("SELECT userId, email, firstName, lastName, address1, address2, zipcode, city, state, country, phone FROM users WHERE email = ?", (session['email'], )) 129 | profileData = cur.fetchone() 130 | conn.close() 131 | return render_template("editProfile.html", profileData=profileData, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems) 132 | 133 | @app.route("/account/profile/changePassword", methods=["GET", "POST"]) 134 | def changePassword(): 135 | if 'email' not in session: 136 | return redirect(url_for('loginForm')) 137 | if request.method == "POST": 138 | oldPassword = request.form['oldpassword'] 139 | oldPassword = hashlib.md5(oldPassword.encode()).hexdigest() 140 | newPassword = request.form['newpassword'] 141 | newPassword = hashlib.md5(newPassword.encode()).hexdigest() 142 | with sqlite3.connect('database.db') as conn: 143 | cur = conn.cursor() 144 | cur.execute("SELECT userId, password FROM users WHERE email = ?", (session['email'], )) 145 | userId, password = cur.fetchone() 146 | if (password == oldPassword): 147 | try: 148 | cur.execute("UPDATE users SET password = ? WHERE userId = ?", (newPassword, userId)) 149 | conn.commit() 150 | msg="Changed successfully" 151 | except: 152 | conn.rollback() 153 | msg = "Failed" 154 | return render_template("changePassword.html", msg=msg) 155 | else: 156 | msg = "Wrong password" 157 | conn.close() 158 | return render_template("changePassword.html", msg=msg) 159 | else: 160 | return render_template("changePassword.html") 161 | 162 | @app.route("/updateProfile", methods=["GET", "POST"]) 163 | def updateProfile(): 164 | if request.method == 'POST': 165 | email = request.form['email'] 166 | firstName = request.form['firstName'] 167 | lastName = request.form['lastName'] 168 | address1 = request.form['address1'] 169 | address2 = request.form['address2'] 170 | zipcode = request.form['zipcode'] 171 | city = request.form['city'] 172 | state = request.form['state'] 173 | country = request.form['country'] 174 | phone = request.form['phone'] 175 | with sqlite3.connect('database.db') as con: 176 | try: 177 | cur = con.cursor() 178 | cur.execute('UPDATE users SET firstName = ?, lastName = ?, address1 = ?, address2 = ?, zipcode = ?, city = ?, state = ?, country = ?, phone = ? WHERE email = ?', (firstName, lastName, address1, address2, zipcode, city, state, country, phone, email)) 179 | 180 | con.commit() 181 | msg = "Saved Successfully" 182 | except: 183 | con.rollback() 184 | msg = "Error occured" 185 | con.close() 186 | return redirect(url_for('editProfile')) 187 | 188 | @app.route("/loginForm") 189 | def loginForm(): 190 | if 'email' in session: 191 | return redirect(url_for('root')) 192 | else: 193 | return render_template('login.html', error='') 194 | 195 | @app.route("/login", methods = ['POST', 'GET']) 196 | def login(): 197 | if request.method == 'POST': 198 | email = request.form['email'] 199 | password = request.form['password'] 200 | if is_valid(email, password): 201 | session['email'] = email 202 | return redirect(url_for('root')) 203 | else: 204 | error = 'Invalid UserId / Password' 205 | return render_template('login.html', error=error) 206 | 207 | @app.route("/productDescription") 208 | def productDescription(): 209 | loggedIn, firstName, noOfItems = getLoginDetails() 210 | productId = request.args.get('productId') 211 | with sqlite3.connect('database.db') as conn: 212 | cur = conn.cursor() 213 | cur.execute('SELECT productId, name, price, description, image, stock FROM products WHERE productId = ?', (productId, )) 214 | productData = cur.fetchone() 215 | conn.close() 216 | return render_template("productDescription.html", data=productData, loggedIn = loggedIn, firstName = firstName, noOfItems = noOfItems) 217 | 218 | @app.route("/addToCart") 219 | def addToCart(): 220 | if 'email' not in session: 221 | return redirect(url_for('loginForm')) 222 | else: 223 | productId = int(request.args.get('productId')) 224 | with sqlite3.connect('database.db') as conn: 225 | cur = conn.cursor() 226 | cur.execute("SELECT userId FROM users WHERE email = ?", (session['email'], )) 227 | userId = cur.fetchone()[0] 228 | try: 229 | cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId)) 230 | conn.commit() 231 | msg = "Added successfully" 232 | except: 233 | conn.rollback() 234 | msg = "Error occured" 235 | conn.close() 236 | return redirect(url_for('root')) 237 | 238 | @app.route("/cart") 239 | def cart(): 240 | if 'email' not in session: 241 | return redirect(url_for('loginForm')) 242 | loggedIn, firstName, noOfItems = getLoginDetails() 243 | email = session['email'] 244 | with sqlite3.connect('database.db') as conn: 245 | cur = conn.cursor() 246 | cur.execute("SELECT userId FROM users WHERE email = ?", (email, )) 247 | userId = cur.fetchone()[0] 248 | cur.execute("SELECT products.productId, products.name, products.price, products.image FROM products, kart WHERE products.productId = kart.productId AND kart.userId = ?", (userId, )) 249 | products = cur.fetchall() 250 | totalPrice = 0 251 | for row in products: 252 | totalPrice += row[2] 253 | return render_template("cart.html", products = products, totalPrice=totalPrice, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems) 254 | 255 | @app.route("/removeFromCart") 256 | def removeFromCart(): 257 | if 'email' not in session: 258 | return redirect(url_for('loginForm')) 259 | email = session['email'] 260 | productId = int(request.args.get('productId')) 261 | with sqlite3.connect('database.db') as conn: 262 | cur = conn.cursor() 263 | cur.execute("SELECT userId FROM users WHERE email = ?", (email, )) 264 | userId = cur.fetchone()[0] 265 | try: 266 | cur.execute("DELETE FROM kart WHERE userId = ? AND productId = ?", (userId, productId)) 267 | conn.commit() 268 | msg = "removed successfully" 269 | except: 270 | conn.rollback() 271 | msg = "error occured" 272 | conn.close() 273 | return redirect(url_for('root')) 274 | 275 | @app.route("/logout") 276 | def logout(): 277 | session.pop('email', None) 278 | return redirect(url_for('root')) 279 | 280 | def is_valid(email, password): 281 | con = sqlite3.connect('database.db') 282 | cur = con.cursor() 283 | cur.execute('SELECT email, password FROM users') 284 | data = cur.fetchall() 285 | for row in data: 286 | if row[0] == email and row[1] == hashlib.md5(password.encode()).hexdigest(): 287 | return True 288 | return False 289 | 290 | @app.route("/register", methods = ['GET', 'POST']) 291 | def register(): 292 | if request.method == 'POST': 293 | #Parse form data 294 | password = request.form['password'] 295 | email = request.form['email'] 296 | firstName = request.form['firstName'] 297 | lastName = request.form['lastName'] 298 | address1 = request.form['address1'] 299 | address2 = request.form['address2'] 300 | zipcode = request.form['zipcode'] 301 | city = request.form['city'] 302 | state = request.form['state'] 303 | country = request.form['country'] 304 | phone = request.form['phone'] 305 | 306 | with sqlite3.connect('database.db') as con: 307 | try: 308 | cur = con.cursor() 309 | cur.execute('INSERT INTO users (password, email, firstName, lastName, address1, address2, zipcode, city, state, country, phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', (hashlib.md5(password.encode()).hexdigest(), email, firstName, lastName, address1, address2, zipcode, city, state, country, phone)) 310 | 311 | con.commit() 312 | 313 | msg = "Registered Successfully" 314 | except: 315 | con.rollback() 316 | msg = "Error occured" 317 | con.close() 318 | return render_template("login.html", error=msg) 319 | 320 | @app.route("/registerationForm") 321 | def registrationForm(): 322 | return render_template("register.html") 323 | 324 | def allowed_file(filename): 325 | return '.' in filename and \ 326 | filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS 327 | 328 | def parse(data): 329 | ans = [] 330 | i = 0 331 | while i < len(data): 332 | curr = [] 333 | for j in range(7): 334 | if i >= len(data): 335 | break 336 | curr.append(data[i]) 337 | i += 1 338 | ans.append(curr) 339 | return ans 340 | 341 | if __name__ == '__main__': 342 | app.run(debug=True) 343 | --------------------------------------------------------------------------------