| <!DOCTYPE html> |
| <html lang="de"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>NoahsKI - Register</title> |
| |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap'); |
| |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| } |
| |
| body { |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); |
| min-height: 100vh; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| position: relative; |
| overflow: hidden; |
| } |
| |
| |
| body::before { |
| content: ''; |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| background: |
| radial-gradient(circle at 20% 50%, rgba(139, 92, 246, 0.3) 0%, transparent 50%), |
| radial-gradient(circle at 80% 80%, rgba(236, 72, 153, 0.3) 0%, transparent 50%), |
| radial-gradient(circle at 40% 20%, rgba(59, 130, 246, 0.2) 0%, transparent 50%); |
| animation: gradientShift 15s ease infinite; |
| pointer-events: none; |
| } |
| |
| @keyframes gradientShift { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: 0.8; } |
| } |
| |
| .register-container { |
| background: rgba(255, 255, 255, 0.1); |
| backdrop-filter: blur(20px); |
| -webkit-backdrop-filter: blur(20px); |
| border-radius: 20px; |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15); |
| padding: 50px 40px; |
| width: 100%; |
| max-width: 450px; |
| position: relative; |
| z-index: 1; |
| animation: slideUp 0.6s ease; |
| } |
| |
| @keyframes slideUp { |
| from { transform: translateY(50px); opacity: 0; } |
| to { transform: translateY(0); opacity: 1; } |
| } |
| |
| .logo { |
| text-align: center; |
| margin-bottom: 40px; |
| } |
| |
| .logo-icon { |
| width: 80px; |
| height: 80px; |
| background: linear-gradient(135deg, #8b5cf6, #ec4899); |
| border-radius: 20px; |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| font-size: 40px; |
| margin-bottom: 20px; |
| animation: float 3s ease-in-out infinite; |
| } |
| |
| @keyframes float { |
| 0%, 100% { transform: translateY(0px); } |
| 50% { transform: translateY(-10px); } |
| } |
| |
| .logo h1 { |
| font-size: 32px; |
| font-weight: 800; |
| background: linear-gradient(135deg, #fff, #e0e7ff); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| background-clip: text; |
| margin-bottom: 10px; |
| } |
| |
| .logo p { |
| font-size: 14px; |
| color: rgba(255, 255, 255, 0.8); |
| font-weight: 500; |
| } |
| |
| .form-group { |
| margin-bottom: 25px; |
| } |
| |
| .form-group label { |
| display: block; |
| color: white; |
| font-weight: 600; |
| margin-bottom: 10px; |
| font-size: 14px; |
| } |
| |
| .form-group input { |
| width: 100%; |
| padding: 15px 20px; |
| border: 2px solid rgba(255, 255, 255, 0.2); |
| border-radius: 12px; |
| font-size: 15px; |
| font-family: 'Inter', sans-serif; |
| background: rgba(255, 255, 255, 0.9); |
| color: #1f2937; |
| outline: none; |
| transition: all 0.3s ease; |
| } |
| |
| .form-group input:focus { |
| border-color: #8b5cf6; |
| background: white; |
| box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.1); |
| } |
| |
| .password-requirements { |
| background: rgba(255, 255, 255, 0.15); |
| border: 1px solid rgba(255, 255, 255, 0.3); |
| border-radius: 10px; |
| padding: 12px 16px; |
| margin-top: 10px; |
| font-size: 12px; |
| color: rgba(255, 255, 255, 0.9); |
| } |
| |
| .password-requirements ul { |
| margin: 8px 0 0 20px; |
| } |
| |
| .password-requirements li { |
| margin: 4px 0; |
| } |
| |
| .requirement-met { |
| color: #10b981; |
| } |
| |
| .requirement-unmet { |
| color: rgba(255, 255, 255, 0.6); |
| } |
| |
| .register-btn { |
| width: 100%; |
| padding: 16px; |
| background: linear-gradient(135deg, #8b5cf6, #ec4899); |
| color: white; |
| border: none; |
| border-radius: 12px; |
| font-size: 16px; |
| font-weight: 700; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| box-shadow: 0 4px 15px rgba(139, 92, 246, 0.4); |
| } |
| |
| .register-btn:hover:not(:disabled) { |
| transform: translateY(-2px); |
| box-shadow: 0 6px 20px rgba(139, 92, 246, 0.5); |
| } |
| |
| .register-btn:disabled { |
| opacity: 0.6; |
| cursor: not-allowed; |
| } |
| |
| .error-message { |
| background: rgba(239, 68, 68, 0.2); |
| border: 1px solid rgba(239, 68, 68, 0.5); |
| color: white; |
| padding: 12px 16px; |
| border-radius: 10px; |
| margin-bottom: 20px; |
| font-size: 14px; |
| text-align: center; |
| display: none; |
| } |
| |
| .error-message.show { |
| display: block; |
| animation: shake 0.5s ease; |
| } |
| |
| @keyframes shake { |
| 0%, 100% { transform: translateX(0); } |
| 25% { transform: translateX(-10px); } |
| 75% { transform: translateX(10px); } |
| } |
| |
| .success-message { |
| background: rgba(16, 185, 129, 0.2); |
| border: 1px solid rgba(16, 185, 129, 0.5); |
| color: white; |
| padding: 12px 16px; |
| border-radius: 10px; |
| margin-bottom: 20px; |
| font-size: 14px; |
| text-align: center; |
| display: none; |
| } |
| |
| .success-message.show { |
| display: block; |
| } |
| |
| .login-link { |
| text-align: center; |
| margin-top: 25px; |
| color: rgba(255, 255, 255, 0.8); |
| font-size: 14px; |
| } |
| |
| .login-link a { |
| color: white; |
| font-weight: 600; |
| text-decoration: none; |
| border-bottom: 2px solid rgba(255, 255, 255, 0.5); |
| transition: all 0.3s ease; |
| } |
| |
| .login-link a:hover { |
| border-bottom-color: white; |
| } |
| |
| .loading { |
| display: inline-block; |
| width: 16px; |
| height: 16px; |
| border: 2px solid rgba(255, 255, 255, 0.3); |
| border-radius: 50%; |
| border-top-color: white; |
| animation: spin 0.6s linear infinite; |
| } |
| |
| @keyframes spin { |
| to { transform: rotate(360deg); } |
| } |
| |
| .info-box { |
| background: rgba(59, 130, 246, 0.2); |
| border: 1px solid rgba(59, 130, 246, 0.5); |
| color: white; |
| padding: 12px 16px; |
| border-radius: 10px; |
| margin-bottom: 20px; |
| font-size: 13px; |
| text-align: center; |
| } |
| </style> |
| </head> |
| <body> |
| <div class="register-container"> |
| <div class="logo"> |
| <div class="logo-icon">🧠</div> |
| <h1>NoahsKI Ultimate</h1> |
| <p>✨ Create Your Account</p> |
| </div> |
| |
| <div class="info-box"> |
| 🎉 Join NoahsKI and get access to AI-powered features! |
| </div> |
| |
| <div id="error-message" class="error-message"></div> |
| <div id="success-message" class="success-message"></div> |
| |
| <form id="register-form"> |
| <div class="form-group"> |
| <label for="name">👤 Full Name</label> |
| <input |
| type="text" |
| id="name" |
| name="name" |
| placeholder="John Doe" |
| required |
| autocomplete="name" |
| minlength="2" |
| > |
| </div> |
| |
| <div class="form-group"> |
| <label for="email">📧 Email</label> |
| <input |
| type="email" |
| id="email" |
| name="email" |
| placeholder="your@email.com" |
| required |
| autocomplete="email" |
| > |
| </div> |
| |
| <div class="form-group"> |
| <label for="password">🔒 Password</label> |
| <input |
| type="password" |
| id="password" |
| name="password" |
| placeholder="Create a strong password" |
| required |
| autocomplete="new-password" |
| minlength="6" |
| > |
| <div class="password-requirements"> |
| <strong>Password must contain:</strong> |
| <ul> |
| <li id="req-length" class="requirement-unmet">✗ At least 6 characters</li> |
| <li id="req-letter" class="requirement-unmet">✗ At least one letter</li> |
| <li id="req-number" class="requirement-unmet">✗ At least one number</li> |
| </ul> |
| </div> |
| </div> |
| |
| <div class="form-group"> |
| <label for="confirm-password">🔒 Confirm Password</label> |
| <input |
| type="password" |
| id="confirm-password" |
| name="confirm-password" |
| placeholder="Re-enter your password" |
| required |
| autocomplete="new-password" |
| > |
| </div> |
| |
| <button type="submit" class="register-btn" id="register-btn"> |
| ✨ Create Account |
| </button> |
| </form> |
| |
| <div class="login-link"> |
| Already have an account? <a href="/login">Login here</a> |
| </div> |
| </div> |
|
|
| <script> |
| const registerForm = document.getElementById('register-form'); |
| const registerBtn = document.getElementById('register-btn'); |
| const errorMessage = document.getElementById('error-message'); |
| const successMessage = document.getElementById('success-message'); |
| const passwordInput = document.getElementById('password'); |
| const confirmPasswordInput = document.getElementById('confirm-password'); |
| |
| |
| passwordInput.addEventListener('input', function() { |
| const password = this.value; |
| |
| |
| const lengthReq = document.getElementById('req-length'); |
| if (password.length >= 6) { |
| lengthReq.classList.remove('requirement-unmet'); |
| lengthReq.classList.add('requirement-met'); |
| lengthReq.innerHTML = '✓ At least 6 characters'; |
| } else { |
| lengthReq.classList.remove('requirement-met'); |
| lengthReq.classList.add('requirement-unmet'); |
| lengthReq.innerHTML = '✗ At least 6 characters'; |
| } |
| |
| |
| const letterReq = document.getElementById('req-letter'); |
| if (/[a-zA-Z]/.test(password)) { |
| letterReq.classList.remove('requirement-unmet'); |
| letterReq.classList.add('requirement-met'); |
| letterReq.innerHTML = '✓ At least one letter'; |
| } else { |
| letterReq.classList.remove('requirement-met'); |
| letterReq.classList.add('requirement-unmet'); |
| letterReq.innerHTML = '✗ At least one letter'; |
| } |
| |
| |
| const numberReq = document.getElementById('req-number'); |
| if (/[0-9]/.test(password)) { |
| numberReq.classList.remove('requirement-unmet'); |
| numberReq.classList.add('requirement-met'); |
| numberReq.innerHTML = '✓ At least one number'; |
| } else { |
| numberReq.classList.remove('requirement-met'); |
| numberReq.classList.add('requirement-unmet'); |
| numberReq.innerHTML = '✗ At least one number'; |
| } |
| }); |
| |
| function showError(message) { |
| errorMessage.textContent = '❌ ' + message; |
| errorMessage.classList.add('show'); |
| successMessage.classList.remove('show'); |
| setTimeout(() => { |
| errorMessage.classList.remove('show'); |
| }, 5000); |
| } |
| |
| function showSuccess(message) { |
| successMessage.textContent = '✅ ' + message; |
| successMessage.classList.add('show'); |
| errorMessage.classList.remove('show'); |
| } |
| |
| function validatePassword(password) { |
| if (password.length < 6) { |
| return 'Password must be at least 6 characters long'; |
| } |
| if (!/[a-zA-Z]/.test(password)) { |
| return 'Password must contain at least one letter'; |
| } |
| if (!/[0-9]/.test(password)) { |
| return 'Password must contain at least one number'; |
| } |
| return null; |
| } |
| |
| registerForm.addEventListener('submit', async function(e) { |
| e.preventDefault(); |
| |
| const name = document.getElementById('name').value.trim(); |
| const email = document.getElementById('email').value.trim(); |
| const password = document.getElementById('password').value; |
| const confirmPassword = document.getElementById('confirm-password').value; |
| |
| |
| if (!name || !email || !password || !confirmPassword) { |
| showError('Please fill in all fields'); |
| return; |
| } |
| |
| if (name.length < 2) { |
| showError('Name must be at least 2 characters long'); |
| return; |
| } |
| |
| const passwordError = validatePassword(password); |
| if (passwordError) { |
| showError(passwordError); |
| return; |
| } |
| |
| if (password !== confirmPassword) { |
| showError('Passwords do not match'); |
| return; |
| } |
| |
| |
| const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; |
| if (!emailRegex.test(email)) { |
| showError('Please enter a valid email address'); |
| return; |
| } |
| |
| |
| registerBtn.disabled = true; |
| registerBtn.innerHTML = '<span class="loading"></span> Creating account...'; |
| |
| try { |
| const response = await fetch('/api/auth/register', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json' |
| }, |
| body: JSON.stringify({ |
| name: name, |
| email: email, |
| password: password |
| }) |
| }); |
| |
| const data = await response.json(); |
| |
| if (response.ok && data.success) { |
| showSuccess('Account created successfully! Redirecting to login...'); |
| |
| |
| setTimeout(() => { |
| window.location.href = '/login'; |
| }, 2000); |
| } else { |
| showError(data.message || 'Registration failed'); |
| registerBtn.disabled = false; |
| registerBtn.innerHTML = '✨ Create Account'; |
| } |
| } catch (error) { |
| console.error('Registration error:', error); |
| showError('Connection error. Please try again.'); |
| registerBtn.disabled = false; |
| registerBtn.innerHTML = '✨ Create Account'; |
| } |
| }); |
| </script> |
| </body> |
| </html> |
|
|