2026-03-27 21:20:07 +01:00

240 lines
8.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Journey Mapper</title>
<!-- Open Props CSS -->
<link rel="stylesheet" href="https://unpkg.com/open-props"/>
<link rel="stylesheet" href="https://unpkg.com/open-props/normalize.min.css"/>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; }
body {
font-family: var(--font-sans);
background: var(--gray-0);
color: var(--gray-9);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
padding: var(--size-4);
}
.login-container {
max-width: 400px;
width: 100%;
background: var(--surface-1);
border-radius: var(--radius-3);
padding: var(--size-6);
box-shadow: var(--shadow-4);
}
.login-header {
text-align: center;
margin-bottom: var(--size-6);
}
.login-header h1 {
color: var(--indigo-8);
margin: 0;
font-size: var(--font-size-5);
}
.auth-tabs {
display: flex;
gap: var(--size-2);
border-bottom: 1px solid var(--surface-4);
margin-bottom: var(--size-4);
}
.auth-tab {
padding: var(--size-2) var(--size-4);
cursor: pointer;
background: none;
border: none;
font-size: var(--font-size-2);
font-weight: var(--font-weight-5);
color: var(--gray-6);
transition: all 0.2s;
}
.auth-tab.active {
color: var(--indigo-7);
border-bottom: 2px solid var(--indigo-7);
}
.auth-form {
display: none;
}
.auth-form.active {
display: block;
}
.form-group {
margin-bottom: var(--size-4);
}
label {
display: block;
margin-bottom: var(--size-1);
font-weight: var(--font-weight-5);
}
input {
width: 100%;
padding: var(--size-2) var(--size-3);
border: 1px solid var(--surface-4);
border-radius: var(--radius-2);
background: var(--surface-2);
font-size: var(--font-size-2);
}
.btn {
width: 100%;
padding: var(--size-2);
border: none;
border-radius: var(--radius-2);
background: var(--indigo-7);
color: white;
font-size: var(--font-size-2);
font-weight: var(--font-weight-5);
cursor: pointer;
transition: background 0.2s;
}
.btn:hover {
background: var(--indigo-8);
}
.toast {
position: fixed;
bottom: var(--size-4);
right: var(--size-4);
background: var(--green-7);
color: white;
padding: var(--size-2) var(--size-4);
border-radius: var(--radius-2);
display: none;
z-index: 1100;
}
</style>
</head>
<body>
<div class="login-container">
<div class="login-header">
<h1><i class="fas fa-map-marked-alt"></i> Journey Mapper</h1>
<p>Sign in to continue</p>
</div>
<div class="auth-tabs">
<button class="auth-tab active" data-tab="login">Login</button>
<button class="auth-tab" data-tab="register">Register</button>
</div>
<div id="login-form" class="auth-form active">
<div class="form-group">
<label>Username</label>
<input type="text" id="login-username" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" id="login-password" required>
</div>
<button id="login-submit" class="btn">Login</button>
</div>
<div id="register-form" class="auth-form">
<div class="form-group">
<label>Username</label>
<input type="text" id="register-username" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" id="register-password" required>
</div>
<button id="register-submit" class="btn">Register</button>
</div>
</div>
<div id="toast" class="toast"></div>
<script>
const API_BASE = 'http://127.0.0.1:5000/api';
function showToast(msg, isError = false) {
const toast = document.getElementById('toast');
toast.textContent = msg;
toast.style.backgroundColor = isError ? 'var(--red-7)' : 'var(--green-7)';
toast.style.display = 'block';
setTimeout(() => { toast.style.display = 'none'; }, 3000);
}
async function login(username, password) {
try {
const res = await fetch(`${API_BASE}/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
credentials: 'include'
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || 'Login failed');
showToast(`Welcome, ${data.username}!`);
window.location.href = 'map-page.html';
} catch (err) {
showToast(err.message, true);
}
}
async function register(username, password) {
try {
const res = await fetch(`${API_BASE}/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
credentials: 'include'
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || 'Registration failed');
showToast(`Registered as ${data.username}. Logging in...`);
window.location.href = 'map-page.html';
} catch (err) {
showToast(err.message, true);
}
}
document.addEventListener('DOMContentLoaded', () => {
// Tab switching
document.querySelectorAll('.auth-tab').forEach(tab => {
tab.addEventListener('click', () => {
const target = tab.dataset.tab;
document.querySelectorAll('.auth-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
document.querySelectorAll('.auth-form').forEach(f => f.classList.remove('active'));
document.getElementById(`${target}-form`).classList.add('active');
});
});
// Login button
document.getElementById('login-submit').addEventListener('click', () => {
const username = document.getElementById('login-username').value.trim();
const password = document.getElementById('login-password').value;
if (!username || !password) {
showToast('Please enter username and password', true);
return;
}
login(username, password);
});
// Register button
document.getElementById('register-submit').addEventListener('click', () => {
const username = document.getElementById('register-username').value.trim();
const password = document.getElementById('register-password').value;
if (!username || !password) {
showToast('Please enter username and password', true);
return;
}
if (password.length < 4) {
showToast('Password must be at least 4 characters', true);
return;
}
register(username, password);
});
});
</script>
</body>
</html>