Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
jinyang628 committed Feb 7, 2025
1 parent e77d001 commit 53d200e
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 32 deletions.
1 change: 0 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from app.routes import init_app
from app.utils.database import close_db


def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
Expand Down
9 changes: 9 additions & 0 deletions app/models/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@ class Product(BaseModel):
UnitsOnOrder: int
ReorderLevel: int
Discontinued: str

class CartItem(BaseModel):
ProductID: int
Quantity: int
ProductName: str
TotalPrice: float

class Cart(BaseModel):
items: dict[int, CartItem]
2 changes: 1 addition & 1 deletion app/routes/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask import Blueprint, render_template

from app.models.product import Product
from app.services.products import ProductService
from app.services.product import ProductService

main_bp = Blueprint("main", __name__)

Expand Down
36 changes: 30 additions & 6 deletions app/routes/product.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
from typing import Optional

from flask import Blueprint, render_template
from flask import Blueprint, jsonify, render_template

from app.models.category import Category
from app.models.product import Product
from app.models.supplier import Supplier
from app.services.category import CategoryService
from app.services.products import ProductService
from app.services.product import ProductService
from app.services.supplier import SupplierService

product_bp = Blueprint("product", __name__)
product_service = ProductService()
category_service = CategoryService()
supplier_service = SupplierService()


@product_bp.route("/<int:product_id>")
@product_bp.route("/<int:product_id>", methods=["GET"])
def index(product_id: int):
product: Product = ProductService().get_product_by_id(product_id)
category: Optional[Category] = CategoryService().get_category_by_id(product.CategoryID)
supplier: Optional[Supplier] = SupplierService().get_supplier_by_id(product.SupplierID)
product: Optional[Product] = product_service.get_product_by_id(product_id)
if not product:
raise ValueError(f"Error rendering product page: product not found with id {product_id}")

category: Optional[Category] = category_service.get_category_by_id(product.CategoryID)
supplier: Optional[Supplier] = supplier_service.get_supplier_by_id(product.SupplierID)
return render_template(
"product/index.html", product=product, category=category, supplier=supplier
)


@product_bp.route("/<int:product_id>", methods=["POST"])
def add_to_cart(product_id):
product: Optional[Product] = product_service.get_product_by_id(product_id)
if not product:
raise ValueError(f"Error adding product to cart: product not found with id {product_id}")

# quantity = int(request.form.get("quantity", 1))

# if quantity > product.UnitsInStock:
# return jsonify({"message": "Requested quantity exceeds available stock"}), 400

# cart = session.get("cart", {})
# cart[product_id] = cart.get(product_id, 0) + quantity
# session["cart"] = cart

return jsonify({"message": f"Added {product.ProductName} to cart"})
12 changes: 12 additions & 0 deletions app/services/cart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from flask import session

from app.models.product import Cart


def get_cart() -> Cart:
return Cart.model_validate(session.get("cart", {}))


def save_cart(cart: Cart):
session["cart"] = cart.model_dump()

47 changes: 47 additions & 0 deletions app/services/product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from typing import Optional

from app.models.product import Product
from app.utils.database import get_db
# from app.utils.logger import setup_logger

# log = setup_logger("ProductService")


class ProductService:

def __init__(self):
self.cursor = None
self.columns = list(Product.model_fields.keys())


def _ensure_cursor(self):
if self.cursor is None:
self.cursor = get_db().cursor()
return self.cursor

def get_all_products(self) -> list[Product]:
cursor = self._ensure_cursor()
cursor.execute("SELECT * FROM Products")
products: list[Product] = [
Product.model_validate(dict(zip(self.columns, row))) for row in cursor.fetchall()
]
return products

def get_product_by_id(self, product_id: Optional[int]) -> Optional[Product]:
if not product_id:
return None
cursor = self._ensure_cursor()
cursor.execute(f"SELECT * FROM Products WHERE ProductID = {product_id}")
rows: list = cursor.fetchall()
match len(rows):
case 0:
log.info(f"No product found with id {product_id}")
return None
case 1:
product: Product = Product.model_validate(dict(zip(self.columns, rows[0])))
return product
case _:
log.error(
f"Invalid number of rows returned for product with id {product_id}: {len(rows)}"
)
raise ValueError("Multiple rows returned")
21 changes: 0 additions & 21 deletions app/services/products.py

This file was deleted.

6 changes: 3 additions & 3 deletions app/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<!doctype html>
<title>{% block title %}{% endblock %} - Online Commerce Site</title>
<title>{% block title %}{% endblock %} - Walmart</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<nav>
<h1>Online Commerce Site</h1>
<h1>Walmart</h1>
<ul>

</ul>
Expand All @@ -15,4 +15,4 @@ <h1>Online Commerce Site</h1>
<div class="flash">{{ message }}</div>
{% endfor %}
{% block content %}{% endblock %}
</section>
</section>
44 changes: 44 additions & 0 deletions app/templates/product/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,52 @@ <h2 class="card-title">{{ product.ProductName }}</h2>
<p>{{ product.QuantityPerUnit }}</p>
</div>
</div>

<div class="d-flex align-items-center mt-3">
<button type="button" class="btn btn-outline-secondary" id="decrease-qty">-</button>
<input type="number" name="quantity" id="quantity" class="form-control mx-2 text-center" min="1"
max="{{ product.UnitsInStock }}" value="1" style="width: 80px;" readonly>
<button type="button" class="btn btn-outline-secondary" id="increase-qty">+</button>
<button type="button" class="btn btn-primary ml-3" id="add-to-cart"
data-product-id="{{ product.ProductID }}">
Add to Cart
</button>
</div>

<a href="{{ url_for('main.index') }}" class="btn btn-secondary mt-3">Back to Products</a>
</div>
</div>
</div>

<style>
/* Hide the spinners (up/down arrows) in the number input */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
</style>

<script>
document.addEventListener('DOMContentLoaded', function () {
const quantityInput = document.getElementById('quantity');
const decreaseButton = document.getElementById('decrease-qty');
const increaseButton = document.getElementById('increase-qty');

decreaseButton.addEventListener('click', function () {
let currentValue = parseInt(quantityInput.value);
if (currentValue > 1) {
quantityInput.value = currentValue - 1;
}
});

increaseButton.addEventListener('click', function () {
let currentValue = parseInt(quantityInput.value);
if (currentValue < parseInt(quantityInput.max)) {
quantityInput.value = currentValue + 1;
}
});
});
</script>

{% endblock %}
12 changes: 12 additions & 0 deletions app/utils/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# import logging

# def setup_logger(name: str) -> logging.Logger:
# """Setup a logger with basic formatting."""
# logger = logging.getLogger(name)
# logger.setLevel(logging.INFO)
# handler = logging.StreamHandler()
# formatter = logging.Formatter("%(levelname)-8s [%(name)s] %(message)s")
# handler.setFormatter(formatter)
# logger.addHandler(handler)
# logger.propagate = False
# return logger

0 comments on commit 53d200e

Please sign in to comment.