diff --git a/src/entities/product.py b/src/entities/product.py
index ae7341f..0dba882 100644
--- a/src/entities/product.py
+++ b/src/entities/product.py
@@ -7,6 +7,7 @@ class Product:
name: str
description: str
price: float
+ quantity: int
def post_init(self):
if self.price < 0:
diff --git a/src/entities/user.py b/src/entities/user.py
new file mode 100644
index 0000000..3063c11
--- /dev/null
+++ b/src/entities/user.py
@@ -0,0 +1,7 @@
+#python imports
+from dataclasses import dataclass
+
+@dataclass
+class User:
+ pass
+ #TODO: implement
\ No newline at end of file
diff --git a/src/framework_driver/db/db_setup.py b/src/framework_driver/db/db_setup.py
index 22a792c..5b135e9 100644
--- a/src/framework_driver/db/db_setup.py
+++ b/src/framework_driver/db/db_setup.py
@@ -41,6 +41,7 @@ def main():
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
price REAL NOT NULL,
+ description TEXT NOT NULL,
quantity INTEGER NOT NULL
)"""
diff --git a/src/framework_driver/db/shop.db b/src/framework_driver/db/shop.db
index 885ea58..1b074fa 100644
Binary files a/src/framework_driver/db/shop.db and b/src/framework_driver/db/shop.db differ
diff --git a/src/framework_driver/ui/src/controller.js b/src/framework_driver/ui/src/controller.js
index 7e45ad4..be844c3 100644
--- a/src/framework_driver/ui/src/controller.js
+++ b/src/framework_driver/ui/src/controller.js
@@ -35,6 +35,14 @@ const Controller = {
event.preventDefault();
alert('User profile functionality not implemented.');
});
+
+ document.querySelectorAll('.product-link').forEach((link) => {
+ link.addEventListener('click', (event) => {
+ event.preventDefault();
+ const productId = event.target.getAttribute('data-id');
+ Controller.showProduct(productId);
+ });
+ });
},
addProductClickHandlers() {
diff --git a/src/framework_driver/ui/static/css/style.css b/src/framework_driver/ui/static/css/style.css
deleted file mode 100644
index 3498937..0000000
--- a/src/framework_driver/ui/static/css/style.css
+++ /dev/null
@@ -1,65 +0,0 @@
-body {
- font-family: Arial, sans-serif;
-}
-
-header {
- background-color: #f8f9fa;
- padding: 1rem;
- text-align: center;
-}
-
-main {
- padding: 1rem;
-}
-
-.btn-primary {
- display: inline-block;
- padding: 10px 20px;
- font-size: 16px;
- color: #fff;
- background-color: #007bff;
- border: none;
- border-radius: 4px;
- text-align: center;
- text-decoration: none;
- cursor: pointer;
-}
-
-.btn-primary:hover {
- background-color: #0056b3;
-}
-
-
-.product-list {
- list-style-type: none;
- padding: 0;
- margin: 0;
-}
-
-.product-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 10px;
- border-bottom: 1px solid #ddd;
-}
-
-/* Styling der Produktnamen, -mengen und -preise */
-.product-name {
- font-weight: bold;
-}
-
-.product-quantity {
- color: #555;
-}
-
-.product-price {
- color: #555;
-}
-
-/* Styling für den Gesamtpreis */
-.total-price {
- font-size: 18px;
- font-weight: bold;
- margin-top: 20px;
-}
\ No newline at end of file
diff --git a/src/framework_driver/ui/static/js/script.js b/src/framework_driver/ui/static/js/script.js
deleted file mode 100644
index 3035a99..0000000
--- a/src/framework_driver/ui/static/js/script.js
+++ /dev/null
@@ -1,3 +0,0 @@
-document.addEventListener('DOMContentLoaded', function() {
- console.log('JavaScript is loaded');
-});
\ No newline at end of file
diff --git a/src/framework_driver/ui/templates/base.html b/src/framework_driver/ui/templates/base.html
deleted file mode 100644
index 4d3d569..0000000
--- a/src/framework_driver/ui/templates/base.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
- {% block title %}My Shop{% endblock %}
-
-
-
-
-
- {% block content %}{% endblock %}
-
-
-
-
\ No newline at end of file
diff --git a/src/framework_driver/ui/templates/cart.html b/src/framework_driver/ui/templates/cart.html
deleted file mode 100644
index 92d7c97..0000000
--- a/src/framework_driver/ui/templates/cart.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Cart{% endblock %}
-
-{% block content %}
-Cart Items
-
-
- {% for item in cart_items['items'] %}
- -
-
Product ID: {{ item.product_id }}
- Quantity: {{ item.quantity }}
- Price: {{ item.price }} €
-
- {% endfor %}
-
-
-Total Price: {{ cart_items.total_price }} €
-
-Back to the prodcuts
-
-{% endblock %}
\ No newline at end of file
diff --git a/src/framework_driver/ui/templates/products.html b/src/framework_driver/ui/templates/products.html
deleted file mode 100644
index f23f82a..0000000
--- a/src/framework_driver/ui/templates/products.html
+++ /dev/null
@@ -1,18 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Products{% endblock %}
-
-{% block content %}
-Product Items
-
- {% for product in products %}
- -
-
{{ product.name }}
- ${{ product.price }}
-
- {% endfor %}
-
-
-Go to Cart
-
-{% endblock %}
\ No newline at end of file
diff --git a/src/interface_adapters/controllers/cart_controller.py b/src/interface_adapters/controllers/cart_controller.py
index 57fe7ac..d288c6a 100644
--- a/src/interface_adapters/controllers/cart_controller.py
+++ b/src/interface_adapters/controllers/cart_controller.py
@@ -3,18 +3,12 @@ from fastapi import APIRouter, HTTPException
from fastapi.responses import JSONResponse
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
-from fastapi.templating import Jinja2Templates
-
-import httpx
#dependency imports
from use_cases import ViewCart
from interface_adapters.dtos import ViewCartRequestDTO, ViewCartResponseDTO, CartItemDTO
from interface_adapters.repositories import SQLCartRepository
-# Set up templates
-templates = Jinja2Templates(directory="framework_driver/ui/templates")
-
# Initialize components
cart_repository = SQLCartRepository()
view_cart_use_case = ViewCart(cart_repository)
@@ -36,14 +30,3 @@ async def view_cart(request_dto: ViewCartRequestDTO):
return response_dto
-
-@router.get("/ui/view_cart", response_class=HTMLResponse, name="ui_view_cart")
-async def ui_view_cart(request: Request, user_id: int=1):
- request_dto = {"user_id": user_id}
- async with httpx.AsyncClient() as client:
- response = await client.post("http://127.0.0.1:8000/view_cart", json=request_dto)
- response.raise_for_status() # Raise an exception for HTTP errors
- response_dto = response.json()
-
- return templates.TemplateResponse("cart.html", {"request": request, "cart_items": response_dto})
-
diff --git a/src/interface_adapters/controllers/product_controller.py b/src/interface_adapters/controllers/product_controller.py
index c09f00c..07e94e8 100644
--- a/src/interface_adapters/controllers/product_controller.py
+++ b/src/interface_adapters/controllers/product_controller.py
@@ -3,9 +3,6 @@ from fastapi import APIRouter, HTTPException
from fastapi.responses import JSONResponse
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
-from fastapi.templating import Jinja2Templates
-
-import httpx
#dependency imports
from use_cases import ViewProduct, ViewAllProducts
@@ -40,7 +37,8 @@ async def view_products():
if not products:
raise HTTPException(status_code=404, detail="Product not found")
-
+ for product in products:
+ print(product)
response_dto = ViewAllProductsResponseDTO(
products=[ProductDTO(id=product.id, name=product.name, description=product.description, price=product.price) for product in products]
)
diff --git a/src/interface_adapters/controllers/user_controller.py b/src/interface_adapters/controllers/user_controller.py
new file mode 100644
index 0000000..235b3f3
--- /dev/null
+++ b/src/interface_adapters/controllers/user_controller.py
@@ -0,0 +1,16 @@
+#python imports
+from fastapi import APIRouter, HTTPException
+from fastapi.responses import JSONResponse
+from fastapi import FastAPI, Request
+from fastapi.responses import HTMLResponse
+from fastapi.templating import Jinja2Templates
+
+#dependency imports
+#TODO: use correct dependencies
+
+# Initialize components
+#TODO: initialize
+
+router = APIRouter()
+
+#TODO: implement routes for creating and viewing user
diff --git a/src/interface_adapters/repositories/sql_cart_repository.py b/src/interface_adapters/repositories/sql_cart_repository.py
index 675c478..def6a23 100644
--- a/src/interface_adapters/repositories/sql_cart_repository.py
+++ b/src/interface_adapters/repositories/sql_cart_repository.py
@@ -4,11 +4,13 @@ import sqlite3
#dependency imports
from use_cases import ICartRepository
+from entities import Cart, CartItem
class SQLCartRepository(ICartRepository):
def __init__(self, db_file="framework_driver/db/shop.db"):
"""Initialize the CartDatabase with a connection to the SQLite database."""
self.conn = sqlite3.connect(db_file)
+ self.conn.row_factory = sqlite3.Row
def add_to_cart(self, user_id, product_id, name, quantity, price):
"""Add a product to the user's cart."""
@@ -21,14 +23,14 @@ class SQLCartRepository(ICartRepository):
except sqlite3.Error as e:
print(e)
- def get_cart_by_user_id(self, user_id: int) -> Optional[List[dict]]:
+ def get_cart_by_user_id(self, user_id: int) -> Optional[Cart]:
"""Fetch cart items from the database for a given user ID."""
sql = "SELECT product_id, name, quantity, price FROM cart WHERE user_id = ?"
try:
c = self.conn.cursor()
c.execute(sql, (user_id,))
rows = c.fetchall()
- return [{'product_id':r[0], 'name':r[1], 'quantity':r[2], 'price':r[3]} for r in rows]
+ return Cart([CartItem(**item) for item in rows])
except sqlite3.Error as e:
print(e)
return None
@@ -66,7 +68,7 @@ class SQLCartRepository(ICartRepository):
def main():
database = "framework_driver/db/shop.db"
- cart_db = CartDatabase(database)
+ cart_db = SQLCartRepository(database)
ex_user_id = 1
@@ -76,11 +78,11 @@ def main():
# user id, product id, name, quantity, price
cart_db.add_to_cart(ex_user_id, 1, "Unsichtbare Tinte", 2, 3.0)
cart_db.add_to_cart(ex_user_id, 3, "Geräuschloser Wecker", 5, 15.0)
- print(f"Cart items for user {ex_user_id}:", cart_db.fetch_cart_items(ex_user_id))
+ print(f"Cart items for user {ex_user_id}:", cart_db.get_cart_by_user_id(ex_user_id))
# user id, product id, quantity
cart_db.update_cart_item(ex_user_id, 2, 3)
- print(f"Cart items for user {ex_user_id}:", cart_db.fetch_cart_items(ex_user_id))
+ print(f"Cart items for user {ex_user_id}:", cart_db.get_cart_by_user_id(ex_user_id))
if __name__ == "__main__":
main()
\ No newline at end of file
diff --git a/src/interface_adapters/repositories/sql_product_repository.py b/src/interface_adapters/repositories/sql_product_repository.py
index fce4e78..0bdbe0d 100644
--- a/src/interface_adapters/repositories/sql_product_repository.py
+++ b/src/interface_adapters/repositories/sql_product_repository.py
@@ -4,15 +4,17 @@ import sqlite3
#dependency imports
from use_cases import IProductRepository
+from entities import Product
class SQLProductRepository(IProductRepository):
def __init__(self, db_file="framework_driver/db/shop.db"):
"""Initialize the ProductDatabase with a connection to the SQLite database."""
self.conn = sqlite3.connect(db_file)
+ self.conn.row_factory = sqlite3.Row
def add_product(self, product):
"""Add a new product to the products table."""
- sql = "INSERT INTO products (name, price, quantity) VALUES (?, ?, ?)"
+ sql = "INSERT INTO products (name, price, description, quantity) VALUES (?, ?, ?, ?)"
try:
c = self.conn.cursor()
c.execute(sql, product)
@@ -21,26 +23,26 @@ class SQLProductRepository(IProductRepository):
except sqlite3.Error as e:
print(e)
- def get_product_by_id(self, product_id):
+ def get_product_by_id(self, product_id) -> Optional[Product]:
"""Retrieve a product by its ID."""
sql = "SELECT * FROM products WHERE id = ?"
try:
c = self.conn.cursor()
c.execute(sql, (product_id,))
r = c.fetchone()
- return {'id':r[0], 'name':str(r[1]), 'description':str(r[2]), 'price':r[3]}
+ return Product(**r)
except sqlite3.Error as e:
print(e)
return None
- def get_all_products(self):
+ def get_all_products(self) -> Optional[List[Product]]:
"""Retrieve all products."""
sql = "SELECT * FROM products"
try:
c = self.conn.cursor()
c.execute(sql)
rows = c.fetchall()
- return [{'id':r[0], 'name':str(r[1]), 'description':str(r[2]), 'price':r[3]} for r in rows]
+ return [Product(**product) for product in rows]
except sqlite3.Error as e:
print(e)
return []
@@ -68,16 +70,16 @@ class SQLProductRepository(IProductRepository):
def main():
database = "framework_driver/db/shop.db"
- product_db = ProductDatabase(database)
+ product_db = SQLProductRepository(database)
# delete all products
for product in product_db.get_all_products():
product_db.delete_product(product[0])
# name, price, quantity
- products = [("Unsichtbare Tinte", 2.5, 5),
- ("Luftdichter Sieb", 7.5, 10),
- ("Geräuschloser Wecker", 15.0, 7)]
+ products = [("Unsichtbare Tinte", 2.5, "unsichtbar", 5),
+ ("Luftdichter Sieb", 7.5, "luftdicht", 10),
+ ("Geräuschloser Wecker", 15.0, "geräuschlos", 7)]
for product in products:
product_db.add_product(product)
diff --git a/src/interface_adapters/repositories/sql_user_repository.py b/src/interface_adapters/repositories/sql_user_repository.py
index c372c9f..c0f3bc0 100644
--- a/src/interface_adapters/repositories/sql_user_repository.py
+++ b/src/interface_adapters/repositories/sql_user_repository.py
@@ -4,11 +4,13 @@ import sqlite3
#dependency imports
from use_cases import IUserRepository
+from entities import User
class SQLUserRepository(IUserRepository):
def __init__(self, db_file="framework_driver/db/shop.db"):
"""Initialize the UserDatabase with a connection to the SQLite database."""
self.conn = sqlite3.connect(db_file)
+ self.conn.row_factory = sqlite3.Row
def add_user(self, user):
"""Add a new user to the users table and return the new user's id."""
@@ -22,7 +24,7 @@ class SQLUserRepository(IUserRepository):
print(e)
return None
- def get_user_by_id(self, user_id):
+ def get_user_by_id(self, user_id) -> Optional[User]:
"""Retrieve a user by their ID."""
sql = "SELECT * FROM users WHERE id = ?"
try:
@@ -67,7 +69,7 @@ class SQLUserRepository(IUserRepository):
def main():
database = "framework_driver/db/shop.db"
- user_db = UserDatabase(database)
+ user_db = SQLUserRepository(database)
# delete all users
for user in user_db.get_all_users():
diff --git a/src/main.py b/src/main.py
index efbd9d8..4eb0880 100644
--- a/src/main.py
+++ b/src/main.py
@@ -1,8 +1,8 @@
from interface_adapters.controllers.cart_controller import router as cart_router
from interface_adapters.controllers.product_controller import router as product_router
+from interface_adapters.controllers.user_controller import router as user_router
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
-from fastapi.templating import Jinja2Templates
from fastapi.responses import RedirectResponse
from fastapi.responses import HTMLResponse
from fastapi.responses import FileResponse
@@ -26,33 +26,9 @@ app.add_middleware(
allow_headers=["*"],
)
-# Serve static files
-# TODO fix this
-#app.mount("/static", StaticFiles(directory="framework_driver/ui/static"), name="static")
-# TODO so this is not needed
-@app.get("/custom_static/{filename:path}", response_class=FileResponse, name="custom_static", include_in_schema=False)
-async def custom_static(filename: str):
- file_path = os.path.join("framework_driver/ui/static", filename)
- if not os.path.exists(file_path):
- raise HTTPException(status_code=404, detail="File not found")
- return FileResponse(file_path)
-
-
-# Set up templates
-templates = Jinja2Templates(directory="framework_driver/ui/templates")
-
@app.get("/", include_in_schema=False)
async def root():
return RedirectResponse(url="/docs")
-
-
-@app.get("/ui", response_class=HTMLResponse)
-async def ui(request: Request):
- products = [
- {"id": 1, "name": "Product 1", "price": 10.0},
- {"id": 2, "name": "Product 2", "price": 20.0}
- ]
- return templates.TemplateResponse("products.html", {"request": request, "products": products})
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
diff --git a/src/setup_db.py b/src/setup_db.py
new file mode 100644
index 0000000..3e16679
--- /dev/null
+++ b/src/setup_db.py
@@ -0,0 +1,8 @@
+from framework_driver.db import db_setup
+from interface_adapters.repositories import sql_cart_repository
+from interface_adapters.repositories import sql_product_repository
+from interface_adapters.repositories import sql_user_repository
+db_setup.main()
+sql_cart_repository.main()
+sql_product_repository.main()
+sql_user_repository.main()
\ No newline at end of file
diff --git a/src/use_cases/cart_repository.py b/src/use_cases/cart_repository.py
index 5cb7452..1503235 100644
--- a/src/use_cases/cart_repository.py
+++ b/src/use_cases/cart_repository.py
@@ -1,7 +1,10 @@
from typing import Optional, List
+#dependency imports
+from entities import Cart
+
class ICartRepository:
- def get_cart_by_user_id(self, user_id: int) -> Optional[List[dict]]:
+ def get_cart_by_user_id(self, user_id: int) -> Optional[Cart]:
"""
Abstract method to fetch cart data by user ID.
"""
diff --git a/src/use_cases/create_user.py b/src/use_cases/create_user.py
new file mode 100644
index 0000000..b29bde5
--- /dev/null
+++ b/src/use_cases/create_user.py
@@ -0,0 +1,14 @@
+#python imports
+from typing import Optional
+
+#dependency imports
+#TODO: use correct dependencies
+
+class CreateUser:
+ def __init__(self):
+ pass
+ #TODO: initialize required Interfaces
+
+ def execute(self):
+ pass
+ #TODO: implement
\ No newline at end of file
diff --git a/src/use_cases/product_repository.py b/src/use_cases/product_repository.py
index b89b4b7..e5a56df 100644
--- a/src/use_cases/product_repository.py
+++ b/src/use_cases/product_repository.py
@@ -1,13 +1,16 @@
from typing import Optional, List
+#dependency imports
+from entities import Product
+
class IProductRepository:
- def get_product_by_id(self, product_id: int):
+ def get_product_by_id(self, product_id: int) -> Optional[Product]:
"""
Abstract method to fetch product data by ID.
"""
raise NotImplementedError("get_product_by_id must be implemented by a subclass")
- def get_all_products(self):
+ def get_all_products(self) -> Optional[List[Product]]:
"""
Abstract method to fetch product data.
"""
diff --git a/src/use_cases/user_repository.py b/src/use_cases/user_repository.py
index 1952ccc..3cd9182 100644
--- a/src/use_cases/user_repository.py
+++ b/src/use_cases/user_repository.py
@@ -1,8 +1,5 @@
from typing import Optional, List
class IUserRepository:
- def get_user_by_id(self, user_id: int):
- """
- Abstract method to fetch user data by user ID.
- """
- raise NotImplementedError("get_user_by_id must be implemented by a subclass")
\ No newline at end of file
+ pass
+ #TODO: define interface functions for creating and getting user
\ No newline at end of file
diff --git a/src/use_cases/view_all_products.py b/src/use_cases/view_all_products.py
index ded48be..ea41298 100644
--- a/src/use_cases/view_all_products.py
+++ b/src/use_cases/view_all_products.py
@@ -1,5 +1,5 @@
#python imports
-from typing import Optional
+from typing import Optional, List
#dependency imports
from entities import Product
@@ -9,12 +9,11 @@ class ViewAllProducts:
def __init__(self, product_repository: IProductRepository):
self.product_repository = product_repository
- def execute(self) -> Optional[Product]:
+ def execute(self) -> Optional[List[Product]]:
"""
- Fetches the product data from the repository, converts it to Product entity.
+ Fetches the product data from the repository.
"""
product_data = self.product_repository.get_all_products()
if not product_data:
return None
- products = [Product(**product) for product in product_data]
- return products
\ No newline at end of file
+ return product_data
\ No newline at end of file
diff --git a/src/use_cases/view_cart.py b/src/use_cases/view_cart.py
index 3ade8b6..9f7008b 100644
--- a/src/use_cases/view_cart.py
+++ b/src/use_cases/view_cart.py
@@ -11,12 +11,10 @@ class ViewCart:
def execute(self, user_id: int) -> Optional[Cart]:
"""
- Fetches the cart data from the repository, converts it to Cart entity.
+ Fetches the cart data from the repository.
"""
cart_data = self.cart_repository.get_cart_by_user_id(user_id)
if not cart_data:
return None
- # Convert raw data to domain entities
- items = [CartItem(**item) for item in cart_data]
- return Cart(items)
\ No newline at end of file
+ return cart_data
\ No newline at end of file
diff --git a/src/use_cases/view_product.py b/src/use_cases/view_product.py
index 54a3938..271f2f1 100644
--- a/src/use_cases/view_product.py
+++ b/src/use_cases/view_product.py
@@ -11,9 +11,10 @@ class ViewProduct:
def execute(self, product_id: int) -> Optional[Product]:
"""
- Fetches the product data from the repository, converts it to Product entity.
+ Fetches the product data from the repository.
"""
product_data = self.product_repository.get_product_by_id(product_id)
if not product_data:
return None
- return Product(**product_data)
\ No newline at end of file
+
+ return product_data
\ No newline at end of file
diff --git a/src/use_cases/view_user.py b/src/use_cases/view_user.py
new file mode 100644
index 0000000..dab7561
--- /dev/null
+++ b/src/use_cases/view_user.py
@@ -0,0 +1,14 @@
+#python imports
+from typing import Optional
+
+#dependency imports
+#TODO: use correct dependencies
+
+class ViewUser:
+ def __init__(self):
+ pass
+ #TODO: initialize required Interfaces
+
+ def execute(self):
+ pass
+ #TODO: implement
\ No newline at end of file