53 lines
2.4 KiB
HTML
53 lines
2.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Vela Platform — Login</title>
|
|
<style>
|
|
* { margin:0; padding:0; box-sizing:border-box; }
|
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background:#0f0f0f; color:#e0e0e0; display:flex; align-items:center; justify-content:center; min-height:100vh; }
|
|
.login-box { background:#1a1a1a; border:1px solid #2a2a2a; border-radius:12px; padding:40px; width:360px; }
|
|
h1 { font-size:24px; margin-bottom:8px; color:#fff; }
|
|
p.sub { color:#888; font-size:14px; margin-bottom:24px; }
|
|
label { display:block; font-size:13px; color:#aaa; margin-bottom:4px; }
|
|
input { width:100%; padding:10px 12px; background:#0f0f0f; border:1px solid #2a2a2a; border-radius:6px; color:#fff; font-size:15px; margin-bottom:16px; }
|
|
input:focus { outline:none; border-color:#3b82f6; }
|
|
button { width:100%; padding:12px; background:#3b82f6; color:#fff; border:none; border-radius:6px; font-size:15px; font-weight:600; cursor:pointer; }
|
|
button:hover { background:#2563eb; }
|
|
.error { color:#ef4444; font-size:13px; margin-top:8px; display:none; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="login-box">
|
|
<h1>Vela Platform</h1>
|
|
<p class="sub">P&L Manager</p>
|
|
<form id="loginForm">
|
|
<label>Username</label>
|
|
<input type="text" id="username" autocomplete="username" required>
|
|
<label>Password</label>
|
|
<input type="password" id="password" autocomplete="current-password" required>
|
|
<button type="submit">Sign in</button>
|
|
<div class="error" id="error"></div>
|
|
</form>
|
|
</div>
|
|
<script>
|
|
document.getElementById('loginForm').addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
const err = document.getElementById('error');
|
|
err.style.display = 'none';
|
|
const form = new FormData();
|
|
form.append('username', document.getElementById('username').value);
|
|
form.append('password', document.getElementById('password').value);
|
|
try {
|
|
const r = await fetch('/api/auth/login', { method:'POST', body:form });
|
|
if (!r.ok) { const d = await r.json(); err.textContent = d.detail || 'Login failed'; err.style.display = 'block'; return; }
|
|
const d = await r.json();
|
|
localStorage.setItem('vela_token', d.token);
|
|
window.location = d.redirect;
|
|
} catch(ex) { err.textContent = 'Network error'; err.style.display = 'block'; }
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|