Skip to content
Snippets Groups Projects
Commit 937b711f authored by Nguyen12.Minh@live.uwe.ac.uk's avatar Nguyen12.Minh@live.uwe.ac.uk
Browse files

Add dashboard

parent 5be1c995
Branches
No related tags found
No related merge requests found
......@@ -55,6 +55,12 @@ def create_product(
return product
@router.get("/list", response_model=list[ProductRead])
def read_all_products(session: Session = Depends(get_session)):
products = session.query(Product).all()
return products
@router.get("/{product_id}", response_model=ProductRead)
def read_product(product_id: int, session: Session = Depends(get_session)):
product = session.get(Product, product_id)
......
......@@ -19,12 +19,12 @@ def create_shop(
description: str = Form(None),
file: UploadFile = File(None),
session: Session = Depends(get_session),
# current_user: User = Depends(get_current_user),
owner_id = int,
current_user: User = Depends(get_current_user),
#owner_id = int,
):
# shop = ShopCreate(name=name, description=description, owner_id=current_user.id)
shop = ShopCreate(name=name, description=description, owner_id=owner_id)
shop = ShopCreate(name=name, description=description, owner_id=current_user.id)
#shop = ShopCreate(name=name, description=description, owner_id=owner_id)
db_shop = Shop.from_orm(shop)
if file and file.filename:
......@@ -42,12 +42,18 @@ def create_shop(
session.commit()
session.refresh(db_shop)
if file:
# Delete the image file after session commit
os.remove(file_location)
# if file:
# # Delete the image file after session commit
# os.remove(file_location)
return db_shop
@router.get("/list", response_model=list[ShopRead])
def get_all_shops(session: Session = Depends(get_session)):
shops = session.query(Shop).all()
return shops
@router.get("/{shop_id}", response_model=ShopRead)
def read_shop(shop_id: int, session: Session = Depends(get_session)):
shop = session.get(Shop, shop_id)
......
......@@ -23,7 +23,8 @@ def login_frame(parent, switch_func, API_URL):
if response.status_code == 200:
access_token = response_data["access_token"]
messagebox.showinfo("Login Successful", f"Welcome back, {email}!")
switch_func("create_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")
......
import customtkinter as ctk
import requests
from PIL import Image, ImageTk
from tkinter import messagebox
import io
SHOPPING = "#00c1ff"
def dashboard_frame(parent, switch_func, API_URL, token):
# Main container frame
frame = ctk.CTkFrame(parent, fg_color="transparent")
# ------------- HEADER (Top Bar) -------------
header_frame = ctk.CTkFrame(frame, fg_color=SHOPPING)
header_frame.place(relx=0, rely=0, relwidth=1, relheight=0.1)
# App Logo (Left)
logo_label = ctk.CTkLabel(
header_frame,
text="Shopping App",
text_color="white",
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
)
search_entry.place(relx=0.25, rely=0.25, relwidth=0.45, relheight=0.5)
def perform_search():
"""Call an endpoint to search products by keyword."""
keyword = search_entry.get().strip()
if not keyword:
messagebox.showinfo("Info", "Please enter a search keyword.")
return
try:
headers = {"Authorization": f"Bearer {token}"}
resp = requests.get(f"{API_URL}/product?search={keyword}", 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.")
except Exception as e:
messagebox.showerror("Error", f"Request error: {e}")
# Search button
search_button = ctk.CTkButton(
header_frame,
text="Search",
fg_color="white",
text_color="black",
command=perform_search
)
search_button.place(relx=0.71, 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.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")
sframe.pack(fill="x", padx=5, pady=5)
# Shop image/logo on left
image_label = ctk.CTkLabel(sframe, text="")
image_label.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_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.pack(fill="both", expand=True, padx=10, pady=5)
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()
if not products:
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)
# 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")
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.")
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)
else:
messagebox.showerror("Error", "Failed to fetch recommended products.")
except Exception as e:
messagebox.showerror("Error", f"Request error: {e}")
# Load data on start
fetch_featured_shops()
fetch_recommendations()
return frame
......@@ -3,9 +3,14 @@ from tkinter import messagebox, filedialog
import requests
import os
def create_shop_frame(parent, switch_func, API_URL, token):
frame = ctk.CTkFrame(parent)
frame.access_token = token
def update_token(new_token):
frame.access_token = new_token
frame.update_token = update_token
selected_file_path = [None]
......@@ -37,14 +42,14 @@ def create_shop_frame(parent, switch_func, API_URL, token):
messagebox.showerror("File Error", f"Unable to open file: {str(e)}")
return
if not token:
if not frame.access_token:
messagebox.showerror(
"Token Error", "Access token not found. Please log in."
)
return
headers = {"Authorization": f"Bearer {token}"}
print(f"Access Token in create_shop: {token}") # Debugging line
headers = {"Authorization": f"Bearer {frame.access_token}"}
print(f"Access Token in create_shop: {frame.access_token}") # Debugging line
try:
response = requests.post(url, data=data, files=files, headers=headers)
......@@ -90,4 +95,4 @@ def create_shop_frame(parent, switch_func, API_URL, token):
command=lambda: switch_func("login"),
).pack(pady=5)
return frame
return frame
\ No newline at end of file
......@@ -35,7 +35,7 @@ def view_shop_frame(parent, switch_func, API_URL, token):
headers = {"Authorization": f"Bearer {token}"}
try:
response = requests.get(
f"{API_URL}/shops/my-shop", headers=headers
f"{API_URL}/shops/1", headers=headers
) # Adjust the endpoint as needed
if response.status_code == 200:
shop_data = response.json()
......@@ -137,4 +137,4 @@ def view_shop_frame(parent, switch_func, API_URL, token):
# Fetch shop data on load
fetch_shop_data()
return frame
return frame
\ No newline at end of file
# main.py
import customtkinter as ctk
from components.auth.login import login_frame
from components.auth.register import register_frame
......@@ -5,40 +6,37 @@ 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
# Backend API URL
API_URL = "http://127.0.0.1:8000"
# Global variable to store the access token
access_token = None
# Function to switch between frames
def switch_frame(frame_name, token=None):
global access_token
if token:
access_token = token
frames.get(frame_name, login).tkraise() # Default to login if frame_name is invalid
frame = frames.get(frame_name, login)
if hasattr(frame, 'update_token'):
frame.update_token(access_token)
frame.tkraise()
# Create main window
ctk.set_appearance_mode("dark") # Light, Dark, or System
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("blue")
root = ctk.CTk()
root.title("Shopping App")
root.geometry("900x800")
# Create Frames inside the main window
# Create Frames
login = login_frame(root, switch_frame, API_URL)
register = register_frame(root, switch_frame, API_URL)
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
# Store frames in a dictionary for easier management
frames = {
"login": login,
"register": register,
......@@ -46,13 +44,13 @@ frames = {
"create_product": product,
"category": category,
"view_shop": view_shop,
"dashboard": dashboard, # add dashboard here
}
# Place all frames responsively
for frame in frames.values():
frame.place(relx=0, rely=0.2, relwidth=1, relheight=0.8)
frame.place(relx=0, rely=0, relwidth=1, relheight=0.8)
# Show the login frame first
switch_frame("login")
# Show the login frame first (or switch to dashboard as needed)
switch_frame("login") # switch to dashboard
root.mainloop()
app/static/default_shop_image.png

16.4 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment