From 7c6e5ec8253116cda23e9a37e1e27b3f929597ee Mon Sep 17 00:00:00 2001 From: nn2-minh <Nguyen12.Minh@live.uwe.ac.uk> Date: Sat, 15 Mar 2025 17:37:01 +0700 Subject: [PATCH] Add many things --- app/frontend/components/admin/category.py | 51 ++++++++++++++----- app/frontend/components/auth/login.py | 5 +- app/frontend/components/auth/register.py | 24 +++++++-- .../components/product/create_product.py | 27 +++++++--- app/frontend/components/shop/create_shop.py | 8 ++- app/frontend/components/shop/view_shop.py | 49 +++++++++++++----- app/frontend/main.py | 4 +- 7 files changed, 124 insertions(+), 44 deletions(-) diff --git a/app/frontend/components/admin/category.py b/app/frontend/components/admin/category.py index c4d3225..29c239e 100644 --- a/app/frontend/components/admin/category.py +++ b/app/frontend/components/admin/category.py @@ -2,10 +2,13 @@ import customtkinter as ctk import requests from tkinter import messagebox + def category_frame(parent, switch_func, API_URL, access_token): frame = ctk.CTkFrame(parent) - ctk.CTkLabel(frame, text="Category Management", font=("Helvetica", 18, "bold")).pack(pady=10) + ctk.CTkLabel( + frame, text="Category Management", font=("Helvetica", 18, "bold") + ).pack(pady=10) ctk.CTkLabel(frame, text="Category Name:").pack(pady=5) entry_name = ctk.CTkEntry(frame) @@ -24,12 +27,18 @@ def category_frame(parent, switch_func, API_URL, access_token): return try: - response = requests.post(f"{API_URL}/category", data={"name": name}, headers=headers) + response = requests.post( + f"{API_URL}/category", data={"name": name}, headers=headers + ) if response.status_code == 200: - messagebox.showinfo("Success", f"Category '{name}' created successfully!") - entry_name.delete(0, 'end') + messagebox.showinfo( + "Success", f"Category '{name}' created successfully!" + ) + entry_name.delete(0, "end") else: - messagebox.showerror("Error", response.json().get("detail", "Failed to create category")) + messagebox.showerror( + "Error", response.json().get("detail", "Failed to create category") + ) except requests.exceptions.RequestException as e: messagebox.showerror("Error", f"Failed to connect to server: {e}") @@ -39,7 +48,9 @@ def category_frame(parent, switch_func, API_URL, access_token): if response.status_code == 200: categories = response.json() if categories: - category_list = "\n".join([f"{cat['id']}: {cat['name']}" for cat in categories]) + category_list = "\n".join( + [f"{cat['id']}: {cat['name']}" for cat in categories] + ) messagebox.showinfo("Categories", category_list) else: messagebox.showinfo("Categories", "No categories available.") @@ -55,17 +66,25 @@ def category_frame(parent, switch_func, API_URL, access_token): messagebox.showwarning("Input Error", "Enter a valid Category ID!") return if not name: - messagebox.showwarning("Input Error", "Category name is required for update!") + messagebox.showwarning( + "Input Error", "Category name is required for update!" + ) return try: - response = requests.put(f"{API_URL}/category/{category_id}", data={"name": name}, headers=headers) + response = requests.put( + f"{API_URL}/category/{category_id}", + data={"name": name}, + headers=headers, + ) if response.status_code == 200: messagebox.showinfo("Success", "Category updated successfully!") - entry_id.delete(0, 'end') - entry_name.delete(0, 'end') + entry_id.delete(0, "end") + entry_name.delete(0, "end") else: - messagebox.showerror("Error", response.json().get("detail", "Failed to update category")) + messagebox.showerror( + "Error", response.json().get("detail", "Failed to update category") + ) except requests.exceptions.RequestException as e: messagebox.showerror("Error", f"Failed to connect to server: {e}") @@ -76,12 +95,16 @@ def category_frame(parent, switch_func, API_URL, access_token): return try: - response = requests.delete(f"{API_URL}/category/{category_id}", headers=headers) + response = requests.delete( + f"{API_URL}/category/{category_id}", headers=headers + ) if response.status_code == 200: messagebox.showinfo("Success", "Category deleted successfully!") - entry_id.delete(0, 'end') + entry_id.delete(0, "end") else: - messagebox.showerror("Error", response.json().get("detail", "Failed to delete category")) + messagebox.showerror( + "Error", response.json().get("detail", "Failed to delete category") + ) except requests.exceptions.RequestException as e: messagebox.showerror("Error", f"Failed to connect to server: {e}") diff --git a/app/frontend/components/auth/login.py b/app/frontend/components/auth/login.py index b0290cc..64a9f81 100644 --- a/app/frontend/components/auth/login.py +++ b/app/frontend/components/auth/login.py @@ -2,6 +2,7 @@ import customtkinter as ctk from tkinter import messagebox import requests + def login_frame(parent, switch_func, API_URL): frame = ctk.CTkFrame(parent) @@ -24,7 +25,9 @@ def login_frame(parent, switch_func, API_URL): messagebox.showinfo("Login Successful", f"Welcome back, {email}!") switch_func("create_shop", access_token) else: - messagebox.showerror("Login Failed", response_data.get("detail", "Invalid credentials")) + messagebox.showerror( + "Login Failed", response_data.get("detail", "Invalid credentials") + ) except requests.exceptions.JSONDecodeError: messagebox.showerror("Login Failed", "Server returned an invalid response.") diff --git a/app/frontend/components/auth/register.py b/app/frontend/components/auth/register.py index 64b238b..e098132 100644 --- a/app/frontend/components/auth/register.py +++ b/app/frontend/components/auth/register.py @@ -2,6 +2,7 @@ import customtkinter as ctk from tkinter import messagebox import requests + def register_frame(parent, switch_func, API_URL): frame = ctk.CTkFrame(parent) @@ -12,7 +13,13 @@ def register_frame(parent, switch_func, API_URL): password = entry_password.get() confirm_password = entry_confirm_password.get() - if not username or not email or not phone_number or not password or not confirm_password: + if ( + not username + or not email + or not phone_number + or not password + or not confirm_password + ): messagebox.showwarning("Input Error", "All fields are required!") return @@ -22,7 +29,12 @@ def register_frame(parent, switch_func, API_URL): response = requests.post( f"{API_URL}/auth/signup", - json={"username": username, "email": email, "phone_number": phone_number, "password": password}, + json={ + "username": username, + "email": email, + "phone_number": phone_number, + "password": password, + }, ) try: @@ -31,9 +43,13 @@ def register_frame(parent, switch_func, API_URL): messagebox.showinfo("Registration Successful", f"Welcome, {username}!") switch_func("login") else: - messagebox.showerror("Registration Failed", response_data.get("detail", "Unknown error")) + messagebox.showerror( + "Registration Failed", response_data.get("detail", "Unknown error") + ) except requests.exceptions.JSONDecodeError: - messagebox.showerror("Registration Failed", "Server returned an invalid response.") + messagebox.showerror( + "Registration Failed", "Server returned an invalid response." + ) ctk.CTkLabel(frame, text="Register", font=("Helvetica", 18, "bold")).pack(pady=10) diff --git a/app/frontend/components/product/create_product.py b/app/frontend/components/product/create_product.py index 2fc5b7a..b95400c 100644 --- a/app/frontend/components/product/create_product.py +++ b/app/frontend/components/product/create_product.py @@ -2,10 +2,13 @@ import customtkinter as ctk import requests from tkinter import messagebox + def product_frame(parent, switch_func, API_URL, token): frame = ctk.CTkFrame(parent) - ctk.CTkLabel(frame, text="Product Management", font=("Helvetica", 18, "bold")).pack(pady=10) + ctk.CTkLabel(frame, text="Product Management", font=("Helvetica", 18, "bold")).pack( + pady=10 + ) ctk.CTkLabel(frame, text="Product Name:").pack(pady=5) entry_name = ctk.CTkEntry(frame) @@ -32,7 +35,9 @@ def product_frame(parent, switch_func, API_URL, token): price = float(price) stock = int(stock) except ValueError: - messagebox.showwarning("Input Error", "Price must be a number and Stock must be an integer.") + messagebox.showwarning( + "Input Error", "Price must be a number and Stock must be an integer." + ) return headers = {"Authorization": f"Bearer {token}"} @@ -42,17 +47,23 @@ def product_frame(parent, switch_func, API_URL, token): response = requests.post(f"{API_URL}/products", json=data, headers=headers) if response.status_code == 200: - messagebox.showinfo("Success", f"Product '{name}' created successfully!") - entry_name.delete(0, 'end') - entry_price.delete(0, 'end') - entry_stock.delete(0, 'end') + messagebox.showinfo( + "Success", f"Product '{name}' created successfully!" + ) + entry_name.delete(0, "end") + entry_price.delete(0, "end") + entry_stock.delete(0, "end") else: - error_message = response.json().get("detail", "Failed to create product") + error_message = response.json().get( + "detail", "Failed to create product" + ) messagebox.showerror("Error", error_message) except requests.exceptions.RequestException as e: messagebox.showerror("Error", f"Failed to connect to server: {e}") ctk.CTkButton(frame, text="Create Product", command=create_product).pack(pady=15) - ctk.CTkButton(frame, text="Back", command=lambda: switch_func("view_shop")).pack(pady=5) + ctk.CTkButton(frame, text="Back", command=lambda: switch_func("view_shop")).pack( + pady=5 + ) return frame diff --git a/app/frontend/components/shop/create_shop.py b/app/frontend/components/shop/create_shop.py index d7ac4e3..5319ebe 100644 --- a/app/frontend/components/shop/create_shop.py +++ b/app/frontend/components/shop/create_shop.py @@ -63,7 +63,9 @@ def create_shop_frame(parent, switch_func, API_URL, token): except Exception as e: messagebox.showerror("Request Error", str(e)) - ctk.CTkLabel(frame, text="Create Shop", font=("Helvetica", 18, "bold")).pack(pady=10) + ctk.CTkLabel(frame, text="Create Shop", font=("Helvetica", 18, "bold")).pack( + pady=10 + ) ctk.CTkLabel(frame, text="Shop Name:").pack(pady=5) entry_name = ctk.CTkEntry(frame, placeholder_text="Enter shop name") @@ -77,7 +79,9 @@ def create_shop_frame(parent, switch_func, API_URL, token): file_label = ctk.CTkLabel(frame, text="No file selected") file_label.pack(pady=5) - ctk.CTkButton(frame, text="Create Shop", fg_color="green", command=create_shop).pack(pady=15) + ctk.CTkButton( + frame, text="Create Shop", fg_color="green", command=create_shop + ).pack(pady=15) ctk.CTkButton( frame, diff --git a/app/frontend/components/shop/view_shop.py b/app/frontend/components/shop/view_shop.py index 2c10314..a5b9141 100644 --- a/app/frontend/components/shop/view_shop.py +++ b/app/frontend/components/shop/view_shop.py @@ -4,6 +4,7 @@ from tkinter import messagebox from PIL import Image, ImageTk import io + def view_shop_frame(parent, switch_func, API_URL, token): frame = ctk.CTkFrame(parent) @@ -12,10 +13,14 @@ def view_shop_frame(parent, switch_func, API_URL, token): title_label.pack(pady=10) # Shop Details - shop_name_label = ctk.CTkLabel(frame, text="Shop Name: ", font=("Helvetica", 14, "bold")) + shop_name_label = ctk.CTkLabel( + frame, text="Shop Name: ", font=("Helvetica", 14, "bold") + ) shop_name_label.pack(pady=5) - - shop_description_label = ctk.CTkLabel(frame, text="Description: ", font=("Helvetica", 12)) + + shop_description_label = ctk.CTkLabel( + frame, text="Description: ", font=("Helvetica", 12) + ) shop_description_label.pack(pady=5) shop_image_label = ctk.CTkLabel(frame, text="") # Placeholder for shop image @@ -26,14 +31,18 @@ def view_shop_frame(parent, switch_func, API_URL, token): product_list_frame.pack(fill="both", expand=True, padx=10, pady=10) def fetch_shop_data(): - """ Fetch the shop created by the logged-in user """ + """Fetch the shop created by the logged-in user""" headers = {"Authorization": f"Bearer {token}"} try: - response = requests.get(f"{API_URL}/shops/my-shop", headers=headers) # Adjust the endpoint as needed + response = requests.get( + f"{API_URL}/shops/my-shop", headers=headers + ) # Adjust the endpoint as needed if response.status_code == 200: shop_data = response.json() shop_name_label.configure(text=f"Shop Name: {shop_data['name']}") - shop_description_label.configure(text=f"Description: {shop_data.get('description', 'No description')}") + shop_description_label.configure( + text=f"Description: {shop_data.get('description', 'No description')}" + ) # Load and display shop image if available if "image_url" in shop_data and shop_data["image_url"]: @@ -47,7 +56,7 @@ def view_shop_frame(parent, switch_func, API_URL, token): shop_image_label.image = img_tk except Exception: pass - + fetch_products(shop_data["id"]) # Fetch products for this shop else: messagebox.showerror("Error", "Failed to fetch shop details.") @@ -55,10 +64,12 @@ def view_shop_frame(parent, switch_func, API_URL, token): messagebox.showerror("Error", f"Request error: {e}") def fetch_products(shop_id): - """ Fetch products that belong to the user's shop """ + """Fetch products that belong to the user's shop""" headers = {"Authorization": f"Bearer {token}"} try: - response = requests.get(f"{API_URL}/products?shop_id={shop_id}", headers=headers) + response = requests.get( + f"{API_URL}/products?shop_id={shop_id}", headers=headers + ) if response.status_code == 200: products = response.json() display_products(products) @@ -68,12 +79,14 @@ def view_shop_frame(parent, switch_func, API_URL, token): messagebox.showerror("Error", f"Request error: {e}") def display_products(products): - """ Display the list of products in the shop """ + """Display the list of products in the shop""" for widget in product_list_frame.winfo_children(): widget.destroy() if not products: - ctk.CTkLabel(product_list_frame, text="No products found.", font=("Helvetica", 12)).pack(pady=10) + ctk.CTkLabel( + product_list_frame, text="No products found.", font=("Helvetica", 12) + ).pack(pady=10) return for product in products: @@ -102,15 +115,23 @@ def view_shop_frame(parent, switch_func, API_URL, token): details_frame = ctk.CTkFrame(product_frame) details_frame.pack(side="left", fill="x", expand=True, padx=10) - ctk.CTkLabel(details_frame, text=product["name"], font=("Helvetica", 12, "bold")).pack(anchor="w") - ctk.CTkLabel(details_frame, text=f"Price: ${product['price']:.2f}", font=("Helvetica", 12)).pack(anchor="w") + ctk.CTkLabel( + details_frame, text=product["name"], font=("Helvetica", 12, "bold") + ).pack(anchor="w") + ctk.CTkLabel( + details_frame, + text=f"Price: ${product['price']:.2f}", + font=("Helvetica", 12), + ).pack(anchor="w") # Refresh Data Button refresh_button = ctk.CTkButton(frame, text="Refresh", command=fetch_shop_data) refresh_button.pack(pady=10) # Back Button - back_button = ctk.CTkButton(frame, text="Back", command=lambda: switch_func("login")) + back_button = ctk.CTkButton( + frame, text="Back", command=lambda: switch_func("login") + ) back_button.pack(pady=10) # Fetch shop data on load diff --git a/app/frontend/main.py b/app/frontend/main.py index cc8b927..2b14d6b 100644 --- a/app/frontend/main.py +++ b/app/frontend/main.py @@ -12,6 +12,7 @@ API_URL = "http://127.0.0.1:8000" # Global variable to store the access token access_token = None + # Function to switch between frames def switch_frame(frame_name, token=None): global access_token @@ -20,6 +21,7 @@ def switch_frame(frame_name, token=None): frames.get(frame_name, login).tkraise() # Default to login if frame_name is invalid + # Create main window ctk.set_appearance_mode("dark") # Light, Dark, or System ctk.set_default_color_theme("blue") @@ -43,7 +45,7 @@ frames = { "create_shop": create_shop, "create_product": product, "category": category, - "view_shop": view_shop + "view_shop": view_shop, } # Place all frames responsively -- GitLab