From 5053815436a511f962e9cd3bf2d0f370d0391709 Mon Sep 17 00:00:00 2001
From: nn2-minh <Nguyen12.Minh@live.uwe.ac.uk>
Date: Thu, 6 Mar 2025 17:16:45 +0700
Subject: [PATCH 1/3] Add frontend for login and sign up

---
 app/core/config.py                  |   2 +-
 app/frontend/components/login.py    |  80 ++++++++++--------
 app/frontend/components/register.py | 125 +++++++++++++++-------------
 app/frontend/main.py                | 104 ++++-------------------
 requirements.txt                    | Bin 959 -> 1996 bytes
 5 files changed, 129 insertions(+), 182 deletions(-)

diff --git a/app/core/config.py b/app/core/config.py
index d61a265..4045933 100644
--- a/app/core/config.py
+++ b/app/core/config.py
@@ -6,7 +6,7 @@ class Settings(BaseSettings):
     app_name: str = "Shopping App"
     database_url: str  # Ensure lowercase to match the .env key
     secret_key: str
-    debug: bool = True  # Lowercase to match Python conventions
+    debug: bool = True
 
     model_config = SettingsConfigDict(
         env_file=str(Path(__file__).resolve().parent.parent / ".env"),
diff --git a/app/frontend/components/login.py b/app/frontend/components/login.py
index 34a1122..a52331b 100644
--- a/app/frontend/components/login.py
+++ b/app/frontend/components/login.py
@@ -1,39 +1,49 @@
 import ttkbootstrap as tb
 from ttkbootstrap.constants import *
 from tkinter import messagebox
+import requests  # Import requests for API communication
 
-# Function to handle login
-def login():
-    username = entry_username.get()
-    password = entry_password.get()
-
-    if username == "admin" and password == "password":  # Dummy credentials
-        messagebox.showinfo("Login Successful", "Welcome, Admin!")
-    else:
-        messagebox.showerror("Login Failed", "Invalid username or password.")
-
-# Create main window
-root = tb.Window(themename="superhero")  # Try different themes like "darkly", "minty", etc.
-root.title("Login Form")
-root.geometry("900x800")
-
-# Title Label
-label_title = tb.Label(root, text="Login", font=("Helvetica", 18, "bold"))
-label_title.pack(pady=10)
-
-# Username Entry
-tb.Label(root, text="Username:").pack(pady=5)
-entry_username = tb.Entry(root, bootstyle="info")
-entry_username.pack(pady=5)
-
-# Password Entry
-tb.Label(root, text="Password:").pack(pady=5)
-entry_password = tb.Entry(root, bootstyle="info", show="*")  # Masked input
-entry_password.pack(pady=5)
-
-# Login Button
-btn_login = tb.Button(root, text="Login", bootstyle="primary", command=login)
-btn_login.pack(pady=15)
-
-# Run the GUI
-root.mainloop()
+def login_frame(parent, switch_func, api_url):  # Added api_url parameter
+    frame = tb.Frame(parent)
+
+    def login():
+        email = entry_email.get()
+        password = entry_password.get()
+
+        if not email or not password:
+            messagebox.showwarning("Input Error", "Both fields are required!")
+            return
+
+        # Sending login request to backend
+        response = requests.post(f"{api_url}/auth/login", json={
+            "email": email,
+            "password": password
+        })
+
+        try:
+            response_data = response.json()
+            if response.status_code == 200:
+                messagebox.showinfo("Login Successful", f"Welcome back, {email}!")
+                # TODO: Implement navigation after login (e.g., open dashboard)
+            else:
+                messagebox.showerror("Login Failed", response_data.get("detail", "Invalid credentials"))
+        except requests.exceptions.JSONDecodeError:
+            messagebox.showerror("Login Failed", "Server returned an invalid response.")
+
+    tb.Label(frame, text="Login", font=("Helvetica", 18, "bold")).pack(pady=10)
+
+    tb.Label(frame, text="Email:").pack(pady=5)
+    entry_email = tb.Entry(frame, bootstyle="info")
+    entry_email.pack(pady=5)
+
+    tb.Label(frame, text="Password:").pack(pady=5)
+    entry_password = tb.Entry(frame, bootstyle="info", show="*")
+    entry_password.pack(pady=5)
+
+    btn_login = tb.Button(frame, text="Login", bootstyle="primary", command=login)
+    btn_login.pack(pady=15)
+
+    tb.Button(frame, text="Don't have an account? Register", bootstyle="link",
+              command=lambda: switch_func("register")).pack()
+
+    return frame
diff --git a/app/frontend/components/register.py b/app/frontend/components/register.py
index f682945..4f0b034 100644
--- a/app/frontend/components/register.py
+++ b/app/frontend/components/register.py
@@ -1,63 +1,70 @@
 import ttkbootstrap as tb
 from ttkbootstrap.constants import *
 from tkinter import messagebox
+import requests  # Import requests for API communication
 
-# Function to handle registration
-def register():
-    username = entry_username.get()
-    email = entry_email.get()
-    phone_number = entry_phone.get()
-    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:
-        messagebox.showwarning("Input Error", "All fields are required!")
-        return
-
-    if password != confirm_password:
-        messagebox.showerror("Password Error", "Passwords do not match!")
-        return
-
-    # Dummy registration success message (Replace with DB logic)
-    messagebox.showinfo("Registration Successful", f"Welcome, {username}!")
-
-# Create main window
-root = tb.Window(themename="superhero")  # Change to "darkly", "superhero", etc.
-root.title("Register")
-root.geometry("900x800")
-
-# Title Label
-label_title = tb.Label(root, text="Register", font=("Helvetica", 18, "bold"))
-label_title.pack(pady=10)
-
-# Username Entry
-tb.Label(root, text="Username:").pack(pady=5)
-entry_username = tb.Entry(root, bootstyle="info")
-entry_username.pack(pady=5)
-
-# Email Entry
-tb.Label(root, text="Email:").pack(pady=5)
-entry_email = tb.Entry(root, bootstyle="info")
-entry_email.pack(pady=5)
-
-# Phone Entry
-tb.Label(root, text="Phone Number:").pack(pady=5)
-entry_phone = tb.Entry(root, bootstyle="info")
-entry_phone.pack(pady=5)
-
-# Password Entry
-tb.Label(root, text="Password:").pack(pady=5)
-entry_password = tb.Entry(root, bootstyle="info", show="*")
-entry_password.pack(pady=5)
-
-# Confirm Password Entry
-tb.Label(root, text="Confirm Password:").pack(pady=5)
-entry_confirm_password = tb.Entry(root, bootstyle="info", show="*")
-entry_confirm_password.pack(pady=5)
-
-# Register Button
-btn_register = tb.Button(root, text="Register", bootstyle="success", command=register)
-btn_register.pack(pady=15)
-
-# Run the GUI
-root.mainloop()
+def register_frame(parent, switch_func, api_url):  # Added api_url parameter
+    frame = tb.Frame(parent)
+
+    def register():
+        username = entry_username.get()
+        email = entry_email.get()
+        phone_number = entry_phone.get()
+        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:
+            messagebox.showwarning("Input Error", "All fields are required!")
+            return
+
+        if password != confirm_password:
+            messagebox.showerror("Password Error", "Passwords do not match!")
+            return
+
+        # Sending registration data to backend
+        response = requests.post(f"{api_url}/auth/signup", json={
+            "username": username,
+            "email": email,
+            "phone_number": phone_number,
+            "password": password
+        })
+
+        try:
+            response_data = response.json()
+            if response.status_code == 200:
+                messagebox.showinfo("Registration Successful", f"Welcome, {username}!")
+                switch_func("login")  # Switch to login after successful registration
+            else:
+                messagebox.showerror("Registration Failed", response_data.get("detail", "Unknown error"))
+        except requests.exceptions.JSONDecodeError:
+            messagebox.showerror("Registration Failed", f"Server returned an invalid response.")
+
+    tb.Label(frame, text="Register", font=("Helvetica", 18, "bold")).pack(pady=10)
+
+    tb.Label(frame, text="Username:").pack(pady=5)
+    entry_username = tb.Entry(frame, bootstyle="info")
+    entry_username.pack(pady=5)
+
+    tb.Label(frame, text="Email:").pack(pady=5)
+    entry_email = tb.Entry(frame, bootstyle="info")
+    entry_email.pack(pady=5)
+
+    tb.Label(frame, text="Phone Number:").pack(pady=5)
+    entry_phone = tb.Entry(frame, bootstyle="info")
+    entry_phone.pack(pady=5)
+
+    tb.Label(frame, text="Password:").pack(pady=5)
+    entry_password = tb.Entry(frame, bootstyle="info", show="*")
+    entry_password.pack(pady=5)
+
+    tb.Label(frame, text="Confirm Password:").pack(pady=5)
+    entry_confirm_password = tb.Entry(frame, bootstyle="info", show="*")
+    entry_confirm_password.pack(pady=5)
+
+    btn_register = tb.Button(frame, text="Register", bootstyle="success", command=register)
+    btn_register.pack(pady=15)
+
+    tb.Button(frame, text="Already have an account? Login", bootstyle="link",
+              command=lambda: switch_func("login")).pack()
+
+    return frame
diff --git a/app/frontend/main.py b/app/frontend/main.py
index ca21b73..680f7df 100644
--- a/app/frontend/main.py
+++ b/app/frontend/main.py
@@ -1,101 +1,31 @@
 import ttkbootstrap as tb
-from ttkbootstrap.constants import *
-from tkinter import messagebox
-import requests
+from components.login import login_frame
+from components.register import register_frame
 
 # Backend API URL
 API_URL = "http://127.0.0.1:8000"
 
-# Function to handle registration
-def register():
-    username = entry_username.get()
-    email = entry_email.get()
-    phone_number = entry_phone.get()
-    password = entry_password.get()
-    confirm_password = entry_confirm_password.get()
-
-    if not username or not email or not password or not confirm_password:
-        messagebox.showwarning("Input Error", "All fields are required!")
-        return
-
-    if password != confirm_password:
-        messagebox.showerror("Password Error", "Passwords do not match!")
-        return
-
-    # Send registration data to backend
-    response = requests.post(f"{API_URL}/auth/signup", json={
-        "username": username,
-        "email": email,
-        "phone_number": phone_number,
-        "password": password
-    })
-
-    try:
-        response_data = response.json()
-        if response.status_code == 200:
-            messagebox.showinfo("Registration Successful", f"Welcome, {username}!")
-        else:
-            messagebox.showerror("Registration Failed", response_data.get("detail", "Unknown error"))
-    except requests.exceptions.JSONDecodeError:
-        messagebox.showerror("Registration Failed", f"Server returned non-JSON response: {response.text}")
-
-# Function to handle login
-def login():
-    email = entry_email.get()
-    password = entry_password.get()
-
-    # Send login data to backend
-    response = requests.post(f"{API_URL}/auth/login", json={
-        "email": email,
-        "password": password
-    })
-
-    if response.status_code == 200:
-        messagebox.showinfo("Login Successful", "Welcome!")
-    else:
-        messagebox.showerror("Login Failed", response.json().get("detail", "Invalid credentials"))
+# Function to switch between login and register
+def switch_frame(frame_name):
+    if frame_name == "login":
+        login.tkraise()
+    elif frame_name == "register":
+        register.tkraise()
 
 # Create main window
-root = tb.Window(themename="superhero")  # Change to "darkly", "superhero", etc.
+root = tb.Window(themename="superhero")
 root.title("Shopping App")
 root.geometry("900x800")
 
-# Title Label
-label_title = tb.Label(root, text="Shopping App", font=("Helvetica", 18, "bold"))
-label_title.pack(pady=10)
-
-# Username Entry
-tb.Label(root, text="Username:").pack(pady=5)
-entry_username = tb.Entry(root, bootstyle="info")
-entry_username.pack(pady=5)
-
-# Email Entry
-tb.Label(root, text="Email:").pack(pady=5)
-entry_email = tb.Entry(root, bootstyle="info")
-entry_email.pack(pady=5)
-
-# Phone Entry
-tb.Label(root, text="Phone Number:").pack(pady=5)
-entry_phone = tb.Entry(root, bootstyle="info")
-entry_phone.pack(pady=5)
-
-# Password Entry
-tb.Label(root, text="Password:").pack(pady=5)
-entry_password = tb.Entry(root, bootstyle="info", show="*")
-entry_password.pack(pady=5)
-
-# Confirm Password Entry
-tb.Label(root, text="Confirm Password:").pack(pady=5)
-entry_confirm_password = tb.Entry(root, bootstyle="info", show="*")
-entry_confirm_password.pack(pady=5)
+# Create Frames
+login = login_frame(root, switch_frame, API_URL)
+register = register_frame(root, switch_frame, API_URL)
 
-# Register Button
-btn_register = tb.Button(root, text="Register", bootstyle="success", command=register)
-btn_register.pack(pady=15)
+for frame in (login, register):
+    frame.place(relx=0, rely=0.2, relwidth=1, relheight=1)
 
-# Login Button
-btn_login = tb.Button(root, text="Login", bootstyle="primary", command=login)
-btn_login.pack(pady=15)
+# Show Login Frame First
+switch_frame("login")
 
 # Run the GUI
-root.mainloop()
\ No newline at end of file
+root.mainloop()
diff --git a/requirements.txt b/requirements.txt
index a9f5493b0494ce61126f5380e9f8c496c94b7327..274404719ffab8b40b176df1b46e4394eb5c7ed1 100644
GIT binary patch
literal 1996
zcmezWFOeaSA&()Sp@bokp@booA%#Jgp@gB5p@1Qkp_svz!Ir^*L65<lL65<JftP`c
z0i?c?A(J5=EN8-?$6x`MOJYc7C<5y(0m~XQ=rI_9F-T`JLn=cNLkUABLmERSSl)=i
zfWe5tltGWdkU@{Zn86TiLo!1eTm?wn5Ntb4E`uSFp@^ZFA(f$oK^N@uB8FUsM1~xO
zOol434InpzYzDavrVAvS%#aPX735x!xfW2{@)>d%@)?R462azxbc1{h(rpG-k;0J2
zP|Q%kP{~ljkin48kOwve<S#_1q=NNkGUPDCGn7GHlL8J=kjWr3LFz#m5{hXIi44Wy
zFfV|H1;|cA2196QK-`V0N|zxS>`RboAk`pj4t8NWLlHwNLn=caLk>7xKq^2X0P-co
zqznd-*&uO{E<*;8?;tM8U?^cIVJKio28Tf^*l!?xAaxMaVJb=(@)<y3g-8`<40;SE
zU>CsDRDkt^^csQF1;qAD22dC#g5@CYg4mtOP{L5m01Br(hIDY;<ujB*QynO*Kp3LZ
ziy@OCk0Fa8k--Sb6g>u0u<fAuFJj1MNMXolC}+rH&}9IbtP74ake@+zg4_f#%NLx2
zvKdMl3K)VJ5*gAMAijpFGJ=|!!cfXk#E=8F52PCuDloZ9hGK?7h8zY^oPbh99z!Za
zG6N`tiWngFBBvEga2|l=AW(|PVkm~EB#^y^;9LfZeNav*0H=;(aBL@m?FZQnN^OwP
z2Bn!CaH=hb%7WxU7~(@vT1{pEnF7fvMPOB+&@^Iz_yD8=67Hb<m<*SPxC4^z(becO
zq%u@6lz?*zdKm#S8=@Dx`MS^?3$hIq*N`*>(gn$l5MNh9(*j6UGDAE{ngppe0+$33
z8v+<A8PXYY!KogUia_xUQe(&f3T;Tb1F7+4sALFc2xRa9`w<jI5Dc>s7Eik1)B`F3
z^BBtDY9aBCsWz9PlpzOPmO(-pQr>}7gD|LE1L*<TAIadz;0v`KlwTn7AX!kJEo3MK
zm$S$|Fb0>I#^6*~#E{95%#Z<f4=AO8d<RJdFgZ|MKyqd_INgIn0%VIJ14un2w2B!r
z7*ZKPX$F*!(iuRdXfD)LP%eVy<6?$9aQO@>p&=zaD6~N4KtdD}l8y{HU{`@ky-Kht
zppXaIY0LmARUx?}mm!}a1#B<OO&~Q!3=qFT%0EyJ1C`~VkcX)<VSt1bD3m~@Q#L~q
zxa<Li5+wZ<fNcf24U+00u7lNEkn|3+%Me_iLc#zd3-NzEG%bV5%wlkD1}fu0_Jc}B
zLvRd0bd@q7=T%5u1u_|u(;y`TsCG$WFb2B`6cV8Dg2|VGV-S?*A@v4GuQ5{jTMn)z
oKyeHTb5QvW$r~WQfz(3cx||`EAqiY&fNC*Nc)?VGTm-QT0P1)m+yDRo

literal 959
zcmYey%gZlGEJ;n#EvYO>Ew;5a&@<OF;7ZJ^%*?m7HPN%sGvG=}E~+djv9&eUGtx8S
zN=_{*$xO?%wKXy@GSxHGGdAQ(P6P1`^$gAR47rjs5{rscOLX({i*gflGOJRHKsrr8
zGC7&a*|xS8dWL!yT*>)4`9+Dji69$I^vt+Y@`?*8OEU8FY;BFePDss7%*=@|OU%hk
zNi4}P0tp-G8E~Z~7MCOzWP-FA8k*`E8p1?$lXJkL272aP=|!ojc{!<IHyi31a%C7A
zf;E`v8E|EkloTZA7p2<T8tQ@6g7_u*`8i;}o9UT=6;yzf8(HWXa%HCEC4xL)Xuy?O
zQk;^Qm!4XbUs?=vj#p-0R-zGDfu1Q>Zeme(N`85sZf1#YK_y7kK+k~7H?b(Yv>-S!
zEfpeS#Fd*;T9gB_!cfnME4Q+^Fh@5zKQAvexg@_x7ZwbbdLaMi7iATL0>xO*&_K`7
zl&c`IxHu;>3FLZnJrk~i%$%J3a$8$NLp?)11FnL~<N{FeLxRhQtDrI^F|Q;u8RT3;
z13fdifNp9<Nl_v!(v3idBUI}ar<Rmt=B0yu2?_+5G4YUqGtx6M*E8Y@s7%jI%_{+`
zGPKk)<O-<ttqczI0l5tn>JX3UrsS8T=9Pg24fG7Tpn|!jIVG6|iA5!#P%zLlGT;iR
zjCAz%v9&eRGte{QDoQOZO)Z9)ZEU1x%vF?`oMCHgXsl<cX9DKvf+8(D6KsH?v7QlE
zaYkxRPG(+uMq)0=GE+ShuHwARv@}pcHq<lLGvo>m^l{8d&PdIz1cirzp0Nd2abZqw
zeo87hG7R*LjJb+S5{q(DOG;8f4l^;+GvF#I$xh18FDWi5N-O{w42lOXP;My#DKRwF
zGXn84^U~u}D@s!HiZk=`ia}Y&5R_X=A+cu)3Sa}S(xRN4%p_xw?Z$crT%~21$@xWj
zAY+U{Nwc&pCqKUc#5Dp%W_e;saz<Ka4k%lK(y9qpd1_K|esXpyC|nFp^$fTGoKYfn

-- 
GitLab


From 5e780ec66ef2424027378336abfd1cc0dde1f57a Mon Sep 17 00:00:00 2001
From: duyanhehe <duyanhex@gmail.com>
Date: Thu, 6 Mar 2025 19:26:49 +0700
Subject: [PATCH 2/3] resolve conflict

---
 .env.example       | 18 +++++++-----------
 app/core/config.py | 11 +++++++++--
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/.env.example b/.env.example
index 56e7c06..5b74985 100644
--- a/.env.example
+++ b/.env.example
@@ -1,11 +1,7 @@
-# Copy this file to .env
-
-APP_NAME = Shopping App
-# Change to your own database
-DATABASE_URL = mysql+pymysql://your_user:your_password@localhost/shopping     # This template use mysql
-# change your_user to your mysql username
-# change your_password to your mysql password
-# change localhost to 127.0.0.1 if youre running on local
-
-SECRET_KEY = your_secret_key
-DEBUG = True    # Only True or False
\ No newline at end of file
+APP_NAME="Shopping App"
+DATABASE_USERNAME="your_mysql_username"
+DATABASE_PASSWORD="your_mysql_password"
+DATABASE_HOST="127.0.0.1"
+DATABASE_NAME="shopping"
+SECRET_KEY="your_secret_key"
+DEBUG=True
diff --git a/app/core/config.py b/app/core/config.py
index 4045933..6aed5e9 100644
--- a/app/core/config.py
+++ b/app/core/config.py
@@ -4,14 +4,21 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
 
 class Settings(BaseSettings):
     app_name: str = "Shopping App"
-    database_url: str  # Ensure lowercase to match the .env key
+    database_username: str
+    database_password: str
+    database_host: str
+    database_name: str
     secret_key: str
     debug: bool = True
 
+    @property
+    def database_url(self) -> str:
+        return f"mysql+pymysql://{self.database_username}:{self.database_password}@{self.database_host}/{self.database_name}"
+
     model_config = SettingsConfigDict(
         env_file=str(Path(__file__).resolve().parent.parent / ".env"),
         env_file_encoding="utf-8",
-        case_sensitive=False,  # Allows case-insensitive environment variable keys
+        case_sensitive=False,
     )
 
 
-- 
GitLab


From 773e24b529eb5fea58edd8192964e9f9890a8bc8 Mon Sep 17 00:00:00 2001
From: duyanhehe <duyanhex@gmail.com>
Date: Thu, 6 Mar 2025 19:28:29 +0700
Subject: [PATCH 3/3] resolve conflict

---
 app/core/config.py                  |  6 +-
 app/frontend/components/login.py    | 32 ++++++++---
 app/frontend/components/register.py | 86 +++++++++++++++++++++++++++++
 app/frontend/main.py                | 13 +++++
 4 files changed, 125 insertions(+), 12 deletions(-)

diff --git a/app/core/config.py b/app/core/config.py
index 6aed5e9..c448ac0 100644
--- a/app/core/config.py
+++ b/app/core/config.py
@@ -9,11 +9,7 @@ class Settings(BaseSettings):
     database_host: str
     database_name: str
     secret_key: str
-    debug: bool = True
-
-    @property
-    def database_url(self) -> str:
-        return f"mysql+pymysql://{self.database_username}:{self.database_password}@{self.database_host}/{self.database_name}"
+    debug: bool = True  # Lowercase to match Python conventions
 
     model_config = SettingsConfigDict(
         env_file=str(Path(__file__).resolve().parent.parent / ".env"),
diff --git a/app/frontend/components/login.py b/app/frontend/components/login.py
index a52331b..02f559e 100644
--- a/app/frontend/components/login.py
+++ b/app/frontend/components/login.py
@@ -3,9 +3,14 @@ from ttkbootstrap.constants import *
 from tkinter import messagebox
 import requests  # Import requests for API communication
 
+
 def login_frame(parent, switch_func, api_url):  # Added api_url parameter
     frame = tb.Frame(parent)
 
+    def login():
+        email = entry_email.get()
+        password = entry_password.get()
+
     def login():
         email = entry_email.get()
         password = entry_password.get()
@@ -15,10 +20,9 @@ def login_frame(parent, switch_func, api_url):  # Added api_url parameter
             return
 
         # Sending login request to backend
-        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}
+        )
 
         try:
             response_data = response.json()
@@ -26,24 +30,38 @@ def login_frame(parent, switch_func, api_url):  # Added api_url parameter
                 messagebox.showinfo("Login Successful", f"Welcome back, {email}!")
                 # TODO: Implement navigation after login (e.g., open dashboard)
             else:
-                messagebox.showerror("Login Failed", response_data.get("detail", "Invalid credentials"))
+                messagebox.showerror(
+                    "Login Failed", response_data.get("detail", "Invalid credentials")
+                )
         except requests.exceptions.JSONDecodeError:
             messagebox.showerror("Login Failed", "Server returned an invalid response.")
 
     tb.Label(frame, text="Login", font=("Helvetica", 18, "bold")).pack(pady=10)
 
+    tb.Label(frame, text="Email:").pack(pady=5)
+    entry_email = tb.Entry(frame, bootstyle="info")
+    entry_email.pack(pady=5)
     tb.Label(frame, text="Email:").pack(pady=5)
     entry_email = tb.Entry(frame, bootstyle="info")
     entry_email.pack(pady=5)
 
+    tb.Label(frame, text="Password:").pack(pady=5)
+    entry_password = tb.Entry(frame, bootstyle="info", show="*")
+    entry_password.pack(pady=5)
     tb.Label(frame, text="Password:").pack(pady=5)
     entry_password = tb.Entry(frame, bootstyle="info", show="*")
     entry_password.pack(pady=5)
 
+    btn_login = tb.Button(frame, text="Login", bootstyle="primary", command=login)
+    btn_login.pack(pady=15)
     btn_login = tb.Button(frame, text="Login", bootstyle="primary", command=login)
     btn_login.pack(pady=15)
 
-    tb.Button(frame, text="Don't have an account? Register", bootstyle="link",
-              command=lambda: switch_func("register")).pack()
+    tb.Button(
+        frame,
+        text="Don't have an account? Register",
+        bootstyle="link",
+        command=lambda: switch_func("register"),
+    ).pack()
 
     return frame
diff --git a/app/frontend/components/register.py b/app/frontend/components/register.py
index 4f0b034..eda5e9d 100644
--- a/app/frontend/components/register.py
+++ b/app/frontend/components/register.py
@@ -3,6 +3,7 @@ from ttkbootstrap.constants import *
 from tkinter import messagebox
 import requests  # Import requests for API communication
 
+<<<<<<< HEAD
 def register_frame(parent, switch_func, api_url):  # Added api_url parameter
     frame = tb.Frame(parent)
 
@@ -66,5 +67,90 @@ def register_frame(parent, switch_func, api_url):  # Added api_url parameter
 
     tb.Button(frame, text="Already have an account? Login", bootstyle="link",
               command=lambda: switch_func("login")).pack()
+=======
+
+def register_frame(parent, switch_func, api_url):  # Added api_url parameter
+    frame = tb.Frame(parent)
+
+    def register():
+        username = entry_username.get()
+        email = entry_email.get()
+        phone_number = entry_phone.get()
+        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
+        ):
+            messagebox.showwarning("Input Error", "All fields are required!")
+            return
+
+        if password != confirm_password:
+            messagebox.showerror("Password Error", "Passwords do not match!")
+            return
+
+        # Sending registration data to backend
+        response = requests.post(
+            f"{api_url}/auth/signup",
+            json={
+                "username": username,
+                "email": email,
+                "phone_number": phone_number,
+                "password": password,
+            },
+        )
+
+        try:
+            response_data = response.json()
+            if response.status_code == 200:
+                messagebox.showinfo("Registration Successful", f"Welcome, {username}!")
+                switch_func("login")  # Switch to login after successful registration
+            else:
+                messagebox.showerror(
+                    "Registration Failed", response_data.get("detail", "Unknown error")
+                )
+        except requests.exceptions.JSONDecodeError:
+            messagebox.showerror(
+                "Registration Failed", f"Server returned an invalid response."
+            )
+
+    tb.Label(frame, text="Register", font=("Helvetica", 18, "bold")).pack(pady=10)
+
+    tb.Label(frame, text="Username:").pack(pady=5)
+    entry_username = tb.Entry(frame, bootstyle="info")
+    entry_username.pack(pady=5)
+
+    tb.Label(frame, text="Email:").pack(pady=5)
+    entry_email = tb.Entry(frame, bootstyle="info")
+    entry_email.pack(pady=5)
+
+    tb.Label(frame, text="Phone Number:").pack(pady=5)
+    entry_phone = tb.Entry(frame, bootstyle="info")
+    entry_phone.pack(pady=5)
+
+    tb.Label(frame, text="Password:").pack(pady=5)
+    entry_password = tb.Entry(frame, bootstyle="info", show="*")
+    entry_password.pack(pady=5)
+
+    tb.Label(frame, text="Confirm Password:").pack(pady=5)
+    entry_confirm_password = tb.Entry(frame, bootstyle="info", show="*")
+    entry_confirm_password.pack(pady=5)
+
+    btn_register = tb.Button(
+        frame, text="Register", bootstyle="success", command=register
+    )
+    btn_register.pack(pady=15)
+
+    tb.Button(
+        frame,
+        text="Already have an account? Login",
+        bootstyle="link",
+        command=lambda: switch_func("login"),
+    ).pack()
+>>>>>>> 510d2b0 (resolve merge)
 
     return frame
diff --git a/app/frontend/main.py b/app/frontend/main.py
index 680f7df..eb1b435 100644
--- a/app/frontend/main.py
+++ b/app/frontend/main.py
@@ -1,10 +1,13 @@
 import ttkbootstrap as tb
 from components.login import login_frame
 from components.register import register_frame
+from components.login import login_frame
+from components.register import register_frame
 
 # Backend API URL
 API_URL = "http://127.0.0.1:8000"
 
+
 # Function to switch between login and register
 def switch_frame(frame_name):
     if frame_name == "login":
@@ -12,8 +15,10 @@ def switch_frame(frame_name):
     elif frame_name == "register":
         register.tkraise()
 
+
 # Create main window
 root = tb.Window(themename="superhero")
+root = tb.Window(themename="superhero")
 root.title("Shopping App")
 root.geometry("900x800")
 
@@ -21,11 +26,19 @@ root.geometry("900x800")
 login = login_frame(root, switch_frame, API_URL)
 register = register_frame(root, switch_frame, API_URL)
 
+for frame in (login, register):
+    frame.place(relx=0, rely=0.2, relwidth=1, relheight=1)
+# Create Frames
+login = login_frame(root, switch_frame, API_URL)
+register = register_frame(root, switch_frame, API_URL)
+
 for frame in (login, register):
     frame.place(relx=0, rely=0.2, relwidth=1, relheight=1)
 
 # Show Login Frame First
 switch_frame("login")
+# Show Login Frame First
+switch_frame("login")
 
 # Run the GUI
 root.mainloop()
-- 
GitLab