amaye15 commited on
Commit
8376eb2
·
1 Parent(s): 202aa5d

Improve style

Browse files
Files changed (3) hide show
  1. static/css/style.css +230 -40
  2. static/js/script.js +95 -22
  3. templates/index.html +75 -38
static/css/style.css CHANGED
@@ -1,84 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  body {
2
- font-family: sans-serif;
 
 
3
  line-height: 1.6;
4
- margin: 20px;
5
- background-color: #f4f4f4;
 
6
  }
7
 
8
  h1, h2 {
9
- color: #333;
10
  }
11
 
12
- .auth-section {
13
- background-color: #fff;
 
 
14
  padding: 20px;
15
- margin-bottom: 20px;
16
- border: 1px solid #ddd;
17
- border-radius: 5px;
18
- max-width: 400px;
19
  }
20
 
21
- #welcome-section {
22
- background-color: #e7f3fe;
23
- padding: 20px;
24
- border: 1px solid #c8e1f8;
25
- border-radius: 5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
 
 
 
 
 
28
 
29
  label {
30
- display: inline-block;
31
- margin-bottom: 5px;
 
32
  }
33
 
34
  input[type="email"],
35
  input[type="password"] {
36
- width: calc(100% - 22px); /* Account for padding/border */
37
- padding: 10px;
38
- margin-bottom: 10px;
39
- border: 1px solid #ccc;
40
- border-radius: 4px;
 
 
 
 
 
 
 
 
 
41
  }
42
 
43
- button {
44
- background-color: #5cb85c;
45
- color: white;
46
- padding: 10px 15px;
 
47
  border: none;
48
- border-radius: 4px;
 
 
49
  cursor: pointer;
50
- font-size: 1em;
 
 
51
  }
52
 
53
- button:hover {
54
- background-color: #4cae4c;
55
  }
56
 
57
- #logout-button {
58
- background-color: #d9534f;
59
- }
60
- #logout-button:hover {
61
- background-color: #c9302c;
62
  }
63
 
 
64
  .status-message {
65
  margin-top: 15px;
66
- color: red;
67
  font-weight: bold;
 
68
  }
 
69
  .status-message.success {
70
- color: green;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
72
 
73
  hr {
74
  margin: 20px 0;
 
75
  }
76
 
 
77
  #notifications {
78
  margin-top: 15px;
79
  padding: 15px;
80
- border: 1px dashed #aaa;
81
- background-color: #f9f9f9;
82
  min-height: 100px;
83
  max-height: 300px;
84
  overflow-y: auto;
@@ -87,8 +276,9 @@ hr {
87
  #notifications p {
88
  margin: 5px 0;
89
  padding-bottom: 5px;
90
- border-bottom: 1px solid #eee;
91
  }
 
92
  #notifications p:last-child {
93
  border-bottom: none;
94
  }
 
1
+ /* Default variables for light mode */
2
+ :root {
3
+ --background-color: #f4f4f4;
4
+ --text-color: #333333;
5
+ --card-background: #ffffff;
6
+ --input-background: #f0f2f5;
7
+ --input-border: #e0e3e9;
8
+ --input-text: #333333;
9
+ --button-primary-bg: #5cb85c;
10
+ --button-primary-text: white;
11
+ --button-secondary-bg: #e0e3e9;
12
+ --button-secondary-text: #4a5568;
13
+ --border-color: #ddd;
14
+ --separator-color: #e0e3e9;
15
+ --error-color: #d9534f;
16
+ --success-color: #5cb85c;
17
+ --link-color: #3182ce;
18
+ --header-color: #333;
19
+ --hero-bg: #e7f3fe;
20
+ --hero-color: #333;
21
+ --welcome-bg: #e7f3fe;
22
+ --logout-button-bg: #d9534f;
23
+ --logout-button-hover: #c9302c;
24
+ }
25
+
26
+ /* Dark mode variables */
27
+ @media (prefers-color-scheme: dark) {
28
+ :root {
29
+ --background-color: #1a202c;
30
+ --text-color: #e2e8f0;
31
+ --card-background: #2d3748;
32
+ --input-background: #4a5568;
33
+ --input-border: #4a5568;
34
+ --input-text: #e2e8f0;
35
+ --button-primary-bg: #6cb46c;
36
+ --button-primary-text: white;
37
+ --button-secondary-bg: #4a5568;
38
+ --button-secondary-text: #e2e8f0;
39
+ --border-color: #4a5568;
40
+ --separator-color: #4a5568;
41
+ --error-color: #fc8181;
42
+ --success-color: #68d391;
43
+ --link-color: #63b3ed;
44
+ --header-color: #e2e8f0;
45
+ --hero-bg: #2d3748;
46
+ --hero-color: #e2e8f0;
47
+ --welcome-bg: #2d3748;
48
+ --logout-button-bg: #e53e3e;
49
+ --logout-button-hover: #c53030;
50
+ }
51
+ }
52
+
53
+ /* Base styles */
54
+ * {
55
+ box-sizing: border-box;
56
+ margin: 0;
57
+ padding: 0;
58
+ }
59
+
60
  body {
61
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
62
+ background-color: var(--background-color);
63
+ color: var(--text-color);
64
  line-height: 1.6;
65
+ transition: background-color 0.3s ease, color 0.3s ease;
66
+ margin: 0;
67
+ padding: 0;
68
  }
69
 
70
  h1, h2 {
71
+ color: var(--header-color);
72
  }
73
 
74
+ .container {
75
+ width: 100%;
76
+ max-width: 1000px;
77
+ margin: 20px auto;
78
  padding: 20px;
 
 
 
 
79
  }
80
 
81
+ .logo {
82
+ text-align: center;
83
+ margin-bottom: 30px;
84
+ }
85
+
86
+ .logo h1 {
87
+ font-size: 2rem;
88
+ margin-bottom: 10px;
89
+ }
90
+
91
+ .logo p {
92
+ font-size: 1.1rem;
93
+ opacity: 0.8;
94
+ }
95
+
96
+ /* Auth container styles */
97
+ .auth-container {
98
+ display: flex;
99
+ flex-direction: column;
100
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
101
+ border-radius: 8px;
102
+ overflow: hidden;
103
+ background-color: var(--card-background);
104
+ transition: box-shadow 0.3s ease, background-color 0.3s ease;
105
+ margin-bottom: 30px;
106
+ }
107
+
108
+ @media (min-width: 768px) {
109
+ .auth-container {
110
+ flex-direction: row;
111
+ height: 500px;
112
+ }
113
+ }
114
+
115
+ .tabs {
116
+ display: flex;
117
+ border-bottom: 1px solid var(--separator-color);
118
+ }
119
+
120
+ .tab {
121
+ padding: 15px 0;
122
+ flex: 1;
123
+ text-align: center;
124
+ cursor: pointer;
125
+ font-weight: 600;
126
+ transition: background-color 0.3s ease;
127
+ }
128
+
129
+ .tab.active {
130
+ border-bottom: 3px solid var(--button-primary-bg);
131
+ color: var(--button-primary-bg);
132
+ }
133
+
134
+ .auth-forms {
135
+ display: flex;
136
+ flex: 1;
137
+ flex-direction: column;
138
+ padding: 30px;
139
+ }
140
+
141
+ .auth-form {
142
+ display: none;
143
+ }
144
+
145
+ .auth-form.active {
146
+ display: block;
147
+ }
148
+
149
+ .hero {
150
+ display: none;
151
+ flex: 1;
152
+ background-color: var(--hero-bg);
153
+ color: var(--hero-color);
154
+ padding: 40px;
155
+ display: flex;
156
+ flex-direction: column;
157
+ justify-content: center;
158
+ }
159
+
160
+ @media (min-width: 768px) {
161
+ .hero {
162
+ display: flex;
163
+ }
164
+ }
165
+
166
+ .hero h2 {
167
+ margin-bottom: 20px;
168
+ color: var(--hero-color);
169
  }
170
 
171
+ /* Form styles */
172
+ .form-group {
173
+ margin-bottom: 20px;
174
+ }
175
 
176
  label {
177
+ display: block;
178
+ margin-bottom: 7px;
179
+ font-weight: 500;
180
  }
181
 
182
  input[type="email"],
183
  input[type="password"] {
184
+ width: 100%;
185
+ padding: 12px 15px;
186
+ border-radius: 6px;
187
+ border: 1px solid var(--input-border);
188
+ background-color: var(--input-background);
189
+ color: var(--input-text);
190
+ font-size: 16px;
191
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
192
+ }
193
+
194
+ input:focus {
195
+ outline: none;
196
+ border-color: var(--button-primary-bg);
197
+ box-shadow: 0 0 0 3px rgba(92, 184, 92, 0.25);
198
  }
199
 
200
+ .button {
201
+ display: inline-block;
202
+ padding: 12px 20px;
203
+ background-color: var(--button-primary-bg);
204
+ color: var(--button-primary-text);
205
  border: none;
206
+ border-radius: 6px;
207
+ font-size: 16px;
208
+ font-weight: 600;
209
  cursor: pointer;
210
+ transition: opacity 0.3s ease, transform 0.1s ease;
211
+ width: 100%;
212
+ text-align: center;
213
  }
214
 
215
+ .button:hover {
216
+ opacity: 0.9;
217
  }
218
 
219
+ .button:active {
220
+ transform: translateY(1px);
 
 
 
221
  }
222
 
223
+ /* Status messages */
224
  .status-message {
225
  margin-top: 15px;
226
+ color: var(--error-color);
227
  font-weight: bold;
228
+ display: none;
229
  }
230
+
231
  .status-message.success {
232
+ color: var(--success-color);
233
+ }
234
+
235
+ .error-message {
236
+ color: var(--error-color);
237
+ font-size: 14px;
238
+ margin-top: 5px;
239
+ display: none;
240
+ }
241
+
242
+ /* Welcome section */
243
+ #welcome-section {
244
+ background-color: var(--welcome-bg);
245
+ padding: 20px;
246
+ border: 1px solid var(--border-color);
247
+ border-radius: 5px;
248
+ }
249
+
250
+ #logout-button {
251
+ background-color: var(--logout-button-bg);
252
+ margin-top: 15px;
253
+ width: auto;
254
+ }
255
+
256
+ #logout-button:hover {
257
+ background-color: var(--logout-button-hover);
258
  }
259
 
260
  hr {
261
  margin: 20px 0;
262
+ border-color: var(--separator-color);
263
  }
264
 
265
+ /* Notifications */
266
  #notifications {
267
  margin-top: 15px;
268
  padding: 15px;
269
+ border: 1px dashed var(--border-color);
270
+ background-color: var(--card-background);
271
  min-height: 100px;
272
  max-height: 300px;
273
  overflow-y: auto;
 
276
  #notifications p {
277
  margin: 5px 0;
278
  padding-bottom: 5px;
279
+ border-bottom: 1px solid var(--separator-color);
280
  }
281
+
282
  #notifications p:last-child {
283
  border-bottom: none;
284
  }
static/js/script.js CHANGED
@@ -1,5 +1,7 @@
1
- const registerSection = document.getElementById('register-section');
 
2
  const loginSection = document.getElementById('login-section');
 
3
  const welcomeSection = document.getElementById('welcome-section');
4
  const registerForm = document.getElementById('register-form');
5
  const loginForm = document.getElementById('login-form');
@@ -14,10 +16,10 @@ const API_URL = '/api'; // Use relative path
14
  let webSocket = null;
15
  let authToken = localStorage.getItem('authToken'); // Load token on script start
16
 
17
- // --- UI Control ---
18
  function showSection(sectionId) {
19
- registerSection.style.display = 'none';
20
  loginSection.style.display = 'none';
 
21
  welcomeSection.style.display = 'none';
22
 
23
  const sectionToShow = document.getElementById(sectionId);
@@ -28,6 +30,25 @@ function showSection(sectionId) {
28
  }
29
  }
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  function setStatus(element, message, isSuccess = false) {
32
  element.textContent = message;
33
  element.className = isSuccess ? 'status-message success' : 'status-message';
@@ -67,7 +88,6 @@ async function apiRequest(endpoint, method = 'GET', body = null, token = null) {
67
  }
68
  }
69
 
70
-
71
  // --- WebSocket Handling ---
72
  function connectWebSocket(token) {
73
  if (!token) {
@@ -84,7 +104,6 @@ function connectWebSocket(token) {
84
  const wsUrl = `${wsProtocol}//${window.location.host}${API_URL}/ws/${token}`;
85
  console.log("Attempting to connect WebSocket:", wsUrl);
86
 
87
-
88
  webSocket = new WebSocket(wsUrl);
89
 
90
  webSocket.onopen = (event) => {
@@ -104,11 +123,10 @@ function connectWebSocket(token) {
104
  p.textContent = messageData.message;
105
  // Add message to the top
106
  notificationsDiv.insertBefore(p, notificationsDiv.firstChild);
107
- // Limit number of messages shown (optional)
108
  while (notificationsDiv.children.length > 10) {
109
  notificationsDiv.removeChild(notificationsDiv.lastChild);
110
  }
111
-
112
  }
113
  } catch (error) {
114
  console.error("Error parsing WebSocket message:", error);
@@ -127,7 +145,6 @@ function connectWebSocket(token) {
127
  console.log("WebSocket connection closed:", event);
128
  webSocket = null; // Reset WebSocket variable
129
  // Optionally try to reconnect or inform user
130
- // Do not clear notifications on close, user might want to see history
131
  if (!event.wasClean) {
132
  const p = document.createElement('p');
133
  p.textContent = `WebSocket disconnected unexpectedly (Code: ${event.code}). Please refresh or log out/in.`;
@@ -164,20 +181,22 @@ async function handleLogin(email, password) {
164
  }
165
 
166
  async function handleRegister(email, password) {
167
- setStatus(registerStatus, "Registering...");
168
- try {
169
  const data = await apiRequest('/register', 'POST', { email, password });
170
  setStatus(registerStatus, `Registration successful for ${data.email}! Please log in.`, true);
171
  registerForm.reset(); // Clear form
172
- showSection('login-section'); // Switch to login
173
- } catch (error) {
 
174
  setStatus(registerStatus, `Registration failed: ${error.message}`);
175
- }
176
  }
177
 
178
  async function showWelcomePage() {
179
  if (!authToken) {
180
  showSection('login-section');
 
181
  return;
182
  }
183
  try {
@@ -199,8 +218,14 @@ function handleLogout() {
199
  disconnectWebSocket();
200
  setStatus(loginStatus, ""); // Clear any previous login errors
201
  showSection('login-section');
 
202
  }
203
 
 
 
 
 
 
204
 
205
  // --- Event Listeners ---
206
  registerForm.addEventListener('submit', (e) => {
@@ -208,27 +233,75 @@ registerForm.addEventListener('submit', (e) => {
208
  const email = document.getElementById('reg-email').value;
209
  const password = document.getElementById('reg-password').value;
210
  const confirmPassword = document.getElementById('reg-confirm-password').value;
211
- if (password !== confirmPassword) {
212
- setStatus(registerStatus, "Passwords do not match.");
213
- return;
 
 
 
 
 
 
 
 
 
 
214
  }
 
 
215
  if (password.length < 8) {
216
- setStatus(registerStatus, "Password must be at least 8 characters.");
217
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  }
219
- handleRegister(email, password);
220
  });
221
 
222
  loginForm.addEventListener('submit', (e) => {
223
  e.preventDefault();
224
  const email = document.getElementById('login-email').value;
225
  const password = document.getElementById('login-password').value;
226
- handleLogin(email, password);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  });
228
 
229
  logoutButton.addEventListener('click', handleLogout);
230
 
231
-
232
  // --- Initial Page Load Logic ---
233
  document.addEventListener('DOMContentLoaded', () => {
234
  if (authToken) {
@@ -236,6 +309,6 @@ document.addEventListener('DOMContentLoaded', () => {
236
  showWelcomePage(); // Try to fetch user info and show welcome
237
  } else {
238
  console.log("No token found, showing login page.");
239
- showSection('login-section'); // Show login if no token
240
  }
241
  });
 
1
+ const loginTab = document.getElementById('login-tab');
2
+ const registerTab = document.getElementById('register-tab');
3
  const loginSection = document.getElementById('login-section');
4
+ const registerSection = document.getElementById('register-section');
5
  const welcomeSection = document.getElementById('welcome-section');
6
  const registerForm = document.getElementById('register-form');
7
  const loginForm = document.getElementById('login-form');
 
16
  let webSocket = null;
17
  let authToken = localStorage.getItem('authToken'); // Load token on script start
18
 
19
+ // --- UI Control & Tab Switching ---
20
  function showSection(sectionId) {
 
21
  loginSection.style.display = 'none';
22
+ registerSection.style.display = 'none';
23
  welcomeSection.style.display = 'none';
24
 
25
  const sectionToShow = document.getElementById(sectionId);
 
30
  }
31
  }
32
 
33
+ // Tab switching logic
34
+ loginTab.addEventListener('click', () => {
35
+ loginTab.classList.add('active');
36
+ registerTab.classList.remove('active');
37
+ loginSection.classList.add('active');
38
+ registerSection.classList.remove('active');
39
+ });
40
+
41
+ registerTab.addEventListener('click', () => {
42
+ registerTab.classList.add('active');
43
+ loginTab.classList.remove('active');
44
+ registerSection.classList.add('active');
45
+ loginSection.classList.remove('active');
46
+ });
47
+
48
+ // Initialize first tab as active
49
+ loginTab.classList.add('active');
50
+ loginSection.classList.add('active');
51
+
52
  function setStatus(element, message, isSuccess = false) {
53
  element.textContent = message;
54
  element.className = isSuccess ? 'status-message success' : 'status-message';
 
88
  }
89
  }
90
 
 
91
  // --- WebSocket Handling ---
92
  function connectWebSocket(token) {
93
  if (!token) {
 
104
  const wsUrl = `${wsProtocol}//${window.location.host}${API_URL}/ws/${token}`;
105
  console.log("Attempting to connect WebSocket:", wsUrl);
106
 
 
107
  webSocket = new WebSocket(wsUrl);
108
 
109
  webSocket.onopen = (event) => {
 
123
  p.textContent = messageData.message;
124
  // Add message to the top
125
  notificationsDiv.insertBefore(p, notificationsDiv.firstChild);
126
+ // Limit number of messages shown (optional)
127
  while (notificationsDiv.children.length > 10) {
128
  notificationsDiv.removeChild(notificationsDiv.lastChild);
129
  }
 
130
  }
131
  } catch (error) {
132
  console.error("Error parsing WebSocket message:", error);
 
145
  console.log("WebSocket connection closed:", event);
146
  webSocket = null; // Reset WebSocket variable
147
  // Optionally try to reconnect or inform user
 
148
  if (!event.wasClean) {
149
  const p = document.createElement('p');
150
  p.textContent = `WebSocket disconnected unexpectedly (Code: ${event.code}). Please refresh or log out/in.`;
 
181
  }
182
 
183
  async function handleRegister(email, password) {
184
+ setStatus(registerStatus, "Registering...");
185
+ try {
186
  const data = await apiRequest('/register', 'POST', { email, password });
187
  setStatus(registerStatus, `Registration successful for ${data.email}! Please log in.`, true);
188
  registerForm.reset(); // Clear form
189
+ // Switch to login tab
190
+ loginTab.click();
191
+ } catch (error) {
192
  setStatus(registerStatus, `Registration failed: ${error.message}`);
193
+ }
194
  }
195
 
196
  async function showWelcomePage() {
197
  if (!authToken) {
198
  showSection('login-section');
199
+ loginTab.click();
200
  return;
201
  }
202
  try {
 
218
  disconnectWebSocket();
219
  setStatus(loginStatus, ""); // Clear any previous login errors
220
  showSection('login-section');
221
+ loginTab.click();
222
  }
223
 
224
+ // --- Form Validation ---
225
+ function validateEmail(email) {
226
+ const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
227
+ return re.test(String(email).toLowerCase());
228
+ }
229
 
230
  // --- Event Listeners ---
231
  registerForm.addEventListener('submit', (e) => {
 
233
  const email = document.getElementById('reg-email').value;
234
  const password = document.getElementById('reg-password').value;
235
  const confirmPassword = document.getElementById('reg-confirm-password').value;
236
+
237
+ const emailError = document.getElementById('register-email-error');
238
+ const passwordError = document.getElementById('register-password-error');
239
+ const confirmError = document.getElementById('register-confirm-error');
240
+
241
+ let isValid = true;
242
+
243
+ // Email validation
244
+ if (!validateEmail(email)) {
245
+ emailError.style.display = 'block';
246
+ isValid = false;
247
+ } else {
248
+ emailError.style.display = 'none';
249
  }
250
+
251
+ // Password validation
252
  if (password.length < 8) {
253
+ passwordError.style.display = 'block';
254
+ isValid = false;
255
+ } else {
256
+ passwordError.style.display = 'none';
257
+ }
258
+
259
+ // Confirm password
260
+ if (password !== confirmPassword) {
261
+ confirmError.style.display = 'block';
262
+ isValid = false;
263
+ } else {
264
+ confirmError.style.display = 'none';
265
+ }
266
+
267
+ if (isValid) {
268
+ handleRegister(email, password);
269
  }
 
270
  });
271
 
272
  loginForm.addEventListener('submit', (e) => {
273
  e.preventDefault();
274
  const email = document.getElementById('login-email').value;
275
  const password = document.getElementById('login-password').value;
276
+
277
+ const emailError = document.getElementById('login-email-error');
278
+ const passwordError = document.getElementById('login-password-error');
279
+
280
+ let isValid = true;
281
+
282
+ // Email validation
283
+ if (!validateEmail(email)) {
284
+ emailError.style.display = 'block';
285
+ isValid = false;
286
+ } else {
287
+ emailError.style.display = 'none';
288
+ }
289
+
290
+ // Simple password validation
291
+ if (password.length < 1) {
292
+ passwordError.style.display = 'block';
293
+ isValid = false;
294
+ } else {
295
+ passwordError.style.display = 'none';
296
+ }
297
+
298
+ if (isValid) {
299
+ handleLogin(email, password);
300
+ }
301
  });
302
 
303
  logoutButton.addEventListener('click', handleLogout);
304
 
 
305
  // --- Initial Page Load Logic ---
306
  document.addEventListener('DOMContentLoaded', () => {
307
  if (authToken) {
 
309
  showWelcomePage(); // Try to fetch user info and show welcome
310
  } else {
311
  console.log("No token found, showing login page.");
312
+ loginTab.click(); // Activate login tab
313
  }
314
  });
templates/index.html CHANGED
@@ -7,47 +7,84 @@
7
  <link rel="stylesheet" href="/static/css/style.css">
8
  </head>
9
  <body>
10
- <h1>Auth & Notification App</h1>
 
 
 
 
11
 
12
- <!-- Registration Section -->
13
- <div id="register-section" class="auth-section">
14
- <h2>Register</h2>
15
- <form id="register-form">
16
- <label for="reg-email">Email:</label>
17
- <input type="email" id="reg-email" name="email" required><br><br>
18
- <label for="reg-password">Password:</label>
19
- <input type="password" id="reg-password" name="password" required minlength="8"><br><br>
20
- <label for="reg-confirm-password">Confirm Password:</label>
21
- <input type="password" id="reg-confirm-password" name="confirm_password" required minlength="8"><br><br>
22
- <button type="submit">Register</button>
23
- </form>
24
- <p id="register-status" class="status-message"></p>
25
- <p>Already have an account? <a href="#" onclick="showSection('login-section')">Login here</a></p>
26
- </div>
27
 
28
- <!-- Login Section -->
29
- <div id="login-section" class="auth-section" style="display: none;">
30
- <h2>Login</h2>
31
- <form id="login-form">
32
- <label for="login-email">Email:</label>
33
- <input type="email" id="login-email" name="email" required><br><br>
34
- <label for="login-password">Password:</label>
35
- <input type="password" id="login-password" name="password" required><br><br>
36
- <button type="submit">Login</button>
37
- </form>
38
- <p id="login-status" class="status-message"></p>
39
- <p>Don't have an account? <a href="#" onclick="showSection('register-section')">Register here</a></p>
40
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- <!-- Welcome Section (shown after login) -->
43
- <div id="welcome-section" style="display: none;">
44
- <h2>Welcome!</h2>
45
- <p id="welcome-message">Welcome, user!</p>
46
- <button id="logout-button">Logout</button>
47
- <hr>
48
- <h2>Real-time Notifications</h2>
49
- <div id="notifications">
50
- <p><em>Notifications will appear here...</em></p>
 
51
  </div>
52
  </div>
53
 
 
7
  <link rel="stylesheet" href="/static/css/style.css">
8
  </head>
9
  <body>
10
+ <div class="container">
11
+ <div class="logo">
12
+ <h1>Auth & Notification App</h1>
13
+ <p>Welcome! Please login to your account or create a new one.</p>
14
+ </div>
15
 
16
+ <div class="auth-container">
17
+ <div class="hero">
18
+ <h2>Welcome</h2>
19
+ <p>Please sign in or create a new account to continue.</p>
20
+ </div>
 
 
 
 
 
 
 
 
 
 
21
 
22
+ <div class="auth-forms">
23
+ <div class="tabs">
24
+ <div class="tab" id="login-tab">Login</div>
25
+ <div class="tab" id="register-tab">Register</div>
26
+ </div>
27
+
28
+ <!-- Login Form -->
29
+ <div class="auth-form" id="login-section">
30
+ <h2>Login to your account</h2>
31
+ <form id="login-form">
32
+ <div class="form-group">
33
+ <label for="login-email">Email Address</label>
34
+ <input type="email" id="login-email" name="email" placeholder="[email protected]" required>
35
+ <div class="error-message" id="login-email-error">Please enter a valid email address</div>
36
+ </div>
37
+
38
+ <div class="form-group">
39
+ <label for="login-password">Password</label>
40
+ <input type="password" id="login-password" name="password" placeholder="Enter your password" required>
41
+ <div class="error-message" id="login-password-error">Password must be at least 8 characters</div>
42
+ </div>
43
+
44
+ <button type="submit" class="button">Login Now</button>
45
+ <p id="login-status" class="status-message"></p>
46
+ </form>
47
+ </div>
48
+
49
+ <!-- Registration Form -->
50
+ <div class="auth-form" id="register-section">
51
+ <h2>Create your account</h2>
52
+ <form id="register-form">
53
+ <div class="form-group">
54
+ <label for="reg-email">Email Address</label>
55
+ <input type="email" id="reg-email" name="email" placeholder="[email protected]" required>
56
+ <div class="error-message" id="register-email-error">Please enter a valid email address</div>
57
+ </div>
58
+
59
+ <div class="form-group">
60
+ <label for="reg-password">Password</label>
61
+ <input type="password" id="reg-password" name="password" placeholder="Create a password" required minlength="8">
62
+ <div class="error-message" id="register-password-error">Password must be at least 8 characters</div>
63
+ </div>
64
+
65
+ <div class="form-group">
66
+ <label for="reg-confirm-password">Confirm Password</label>
67
+ <input type="password" id="reg-confirm-password" name="confirm_password" placeholder="Confirm your password" required minlength="8">
68
+ <div class="error-message" id="register-confirm-error">Passwords do not match</div>
69
+ </div>
70
+
71
+ <button type="submit" class="button">Create Account</button>
72
+ <p id="register-status" class="status-message"></p>
73
+ </form>
74
+ </div>
75
+ </div>
76
+ </div>
77
 
78
+ <!-- Welcome Section (shown after login) -->
79
+ <div id="welcome-section" style="display: none;">
80
+ <h2>Welcome!</h2>
81
+ <p id="welcome-message">Welcome, user!</p>
82
+ <button id="logout-button" class="button">Logout</button>
83
+ <hr>
84
+ <h2>Real-time Notifications</h2>
85
+ <div id="notifications">
86
+ <p><em>Notifications will appear here...</em></p>
87
+ </div>
88
  </div>
89
  </div>
90