transpolymer commited on
Commit
36bebed
·
verified ·
1 Parent(s): 947b5a1

Update login_page.py

Browse files
Files changed (1) hide show
  1. login_page.py +439 -72
login_page.py CHANGED
@@ -1,6 +1,7 @@
1
  import streamlit as st
2
  import bcrypt
3
  from db import get_database
 
4
 
5
  def create_users_collection():
6
  db = get_database()
@@ -10,12 +11,14 @@ def create_users_collection():
10
  def signup(data):
11
  db = get_database()
12
  if db.users.find_one({"username": data["username"]}):
13
- st.error("Username already exists")
 
 
14
  else:
15
  hashed = bcrypt.hashpw(data["password"].encode(), bcrypt.gensalt())
16
  data["password"] = hashed
17
  db.users.insert_one(data)
18
- st.success("Account created. Please log in.")
19
 
20
  def login_user(username, password):
21
  db = get_database()
@@ -25,8 +28,8 @@ def login_user(username, password):
25
  if isinstance(stored_password, str):
26
  stored_password = stored_password.encode('utf-8')
27
  if bcrypt.checkpw(password.encode(), stored_password):
28
- return True
29
- return False
30
 
31
  def reset_password(email, new_password):
32
  db = get_database()
@@ -38,121 +41,485 @@ def reset_password(email, new_password):
38
  return False
39
 
40
  def show_login_page():
 
41
  st.markdown("""
42
  <style>
43
- .main .block-container {
44
- padding-top: 1rem !important;
45
- padding-bottom: 1rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
 
 
 
 
 
 
 
47
  .login-card {
48
- background-color: #f0f2f6;
49
- border-radius: 12px;
50
- padding: 25px 30px;
51
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
 
 
 
 
 
 
 
 
 
 
52
  }
 
53
  .centered-heading {
54
  text-align: center;
55
- color: #4B8BBE;
 
 
 
 
 
 
 
56
  }
 
57
  .subheading {
58
  text-align: center;
59
- color: gray;
 
 
 
 
60
  }
 
61
  .stButton > button {
62
  width: 100%;
63
- padding: 6px 0;
64
- font-size: 14px;
65
- background-color: #4B8BBE;
66
  color: white;
67
  border: none;
68
- border-radius: 5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
  </style>
71
  """, unsafe_allow_html=True)
72
 
73
- st.markdown("<h1 class='centered-heading'>TransPolymer</h1>", unsafe_allow_html=True)
74
- st.markdown("<h4 class='subheading'>Get quick predictions using TransPolymer</h4>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
- col1, col2, col3 = st.columns([1, 2, 1])
 
77
  with col2:
78
  st.markdown("<div class='login-card'>", unsafe_allow_html=True)
79
 
80
- col_login, col_signup = st.columns(2)
81
- with col_login:
82
- if st.button("Login", key="login_btn"):
83
- st.session_state.auth_mode = "login"
84
- with col_signup:
85
- if st.button("Sign Up", key="signup_btn"):
86
- st.session_state.auth_mode = "signup"
87
-
88
- if "auth_mode" not in st.session_state:
89
- st.session_state.auth_mode = "login"
90
-
91
- st.markdown("<br>", unsafe_allow_html=True)
92
-
93
- # --- Login Mode ---
94
- if st.session_state.auth_mode == "login":
95
- username = st.text_input("Username", key="login_username")
96
- password = st.text_input("Password", type="password", key="login_password")
97
- if st.button("Login Now"):
98
- if login_user(username, password):
 
 
 
 
 
 
 
 
 
 
99
  st.session_state.logged_in = True
100
- st.success("Login Successful")
101
- st.rerun()
102
  else:
103
- st.error("Invalid username or password")
104
- if st.button("Forgot Password?"):
105
- st.session_state.auth_mode = "forgot"
 
 
 
106
  st.rerun()
 
 
107
 
108
- # --- Signup Mode ---
109
  elif st.session_state.auth_mode == "signup":
110
- role = st.selectbox("Sign up as", ["Scientist", "Student", "Researcher"], key="role")
111
-
112
- username = st.text_input("Username", key="signup_username")
113
- email = st.text_input("Email", key="signup_email")
114
- state = st.text_input("State", key="signup_state")
115
- password = st.text_input("Password", type="password", key="signup_password")
116
-
117
- # Role-specific fields in the desired order
118
- if role == "Scientist" or role == "Researcher":
119
- organisation = st.text_input("Organisation", key="signup_organisation")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  signup_data = {
121
  "role": role,
122
  "username": username,
 
 
123
  "email": email,
124
- "organisation": organisation,
125
  "state": state,
126
  "password": password
127
  }
128
- elif role == "Student":
129
- student_id = st.text_input("Student ID", key="signup_student_id")
130
- college_name = st.text_input("College Name", key="signup_college")
131
  signup_data = {
132
  "role": role,
133
  "username": username,
134
- "student_id": student_id,
135
- "college_name": college_name,
136
  "email": email,
 
137
  "state": state,
138
  "password": password
139
  }
140
-
141
- if st.button("Create Account"):
142
- signup(signup_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  st.session_state.auth_mode = "login"
144
  st.rerun()
 
 
145
 
146
- # --- Forgot Password Mode ---
147
  elif st.session_state.auth_mode == "forgot":
148
- email = st.text_input("Enter registered email", key="forgot_email")
149
- new_password = st.text_input("New password", type="password", key="forgot_password")
150
- if st.button("Reset Password"):
151
- if reset_password(email, new_password):
152
- st.success("Password reset successful. Please login.")
153
- st.session_state.auth_mode = "login"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  st.rerun()
155
  else:
156
- st.error("Email not found.")
 
 
 
 
 
 
 
 
 
 
 
 
 
157
 
158
  st.markdown("</div>", unsafe_allow_html=True)
 
1
  import streamlit as st
2
  import bcrypt
3
  from db import get_database
4
+ import time
5
 
6
  def create_users_collection():
7
  db = get_database()
 
11
  def signup(data):
12
  db = get_database()
13
  if db.users.find_one({"username": data["username"]}):
14
+ return False, "Username already exists"
15
+ elif db.users.find_one({"email": data["email"]}):
16
+ return False, "Email already exists"
17
  else:
18
  hashed = bcrypt.hashpw(data["password"].encode(), bcrypt.gensalt())
19
  data["password"] = hashed
20
  db.users.insert_one(data)
21
+ return True, "Account created successfully!"
22
 
23
  def login_user(username, password):
24
  db = get_database()
 
28
  if isinstance(stored_password, str):
29
  stored_password = stored_password.encode('utf-8')
30
  if bcrypt.checkpw(password.encode(), stored_password):
31
+ return True, user
32
+ return False, None
33
 
34
  def reset_password(email, new_password):
35
  db = get_database()
 
41
  return False
42
 
43
  def show_login_page():
44
+ # Apply custom CSS for modern, animated UI
45
  st.markdown("""
46
  <style>
47
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
48
+
49
+ * {
50
+ font-family: 'Poppins', sans-serif;
51
+ margin: 0;
52
+ padding: 0;
53
+ box-sizing: border-box;
54
+ }
55
+
56
+ /* Dark theme background */
57
+ body {
58
+ background-color: #121420 !important;
59
+ color: #fff;
60
+ }
61
+
62
+ /* Override Streamlit's default spacing */
63
+ .block-container {
64
+ padding-top: 0 !important;
65
+ padding-bottom: 0 !important;
66
+ margin-top: 0 !important;
67
+ max-width: 1000px;
68
+ }
69
+
70
+ /* Target all Streamlit containers */
71
+ .css-18e3th9, .css-1d391kg, .css-1wrcr25, .css-ocqkz7, .css-j7qwjs {
72
+ padding-top: 0 !important;
73
+ margin-top: 0 !important;
74
  }
75
+
76
+ /* Override header spacing */
77
+ header {
78
+ margin-bottom: 0 !important;
79
+ padding-bottom: 0 !important;
80
+ }
81
+
82
  .login-card {
83
+ background: rgba(30, 33, 43, 0.6);
84
+ backdrop-filter: blur(10px);
85
+ border-radius: 16px;
86
+ padding: 30px;
87
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
88
+ transition: all 0.3s ease;
89
+ border: 1px solid rgba(255, 255, 255, 0.1);
90
+ margin-top: 10px;
91
+ }
92
+
93
+ .app-header-container {
94
+ margin: 0 !important;
95
+ padding: 20px 0 10px 0 !important;
96
+ line-height: 1 !important;
97
  }
98
+
99
  .centered-heading {
100
  text-align: center;
101
+ font-weight: 700;
102
+ background: linear-gradient(90deg, #4B8BBE, #306998);
103
+ -webkit-background-clip: text;
104
+ -webkit-text-fill-color: transparent;
105
+ margin: 0 !important;
106
+ padding: 0 !important;
107
+ line-height: 1.2 !important;
108
+ font-size: 2.5rem !important;
109
  }
110
+
111
  .subheading {
112
  text-align: center;
113
+ color: #ddd;
114
+ font-weight: 400;
115
+ margin: 10px 0 20px 0 !important;
116
+ padding: 0 !important;
117
+ line-height: 1.2 !important;
118
  }
119
+
120
  .stButton > button {
121
  width: 100%;
122
+ padding: 12px 0;
123
+ font-size: 16px;
124
+ background: linear-gradient(90deg, #4B8BBE, #306998);
125
  color: white;
126
  border: none;
127
+ border-radius: 8px;
128
+ cursor: pointer;
129
+ transition: all 0.3s ease;
130
+ font-weight: 500;
131
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
132
+ margin-top: 10px;
133
+ }
134
+
135
+ .stButton > button:hover {
136
+ transform: translateY(-2px);
137
+ box-shadow: 0 7px 14px rgba(0, 0, 0, 0.3);
138
+ }
139
+
140
+ .stTextInput > div > div > input {
141
+ border-radius: 8px;
142
+ border: 1px solid #444;
143
+ background-color: rgba(30, 33, 43, 0.8);
144
+ color: #fff;
145
+ padding: 10px 15px;
146
+ transition: all 0.3s ease;
147
+ }
148
+
149
+ .stTextInput > div > div > input:focus {
150
+ border-color: #4B8BBE;
151
+ box-shadow: 0 0 0 2px rgba(75, 139, 190, 0.2);
152
+ }
153
+
154
+ .stSelectbox > div > div > div {
155
+ border-radius: 8px;
156
+ border: 1px solid #444;
157
+ background-color: rgba(30, 33, 43, 0.8);
158
+ color: #fff;
159
+ padding: 2px 15px;
160
+ }
161
+
162
+ .form-fade {
163
+ animation: fadeIn 0.5s ease forwards;
164
+ opacity: 0;
165
+ }
166
+
167
+ @keyframes fadeIn {
168
+ from { opacity: 0; transform: translateY(10px); }
169
+ to { opacity: 1; transform: translateY(0); }
170
+ }
171
+
172
+ .loader {
173
+ display: inline-block;
174
+ width: 80px;
175
+ height: 80px;
176
+ margin: 0 auto;
177
+ }
178
+
179
+ .loader:after {
180
+ content: " ";
181
+ display: block;
182
+ width: 64px;
183
+ height: 64px;
184
+ margin: 8px;
185
+ border-radius: 50%;
186
+ border: 6px solid #4B8BBE;
187
+ border-color: #4B8BBE transparent #4B8BBE transparent;
188
+ animation: loader 1.2s linear infinite;
189
+ }
190
+
191
+ @keyframes loader {
192
+ 0% { transform: rotate(0deg); }
193
+ 100% { transform: rotate(360deg); }
194
+ }
195
+
196
+ .switch-link {
197
+ color: #4B8BBE;
198
+ text-align: center;
199
+ cursor: pointer;
200
+ margin-top: 15px;
201
+ font-size: 14px;
202
+ text-decoration: none;
203
+ display: block;
204
+ }
205
+
206
+ .switch-link:hover {
207
+ text-decoration: underline;
208
+ }
209
+
210
+ .back-btn {
211
+ color: #4B8BBE;
212
+ cursor: pointer;
213
+ margin-top: 15px;
214
+ font-size: 14px;
215
+ display: flex;
216
+ align-items: center;
217
+ gap: 5px;
218
+ }
219
+
220
+ .back-btn:hover {
221
+ text-decoration: underline;
222
+ }
223
+
224
+ .form-group {
225
+ margin-bottom: 15px;
226
+ }
227
+
228
+ .form-label {
229
+ font-size: 14px;
230
+ color: #bbb;
231
+ margin-bottom: 5px;
232
+ font-weight: 500;
233
+ }
234
+
235
+ /* Toast notification */
236
+ .toast {
237
+ position: fixed;
238
+ top: 20px;
239
+ right: 20px;
240
+ padding: 15px 25px;
241
+ background: #1e212b;
242
+ color: #fff;
243
+ border-radius: 8px;
244
+ box-shadow: 0 4px 12px rgba(0,0,0,0.25);
245
+ z-index: 9999;
246
+ opacity: 0;
247
+ transform: translateY(-20px);
248
+ animation: toast-in 0.3s forwards, toast-out 0.3s forwards 3s;
249
+ display: flex;
250
+ align-items: center;
251
+ gap: 10px;
252
+ }
253
+
254
+ .toast.success {
255
+ border-left: 4px solid #4CAF50;
256
+ }
257
+
258
+ .toast.error {
259
+ border-left: 4px solid #F44336;
260
+ }
261
+
262
+ @keyframes toast-in {
263
+ to { opacity: 1; transform: translateY(0); }
264
+ }
265
+
266
+ @keyframes toast-out {
267
+ to { opacity: 0; transform: translateY(-20px); }
268
+ }
269
+ </style>
270
+ """, unsafe_allow_html=True)
271
+
272
+ # Hide Streamlit default elements
273
+ st.markdown("""
274
+ <style>
275
+ #MainMenu {visibility: hidden;}
276
+ footer {visibility: hidden;}
277
+ .stDeployButton {display:none;}
278
+
279
+ /* Zero out all padding and margins at the top */
280
+ .stApp > header {
281
+ display: none;
282
+ }
283
+
284
+ /* Ensure the app starts from the very top */
285
+ .stApp {
286
+ margin-top: 0 !important;
287
+ }
288
+
289
+ /* Force no spacing at the top */
290
+ .element-container:first-child {
291
+ margin-top: 0 !important;
292
+ padding-top: 0 !important;
293
  }
294
  </style>
295
  """, unsafe_allow_html=True)
296
 
297
+ # Logo and Header - Using a div container with strict spacing control
298
+ st.markdown("""
299
+ <div class="app-header-container">
300
+ <h1 class="centered-heading">TransPolymer</h1>
301
+ <h4 class="subheading">Get quick predictions using advanced polymer technology</h4>
302
+ </div>
303
+ """, unsafe_allow_html=True)
304
+
305
+ # Initialize session state variables
306
+ if "auth_mode" not in st.session_state:
307
+ st.session_state.auth_mode = "login"
308
+ if "loading" not in st.session_state:
309
+ st.session_state.loading = False
310
+ if "toast" not in st.session_state:
311
+ st.session_state.toast = None
312
+
313
+ # Display toast notification if needed
314
+ if st.session_state.toast:
315
+ toast_type, message = st.session_state.toast
316
+ st.markdown(f"""
317
+ <div class="toast {toast_type}">
318
+ <span>{message}</span>
319
+ </div>
320
+ """, unsafe_allow_html=True)
321
+ # Clear toast after displaying
322
+ st.session_state.toast = None
323
 
324
+ # Create a centered card layout
325
+ col1, col2, col3 = st.columns([1, 10, 1])
326
  with col2:
327
  st.markdown("<div class='login-card'>", unsafe_allow_html=True)
328
 
329
+ # Loading spinner
330
+ if st.session_state.loading:
331
+ st.markdown('<div class="form-fade">', unsafe_allow_html=True)
332
+ st.markdown('<div class="loader"></div>', unsafe_allow_html=True)
333
+ st.markdown('<p style="text-align: center; margin-top: 20px;">Processing...</p>', unsafe_allow_html=True)
334
+ st.markdown('</div>', unsafe_allow_html=True)
335
+ time.sleep(1.5) # Simulated loading time
336
+ st.session_state.loading = False
337
+ st.rerun()
338
+
339
+ # --- Login Form ---
340
+ elif st.session_state.auth_mode == "login":
341
+ st.markdown('<div class="form-fade">', unsafe_allow_html=True)
342
+
343
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
344
+ st.markdown('<div class="form-label">Username</div>', unsafe_allow_html=True)
345
+ username = st.text_input("", key="login_username", placeholder="Enter your username")
346
+ st.markdown('</div>', unsafe_allow_html=True)
347
+
348
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
349
+ st.markdown('<div class="form-label">Password</div>', unsafe_allow_html=True)
350
+ password = st.text_input("", type="password", key="login_password", placeholder="Enter your password")
351
+ st.markdown('</div>', unsafe_allow_html=True)
352
+
353
+ # Login button with animation
354
+ if st.button("Login Now", key="login_submit"):
355
+ st.session_state.loading = True
356
+ success, user = login_user(username, password)
357
+ if success:
358
  st.session_state.logged_in = True
359
+ st.session_state.user = user
360
+ st.session_state.toast = ("success", "Login successful! Redirecting...")
361
  else:
362
+ st.session_state.toast = ("error", "Invalid username or password")
363
+ st.rerun()
364
+
365
+ # Switch to Sign Up link
366
+ if st.button("Sign Up", key="switch_to_signup"):
367
+ st.session_state.auth_mode = "signup"
368
  st.rerun()
369
+
370
+ st.markdown('</div>', unsafe_allow_html=True)
371
 
372
+ # --- Sign Up Form ---
373
  elif st.session_state.auth_mode == "signup":
374
+ st.markdown('<div class="form-fade">', unsafe_allow_html=True)
375
+
376
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
377
+ st.markdown('<div class="form-label">Sign up as</div>', unsafe_allow_html=True)
378
+ role = st.selectbox("", ["Scientist", "Student", "Researcher"], key="role")
379
+ st.markdown('</div>', unsafe_allow_html=True)
380
+
381
+ col1, col2 = st.columns(2)
382
+
383
+ with col1:
384
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
385
+ st.markdown('<div class="form-label">Username</div>', unsafe_allow_html=True)
386
+ username = st.text_input("", key="signup_username", placeholder="Choose a username")
387
+ st.markdown('</div>', unsafe_allow_html=True)
388
+
389
+ with col2:
390
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
391
+ st.markdown('<div class="form-label">Email</div>', unsafe_allow_html=True)
392
+ email = st.text_input("", key="signup_email", placeholder="Your email address")
393
+ st.markdown('</div>', unsafe_allow_html=True)
394
+
395
+ # Role-specific fields
396
+ if role == "Student":
397
+ col1, col2 = st.columns(2)
398
+ with col1:
399
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
400
+ st.markdown('<div class="form-label">Student ID</div>', unsafe_allow_html=True)
401
+ student_id = st.text_input("", key="signup_student_id", placeholder="Your student ID")
402
+ st.markdown('</div>', unsafe_allow_html=True)
403
+
404
+ with col2:
405
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
406
+ st.markdown('<div class="form-label">College Name</div>', unsafe_allow_html=True)
407
+ college_name = st.text_input("", key="signup_college", placeholder="Your college name")
408
+ st.markdown('</div>', unsafe_allow_html=True)
409
+
410
+ elif role in ["Scientist", "Researcher"]:
411
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
412
+ st.markdown('<div class="form-label">Organisation</div>', unsafe_allow_html=True)
413
+ organisation = st.text_input("", key="signup_organisation", placeholder="Your organisation name")
414
+ st.markdown('</div>', unsafe_allow_html=True)
415
+
416
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
417
+ st.markdown('<div class="form-label">State</div>', unsafe_allow_html=True)
418
+ state = st.text_input("", key="signup_state", placeholder="Your state")
419
+ st.markdown('</div>', unsafe_allow_html=True)
420
+
421
+ col1, col2 = st.columns(2)
422
+ with col1:
423
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
424
+ st.markdown('<div class="form-label">Password</div>', unsafe_allow_html=True)
425
+ password = st.text_input("", type="password", key="signup_password", placeholder="Create a password")
426
+ st.markdown('</div>', unsafe_allow_html=True)
427
+
428
+ with col2:
429
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
430
+ st.markdown('<div class="form-label">Confirm Password</div>', unsafe_allow_html=True)
431
+ confirm_password = st.text_input("", type="password", key="signup_confirm", placeholder="Confirm password")
432
+ st.markdown('</div>', unsafe_allow_html=True)
433
+
434
+ # Prepare signup data
435
+ if role == "Student":
436
  signup_data = {
437
  "role": role,
438
  "username": username,
439
+ "student_id": student_id if 'student_id' in locals() else "",
440
+ "college_name": college_name if 'college_name' in locals() else "",
441
  "email": email,
 
442
  "state": state,
443
  "password": password
444
  }
445
+ else:
 
 
446
  signup_data = {
447
  "role": role,
448
  "username": username,
 
 
449
  "email": email,
450
+ "organisation": organisation if 'organisation' in locals() else "",
451
  "state": state,
452
  "password": password
453
  }
454
+
455
+ # Register button
456
+ if st.button("Create Account", key="signup_submit"):
457
+ if password != confirm_password:
458
+ st.session_state.toast = ("error", "Passwords don't match")
459
+ st.rerun()
460
+ elif not username or not email or not password:
461
+ st.session_state.toast = ("error", "Please fill all required fields")
462
+ st.rerun()
463
+ else:
464
+ st.session_state.loading = True
465
+ success, message = signup(signup_data)
466
+ if success:
467
+ st.session_state.auth_mode = "login"
468
+ st.session_state.toast = ("success", message)
469
+ else:
470
+ st.session_state.toast = ("error", message)
471
+ st.rerun()
472
+
473
+ # Back to login button
474
+ if st.button("Back to Login", key="back_to_login"):
475
  st.session_state.auth_mode = "login"
476
  st.rerun()
477
+
478
+ st.markdown('</div>', unsafe_allow_html=True)
479
 
480
+ # --- Forgot Password Form (only accessible from login page, but keeping code in case it's needed) ---
481
  elif st.session_state.auth_mode == "forgot":
482
+ st.markdown('<div class="form-fade">', unsafe_allow_html=True)
483
+
484
+ st.markdown("<h3 style='text-align: center; margin-bottom: 20px;'>Reset Password</h3>", unsafe_allow_html=True)
485
+
486
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
487
+ st.markdown('<div class="form-label">Email</div>', unsafe_allow_html=True)
488
+ email = st.text_input("", key="forgot_email", placeholder="Enter your registered email")
489
+ st.markdown('</div>', unsafe_allow_html=True)
490
+
491
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
492
+ st.markdown('<div class="form-label">New Password</div>', unsafe_allow_html=True)
493
+ new_password = st.text_input("", type="password", key="forgot_password", placeholder="Enter new password")
494
+ st.markdown('</div>', unsafe_allow_html=True)
495
+
496
+ st.markdown('<div class="form-group">', unsafe_allow_html=True)
497
+ st.markdown('<div class="form-label">Confirm New Password</div>', unsafe_allow_html=True)
498
+ confirm_password = st.text_input("", type="password", key="forgot_confirm", placeholder="Confirm new password")
499
+ st.markdown('</div>', unsafe_allow_html=True)
500
+
501
+ # Reset button
502
+ if st.button("Reset Password", key="reset_submit"):
503
+ if not email or not new_password:
504
+ st.session_state.toast = ("error", "Please fill all fields")
505
+ st.rerun()
506
+ elif new_password != confirm_password:
507
+ st.session_state.toast = ("error", "Passwords don't match")
508
  st.rerun()
509
  else:
510
+ st.session_state.loading = True
511
+ if reset_password(email, new_password):
512
+ st.session_state.auth_mode = "login"
513
+ st.session_state.toast = ("success", "Password reset successful")
514
+ else:
515
+ st.session_state.toast = ("error", "Email not found")
516
+ st.rerun()
517
+
518
+ # Back to login button
519
+ if st.button("Back to Login", key="back_btn"):
520
+ st.session_state.auth_mode = "login"
521
+ st.rerun()
522
+
523
+ st.markdown('</div>', unsafe_allow_html=True)
524
 
525
  st.markdown("</div>", unsafe_allow_html=True)