Spaces:
Sleeping
Sleeping
| {% extends "base.html" %} | |
| {% block title %}Register - Chatty{% endblock %} | |
| {% block content %} | |
| <div class="auth-container"> | |
| <div class="auth-form-wrapper"> | |
| <form method="POST" class="auth-form" id="registerForm" novalidate> | |
| {% if config.WTF_CSRF_ENABLED %} | |
| <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> | |
| {% endif %} | |
| <h2>Create Account</h2> | |
| <div class="form-group"> | |
| <label for="email">Email Address</label> | |
| <input | |
| type="email" | |
| id="email" | |
| name="email" | |
| required | |
| autocomplete="email" | |
| value="{{ request.form.email or '' }}" | |
| placeholder="Enter your email" | |
| > | |
| <div class="form-error" id="emailError"></div> | |
| </div> | |
| <div class="form-group"> | |
| <label for="password">Password</label> | |
| <input | |
| type="password" | |
| id="password" | |
| name="password" | |
| required | |
| autocomplete="new-password" | |
| placeholder="Enter your password (min 8 characters)" | |
| > | |
| <div class="form-error" id="passwordError"></div> | |
| </div> | |
| <div class="form-group"> | |
| <label for="confirmPassword">Confirm Password</label> | |
| <input | |
| type="password" | |
| id="confirmPassword" | |
| name="confirm_password" | |
| required | |
| autocomplete="new-password" | |
| placeholder="Confirm your password" | |
| > | |
| <div class="form-error" id="confirmPasswordError"></div> | |
| </div> | |
| <button type="submit" class="auth-button" id="registerButton"> | |
| <span id="registerButtonText">Create Account</span> | |
| <div class="spinner" id="registerSpinner" style="display: none;"></div> | |
| </button> | |
| <div class="auth-links"> | |
| <p>Already have an account? <a href="{{ url_for('login') }}">Login here</a></p> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| {% endblock %} | |
| {% block scripts %} | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const form = document.getElementById('registerForm'); | |
| const emailInput = document.getElementById('email'); | |
| const passwordInput = document.getElementById('password'); | |
| const confirmPasswordInput = document.getElementById('confirmPassword'); | |
| const registerButton = document.getElementById('registerButton'); | |
| const registerButtonText = document.getElementById('registerButtonText'); | |
| const registerSpinner = document.getElementById('registerSpinner'); | |
| // Email validation | |
| function validateEmail(email) { | |
| const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | |
| return emailRegex.test(email); | |
| } | |
| // Password validation | |
| function validatePassword(password) { | |
| return password.length >= 8; | |
| } | |
| // Show error message | |
| function showError(inputId, message) { | |
| const errorElement = document.getElementById(inputId + 'Error'); | |
| errorElement.textContent = message; | |
| errorElement.classList.add('show'); | |
| document.getElementById(inputId).style.borderColor = '#ef4444'; | |
| } | |
| // Clear error message | |
| function clearError(inputId) { | |
| const errorElement = document.getElementById(inputId + 'Error'); | |
| errorElement.textContent = ''; | |
| errorElement.classList.remove('show'); | |
| document.getElementById(inputId).style.borderColor = 'black'; | |
| } | |
| // Real-time email validation | |
| emailInput.addEventListener('blur', function() { | |
| const email = this.value.trim(); | |
| if (email && !validateEmail(email)) { | |
| showError('email', 'Please enter a valid email address'); | |
| } else { | |
| clearError('email'); | |
| } | |
| }); | |
| emailInput.addEventListener('input', function() { | |
| if (this.style.borderColor === 'rgb(239, 68, 68)') { | |
| clearError('email'); | |
| } | |
| }); | |
| // Real-time password validation | |
| passwordInput.addEventListener('blur', function() { | |
| const password = this.value; | |
| if (password && !validatePassword(password)) { | |
| showError('password', 'Password must be at least 8 characters long'); | |
| } else { | |
| clearError('password'); | |
| // Re-validate confirm password if it has a value | |
| if (confirmPasswordInput.value) { | |
| validatePasswordMatch(); | |
| } | |
| } | |
| }); | |
| passwordInput.addEventListener('input', function() { | |
| if (this.style.borderColor === 'rgb(239, 68, 68)') { | |
| clearError('password'); | |
| } | |
| // Re-validate confirm password if it has a value | |
| if (confirmPasswordInput.value) { | |
| validatePasswordMatch(); | |
| } | |
| }); | |
| // Password matching validation | |
| function validatePasswordMatch() { | |
| const password = passwordInput.value; | |
| const confirmPassword = confirmPasswordInput.value; | |
| if (confirmPassword && password !== confirmPassword) { | |
| showError('confirmPassword', 'Passwords do not match'); | |
| return false; | |
| } else { | |
| clearError('confirmPassword'); | |
| return true; | |
| } | |
| } | |
| confirmPasswordInput.addEventListener('blur', validatePasswordMatch); | |
| confirmPasswordInput.addEventListener('input', function() { | |
| if (this.style.borderColor === 'rgb(239, 68, 68)') { | |
| validatePasswordMatch(); | |
| } | |
| }); | |
| // Form submission | |
| form.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| // Clear previous errors | |
| clearError('email'); | |
| clearError('password'); | |
| clearError('confirmPassword'); | |
| const email = emailInput.value.trim(); | |
| const password = passwordInput.value; | |
| const confirmPassword = confirmPasswordInput.value; | |
| let hasErrors = false; | |
| // Validate email | |
| if (!email) { | |
| showError('email', 'Email is required'); | |
| hasErrors = true; | |
| } else if (!validateEmail(email)) { | |
| showError('email', 'Please enter a valid email address'); | |
| hasErrors = true; | |
| } | |
| // Validate password | |
| if (!password) { | |
| showError('password', 'Password is required'); | |
| hasErrors = true; | |
| } else if (!validatePassword(password)) { | |
| showError('password', 'Password must be at least 8 characters long'); | |
| hasErrors = true; | |
| } | |
| // Validate confirm password | |
| if (!confirmPassword) { | |
| showError('confirmPassword', 'Please confirm your password'); | |
| hasErrors = true; | |
| } else if (password !== confirmPassword) { | |
| showError('confirmPassword', 'Passwords do not match'); | |
| hasErrors = true; | |
| } | |
| if (hasErrors) { | |
| return; | |
| } | |
| // Show loading state | |
| registerButton.disabled = true; | |
| registerButtonText.style.display = 'none'; | |
| registerSpinner.style.display = 'inline-block'; | |
| // Submit form | |
| this.submit(); | |
| }); | |
| // Focus first input | |
| emailInput.focus(); | |
| // Handle browser back button to reset form state | |
| window.addEventListener('pageshow', function(event) { | |
| if (event.persisted) { | |
| registerButton.disabled = false; | |
| registerButtonText.style.display = 'inline'; | |
| registerSpinner.style.display = 'none'; | |
| } | |
| }); | |
| }); | |
| </script> | |
| {% endblock %} |