| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Login - Ollama Manager</title> |
| <link rel="stylesheet" href="/static/style.css"> |
| </head> |
| <body> |
| <div class="container"> |
| <header> |
| <h1>Ollama Model Manager</h1> |
| </header> |
| <div class="auth-box"> |
| <div class="tabs"> |
| <button class="tab active" onclick="showTab('login')">Login</button> |
| <button class="tab" onclick="showTab('register')">Register</button> |
| </div> |
| <form id="login-form" class="auth-form" onsubmit="handleLogin(event)"> |
| <h2>Login</h2> |
| <input type="text" name="username" placeholder="Username" required> |
| <input type="password" name="password" placeholder="Password" required> |
| <button type="submit" class="btn btn-primary">Login</button> |
| <p id="login-error" class="error"></p> |
| </form> |
| <form id="register-form" class="auth-form hidden" onsubmit="handleRegister(event)"> |
| <h2>Register</h2> |
| <input type="text" name="username" placeholder="Username" required> |
| <input type="email" name="email" placeholder="Email" required> |
| <input type="password" name="password" placeholder="Password" required> |
| <button type="submit" class="btn btn-primary">Register</button> |
| <p id="register-error" class="error"></p> |
| </form> |
| </div> |
| </div> |
| <script> |
| function showTab(name) { |
| document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); |
| document.querySelectorAll('.auth-form').forEach(f => f.classList.add('hidden')); |
| document.querySelector(`.tab[onclick*="${name}"]`).classList.add('active'); |
| document.getElementById(`${name}-form`).classList.remove('hidden'); |
| } |
| |
| async function handleLogin(e) { |
| e.preventDefault(); |
| const fd = new FormData(e.target); |
| const res = await fetch('/api/login', { |
| method: 'POST', |
| headers: {'Content-Type': 'application/json'}, |
| body: JSON.stringify({username: fd.get('username'), password: fd.get('password')}) |
| }); |
| if (res.ok) { |
| const data = await res.json(); |
| localStorage.setItem('token', data.access_token); |
| window.location.href = '/dashboard'; |
| } else { |
| const err = await res.json(); |
| document.getElementById('login-error').textContent = err.detail || 'Login failed'; |
| } |
| } |
| |
| async function handleRegister(e) { |
| e.preventDefault(); |
| const fd = new FormData(e.target); |
| const res = await fetch('/api/register', { |
| method: 'POST', |
| headers: {'Content-Type': 'application/json'}, |
| body: JSON.stringify({username: fd.get('username'), email: fd.get('email'), password: fd.get('password')}) |
| }); |
| if (res.ok) { |
| document.getElementById('register-error').textContent = 'Registered! You can now login.'; |
| document.getElementById('register-error').style.color = 'green'; |
| } else { |
| const err = await res.json(); |
| document.getElementById('register-error').textContent = err.detail || 'Registration failed'; |
| } |
| } |
| </script> |
| </body> |
| </html> |
|
|