From 6bf1f29843abd2c173e3cca87740db23b3f68225 Mon Sep 17 00:00:00 2001
From: nn2-minh <Nguyen12.Minh@live.uwe.ac.uk>
Date: Mon, 17 Mar 2025 22:07:12 +0700
Subject: [PATCH 1/7] Using Ruff for frontend

---
 app/frontend/components/auth/login.py       |  5 ++-
 app/frontend/components/auth/register.py    | 17 +++++++--
 app/frontend/components/dashboard.py        | 40 +++++++++++---------
 app/frontend/components/shop/create_shop.py | 13 +++++--
 app/frontend/components/shop/view_shop.py   | 41 ++++++++++++++++-----
 app/frontend/utils/api_requests.py          | 32 ++++++++++------
 6 files changed, 103 insertions(+), 45 deletions(-)

diff --git a/app/frontend/components/auth/login.py b/app/frontend/components/auth/login.py
index 87b5082..79570d5 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
 from utils.api_requests import login_api  # Import the login function from login_api.py
 
+
 def login_frame(parent, switch_func, API_URL):
     frame = ctk.CTkFrame(parent)
 
@@ -22,7 +23,9 @@ def login_frame(parent, switch_func, API_URL):
             switch_func("view_shop", access_token)
             print(f"Access Token in login: {access_token}")  # Debugging line
         else:
-            messagebox.showerror("Login Failed", response_data.get("detail", "Invalid credentials"))
+            messagebox.showerror(
+                "Login Failed", response_data.get("detail", "Invalid credentials")
+            )
 
     ctk.CTkLabel(frame, text="Login", font=("Helvetica", 18, "bold")).pack(pady=10)
 
diff --git a/app/frontend/components/auth/register.py b/app/frontend/components/auth/register.py
index 01b1b75..1be5aab 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
 from utils.api_requests import register_api  # Import the API function
 
+
 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
 
@@ -21,13 +28,17 @@ def register_frame(parent, switch_func, API_URL):
             return
 
         # Call the API function from register_api.py
-        status_code, response_data = register_api(username, email, phone_number, password, API_URL)
+        status_code, response_data = register_api(
+            username, email, phone_number, password, API_URL
+        )
 
         if status_code == 200:
             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")
+            )
 
     ctk.CTkLabel(frame, text="Register", font=("Helvetica", 18, "bold")).pack(pady=10)
 
diff --git a/app/frontend/components/dashboard.py b/app/frontend/components/dashboard.py
index 32a128a..934e685 100644
--- a/app/frontend/components/dashboard.py
+++ b/app/frontend/components/dashboard.py
@@ -6,8 +6,8 @@ import io
 
 SHOPPING = "#00c1ff"
 
+
 def dashboard_frame(parent, switch_func, API_URL, token):
-    
     # Main container frame
     frame = ctk.CTkFrame(parent, fg_color="transparent")
 
@@ -20,15 +20,13 @@ def dashboard_frame(parent, switch_func, API_URL, token):
         header_frame,
         text="Shopping App",
         text_color="white",
-        font=("Helvetica", 20, "bold")
+        font=("Helvetica", 20, "bold"),
     )
     logo_label.place(relx=0.01, rely=0.1, relwidth=0.15, relheight=0.8)
 
     # Search bar (Center)
     search_entry = ctk.CTkEntry(
-        header_frame,
-        placeholder_text="Search in Shop...",
-        height=30
+        header_frame, placeholder_text="Search in Shop...", height=30
     )
     search_entry.place(relx=0.25, rely=0.25, relwidth=0.45, relheight=0.5)
 
@@ -55,7 +53,7 @@ def dashboard_frame(parent, switch_func, API_URL, token):
         text="Search",
         fg_color="white",
         text_color="black",
-        command=perform_search
+        command=perform_search,
     )
     search_button.place(relx=0.71, rely=0.25, relwidth=0.08, relheight=0.5)
 
@@ -65,26 +63,24 @@ def dashboard_frame(parent, switch_func, API_URL, token):
 
     # Section Title
     featured_label = ctk.CTkLabel(
-        middle_frame,
-        text="TOP SHOP",
-        font=("Helvetica", 16, "bold")
+        middle_frame, text="TOP SHOP", font=("Helvetica", 16, "bold")
     )
     featured_label.pack(pady=5)
 
     # A frame to hold the featured shops
     top_shops_frame = ctk.CTkFrame(middle_frame, fg_color="transparent")
     top_shops_frame.pack(fill="both", expand=True, padx=10, pady=5)
-    
+
     def display_shops(shops, container):
         """Given a list of shop dicts, display them in the given container."""
         # Clear old widgets
         for widget in container.winfo_children():
             widget.destroy()
-        
+
         if not shops:
             ctk.CTkLabel(container, text="No shops found.").pack(pady=10)
             return
-        
+
         # Display shops in a vertical list
         for shop in shops:
             sframe = ctk.CTkFrame(container, corner_radius=5, fg_color="#2b2b2b")
@@ -111,10 +107,16 @@ def dashboard_frame(parent, switch_func, API_URL, token):
             info_frame = ctk.CTkFrame(sframe, fg_color="transparent")
             info_frame.pack(side="left", fill="both", expand=True, padx=10)
 
-            ctk.CTkLabel(info_frame, text=shop.get("name", "No Name"), font=("Helvetica", 13, "bold")).pack(anchor="w")
+            ctk.CTkLabel(
+                info_frame,
+                text=shop.get("name", "No Name"),
+                font=("Helvetica", 13, "bold"),
+            ).pack(anchor="w")
             # Optionally add more shop details, for example a rating if available:
             if shop.get("rating"):
-                ctk.CTkLabel(info_frame, text=f"Rating: {shop['rating']}").pack(anchor="w")
+                ctk.CTkLabel(info_frame, text=f"Rating: {shop['rating']}").pack(
+                    anchor="w"
+                )
 
     # ------------- BOTTOM (Recommendations - Products) -------------
     bottom_frame = ctk.CTkFrame(frame, fg_color="transparent")
@@ -122,9 +124,7 @@ def dashboard_frame(parent, switch_func, API_URL, token):
 
     # Section Title
     recommend_label = ctk.CTkLabel(
-        bottom_frame,
-        text="TODAY'S RECOMMENDATIONS",
-        font=("Helvetica", 16, "bold")
+        bottom_frame, text="TODAY'S RECOMMENDATIONS", font=("Helvetica", 16, "bold")
     )
     recommend_label.pack(pady=5)
 
@@ -167,7 +167,11 @@ def dashboard_frame(parent, switch_func, API_URL, token):
             info_frame = ctk.CTkFrame(pframe, fg_color="transparent")
             info_frame.pack(side="left", fill="both", expand=True, padx=10)
 
-            ctk.CTkLabel(info_frame, text=product.get("name", "No Name"), font=("Helvetica", 13, "bold")).pack(anchor="w")
+            ctk.CTkLabel(
+                info_frame,
+                text=product.get("name", "No Name"),
+                font=("Helvetica", 13, "bold"),
+            ).pack(anchor="w")
             price = product.get("price", 0.0)
             ctk.CTkLabel(info_frame, text=f"Price: {price:.2f}").pack(anchor="w")
 
diff --git a/app/frontend/components/shop/create_shop.py b/app/frontend/components/shop/create_shop.py
index ed6ba4b..e73fb5b 100644
--- a/app/frontend/components/shop/create_shop.py
+++ b/app/frontend/components/shop/create_shop.py
@@ -3,6 +3,7 @@ from tkinter import messagebox, filedialog
 import os
 from utils.api_requests import create_shop_api  # Import API function
 
+
 def create_shop_frame(parent, switch_func, API_URL, token):
     frame = ctk.CTkFrame(parent)
     frame.access_token = token
@@ -39,9 +40,13 @@ def create_shop_frame(parent, switch_func, API_URL, token):
         if status_code == 200:
             messagebox.showinfo("Shop Created", f"Shop '{name}' created successfully!")
         else:
-            messagebox.showerror("Error", response_data.get("detail", "An error occurred"))
+            messagebox.showerror(
+                "Error", response_data.get("detail", "An error occurred")
+            )
 
-    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")
@@ -55,7 +60,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, text="Back", fg_color="transparent", command=lambda: switch_func("login")
diff --git a/app/frontend/components/shop/view_shop.py b/app/frontend/components/shop/view_shop.py
index 2c10665..3c4ae23 100644
--- a/app/frontend/components/shop/view_shop.py
+++ b/app/frontend/components/shop/view_shop.py
@@ -1,7 +1,12 @@
 import customtkinter as ctk
 from tkinter import messagebox
 from PIL import ImageTk
-from utils.api_requests import fetch_shop_details, fetch_shop_products, load_image_from_url
+from utils.api_requests import (
+    fetch_shop_details,
+    fetch_shop_products,
+    load_image_from_url,
+)
+
 
 def view_shop_frame(parent, switch_func, API_URL, token):
     frame = ctk.CTkFrame(parent)
@@ -11,10 +16,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
@@ -33,7 +42,9 @@ def view_shop_frame(parent, switch_func, API_URL, token):
             return
 
         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')}"
+        )
 
         if "image_url" in shop_data and shop_data["image_url"]:
             image = load_image_from_url(shop_data["image_url"])
@@ -56,7 +67,9 @@ def view_shop_frame(parent, switch_func, API_URL, token):
             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:
@@ -79,15 +92,25 @@ 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 Button
-    refresh_button = ctk.CTkButton(frame, text="Refresh", command=fetch_and_display_shop)
+    refresh_button = ctk.CTkButton(
+        frame, text="Refresh", command=fetch_and_display_shop
+    )
     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/utils/api_requests.py b/app/frontend/utils/api_requests.py
index 4f50771..d17146c 100644
--- a/app/frontend/utils/api_requests.py
+++ b/app/frontend/utils/api_requests.py
@@ -2,28 +2,32 @@ import requests
 from PIL import Image
 import io
 
-#Login API
+
+# Login API
 def login_api(email, password, api_url):
     """
     Sends login request to the API.
-    
+
     :param email: User's email
     :param password: User's password
     :param api_url: Base API URL
     :return: Tuple (status_code, response_data)
     """
     try:
-        response = requests.post(f"{api_url}/auth/login", json={"email": email, "password": password})
+        response = requests.post(
+            f"{api_url}/auth/login", json={"email": email, "password": password}
+        )
         response.raise_for_status()  # Raise an error for 4xx and 5xx responses
         return response.status_code, response.json()  # Return status and response data
     except requests.exceptions.RequestException as e:
         return None, {"error": str(e)}  # Return error message if request fails
 
-#Register API
+
+# Register API
 def register_api(username, email, phone_number, password, api_url):
     """
     Sends a registration request to the API.
-    
+
     :param username: User's username
     :param email: User's email
     :param phone_number: User's phone number
@@ -46,7 +50,8 @@ def register_api(username, email, phone_number, password, api_url):
     except requests.exceptions.RequestException as e:
         return None, {"detail": str(e)}  # Return error message if request fails
 
-#Create Shop
+
+# Create Shop
 def create_shop_api(name, description, file_path, api_url, access_token):
     """
     Sends a request to create a shop with optional image upload.
@@ -81,7 +86,8 @@ def create_shop_api(name, description, file_path, api_url, access_token):
     except requests.exceptions.RequestException as e:
         return None, {"detail": str(e)}
 
-#View Shop
+
+# View Shop
 def fetch_shop_details(api_url, token, shop_id=1):
     """
     Fetches details of the shop owned by the logged-in user.
@@ -101,7 +107,8 @@ def fetch_shop_details(api_url, token, shop_id=1):
     except requests.exceptions.RequestException as e:
         return {"error": str(e)}
 
-#Fetch Products
+
+# Fetch Products
 def fetch_shop_products(api_url, token, shop_id):
     """
     Fetches products for a given shop.
@@ -113,7 +120,9 @@ def fetch_shop_products(api_url, token, shop_id):
     """
     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:
             return response.json()
         else:
@@ -121,7 +130,8 @@ def fetch_shop_products(api_url, token, shop_id):
     except requests.exceptions.RequestException as e:
         return {"error": str(e)}
 
-#Load Image from URL
+
+# Load Image from URL
 def load_image_from_url(image_url, size=(150, 150)):
     """
     Loads and resizes an image from a given URL.
@@ -136,4 +146,4 @@ def load_image_from_url(image_url, size=(150, 150)):
         image = image.resize(size)
         return image
     except Exception:
-        return None
\ No newline at end of file
+        return None
-- 
GitLab


From b31e9f3dd1a9b02eb53c82ad03741b1c8821bc45 Mon Sep 17 00:00:00 2001
From: nn2-minh <Nguyen12.Minh@live.uwe.ac.uk>
Date: Mon, 17 Mar 2025 22:59:50 +0700
Subject: [PATCH 2/7] Fix color for main.py in the frontend

---
 app/frontend/main.py | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/app/frontend/main.py b/app/frontend/main.py
index 62b98c4..7deb904 100644
--- a/app/frontend/main.py
+++ b/app/frontend/main.py
@@ -1,4 +1,3 @@
-# main.py
 import customtkinter as ctk
 from components.auth.login import login_frame
 from components.auth.register import register_frame
@@ -28,7 +27,7 @@ ctk.set_default_color_theme("blue")
 
 root = ctk.CTk()
 root.title("Shopping App")
-root.geometry("900x800")
+root.geometry("1000x800")
 
 # Create Frames
 login = login_frame(root, switch_frame, API_URL)
@@ -37,9 +36,7 @@ create_shop = create_shop_frame(root, switch_frame, API_URL, access_token)
 view_shop = view_shop_frame(root, switch_frame, API_URL, access_token)
 product = product_frame(root, switch_frame, API_URL, access_token)
 category = category_frame(root, switch_frame, API_URL, access_token)
-dashboard = dashboard_frame(
-    root, switch_frame, API_URL, access_token
-)  # new dashboard frame
+dashboard = dashboard_frame(root, switch_frame, API_URL, access_token)
 
 frames = {
     "login": login,
@@ -48,13 +45,13 @@ frames = {
     "create_product": product,
     "category": category,
     "view_shop": view_shop,
-    "dashboard": dashboard,  # add dashboard here
+    "dashboard": dashboard,
 }
 
 for frame in frames.values():
-    frame.place(relx=0, rely=0, relwidth=1, relheight=0.8)
+    frame.place(relx=0, rely=0, relwidth=1, relheight=1)  # Adjusted height for full scaling
 
-# Show the login frame first (or switch to dashboard as needed)
-switch_frame("login")  # switch to dashboard
+# Show the login frame first
+switch_frame("login")
 
 root.mainloop()
-- 
GitLab


From aba7ea1ec0363ea9f6490c997bdec1a531320c35 Mon Sep 17 00:00:00 2001
From: nn2-minh <Nguyen12.Minh@live.uwe.ac.uk>
Date: Mon, 17 Mar 2025 23:58:22 +0700
Subject: [PATCH 3/7] Modified .gitignore and change frontend components

---
 .gitignore                            |   3 +-
 app/frontend/components/auth/login.py |  38 +++++++++++++++++++-------
 app/frontend/main.py                  |   4 ++-
 app/static/front_end_img/login.jpg    | Bin 0 -> 70252 bytes
 4 files changed, 33 insertions(+), 12 deletions(-)
 create mode 100644 app/static/front_end_img/login.jpg

diff --git a/.gitignore b/.gitignore
index cee315c..5085a4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,4 +8,5 @@ __pycache__
 
 # ignore all files in the static folder except the default folder
 app/static/*
-!app/static/default/
\ No newline at end of file
+!app/static/default/
+!app/static/front_end_img/
\ No newline at end of file
diff --git a/app/frontend/components/auth/login.py b/app/frontend/components/auth/login.py
index 79570d5..38f9228 100644
--- a/app/frontend/components/auth/login.py
+++ b/app/frontend/components/auth/login.py
@@ -1,10 +1,28 @@
 import customtkinter as ctk
 from tkinter import messagebox
+from PIL import Image
 from utils.api_requests import login_api  # Import the login function from login_api.py
 
-
 def login_frame(parent, switch_func, API_URL):
-    frame = ctk.CTkFrame(parent)
+    # Create a container frame to hold both left (empty) and right (login) frames
+    container = ctk.CTkFrame(parent)
+    container.grid_columnconfigure(0, weight=1)  # Left empty frame
+    container.grid_columnconfigure(1, weight=1)  # Right login frame
+    container.grid_rowconfigure(0, weight=1)
+
+    # Left empty frame (Just an empty frame to balance the layout)
+    left_frame = ctk.CTkFrame(container)
+    left_frame.grid(row=0, column=0, sticky="nsew")
+
+    # Load and display the image
+    image_path = "app\static\login.jpg"  # Change this to your image path
+    img = ctk.CTkImage(light_image=Image.open(image_path), size=(1000, 1000))  # Resize as needed
+    image_label = ctk.CTkLabel(left_frame, image=img, text="")  # No text, only image
+    image_label.place(relwidth=1, relheight=1)
+    
+    # Right login frame
+    right_frame = ctk.CTkFrame(container)
+    right_frame.grid(row=0, column=1, sticky="nsew")
 
     def login():
         email = entry_email.get()
@@ -27,22 +45,22 @@ def login_frame(parent, switch_func, API_URL):
                 "Login Failed", response_data.get("detail", "Invalid credentials")
             )
 
-    ctk.CTkLabel(frame, text="Login", font=("Helvetica", 18, "bold")).pack(pady=10)
+    ctk.CTkLabel(right_frame, text="Login", font=("Helvetica", 18, "bold")).pack(pady=10)
 
-    ctk.CTkLabel(frame, text="Email:").pack(pady=5)
-    entry_email = ctk.CTkEntry(frame)
+    ctk.CTkLabel(right_frame, text="Email:").pack(pady=5)
+    entry_email = ctk.CTkEntry(right_frame)
     entry_email.pack(pady=5)
 
-    ctk.CTkLabel(frame, text="Password:").pack(pady=5)
-    entry_password = ctk.CTkEntry(frame, show="*")
+    ctk.CTkLabel(right_frame, text="Password:").pack(pady=5)
+    entry_password = ctk.CTkEntry(right_frame, show="*")
     entry_password.pack(pady=5)
 
-    ctk.CTkButton(frame, text="Login", command=login).pack(pady=15)
+    ctk.CTkButton(right_frame, text="Login", command=login).pack(pady=15)
 
     ctk.CTkButton(
-        frame,
+        right_frame,
         text="Don't have an account? Register",
         command=lambda: switch_func("register"),
     ).pack()
 
-    return frame
+    return container
diff --git a/app/frontend/main.py b/app/frontend/main.py
index 7deb904..6773394 100644
--- a/app/frontend/main.py
+++ b/app/frontend/main.py
@@ -49,7 +49,9 @@ frames = {
 }
 
 for frame in frames.values():
-    frame.place(relx=0, rely=0, relwidth=1, relheight=1)  # Adjusted height for full scaling
+    frame.place(
+        relx=0, rely=0, relwidth=1, relheight=1
+    )  # Adjusted height for full scaling
 
 # Show the login frame first
 switch_frame("login")
diff --git a/app/static/front_end_img/login.jpg b/app/static/front_end_img/login.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..b8235c6d4067b453380179dda20c7c72e6da8ab5
GIT binary patch
literal 70252
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

literal 0
HcmV?d00001

-- 
GitLab


From b08671256f4f8d3a623beebca597b39c9f4a7444 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20Minh?= <w11220031@st.phenikaa-uni.edu.vn>
Date: Tue, 18 Mar 2025 09:42:42 +0700
Subject: [PATCH 4/7] Modified login frontend

---
 app/frontend/components/auth/login.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/frontend/components/auth/login.py b/app/frontend/components/auth/login.py
index 38f9228..f2330a5 100644
--- a/app/frontend/components/auth/login.py
+++ b/app/frontend/components/auth/login.py
@@ -15,7 +15,7 @@ def login_frame(parent, switch_func, API_URL):
     left_frame.grid(row=0, column=0, sticky="nsew")
 
     # Load and display the image
-    image_path = "app\static\login.jpg"  # Change this to your image path
+    image_path = "app/static/front_end_img/login.jpg"  # Change this to your image path
     img = ctk.CTkImage(light_image=Image.open(image_path), size=(1000, 1000))  # Resize as needed
     image_label = ctk.CTkLabel(left_frame, image=img, text="")  # No text, only image
     image_label.place(relwidth=1, relheight=1)
-- 
GitLab


From f2245f5f07e10e2aab12b0ee1291af4c09d2bc7d Mon Sep 17 00:00:00 2001
From: nn2-minh <Nguyen12.Minh@live.uwe.ac.uk>
Date: Tue, 25 Mar 2025 21:55:18 +0700
Subject: [PATCH 5/7] Add user_details and orders

---
 app/frontend/components/auth/login.py   |  13 +-
 app/frontend/components/dashboard.py    |  67 ++++++
 app/frontend/components/user_details.py | 297 ++++++++++++++++++++++++
 app/frontend/components/user_orders.py  | 228 ++++++++++++++++++
 app/frontend/main.py                    |   8 +-
 requirements.txt                        | Bin 1045 -> 2206 bytes
 6 files changed, 608 insertions(+), 5 deletions(-)
 create mode 100644 app/frontend/components/user_details.py
 create mode 100644 app/frontend/components/user_orders.py

diff --git a/app/frontend/components/auth/login.py b/app/frontend/components/auth/login.py
index f2330a5..79f360b 100644
--- a/app/frontend/components/auth/login.py
+++ b/app/frontend/components/auth/login.py
@@ -3,6 +3,7 @@ from tkinter import messagebox
 from PIL import Image
 from utils.api_requests import login_api  # Import the login function from login_api.py
 
+
 def login_frame(parent, switch_func, API_URL):
     # Create a container frame to hold both left (empty) and right (login) frames
     container = ctk.CTkFrame(parent)
@@ -16,10 +17,12 @@ def login_frame(parent, switch_func, API_URL):
 
     # Load and display the image
     image_path = "app/static/front_end_img/login.jpg"  # Change this to your image path
-    img = ctk.CTkImage(light_image=Image.open(image_path), size=(1000, 1000))  # Resize as needed
+    img = ctk.CTkImage(
+        light_image=Image.open(image_path), size=(1000, 1000)
+    )  # Resize as needed
     image_label = ctk.CTkLabel(left_frame, image=img, text="")  # No text, only image
     image_label.place(relwidth=1, relheight=1)
-    
+
     # Right login frame
     right_frame = ctk.CTkFrame(container)
     right_frame.grid(row=0, column=1, sticky="nsew")
@@ -38,14 +41,16 @@ def login_frame(parent, switch_func, API_URL):
         if status_code == 200:
             access_token = response_data.get("access_token")
             messagebox.showinfo("Login Successful", f"Welcome back, {email}!")
-            switch_func("view_shop", access_token)
+            switch_func("dashboard", access_token)
             print(f"Access Token in login: {access_token}")  # Debugging line
         else:
             messagebox.showerror(
                 "Login Failed", response_data.get("detail", "Invalid credentials")
             )
 
-    ctk.CTkLabel(right_frame, text="Login", font=("Helvetica", 18, "bold")).pack(pady=10)
+    ctk.CTkLabel(right_frame, text="Login", font=("Helvetica", 18, "bold")).pack(
+        pady=10
+    )
 
     ctk.CTkLabel(right_frame, text="Email:").pack(pady=5)
     entry_email = ctk.CTkEntry(right_frame)
diff --git a/app/frontend/components/dashboard.py b/app/frontend/components/dashboard.py
index 934e685..75622c9 100644
--- a/app/frontend/components/dashboard.py
+++ b/app/frontend/components/dashboard.py
@@ -57,6 +57,73 @@ def dashboard_frame(parent, switch_func, API_URL, token):
     )
     search_button.place(relx=0.71, rely=0.25, relwidth=0.08, relheight=0.5)
 
+    # ------------- USER & CART ICONS (Top-Right) -------------
+    def open_user_details():
+        # Switch to user_details.py screen or run it
+        switch_func("user_details")
+        # Alternatively, use os.system("python user_details.py")
+
+    def open_cart_details():
+        # Switch to cart_shopping.py screen or run it
+        switch_func("cart_shopping")
+        # Alternatively, use os.system("python cart_shopping.py")
+
+    # Try loading icon images; update paths as needed.
+    try:
+        user_image = Image.open("path/to/user_icon.png").resize((30, 30))
+        user_icon = ImageTk.PhotoImage(user_image)
+    except Exception as e:
+        print(f"User icon load error: {e}")
+        user_icon = None
+
+    try:
+        cart_image = Image.open("path/to/cart_icon.png").resize((30, 30))
+        cart_icon = ImageTk.PhotoImage(cart_image)
+    except Exception as e:
+        print(f"Cart icon load error: {e}")
+        cart_icon = None
+
+    if user_icon:
+        user_button = ctk.CTkButton(
+            header_frame,
+            image=user_icon,
+            text="",
+            fg_color="transparent",
+            command=open_user_details,
+        )
+        switch_func("user_details")
+        user_button.image = user_icon
+        user_button.place(relx=0.82, rely=0.25, relwidth=0.08, relheight=0.5)
+    else:
+        user_button = ctk.CTkButton(
+            header_frame,
+            text="User",
+            fg_color="white",
+            text_color="black",
+            command=open_user_details,
+        )
+        user_button.place(relx=0.82, rely=0.25, relwidth=0.08, relheight=0.5)
+
+    if cart_icon:
+        cart_button = ctk.CTkButton(
+            header_frame,
+            image=cart_icon,
+            text="",
+            fg_color="transparent",
+            command=open_cart_details,
+        )
+        cart_button.image = cart_icon
+        cart_button.place(relx=0.91, rely=0.25, relwidth=0.08, relheight=0.5)
+    else:
+        cart_button = ctk.CTkButton(
+            header_frame,
+            text="Cart",
+            fg_color="white",
+            text_color="black",
+            command=open_cart_details,
+        )
+        cart_button.place(relx=0.91, rely=0.25, relwidth=0.08, relheight=0.5)
+
     # ------------- MIDDLE (Featured/Top Shops) -------------
     middle_frame = ctk.CTkFrame(frame, fg_color="transparent")
     middle_frame.place(relx=0, rely=0.1, relwidth=1, relheight=0.25)
diff --git a/app/frontend/components/user_details.py b/app/frontend/components/user_details.py
new file mode 100644
index 0000000..7a49032
--- /dev/null
+++ b/app/frontend/components/user_details.py
@@ -0,0 +1,297 @@
+import customtkinter as ctk
+import requests
+from PIL import Image, ImageTk
+from tkinter import messagebox, filedialog
+import io
+
+SHOPPING = "#00c1ff"
+
+def user_details_frame(parent, switch_func, API_URL, token):
+    """
+    A two-column user details page that matches the dashboard color scheme:
+      - Top bar with SHOPPING color (#00c1ff)
+      - Left sidebar with a dark background (#2b2b2b)
+      - Right content area (profile form, profile picture)
+    """
+
+    # Main container frame (transparent background, like dashboard)
+    frame = ctk.CTkFrame(parent, fg_color="transparent")
+
+    # ----------------- TOP BAR -----------------
+    top_bar = ctk.CTkFrame(frame, fg_color=SHOPPING, height=40)
+    top_bar.pack(fill="x", side="top")
+
+    top_label = ctk.CTkLabel(
+        top_bar,
+        text="My Profile",
+        text_color="white",
+        font=("Helvetica", 16, "bold"),
+    )
+    top_label.pack(side="left", padx=20)
+
+    def go_back():
+        switch_func("dashboard")
+
+    back_button = ctk.CTkButton(
+        top_bar,
+        text="Back",
+        fg_color="white",
+        text_color="black",
+        command=go_back,
+        width=60,
+        height=30,
+    )
+    back_button.pack(side="right", padx=20, pady=5)
+
+    # ----------------- MAIN SECTION (Sidebar + Content) -----------------
+    main_section = ctk.CTkFrame(frame, fg_color="transparent")
+    main_section.pack(fill="both", expand=True)
+
+    # ----------------- LEFT SIDEBAR -----------------
+
+    sidebar_frame = ctk.CTkFrame(main_section, width=200, fg_color="#2b2b2b")
+    sidebar_frame.pack(side="left", fill="y")
+
+    sidebar_title = ctk.CTkLabel(
+        sidebar_frame, 
+        text="Menu", 
+        font=("Helvetica", 14, "bold"), 
+        text_color="white"
+    )
+    sidebar_title.pack(pady=(10, 5))
+
+    nav_dashboard = ctk.CTkButton(
+        sidebar_frame,
+        text="Dashboard",
+        fg_color="#2b2b2b",
+        text_color="white",
+        hover_color="#3b3b3b",
+        command=go_back
+    )
+    nav_dashboard.pack(fill="x", padx=10, pady=5)
+
+    nav_profile = ctk.CTkButton(
+        sidebar_frame,
+        text="My Profile",
+        fg_color="#3b3b3b",  # Active/selected state
+        text_color="white",
+        hover_color="#3b3b3b",
+        state="disabled"
+    )
+    nav_profile.pack(fill="x", padx=10, pady=5)
+
+    nav_orders = ctk.CTkButton(
+        sidebar_frame,
+        text="My Orders",
+        fg_color="#2b2b2b",
+        text_color="white",
+        hover_color="#3b3b3b",
+        command=lambda: switch_func("user_orders")
+    )
+    nav_orders.pack(fill="x", padx=10, pady=5)
+
+    nav_address = ctk.CTkButton(
+        sidebar_frame,
+        text="Address Book",
+        fg_color="#2b2b2b",
+        text_color="white",
+        hover_color="#3b3b3b",
+        command=lambda: messagebox.showinfo("Info", "Address Book clicked!")
+    )
+    nav_address.pack(fill="x", padx=10, pady=5)
+
+    # ----------------- RIGHT CONTENT (User Details) -----------------
+    content_frame = ctk.CTkFrame(main_section, fg_color="transparent")
+    content_frame.pack(side="left", fill="both", expand=True, padx=20, pady=20)
+
+    # Title / Subtitle
+    title_label = ctk.CTkLabel(
+        content_frame,
+        text="My Profile",
+        font=("Helvetica", 18, "bold"),
+        text_color="white"
+    )
+    title_label.pack(anchor="w", pady=(0, 5))
+
+    subtitle_label = ctk.CTkLabel(
+        content_frame,
+        text="Manage your profile information to keep your account secure",
+        font=("Helvetica", 12),
+        text_color="#cccccc"
+    )
+    subtitle_label.pack(anchor="w", pady=(0, 15))
+
+    # -- Split the right content into two frames: Left form & Right picture --
+    right_main = ctk.CTkFrame(content_frame, fg_color="transparent")
+    right_main.pack(fill="both", expand=True)
+
+    # LEFT FORM
+    form_frame = ctk.CTkFrame(right_main, fg_color="transparent")
+    form_frame.pack(side="left", fill="both", expand=True, padx=(0, 20))
+
+    # Username
+    username_label = ctk.CTkLabel(form_frame, text="Username", font=("Helvetica", 12), text_color="white")
+    username_label.pack(anchor="w")
+    username_entry = ctk.CTkEntry(form_frame, placeholder_text="Enter your username...")
+    username_entry.pack(anchor="w", pady=(0, 10))
+
+    # Name
+    name_label = ctk.CTkLabel(form_frame, text="Name", font=("Helvetica", 12), text_color="white")
+    name_label.pack(anchor="w")
+    name_entry = ctk.CTkEntry(form_frame, placeholder_text="Enter your name...")
+    name_entry.pack(anchor="w", pady=(0, 10))
+
+    # Email
+    email_label = ctk.CTkLabel(form_frame, text="Email", font=("Helvetica", 12), text_color="white")
+    email_label.pack(anchor="w")
+    email_entry = ctk.CTkEntry(form_frame, placeholder_text="Enter your email...")
+    email_entry.pack(anchor="w", pady=(0, 10))
+
+    # Phone
+    phone_label = ctk.CTkLabel(form_frame, text="Phone", font=("Helvetica", 12), text_color="white")
+    phone_label.pack(anchor="w")
+    phone_entry = ctk.CTkEntry(form_frame, placeholder_text="Enter your phone...")
+    phone_entry.pack(anchor="w", pady=(0, 10))
+
+    # Gender
+    gender_label = ctk.CTkLabel(form_frame, text="Gender", font=("Helvetica", 12), text_color="white")
+    gender_label.pack(anchor="w", pady=(10, 0))
+
+    gender_var = ctk.StringVar(value="Male")  # Default
+    gender_frame = ctk.CTkFrame(form_frame, fg_color="transparent")
+    gender_frame.pack(anchor="w", pady=5)
+
+    male_radio = ctk.CTkRadioButton(gender_frame, text="Male", variable=gender_var, value="Male", text_color="white")
+    female_radio = ctk.CTkRadioButton(gender_frame, text="Female", variable=gender_var, value="Female", text_color="white")
+    other_radio = ctk.CTkRadioButton(gender_frame, text="Other", variable=gender_var, value="Other", text_color="white")
+    male_radio.pack(side="left", padx=5)
+    female_radio.pack(side="left", padx=5)
+    other_radio.pack(side="left", padx=5)
+
+    # Birthday
+    birthday_label = ctk.CTkLabel(form_frame, text="Date of Birth", font=("Helvetica", 12), text_color="white")
+    birthday_label.pack(anchor="w", pady=(10, 0))
+    birthday_entry = ctk.CTkEntry(form_frame, placeholder_text="dd/mm/yyyy")
+    birthday_entry.pack(anchor="w", pady=(0, 10))
+
+    # Save Button
+    def save_profile():
+        """
+        Example: Send a request to update user details.
+        Adjust the endpoint and payload for your backend.
+        """
+        headers = {"Authorization": f"Bearer {token}"}
+        payload = {
+            "username": username_entry.get().strip(),
+            "name": name_entry.get().strip(),
+            "email": email_entry.get().strip(),
+            "phone": phone_entry.get().strip(),
+            "gender": gender_var.get(),
+            "birthday": birthday_entry.get().strip()
+        }
+        try:
+            resp = requests.put(f"{API_URL}/user/update", headers=headers, json=payload)
+            if resp.status_code == 200:
+                messagebox.showinfo("Success", "Profile updated successfully!")
+            else:
+                messagebox.showerror("Error", "Unable to update profile.")
+        except Exception as e:
+            messagebox.showerror("Error", f"Request error: {e}")
+
+    save_button = ctk.CTkButton(
+        form_frame,
+        text="Save",
+        fg_color=SHOPPING,  # #00c1ff
+        text_color="white",
+        command=save_profile,
+        width=80
+    )
+    save_button.pack(anchor="w", pady=(20, 10))
+
+    # RIGHT PICTURE SECTION
+    pic_frame = ctk.CTkFrame(right_main, fg_color="transparent")
+    pic_frame.pack(side="left", fill="both", expand=True)
+
+    pic_label = ctk.CTkLabel(pic_frame, text="Profile Picture", font=("Helvetica", 12, "bold"), text_color="white")
+    pic_label.pack(anchor="w", pady=(0, 10))
+
+    photo_label = ctk.CTkLabel(pic_frame, text="No image", text_color="white")
+    photo_label.pack(anchor="w", pady=(0, 10))
+
+    def choose_photo():
+        """
+        Let the user pick a photo from their files.
+        Then optionally upload it or just display it.
+        """
+        file_path = filedialog.askopenfilename(
+            title="Choose a Profile Picture",
+            filetypes=[("Image Files", "*.png *.jpg *.jpeg *.gif")]
+        )
+        if file_path:
+            # Display chosen image
+            try:
+                pil_img = Image.open(file_path).resize((100, 100))
+                tk_img = ImageTk.PhotoImage(pil_img)
+                photo_label.configure(image=tk_img, text="")
+                photo_label.image = tk_img
+
+                # Optionally, upload the file to your server:
+                # headers = {"Authorization": f"Bearer {token}"}
+                # with open(file_path, 'rb') as f:
+                #     requests.post(f'{API_URL}/user/upload_photo', files={'file': f}, headers=headers)
+            except Exception as e:
+                print(f"Image load error: {e}")
+                messagebox.showerror("Error", "Cannot load the image.")
+
+    change_photo_button = ctk.CTkButton(
+        pic_frame,
+        text="Choose Image",
+        fg_color="white",
+        text_color="black",
+        command=choose_photo,
+        width=80
+    )
+    change_photo_button.pack(anchor="w")
+
+    # Fetch existing user info (if needed)
+    def fetch_user_info():
+        """
+        Fetch the user's existing data to populate the form fields.
+        """
+        headers = {"Authorization": f"Bearer {token}"}
+        try:
+            resp = requests.get(f"{API_URL}/user/profile", headers=headers)
+            if resp.status_code == 200:
+                data = resp.json()
+                username_entry.delete(0, "end")
+                username_entry.insert(0, data.get("username", ""))
+                name_entry.delete(0, "end")
+                name_entry.insert(0, data.get("name", ""))
+                email_entry.delete(0, "end")
+                email_entry.insert(0, data.get("email", ""))
+                phone_entry.delete(0, "end")
+                phone_entry.insert(0, data.get("phone", ""))
+                gender_var.set(data.get("gender", "Male"))
+                birthday_entry.delete(0, "end")
+                birthday_entry.insert(0, data.get("birthday", ""))
+
+                # If there's a profile picture URL, load it
+                pic_url = data.get("photo_url")
+                if pic_url:
+                    try:
+                        resp_pic = requests.get(pic_url)
+                        if resp_pic.status_code == 200:
+                            pil_img = Image.open(io.BytesIO(resp_pic.content)).resize((100, 100))
+                            tk_img = ImageTk.PhotoImage(pil_img)
+                            photo_label.configure(image=tk_img, text="")
+                            photo_label.image = tk_img
+                    except Exception as e:
+                        print(f"Profile picture load error: {e}")
+            else:
+                messagebox.showerror("Error", "Unable to retrieve user information.")
+        except Exception as e:
+            messagebox.showerror("Error", f"Request error: {e}")
+
+    fetch_user_info()
+
+    return frame
diff --git a/app/frontend/components/user_orders.py b/app/frontend/components/user_orders.py
new file mode 100644
index 0000000..b71b34f
--- /dev/null
+++ b/app/frontend/components/user_orders.py
@@ -0,0 +1,228 @@
+import customtkinter as ctk
+import requests
+from PIL import Image, ImageTk
+from tkinter import messagebox
+import io
+
+SHOPPING = "#00c1ff"
+
+def user_orders_frame(parent, switch_func, API_URL, token):
+    """
+    A two-column user orders page that displays the products the user has purchased 
+    along with associated shop details. The layout and color scheme match your dashboard.
+    """
+
+    # Main container frame with transparent background
+    frame = ctk.CTkFrame(parent, fg_color="transparent")
+
+    # ----------------- TOP BAR -----------------
+    top_bar = ctk.CTkFrame(frame, fg_color=SHOPPING, height=40)
+    top_bar.pack(fill="x", side="top")
+
+    top_label = ctk.CTkLabel(
+        top_bar,
+        text="My Orders",
+        text_color="white",
+        font=("Helvetica", 16, "bold")
+    )
+    top_label.pack(side="left", padx=20)
+
+    def go_back():
+        switch_func("dashboard")
+
+    back_button = ctk.CTkButton(
+        top_bar,
+        text="Back",
+        fg_color="white",
+        text_color="black",
+        command=go_back,
+        width=60,
+        height=30
+    )
+    back_button.pack(side="right", padx=20, pady=5)
+
+    # ----------------- MAIN SECTION (Sidebar + Content) -----------------
+    main_section = ctk.CTkFrame(frame, fg_color="transparent")
+    main_section.pack(fill="both", expand=True)
+
+    # ----------------- LEFT SIDEBAR -----------------
+    sidebar_frame = ctk.CTkFrame(main_section, width=200, fg_color="#2b2b2b")
+    sidebar_frame.pack(side="left", fill="y")
+
+    sidebar_title = ctk.CTkLabel(
+        sidebar_frame,
+        text="Menu",
+        font=("Helvetica", 14, "bold"),
+        text_color="white"
+    )
+    sidebar_title.pack(pady=(10, 5))
+
+    def open_profile():
+        switch_func("user_details")
+
+    nav_dashboard = ctk.CTkButton(
+        sidebar_frame,
+        text="Dashboard",
+        fg_color="#2b2b2b",
+        text_color="white",
+        hover_color="#3b3b3b",
+        command=go_back
+    )
+    nav_dashboard.pack(fill="x", padx=10, pady=5)
+
+    nav_profile = ctk.CTkButton(
+        sidebar_frame,
+        text="My Profile",
+        fg_color="#2b2b2b",
+        text_color="white",
+        hover_color="#3b3b3b",
+        command=open_profile
+    )
+    nav_profile.pack(fill="x", padx=10, pady=5)
+
+    nav_orders = ctk.CTkButton(
+        sidebar_frame,
+        text="My Orders",
+        fg_color="#3b3b3b",  # Active/selected state
+        text_color="white",
+        hover_color="#3b3b3b",
+        state="disabled"
+    )
+    nav_orders.pack(fill="x", padx=10, pady=5)
+
+    # ----------------- RIGHT CONTENT (Orders List) -----------------
+    content_frame = ctk.CTkFrame(main_section, fg_color="transparent")
+    content_frame.pack(side="left", fill="both", expand=True, padx=20, pady=20)
+
+    main_title_label = ctk.CTkLabel(
+        content_frame,
+        text="Your Orders",
+        font=("Helvetica", 18, "bold"),
+        text_color="white"
+    )
+    main_title_label.pack(anchor="w", pady=(0, 5))
+
+    subtitle_label = ctk.CTkLabel(
+        content_frame,
+        text="Review the products you have purchased.",
+        font=("Helvetica", 12),
+        text_color="#cccccc"
+    )
+    subtitle_label.pack(anchor="w", pady=(0, 15))
+
+    # A frame to hold the list of orders
+    orders_list_frame = ctk.CTkFrame(content_frame, fg_color="transparent")
+    orders_list_frame.pack(fill="both", expand=True)
+
+    # ----------- Functions to fetch and display orders -----------
+    def fetch_orders():
+        """
+        Fetch the list of user orders from the API.
+        """
+        headers = {"Authorization": f"Bearer {token}"}
+        try:
+            resp = requests.get(f"{API_URL}/orders/list", headers=headers)
+            if resp.status_code == 200:
+                orders = resp.json()  # Expect a list of order dicts
+                display_orders(orders, orders_list_frame)
+            else:
+                messagebox.showerror("Error", "Failed to fetch orders.")
+        except Exception as ex:
+            messagebox.showerror("Error", f"Request error: {ex}")
+
+    def display_orders(orders, container):
+        """
+        Display each order with product and shop details.
+        """
+        # Clear previous content
+        for widget in container.winfo_children():
+            widget.destroy()
+
+        if not orders:
+            ctk.CTkLabel(container, text="No orders found.", text_color="white").pack(pady=10)
+            return
+
+        for order in orders:
+            # Assume each order dict includes a 'product' dict and an 'order_date'
+            product = order.get("product", {})
+            order_date = order.get("order_date", "Unknown Date")
+
+            order_frame = ctk.CTkFrame(container, corner_radius=5, fg_color="#2b2b2b")
+            order_frame.pack(fill="x", padx=5, pady=5)
+
+            # Left: Product image
+            image_label = ctk.CTkLabel(order_frame, text="")
+            image_label.pack(side="left", padx=5, pady=5)
+            if product.get("images"):
+                try:
+                    img_url = product["images"][0]["image_url"]
+                    img_resp = requests.get(img_url)
+                    if img_resp.status_code == 200:
+                        pil_img = Image.open(io.BytesIO(img_resp.content)).resize((60, 60))
+                        tk_img = ImageTk.PhotoImage(pil_img)
+                        image_label.configure(image=tk_img, text="")
+                        image_label.image = tk_img
+                except Exception as ex:
+                    print(f"Product image error: {ex}")
+
+            # Right: Order details and shop info
+            info_frame = ctk.CTkFrame(order_frame, fg_color="transparent")
+            info_frame.pack(side="left", fill="both", expand=True, padx=10)
+
+            # Product Name
+            ctk.CTkLabel(
+                info_frame,
+                text=product.get("name", "No Name"),
+                font=("Helvetica", 13, "bold"),
+                text_color="white"
+            ).pack(anchor="w")
+
+            # Price (and order date)
+            price = product.get("price", 0.0)
+            ctk.CTkLabel(
+                info_frame,
+                text=f"Price: {price:.2f}",
+                text_color="#cccccc"
+            ).pack(anchor="w")
+            ctk.CTkLabel(
+                info_frame,
+                text=f"Ordered on: {order_date}",
+                text_color="#cccccc"
+            ).pack(anchor="w")
+
+            # Shop Name
+            shop_id = product.get("shop_id")
+            shop_name_label = ctk.CTkLabel(info_frame, text="Shop: Loading...", text_color="#cccccc")
+            shop_name_label.pack(anchor="w")
+
+            def fetch_shop_and_update_label(sid, label_widget):
+                headers = {"Authorization": f"Bearer {token}"}
+                try:
+                    sresp = requests.get(f"{API_URL}/shop/get/{sid}", headers=headers)
+                    if sresp.status_code == 200:
+                        shop_data = sresp.json()
+                        label_widget.configure(text=f"Shop: {shop_data.get('name', 'No Shop Name')}")
+                    else:
+                        label_widget.configure(text="Shop: Not found")
+                except Exception:
+                    label_widget.configure(text="Shop: Error fetching")
+
+            fetch_shop_and_update_label(shop_id, shop_name_label)
+
+            # "View Order" button (placeholder action)
+            def view_order():
+                messagebox.showinfo("Order Details", f"View details for order of {product.get('name')}")
+
+            view_button = ctk.CTkButton(
+                info_frame,
+                text="View Order",
+                fg_color=SHOPPING,
+                text_color="white",
+                command=view_order
+            )
+            view_button.pack(anchor="e", pady=(5, 0))
+
+    # Fetch orders when the frame loads
+    fetch_orders()
+
+    return frame
diff --git a/app/frontend/main.py b/app/frontend/main.py
index 6773394..65b8f0a 100644
--- a/app/frontend/main.py
+++ b/app/frontend/main.py
@@ -5,7 +5,9 @@ from components.shop.create_shop import create_shop_frame
 from components.shop.view_shop import view_shop_frame
 from components.product.create_product import product_frame
 from components.admin.category import category_frame
-from components.dashboard import dashboard_frame  # import the dashboard
+from components.dashboard import dashboard_frame
+from components.user_details import user_details_frame
+from components.user_orders import user_orders_frame
 
 API_URL = "http://127.0.0.1:8000"
 access_token = None
@@ -37,6 +39,8 @@ view_shop = view_shop_frame(root, switch_frame, API_URL, access_token)
 product = product_frame(root, switch_frame, API_URL, access_token)
 category = category_frame(root, switch_frame, API_URL, access_token)
 dashboard = dashboard_frame(root, switch_frame, API_URL, access_token)
+user_details = user_details_frame(root, switch_frame, API_URL, access_token)
+user_orders = user_orders_frame(root, switch_frame, API_URL, access_token)
 
 frames = {
     "login": login,
@@ -46,6 +50,8 @@ frames = {
     "category": category,
     "view_shop": view_shop,
     "dashboard": dashboard,
+    "user_details": user_details,
+    "user_orders": user_orders,
 }
 
 for frame in frames.values():
diff --git a/requirements.txt b/requirements.txt
index 2383f12bc661c32a3b8eac0fcf9146bd60a0f3fe..1c5bb150f1acbbb5b29d84ddfede66a9ed8b7204 100644
GIT binary patch
literal 2206
zcmZvd%}yIZ5QOI(DUY%U+k}uq4qQ=?5)moN2^s&bF<!&2!H|bfQeW4O#~`#?+j4hT
zcURZ+{QEmjjh;=~rm@~xnx;zMFX>*tyYyAhaXLz$^&Y2>>4Ur)S(l2ycB22!_O_ce
zNo~Y#!#a{>7%!0%A-2L^rnz3Chr%4DPx2V(9qH44^SuZE4<dWE)vBOXWiugFQF)uz
z`tMGde<B0OWTv(pg>{lvk(GMEJ?pb=6uS}TIB;^uM4$E^xu;E9gx`It)usE#4~B-l
z@1ttl3U95?m9jSarf<CIwD2*FPF7-^US_J#tbtZIoeH7TG+tz_h1&!YC}k$IsC=nD
zuG3S`1?be_%+8u;IG2qo$HMg_$T`sCS(vrgUX|*D#mtXY!Mql#{g4@$#`9)hsg+|t
zIst=<%7ox`rl(OPY~aBRJ%6&)QD4qJh*;y+^53eHNpw4lSmH{B*#kb9cG2}|RAGFh
zJV!jS!<d4(SZYd*_$qZd_fnZV**F#S*9sp6<PPc5o)@8oTX_x-P>#en*->ySy-XFq
z6ILZ}^qtv)3u-dfW$*nc`;~srl{r`D%8fZyEv@=3tYw|9HH9uc$i`ezRU-@(h+>@g
zP;Xy?kDMQ$Tg7KJdQxOYLFB$yRh+l6Sm6vTdPbPIPYNELo}v_HhNe$?1oX_w+(j(v
zv>wa>%uFJWx51&#bB33GGVGj5UjZ0Y>az`sr)Qr^EIf+^w!zyy$SfWEK7OTc&@M=H
zTvXtVV_sh8yH;JW>G}DT!hth<S9J?%gL8q-vZ@A&d03hFT%=#==YiFeARpFCy;tc+
z`quMk79CChdCpa+k4@BQi;ydyqW65)($-z{$|TwAS!GtBr$qkW>0C89JLk=Is-y1*
z;c(L&_BT@h+z0kyc6DD5N~3pcq>Z`OF)5#HHg2h85Ie+NcEXs2qC6e$k@dby_MS02
zb<YjO9pyU?7OZgUF_Y&)qAE6T*=KY%>hBewuC*}O@8t}-d-vuY%n7w_tO7hvq|bcX
z@@;H|WA&bPU$(lZYvG_?CfG&&d@~nsTI-809$%ebZ+(zGHE#`{%u&R99>xA7bSu~Q
m5wWAlVuYR8-3CMONPn&)E6QB&^#6@48+oquJ8QuG9jE{G_(BZ;

literal 1045
zcmYLIOK;mS48H5XSnw-pdhnswVgWjIz_3%H%8IQ<mQ;yu>iznCl-KPjisbhosk{%Q
z$cz<j(d1#M<(;gB@|z9A(907ZuR3j!hM|+KY=t(7?8Od4Tek<<$gUCk!tX{lcM^|T
zrEIA3AuY<;-zITo&p*!U>oA;9bP_takkq0Wv6n|tFv65noHqdXvSzF`Q&{L~J#m{u
zAuy_R9Ss=`N_8PP`W!c!g9oWX-z>_ymk+>?iUKM@96~NClZv2P%ccSM<||Tx8b={s
zOlD_c5qssznnMw!+M;4g#&~CnACN5OrYQ}<Sj<FGhh*3c?!|8k!4+SRvM+&8PH*9Y
zu%n0mPByi$lt<+!lfsJRo$jOcZ>lW`@*ozL9d5p|R56<l2(>sPy2fX90VYRUv5aeS
zg%Llt{O&3pyoX&Op>Vh9zW5Q+TV~Ukfou*UDt%Rx^%EHMsE#V<VnPE~dl9X3;RbDx
z4d}S($fMrvMfL^-WHr-AzvI6^Wj-mXuLUcg|FbLX3IVdHW>db}yzEB8iaStw+NQ;L
zDp}1v(w?@*pFjRW@$0-jfB#mNu=HS=)fmY5k9`>2xCEEgkp=OxJus|B@vnz7YLCUg
zWZqYkcciYBok&*C=+Vi0c)*W}M|!oT0m7}wvvCd@X0<Tb0eRV590g7Y2LeLi_Tcnv
zma;~*>`nrMS;A<_s6e9=*v*8!B1{q|0WyM567KSBfPxn=USOv2*#-|Ua8-Pg>pn(o
uG_M54kD+z!4K_lo9~Mqx%0T5Ey(!Z3#X3HA-qK#&%xez%YFIOnYVil?XFVtY

-- 
GitLab


From 1c39532ed5079c32e3026ae24ab48b00ebd91acc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20Minh?= <w11220031@st.phenikaa-uni.edu.vn>
Date: Fri, 28 Mar 2025 21:04:26 +0700
Subject: [PATCH 6/7] update frontend for login, register, dashboard and user
 details

---
 app/frontend/components/auth/login.py    |  85 +++++++++++-------
 app/frontend/components/auth/register.py | 107 ++++++++++++++---------
 app/frontend/components/dashboard.py     |   3 +-
 app/frontend/components/user_details.py  |  10 ---
 4 files changed, 124 insertions(+), 81 deletions(-)

diff --git a/app/frontend/components/auth/login.py b/app/frontend/components/auth/login.py
index 79f360b..dc2d30d 100644
--- a/app/frontend/components/auth/login.py
+++ b/app/frontend/components/auth/login.py
@@ -1,32 +1,31 @@
 import customtkinter as ctk
 from tkinter import messagebox
 from PIL import Image
-from utils.api_requests import login_api  # Import the login function from login_api.py
+from utils.api_requests import login_api
 
 
 def login_frame(parent, switch_func, API_URL):
-    # Create a container frame to hold both left (empty) and right (login) frames
-    container = ctk.CTkFrame(parent)
-    container.grid_columnconfigure(0, weight=1)  # Left empty frame
-    container.grid_columnconfigure(1, weight=1)  # Right login frame
+    # Overall container
+    container = ctk.CTkFrame(parent, fg_color="#F3F4F6")  # Light gray background
+    container.grid_columnconfigure(0, weight=1)
+    container.grid_columnconfigure(1, weight=1)
     container.grid_rowconfigure(0, weight=1)
 
-    # Left empty frame (Just an empty frame to balance the layout)
-    left_frame = ctk.CTkFrame(container)
+    # Left image frame
+    left_frame = ctk.CTkFrame(container, fg_color="transparent")
     left_frame.grid(row=0, column=0, sticky="nsew")
 
-    # Load and display the image
-    image_path = "app/static/front_end_img/login.jpg"  # Change this to your image path
-    img = ctk.CTkImage(
-        light_image=Image.open(image_path), size=(1000, 1000)
-    )  # Resize as needed
-    image_label = ctk.CTkLabel(left_frame, image=img, text="")  # No text, only image
+    image_path = "app/static/front_end_img/login.jpg"
+    img = ctk.CTkImage(light_image=Image.open(image_path), size=(800, 800))
+    image_label = ctk.CTkLabel(left_frame, image=img, text="")
     image_label.place(relwidth=1, relheight=1)
 
     # Right login frame
-    right_frame = ctk.CTkFrame(container)
-    right_frame.grid(row=0, column=1, sticky="nsew")
+    right_frame = ctk.CTkFrame(container, fg_color="white", corner_radius=20)
+    right_frame.grid(row=0, column=1, sticky="nsew", padx=50, pady=100)
+    right_frame.grid_columnconfigure(0, weight=1)
 
+    # Login Function
     def login():
         email = entry_email.get()
         password = entry_password.get()
@@ -35,37 +34,61 @@ def login_frame(parent, switch_func, API_URL):
             messagebox.showwarning("Input Error", "Both fields are required!")
             return
 
-        # Call the API function from login_api.py
         status_code, response_data = login_api(email, password, API_URL)
 
         if status_code == 200:
             access_token = response_data.get("access_token")
             messagebox.showinfo("Login Successful", f"Welcome back, {email}!")
             switch_func("dashboard", access_token)
-            print(f"Access Token in login: {access_token}")  # Debugging line
         else:
-            messagebox.showerror(
-                "Login Failed", response_data.get("detail", "Invalid credentials")
-            )
+            messagebox.showerror("Login Failed", response_data.get("detail", "Invalid credentials"))
 
-    ctk.CTkLabel(right_frame, text="Login", font=("Helvetica", 18, "bold")).pack(
-        pady=10
-    )
+    # Title
+    ctk.CTkLabel(
+        right_frame,
+        text="Login",
+        font=ctk.CTkFont("Helvetica", size=26, weight="bold"),
+        text_color="#111827"
+    ).pack(pady=(20, 10))
 
-    ctk.CTkLabel(right_frame, text="Email:").pack(pady=5)
-    entry_email = ctk.CTkEntry(right_frame)
-    entry_email.pack(pady=5)
+    # Email
+    ctk.CTkLabel(
+        right_frame, text="Email", font=("Helvetica", 14), text_color="#374151"
+    ).pack(pady=(10, 5))
+    entry_email = ctk.CTkEntry(
+        right_frame, height=40, corner_radius=10, placeholder_text="Enter your email"
+    )
+    entry_email.pack(pady=5, padx=20, fill="x")
 
-    ctk.CTkLabel(right_frame, text="Password:").pack(pady=5)
-    entry_password = ctk.CTkEntry(right_frame, show="*")
-    entry_password.pack(pady=5)
+    # Password
+    ctk.CTkLabel(
+        right_frame, text="Password", font=("Helvetica", 14), text_color="#374151"
+    ).pack(pady=(10, 5))
+    entry_password = ctk.CTkEntry(
+        right_frame, height=40, show="*", corner_radius=10, placeholder_text="Enter your password"
+    )
+    entry_password.pack(pady=5, padx=20, fill="x")
 
-    ctk.CTkButton(right_frame, text="Login", command=login).pack(pady=15)
+    # Login Button
+    ctk.CTkButton(
+        right_frame,
+        text="Login",
+        command=login,
+        corner_radius=10,
+        height=45,
+        font=("Helvetica", 14),
+        fg_color="#2563EB",
+        hover_color="#1E40AF"
+    ).pack(pady=20, padx=20, fill="x")
 
+    # Register Redirect
     ctk.CTkButton(
         right_frame,
         text="Don't have an account? Register",
         command=lambda: switch_func("register"),
-    ).pack()
+        fg_color="transparent",
+        hover_color="#E5E7EB",
+        text_color="#2563EB"
+    ).pack(pady=(5, 20))
 
     return container
diff --git a/app/frontend/components/auth/register.py b/app/frontend/components/auth/register.py
index 1be5aab..d2a6353 100644
--- a/app/frontend/components/auth/register.py
+++ b/app/frontend/components/auth/register.py
@@ -4,7 +4,14 @@ from utils.api_requests import register_api  # Import the API function
 
 
 def register_frame(parent, switch_func, API_URL):
-    frame = ctk.CTkFrame(parent)
+    # Create a full-window container with a light gray background
+    container = ctk.CTkFrame(parent, fg_color="#F3F4F6")
+    container.pack(expand=True, fill="both")
+    
+    # Center the register panel (the white card) in the middle of the container.
+    # Width and height are set to ensure a consistent size.
+    register_panel = ctk.CTkFrame(container, fg_color="white", corner_radius=20, width=400, height=500)
+    register_panel.place(relx=0.5, rely=0.5, anchor="center")
 
     def register():
         username = entry_username.get()
@@ -13,13 +20,7 @@ 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
 
@@ -36,38 +37,66 @@ 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")
-            )
-
-    ctk.CTkLabel(frame, text="Register", font=("Helvetica", 18, "bold")).pack(pady=10)
-
-    ctk.CTkLabel(frame, text="Username:").pack(pady=5)
-    entry_username = ctk.CTkEntry(frame)
-    entry_username.pack(pady=5)
-
-    ctk.CTkLabel(frame, text="Email:").pack(pady=5)
-    entry_email = ctk.CTkEntry(frame)
-    entry_email.pack(pady=5)
-
-    ctk.CTkLabel(frame, text="Phone Number:").pack(pady=5)
-    entry_phone = ctk.CTkEntry(frame)
-    entry_phone.pack(pady=5)
-
-    ctk.CTkLabel(frame, text="Password:").pack(pady=5)
-    entry_password = ctk.CTkEntry(frame, show="*")
-    entry_password.pack(pady=5)
-
-    ctk.CTkLabel(frame, text="Confirm Password:").pack(pady=5)
-    entry_confirm_password = ctk.CTkEntry(frame, show="*")
-    entry_confirm_password.pack(pady=5)
-
-    ctk.CTkButton(frame, text="Register", command=register).pack(pady=15)
-
+            messagebox.showerror("Registration Failed", response_data.get("detail", "Unknown error"))
+
+    # Title for the registration form
+    ctk.CTkLabel(
+        register_panel,
+        text="Create Account",
+        font=ctk.CTkFont("Helvetica", size=26, weight="bold"),
+        text_color="#111827"
+    ).pack(pady=(20, 10))
+
+    # Username Entry
+    entry_username = ctk.CTkEntry(
+        register_panel, placeholder_text="Username", height=40, corner_radius=10, width=250
+    )
+    entry_username.pack(pady=10, padx=20, fill="x")
+
+    # Email Entry
+    entry_email = ctk.CTkEntry(
+        register_panel, placeholder_text="Email", height=40, corner_radius=10, width=250
+    )
+    entry_email.pack(pady=10, padx=20, fill="x")
+
+    # Phone Number Entry
+    entry_phone = ctk.CTkEntry(
+        register_panel, placeholder_text="Phone Number", height=40, corner_radius=10, width=250
+    )
+    entry_phone.pack(pady=10, padx=20, fill="x")
+
+    # Password Entry
+    entry_password = ctk.CTkEntry(
+        register_panel, placeholder_text="Password", show="*", height=40, corner_radius=10, width=250
+    )
+    entry_password.pack(pady=10, padx=20, fill="x")
+
+    # Confirm Password Entry
+    entry_confirm_password = ctk.CTkEntry(
+        register_panel, placeholder_text="Confirm Password", show="*", height=40, corner_radius=10, width=250
+    )
+    entry_confirm_password.pack(pady=10, padx=20, fill="x")
+
+    # Register Button
+    ctk.CTkButton(
+        register_panel,
+        text="Register",
+        command=register,
+        corner_radius=10,
+        height=45,
+        font=("Helvetica", 14),
+        fg_color="#2563EB",
+        hover_color="#1E40AF"
+    ).pack(pady=20, padx=20, fill="x")
+
+    # Link to Login Page
     ctk.CTkButton(
-        frame,
+        register_panel,
         text="Already have an account? Login",
         command=lambda: switch_func("login"),
-    ).pack()
+        fg_color="transparent",
+        hover_color="#E5E7EB",
+        text_color="#2563EB"
+    ).pack(pady=(5, 20))
 
-    return frame
+    return container
diff --git a/app/frontend/components/dashboard.py b/app/frontend/components/dashboard.py
index 75622c9..f6c1af4 100644
--- a/app/frontend/components/dashboard.py
+++ b/app/frontend/components/dashboard.py
@@ -65,7 +65,7 @@ def dashboard_frame(parent, switch_func, API_URL, token):
 
     def open_cart_details():
         # Switch to cart_shopping.py screen or run it
-        switch_func("cart_shopping")
+        switch_func("user_orders")
         # Alternatively, use os.system("python cart_shopping.py")
 
     # Try loading icon images; update paths as needed.
@@ -112,6 +112,7 @@ def dashboard_frame(parent, switch_func, API_URL, token):
             fg_color="transparent",
             command=open_cart_details,
         )
+        switch_func("user_orders")
         cart_button.image = cart_icon
         cart_button.place(relx=0.91, rely=0.25, relwidth=0.08, relheight=0.5)
     else:
diff --git a/app/frontend/components/user_details.py b/app/frontend/components/user_details.py
index 7a49032..a6b1a8f 100644
--- a/app/frontend/components/user_details.py
+++ b/app/frontend/components/user_details.py
@@ -90,16 +90,6 @@ def user_details_frame(parent, switch_func, API_URL, token):
     )
     nav_orders.pack(fill="x", padx=10, pady=5)
 
-    nav_address = ctk.CTkButton(
-        sidebar_frame,
-        text="Address Book",
-        fg_color="#2b2b2b",
-        text_color="white",
-        hover_color="#3b3b3b",
-        command=lambda: messagebox.showinfo("Info", "Address Book clicked!")
-    )
-    nav_address.pack(fill="x", padx=10, pady=5)
-
     # ----------------- RIGHT CONTENT (User Details) -----------------
     content_frame = ctk.CTkFrame(main_section, fg_color="transparent")
     content_frame.pack(side="left", fill="both", expand=True, padx=20, pady=20)
-- 
GitLab


From b02b661896dc99282382b7e6e49a22be969f902f Mon Sep 17 00:00:00 2001
From: nn2-minh <Nguyen12.Minh@live.uwe.ac.uk>
Date: Fri, 28 Mar 2025 22:30:40 +0700
Subject: [PATCH 7/7] Make change for product and shop also main to show img
 for frontend and make change for dashboard for prettier appearance

---
 app/backend/main.py                   |   9 +-
 app/backend/routes/product.py         |  69 +++---
 app/backend/routes/shop.py            |  36 ++--
 app/frontend/components/auth/login.py |   2 +-
 app/frontend/components/dashboard.py  | 290 +++++++++++++-------------
 5 files changed, 201 insertions(+), 205 deletions(-)

diff --git a/app/backend/main.py b/app/backend/main.py
index 658f0ca..9606ccc 100644
--- a/app/backend/main.py
+++ b/app/backend/main.py
@@ -4,13 +4,20 @@ import os
 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
 from fastapi import FastAPI
+from fastapi.staticfiles import StaticFiles
 from backend.routes import auth, shop, product, category, search, order
 from backend.database import init_db
 from core.config import settings
 
 app = FastAPI(title="Shopping App", version="1.0.0", debug=settings.debug)
 
-# initialize database
+# ------------------- NEW: MOUNT STATIC FILES -------------------
+# Suppose your static files are located in "app/static"
+# Adjust the path if needed.
+static_dir_path = os.path.join(os.path.dirname(__file__), "..", "static")
+app.mount("/static", StaticFiles(directory=static_dir_path), name="static")
+
+# Initialize database
 init_db()
 
 # Include API routes
diff --git a/app/backend/routes/product.py b/app/backend/routes/product.py
index fcad951..30ca0e9 100644
--- a/app/backend/routes/product.py
+++ b/app/backend/routes/product.py
@@ -11,9 +11,7 @@ import os
 
 router = APIRouter()
 
-static_dir = os.path.join("app", "static")
-os.makedirs(static_dir, exist_ok=True)
-
+BACKEND_HOST = "http://127.0.0.1:8000"  # Or use settings.backend_url if available
 
 @router.post("/create", response_model=ProductRead)
 def create_product(
@@ -27,6 +25,12 @@ def create_product(
     session: Session = Depends(get_session),
     current_user: User = Depends(get_current_user),
 ):
+    shop = session.get(Shop, shop_id)
+    if not shop or shop.owner_id != current_user.id:
+        raise HTTPException(
+            status_code=403, detail="Unauthorized to create product for this shop"
+        )
+
     product = Product(
         name=name,
         description=description,
@@ -40,35 +44,31 @@ def create_product(
     session.commit()
     session.refresh(product)
 
-    shop = session.get(Shop, shop_id)
-    if not shop or shop.owner_id != current_user.id:
-        raise HTTPException(
-            status_code=403, detail="Unauthorized to create product for this shop"
-        )
-
-    # Directory structure: static/shop_{shop_name}/product_{product_name}/
+    # Directory: static/shop_{shop.name}/product_{product.name}/
     shop_dir = os.path.join(settings.static_dir, f"shop_{shop.name}")
     os.makedirs(shop_dir, exist_ok=True)
     product_dir = os.path.join(shop_dir, f"product_{product.name}")
     os.makedirs(product_dir, exist_ok=True)
 
-    # Handling multiple image uploads
     if images:
         for image in images:
             if image.filename:
                 file_location = os.path.join(product_dir, image.filename)
                 with open(file_location, "wb") as buffer:
                     shutil.copyfileobj(image.file, buffer)
-
-                # Save image record in ProductImage
-                product_image = ProductImage(
-                    product_id=product.id, image_url=file_location
-                )
+                relative_path = os.path.relpath(file_location, settings.static_dir)
+                relative_path = relative_path.replace("\\", "/")
+                public_url = f"{BACKEND_HOST}/static/{relative_path}"
+                product_image = ProductImage(product_id=product.id, image_url=public_url)
                 session.add(product_image)
                 session.commit()
-    else:  # Save default image
-        file_location = os.path.join(settings.static_dir, "default/default_product.png")
-        product_image = ProductImage(product_id=product.id, image_url=file_location)
+    else:
+        # Use default product image from static/default folder
+        default_path = os.path.join(settings.static_dir, "default", "default_product.png")
+        relative_path = os.path.relpath(default_path, settings.static_dir)
+        relative_path = relative_path.replace("\\", "/")
+        public_url = f"{BACKEND_HOST}/static/{relative_path}"
+        product_image = ProductImage(product_id=product.id, image_url=public_url)
         session.add(product_image)
         session.commit()
 
@@ -82,7 +82,6 @@ def read_all_products(order: str = "desc", session: Session = Depends(get_sessio
         if order == "desc"
         else func.count(OrderItem.id).asc()
     )
-
     products = (
         session.query(Product)
         .outerjoin(OrderItem, Product.id == OrderItem.product_id)
@@ -90,7 +89,6 @@ def read_all_products(order: str = "desc", session: Session = Depends(get_sessio
         .order_by(order_by)
         .all()
     )
-
     return products
 
 
@@ -120,28 +118,16 @@ def update_product(
             status_code=403, detail="Unauthorized to update this product"
         )
 
-    if name:
-        product.name = name
-    if description:
-        product.description = description
-    if price is not None:
-        product.price = price
-    if stock is not None:
-        product.stock = stock
-    if category_id is not None:
-        product.category_id = category_id
+    product.name = name
+    product.description = description
+    product.price = price
+    product.stock = stock
+    product.category_id = category_id
 
     session.add(product)
     session.commit()
     session.refresh(product)
 
-    product = session.get(Product, product_id)
-    if not product or product.shop.owner_id != current_user.id:
-        raise HTTPException(
-            status_code=403, detail="Unauthorized to update this product"
-        )
-
-    # Directory structure: static/shop_{shop_name}/product_{product_name}/
     shop = session.get(Shop, product.shop_id)
     shop_dir = os.path.join(settings.static_dir, f"shop_{shop.name}")
     os.makedirs(shop_dir, exist_ok=True)
@@ -154,8 +140,10 @@ def update_product(
                 file_location = os.path.join(product_dir, file.filename)
                 with open(file_location, "wb") as buffer:
                     shutil.copyfileobj(file.file, buffer)
-
-                image = ProductImage(product_id=product.id, image_url=file_location)
+                relative_path = os.path.relpath(file_location, settings.static_dir)
+                relative_path = relative_path.replace("\\", "/")
+                public_url = f"{BACKEND_HOST}/static/{relative_path}"
+                image = ProductImage(product_id=product.id, image_url=public_url)
                 session.add(image)
                 session.commit()
 
@@ -173,7 +161,6 @@ def delete_product(
         raise HTTPException(
             status_code=403, detail="Unauthorized to delete this product"
         )
-
     session.delete(product)
     session.commit()
     return {"message": "Product deleted successfully"}
diff --git a/app/backend/routes/shop.py b/app/backend/routes/shop.py
index a240d1b..d5a651a 100644
--- a/app/backend/routes/shop.py
+++ b/app/backend/routes/shop.py
@@ -11,6 +11,8 @@ import os
 
 router = APIRouter()
 
+# Define your backend host URL.
+BACKEND_HOST = "http://127.0.0.1:8000"  # Or use settings.backend_url if available
 
 @router.post("/create", response_model=ShopRead)
 def create_shop(
@@ -39,6 +41,7 @@ def create_shop(
     session.commit()
     session.refresh(shop)
 
+    # Create a folder in the static directory for the shop
     shop_dir = os.path.join(settings.static_dir, f"shop_{shop.name}")
     os.makedirs(shop_dir, exist_ok=True)
 
@@ -46,13 +49,20 @@ def create_shop(
         file_location = os.path.join(shop_dir, file.filename)
         with open(file_location, "wb") as buffer:
             shutil.copyfileobj(file.file, buffer)
-        shop.image_url = file_location
+        relative_path = os.path.relpath(file_location, settings.static_dir)
+        relative_path = relative_path.replace("\\", "/")
+        public_url = f"{BACKEND_HOST}/static/{relative_path}"
+        shop.image_url = public_url
     else:
-        shop.image_url = os.path.join(settings.static_dir, "default/default_shop.png")
+        # Use default shop image from static/default folder
+        default_path = os.path.join(settings.static_dir, "default", "default_shop.png")
+        relative_path = os.path.relpath(default_path, settings.static_dir)
+        relative_path = relative_path.replace("\\", "/")
+        public_url = f"{BACKEND_HOST}/static/{relative_path}"
+        shop.image_url = public_url
 
     session.commit()
     session.refresh(shop)
-
     return shop
 
 
@@ -61,7 +71,6 @@ def get_all_shops(order: str = "desc", session: Session = Depends(get_session)):
     order_by = (
         func.count(Order.id).desc() if order == "desc" else func.count(Order.id).asc()
     )
-
     shops = (
         session.query(Shop)
         .outerjoin(Order, Shop.id == Order.shop_id)
@@ -69,7 +78,6 @@ def get_all_shops(order: str = "desc", session: Session = Depends(get_session)):
         .order_by(order_by)
         .all()
     )
-
     return shops
 
 
@@ -94,10 +102,9 @@ def update_shop(
     shop = session.get(Shop, shop_id)
     if not shop:
         raise HTTPException(status_code=404, detail="Shop not found")
-
-    # Ensure the current user is the shop owner
     if shop.owner_id != current_user.id:
         raise HTTPException(status_code=403, detail="Unauthorized to update this shop")
+    
     if name:
         shop.name = name
     if description:
@@ -118,14 +125,20 @@ def update_shop(
         file_location = os.path.join(shop_dir, file.filename)
         with open(file_location, "wb") as buffer:
             shutil.copyfileobj(file.file, buffer)
-        shop.image_url = file_location
+        relative_path = os.path.relpath(file_location, settings.static_dir)
+        relative_path = relative_path.replace("\\", "/")
+        public_url = f"{BACKEND_HOST}/static/{relative_path}"
+        shop.image_url = public_url
     else:
-        shop.image_url = os.path.join(settings.static_dir, "default/default_shop.png")
+        default_path = os.path.join(settings.static_dir, "default", "default_shop.png")
+        relative_path = os.path.relpath(default_path, settings.static_dir)
+        relative_path = relative_path.replace("\\", "/")
+        public_url = f"{BACKEND_HOST}/static/{relative_path}"
+        shop.image_url = public_url
 
     session.add(shop)
     session.commit()
     session.refresh(shop)
-
     return shop
 
 
@@ -138,11 +151,8 @@ def delete_shop(
     shop = session.get(Shop, shop_id)
     if not shop:
         raise HTTPException(status_code=404, detail="Shop not found")
-
-    # Ensure the current user is the shop owner
     if shop.owner_id != current_user.id:
         raise HTTPException(status_code=403, detail="Unauthorized to delete this shop")
-
     session.delete(shop)
     session.commit()
     return {"message": "Shop deleted successfully"}
diff --git a/app/frontend/components/auth/login.py b/app/frontend/components/auth/login.py
index dc2d30d..31d2560 100644
--- a/app/frontend/components/auth/login.py
+++ b/app/frontend/components/auth/login.py
@@ -15,7 +15,7 @@ def login_frame(parent, switch_func, API_URL):
     left_frame = ctk.CTkFrame(container, fg_color="transparent")
     left_frame.grid(row=0, column=0, sticky="nsew")
 
-    image_path = "app/static/front_end_img/login.jpg"
+    image_path = "../../app/static/front_end_img/login.jpg"
     img = ctk.CTkImage(light_image=Image.open(image_path), size=(800, 800))
     image_label = ctk.CTkLabel(left_frame, image=img, text="")
     image_label.place(relwidth=1, relheight=1)
diff --git a/app/frontend/components/dashboard.py b/app/frontend/components/dashboard.py
index f6c1af4..f5707c9 100644
--- a/app/frontend/components/dashboard.py
+++ b/app/frontend/components/dashboard.py
@@ -5,10 +5,29 @@ from tkinter import messagebox
 import io
 
 SHOPPING = "#00c1ff"
-
+BACKEND_HOST = "http://127.0.0.1:8000"  # Adjust if needed
+
+def fix_url(url):
+    """
+    If the provided URL does not start with http, assume it's a relative path.
+    Remove any unwanted prefix (e.g., "app/static/") and prepend the public URL.
+    """
+    if url.startswith("http"):
+        return url
+    # If the URL starts with "app/static/", remove that part.
+    prefix = "app/static/"
+    if url.startswith(prefix):
+        url = url[len(prefix):]
+    # Prepend the public URL
+    return f"{BACKEND_HOST}/static/{url}"
 
 def dashboard_frame(parent, switch_func, API_URL, token):
-    # Main container frame
+    """
+    Main dashboard UI:
+      - Header (top bar) with logo, search, user, cart
+      - Middle area with horizontal scroll of top shops
+      - Bottom area with grid layout of recommended products
+    """
     frame = ctk.CTkFrame(parent, fg_color="transparent")
 
     # ------------- HEADER (Top Bar) -------------
@@ -38,16 +57,16 @@ def dashboard_frame(parent, switch_func, API_URL, token):
             return
         try:
             headers = {"Authorization": f"Bearer {token}"}
-            resp = requests.get(f"{API_URL}/product?search={keyword}", headers=headers)
+            # Adjust endpoint/params as needed
+            resp = requests.get(f"{API_URL}/search?name={keyword}&search_type=products", headers=headers)
             if resp.status_code == 200:
                 products = resp.json()
                 display_products(products, bottom_products_frame)
             else:
-                messagebox.showerror("Error", "Failed to fetch search results.")
+                messagebox.showerror("Error", f"Search failed. Status code: {resp.status_code}")
         except Exception as e:
             messagebox.showerror("Error", f"Request error: {e}")
 
-    # Search button
     search_button = ctk.CTkButton(
         header_frame,
         text="Search",
@@ -59,89 +78,80 @@ def dashboard_frame(parent, switch_func, API_URL, token):
 
     # ------------- USER & CART ICONS (Top-Right) -------------
     def open_user_details():
-        # Switch to user_details.py screen or run it
         switch_func("user_details")
-        # Alternatively, use os.system("python user_details.py")
 
     def open_cart_details():
-        # Switch to cart_shopping.py screen or run it
-        switch_func("user_orders")
-        # Alternatively, use os.system("python cart_shopping.py")
-
-    # Try loading icon images; update paths as needed.
-    try:
-        user_image = Image.open("path/to/user_icon.png").resize((30, 30))
-        user_icon = ImageTk.PhotoImage(user_image)
-    except Exception as e:
-        print(f"User icon load error: {e}")
-        user_icon = None
-
-    try:
-        cart_image = Image.open("path/to/cart_icon.png").resize((30, 30))
-        cart_icon = ImageTk.PhotoImage(cart_image)
-    except Exception as e:
-        print(f"Cart icon load error: {e}")
-        cart_icon = None
-
-    if user_icon:
-        user_button = ctk.CTkButton(
-            header_frame,
-            image=user_icon,
-            text="",
-            fg_color="transparent",
-            command=open_user_details,
-        )
-        switch_func("user_details")
-        user_button.image = user_icon
-        user_button.place(relx=0.82, rely=0.25, relwidth=0.08, relheight=0.5)
-    else:
-        user_button = ctk.CTkButton(
-            header_frame,
-            text="User",
-            fg_color="white",
-            text_color="black",
-            command=open_user_details,
-        )
-        user_button.place(relx=0.82, rely=0.25, relwidth=0.08, relheight=0.5)
-
-    if cart_icon:
-        cart_button = ctk.CTkButton(
-            header_frame,
-            image=cart_icon,
-            text="",
-            fg_color="transparent",
-            command=open_cart_details,
-        )
         switch_func("user_orders")
-        cart_button.image = cart_icon
-        cart_button.place(relx=0.91, rely=0.25, relwidth=0.08, relheight=0.5)
-    else:
-        cart_button = ctk.CTkButton(
-            header_frame,
-            text="Cart",
-            fg_color="white",
-            text_color="black",
-            command=open_cart_details,
-        )
-        cart_button.place(relx=0.91, rely=0.25, relwidth=0.08, relheight=0.5)
+
+    user_button = ctk.CTkButton(
+        header_frame,
+        text="User",
+        fg_color="white",
+        text_color="black",
+        command=open_user_details,
+    )
+    user_button.place(relx=0.82, rely=0.25, relwidth=0.08, relheight=0.5)
+
+    cart_button = ctk.CTkButton(
+        header_frame,
+        text="Cart",
+        fg_color="white",
+        text_color="black",
+        command=open_cart_details,
+    )
+    cart_button.place(relx=0.91, rely=0.25, relwidth=0.08, relheight=0.5)
 
     # ------------- MIDDLE (Featured/Top Shops) -------------
     middle_frame = ctk.CTkFrame(frame, fg_color="transparent")
     middle_frame.place(relx=0, rely=0.1, relwidth=1, relheight=0.25)
 
-    # Section Title
     featured_label = ctk.CTkLabel(
         middle_frame, text="TOP SHOP", font=("Helvetica", 16, "bold")
     )
     featured_label.pack(pady=5)
 
-    # A frame to hold the featured shops
-    top_shops_frame = ctk.CTkFrame(middle_frame, fg_color="transparent")
+    top_shops_frame = ctk.CTkScrollableFrame(
+        middle_frame, fg_color="transparent", width=750, height=150
+    )
     top_shops_frame.pack(fill="both", expand=True, padx=10, pady=5)
 
+    def create_shop_card(parent, shop_data):
+        """
+        Create a card for a shop with its image on top and name below.
+        """
+        card = ctk.CTkFrame(parent, corner_radius=5, fg_color="#2b2b2b", width=100, height=130)
+        card.pack_propagate(False)
+
+        image_label = ctk.CTkLabel(card, text="")
+        image_label.pack(pady=5)
+
+        # Use "image_url" as returned by the backend, then fix it if needed.
+        image_url = shop_data.get("image_url")
+        if image_url:
+            fixed_url = fix_url(image_url)
+            print(f"[DEBUG] Fetching shop image from: {fixed_url}")
+            try:
+                resp = requests.get(fixed_url)
+                print(f"[DEBUG] Status code for shop image: {resp.status_code}")
+                if resp.status_code == 200:
+                    pil_img = Image.open(io.BytesIO(resp.content)).resize((60, 60))
+                    tk_img = ImageTk.PhotoImage(pil_img)
+                    image_label.configure(image=tk_img, text="")
+                    image_label.image = tk_img
+                else:
+                    print(f"[DEBUG] Failed to fetch shop image. Status: {resp.status_code}")
+            except Exception as e:
+                print(f"[DEBUG] Shop image error: {e}")
+        else:
+            print(f"[DEBUG] No 'image_url' found for shop: {shop_data.get('name')}")
+
+        name_text = shop_data.get("name", "No Name")
+        name_label = ctk.CTkLabel(card, text=name_text, font=("Helvetica", 11, "bold"), wraplength=90)
+        name_label.pack()
+
+        return card
+
     def display_shops(shops, container):
-        """Given a list of shop dicts, display them in the given container."""
-        # Clear old widgets
         for widget in container.winfo_children():
             widget.destroy()
 
@@ -149,59 +159,68 @@ def dashboard_frame(parent, switch_func, API_URL, token):
             ctk.CTkLabel(container, text="No shops found.").pack(pady=10)
             return
 
-        # Display shops in a vertical list
-        for shop in shops:
-            sframe = ctk.CTkFrame(container, corner_radius=5, fg_color="#2b2b2b")
-            sframe.pack(fill="x", padx=5, pady=5)
+        inner_frame = ctk.CTkFrame(container, fg_color="transparent")
+        inner_frame.pack(side="top", fill="both", expand=True)
 
-            # Shop image/logo on left
-            image_label = ctk.CTkLabel(sframe, text="")
-            image_label.pack(side="left", padx=5, pady=5)
+        for shop in shops:
+            shop_card = create_shop_card(inner_frame, shop)
+            shop_card.pack(side="left", padx=5, pady=5)
 
-            # Load shop logo if available (assumes key "logo_url")
-            logo_url = shop.get("logo_url")
-            if logo_url:
-                try:
-                    resp = requests.get(logo_url)
-                    if resp.status_code == 200:
-                        pil_img = Image.open(io.BytesIO(resp.content)).resize((50, 50))
-                        tk_img = ImageTk.PhotoImage(pil_img)
-                        image_label.configure(image=tk_img, text="")
-                        image_label.image = tk_img
-                except Exception as e:
-                    print(f"Shop image error: {e}")
-
-            # Shop info on right
-            info_frame = ctk.CTkFrame(sframe, fg_color="transparent")
-            info_frame.pack(side="left", fill="both", expand=True, padx=10)
-
-            ctk.CTkLabel(
-                info_frame,
-                text=shop.get("name", "No Name"),
-                font=("Helvetica", 13, "bold"),
-            ).pack(anchor="w")
-            # Optionally add more shop details, for example a rating if available:
-            if shop.get("rating"):
-                ctk.CTkLabel(info_frame, text=f"Rating: {shop['rating']}").pack(
-                    anchor="w"
-                )
-
-    # ------------- BOTTOM (Recommendations - Products) -------------
+    # ------------- BOTTOM (Products) -------------
     bottom_frame = ctk.CTkFrame(frame, fg_color="transparent")
     bottom_frame.place(relx=0, rely=0.35, relwidth=1, relheight=0.65)
 
-    # Section Title
     recommend_label = ctk.CTkLabel(
         bottom_frame, text="TODAY'S RECOMMENDATIONS", font=("Helvetica", 16, "bold")
     )
     recommend_label.pack(pady=5)
 
-    bottom_products_frame = ctk.CTkFrame(bottom_frame, fg_color="transparent")
+    bottom_products_frame = ctk.CTkScrollableFrame(
+        bottom_frame, fg_color="transparent", width=750, height=300
+    )
     bottom_products_frame.pack(fill="both", expand=True, padx=10, pady=5)
 
+    def create_product_card(parent, product_data):
+        card_width = 130
+        card_height = 210
+        card = ctk.CTkFrame(parent, corner_radius=5, fg_color="#2b2b2b", width=card_width, height=card_height)
+        card.pack_propagate(False)
+
+        image_label = ctk.CTkLabel(card, text="")
+        image_label.pack(pady=5)
+
+        product_images = product_data.get("images", [])
+        if product_images:
+            img_url = product_images[0].get("image_url")
+            if img_url:
+                fixed_url = fix_url(img_url)
+                print(f"[DEBUG] Fetching product image from: {fixed_url}")
+                try:
+                    resp = requests.get(fixed_url)
+                    print(f"[DEBUG] Status code for product image: {resp.status_code}")
+                    if resp.status_code == 200:
+                        pil_img = Image.open(io.BytesIO(resp.content)).resize((70, 70))
+                        tk_img = ImageTk.PhotoImage(pil_img)
+                        image_label.configure(image=tk_img, text="")
+                        image_label.image = tk_img
+                    else:
+                        print(f"[DEBUG] Failed to fetch product image. Status: {resp.status_code}")
+                except Exception as e:
+                    print(f"[DEBUG] Product image error: {e}")
+        else:
+            print(f"[DEBUG] No images found for product: {product_data.get('name')}")
+
+        name_text = product_data.get("name", "No Name")
+        name_label = ctk.CTkLabel(card, text=name_text, font=("Helvetica", 11, "bold"), wraplength=120, anchor="center", justify="center")
+        name_label.pack(padx=5, pady=3)
+
+        price_val = product_data.get("price", 0.0)
+        price_label = ctk.CTkLabel(card, text=f"â‚« {price_val:,.1f}", font=("Helvetica", 10, "bold"), text_color="#ff4242")
+        price_label.pack(side="bottom", pady=5)
+
+        return card
+
     def display_products(products, container):
-        """Given a list of product dicts, display them in the given container."""
-        # Clear old widgets
         for widget in container.winfo_children():
             widget.destroy()
 
@@ -209,64 +228,37 @@ def dashboard_frame(parent, switch_func, API_URL, token):
             ctk.CTkLabel(container, text="No products found.").pack(pady=10)
             return
 
-        # Display products in a vertical list
-        for product in products:
-            pframe = ctk.CTkFrame(container, corner_radius=5, fg_color="#2b2b2b")
-            pframe.pack(fill="x", padx=5, pady=5)
+        grid_frame = ctk.CTkFrame(container, fg_color="transparent")
+        grid_frame.pack(fill="both", expand=True)
 
-            # Product image on left
-            image_label = ctk.CTkLabel(pframe, text="")
-            image_label.pack(side="left", padx=5, pady=5)
-
-            # Load first image if available
-            if product.get("images"):
-                try:
-                    img_url = product["images"][0]["image_url"]
-                    resp = requests.get(img_url)
-                    if resp.status_code == 200:
-                        pil_img = Image.open(io.BytesIO(resp.content)).resize((50, 50))
-                        tk_img = ImageTk.PhotoImage(pil_img)
-                        image_label.configure(image=tk_img, text="")
-                        image_label.image = tk_img
-                except Exception as e:
-                    print(f"Product image error: {e}")
-
-            # Product info on right
-            info_frame = ctk.CTkFrame(pframe, fg_color="transparent")
-            info_frame.pack(side="left", fill="both", expand=True, padx=10)
-
-            ctk.CTkLabel(
-                info_frame,
-                text=product.get("name", "No Name"),
-                font=("Helvetica", 13, "bold"),
-            ).pack(anchor="w")
-            price = product.get("price", 0.0)
-            ctk.CTkLabel(info_frame, text=f"Price: {price:.2f}").pack(anchor="w")
+        columns = 7  # 7 products per row
+        for idx, product in enumerate(products):
+            row = idx // columns
+            col = idx % columns
+            product_card = create_product_card(grid_frame, product)
+            product_card.grid(row=row, column=col, padx=5, pady=5)
 
     def fetch_featured_shops():
-        """Fetch some 'featured' or 'top' shops for the middle section."""
         headers = {"Authorization": f"Bearer {token}"}
         try:
             resp = requests.get(f"{API_URL}/shops/list", headers=headers)
             if resp.status_code == 200:
                 shops = resp.json()
-                # Slice the list to display only a handful of top shops
                 display_shops(shops[:5], top_shops_frame)
             else:
-                messagebox.showerror("Error", "Failed to fetch featured shops.")
+                messagebox.showerror("Error", f"Failed to fetch featured shops. Status: {resp.status_code}")
         except Exception as e:
             messagebox.showerror("Error", f"Request error: {e}")
 
     def fetch_recommendations():
-        """Fetch recommended products for the bottom section."""
         headers = {"Authorization": f"Bearer {token}"}
         try:
             resp = requests.get(f"{API_URL}/product/list", headers=headers)
             if resp.status_code == 200:
                 products = resp.json()
-                display_products(products, bottom_products_frame)
+                display_products(products[:20], bottom_products_frame)
             else:
-                messagebox.showerror("Error", "Failed to fetch recommended products.")
+                messagebox.showerror("Error", f"Failed to fetch recommended products. Status: {resp.status_code}")
         except Exception as e:
             messagebox.showerror("Error", f"Request error: {e}")
 
-- 
GitLab