test/moxie/web/templates/login.html
Z User 1f9535d683 Add complete MOXIE web UI with authentication and user management
- New web UI with OpenWebUI-like interface using Tailwind CSS
- SQLite-based authentication with session management
- User registration, login, and profile pages
- Chat interface with conversation history
- Streaming responses with visible thinking phase
- File attachments support
- User document uploads in profile
- Rate limiting (5 requests/day for free users)
- Admin panel user management with promote/demote/delete
- Custom color theme matching balloon logo design
- Compatible with Nuitka build system
2026-03-24 05:15:50 +00:00

138 lines
5.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sign In - MOXIE</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
background: '#0B0C1C',
surface: '#1A1A1A',
'balloon-red': '#EA744C',
'balloon-yellow': '#ECDC67',
'balloon-blue': '#4F9AC3',
'balloon-purple': '#6A4477',
'text-main': '#F0F0F0',
}
}
}
}
</script>
</head>
<body class="bg-background min-h-screen flex items-center justify-center text-text-main">
<!-- Background effects -->
<div class="fixed inset-0 overflow-hidden pointer-events-none">
<div class="absolute top-1/3 left-1/4 w-96 h-96 bg-balloon-red/10 rounded-full blur-3xl"></div>
<div class="absolute bottom-1/3 right-1/4 w-96 h-96 bg-balloon-purple/10 rounded-full blur-3xl"></div>
</div>
<div class="relative z-10 w-full max-w-md px-4">
<!-- Logo -->
<div class="text-center mb-8">
<a href="/">
<img src="/static/moxie_logo.jpg" alt="MOXIE" class="w-20 h-20 mx-auto rounded-full shadow-lg shadow-balloon-purple/30 mb-4">
</a>
<h1 class="text-2xl font-bold">Welcome Back</h1>
<p class="text-text-main/50 text-sm mt-1">Sign in to continue to MOXIE</p>
</div>
<!-- Login form -->
<div class="bg-surface/80 backdrop-blur-sm rounded-2xl p-8 border border-balloon-purple/20">
<form id="loginForm" class="space-y-6">
{% if error %}
<div class="p-3 bg-balloon-red/20 border border-balloon-red/50 rounded-lg text-balloon-red text-sm">
{{ error }}
</div>
{% endif %}
<div>
<label for="username" class="block text-sm font-medium text-text-main/70 mb-2">Username</label>
<input
type="text"
id="username"
name="username"
required
class="w-full px-4 py-3 bg-background/50 border border-balloon-purple/30 rounded-lg focus:outline-none focus:border-balloon-blue focus:ring-1 focus:ring-balloon-blue transition-colors"
placeholder="Enter your username"
>
</div>
<div>
<label for="password" class="block text-sm font-medium text-text-main/70 mb-2">Password</label>
<input
type="password"
id="password"
name="password"
required
class="w-full px-4 py-3 bg-background/50 border border-balloon-purple/30 rounded-lg focus:outline-none focus:border-balloon-blue focus:ring-1 focus:ring-balloon-blue transition-colors"
placeholder="Enter your password"
>
</div>
<button
type="submit"
class="w-full py-3 bg-gradient-to-r from-balloon-red to-balloon-purple hover:from-balloon-red/80 hover:to-balloon-purple/80 text-white font-semibold rounded-lg transition-all duration-300 transform hover:scale-[1.02] shadow-lg shadow-balloon-purple/20"
>
Sign In
</button>
</form>
<div class="mt-6 text-center text-sm text-text-main/50">
Don't have an account?
<a href="/signup" class="text-balloon-blue hover:text-balloon-yellow transition-colors">Create one</a>
</div>
</div>
<!-- Back to home -->
<div class="mt-4 text-center">
<a href="/" class="text-text-main/40 hover:text-text-main/60 text-sm transition-colors">
← Back to Home
</a>
</div>
</div>
<script>
document.getElementById('loginForm').addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
const username = form.username.value;
const password = form.password.value;
const submitBtn = form.querySelector('button[type="submit"]');
submitBtn.disabled = true;
submitBtn.textContent = 'Signing in...';
try {
const formData = new FormData();
formData.append('username', username);
formData.append('password', password);
const response = await fetch('/login', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success && data.redirect) {
window.location.href = data.redirect;
} else {
// Reload to show error
window.location.reload();
}
} catch (error) {
console.error('Login error:', error);
alert('An error occurred. Please try again.');
submitBtn.disabled = false;
submitBtn.textContent = 'Sign In';
}
});
</script>
</body>
</html>