ai added simple ui for register and login

This commit is contained in:
2026-03-07 21:14:50 +01:00
parent cae24c5c0c
commit 533fcaa498
9 changed files with 248 additions and 2 deletions
+64 -1
View File
@@ -13,10 +13,17 @@ class LoginController implements HttpServerInterface
public function onOpen(ConnectionInterface $conn, RequestInterface $request = null): void
{
$params = [];
parse_str($request->getUri()->getQuery(), $params);
if (empty($params["username"]) && empty($params["password"])) {
Utils::respondHtml($conn, $this->loginPage());
$conn->close();
return;
}
$login = true;
$responseHead = "";
$json = "";
parse_str($request->getUri()->getQuery(), $params);
$username = $params["username"];
$password = $params["password"];
@@ -49,6 +56,62 @@ class LoginController implements HttpServerInterface
$conn->close();
}
private function loginPage(): string
{
return <<<'HTML'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login — ComCen</title>
<style>
body { font-family: monospace; max-width: 360px; margin: 80px auto; padding: 0 16px; }
h2 { margin-bottom: 24px; }
input { width: 100%; box-sizing: border-box; padding: 6px; font-family: monospace; font-size: 14px; margin-bottom: 10px; border: 1px solid #ccc; }
button { padding: 6px 16px; font-family: monospace; font-size: 14px; cursor: pointer; }
#msg { margin-top: 12px; font-size: 13px; }
.error { color: #c00; }
#token-box { margin-top: 16px; display: none; }
#token-box p { margin: 0 0 6px; }
#token-val { width: 100%; box-sizing: border-box; padding: 6px; font-family: monospace; font-size: 12px; background: #f4f4f4; border: 1px solid #ccc; }
a { color: inherit; }
</style>
</head>
<body>
<h2>Login</h2>
<input id="username" type="text" placeholder="Username" />
<input id="password" type="password" placeholder="Password" />
<button onclick="login()">Login</button>
<div id="msg"></div>
<div id="token-box">
<p>Your token (paste into chat):</p>
<input id="token-val" type="text" readonly onclick="this.select()" />
</div>
<p><a href="/register">No account? Register</a></p>
<script>
async function login() {
const u = document.getElementById('username').value.trim();
const p = document.getElementById('password').value.trim();
const msg = document.getElementById('msg');
if (!u || !p) { msg.className = 'error'; msg.textContent = 'Fill in all fields.'; return; }
msg.textContent = '';
const res = await fetch('/login?username=' + encodeURIComponent(u) + '&password=' + encodeURIComponent(p));
const data = await res.json();
if (data.token) {
document.getElementById('token-val').value = data.token;
document.getElementById('token-box').style.display = 'block';
} else {
msg.className = 'error';
msg.textContent = data.error || 'Login failed.';
}
}
document.addEventListener('keydown', e => { if (e.key === 'Enter') login(); });
</script>
</body>
</html>
HTML;
}
public function onMessage(ConnectionInterface $from, $msg): void {}
public function onClose(ConnectionInterface $conn): void {}
public function onError(ConnectionInterface $conn, \Exception $e): void { $conn->close(); }
+59 -1
View File
@@ -12,10 +12,17 @@ class RegisterController implements HttpServerInterface
public function onOpen(ConnectionInterface $conn, RequestInterface $request = null): void
{
$params = [];
parse_str($request->getUri()->getQuery(), $params);
if (empty($params["username"]) && empty($params["password"])) {
Utils::respondHtml($conn, $this->registerPage());
$conn->close();
return;
}
$createAccount = true;
$responseHead = "";
$json = "";
parse_str($request->getUri()->getQuery(), $params);
$username = $params["username"];
$password = $params["password"];
@@ -53,6 +60,57 @@ class RegisterController implements HttpServerInterface
$conn->close();
}
private function registerPage(): string
{
return <<<'HTML'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Register — ComCen</title>
<style>
body { font-family: monospace; max-width: 360px; margin: 80px auto; padding: 0 16px; }
h2 { margin-bottom: 24px; }
input { width: 100%; box-sizing: border-box; padding: 6px; font-family: monospace; font-size: 14px; margin-bottom: 10px; border: 1px solid #ccc; }
button { padding: 6px 16px; font-family: monospace; font-size: 14px; cursor: pointer; }
#msg { margin-top: 12px; font-size: 13px; }
.error { color: #c00; }
.success { color: #080; }
a { color: inherit; }
</style>
</head>
<body>
<h2>Register</h2>
<input id="username" type="text" placeholder="Username" />
<input id="password" type="password" placeholder="Password (min 5 chars)" />
<button onclick="register()">Register</button>
<div id="msg"></div>
<p><a href="/login">Already have an account? Login</a></p>
<script>
async function register() {
const u = document.getElementById('username').value.trim();
const p = document.getElementById('password').value.trim();
const msg = document.getElementById('msg');
if (!u || !p) { msg.className = 'error'; msg.textContent = 'Fill in all fields.'; return; }
msg.textContent = '';
const res = await fetch('/register?username=' + encodeURIComponent(u) + '&password=' + encodeURIComponent(p));
const data = await res.json();
if (data.error === 'none') {
msg.className = 'success';
msg.textContent = 'Account created! Redirecting to login...';
setTimeout(() => window.location.href = '/login', 1200);
} else {
msg.className = 'error';
msg.textContent = data.error || 'Registration failed.';
}
}
document.addEventListener('keydown', e => { if (e.key === 'Enter') register(); });
</script>
</body>
</html>
HTML;
}
public function onMessage(ConnectionInterface $from, $msg): void {}
public function onClose(ConnectionInterface $conn): void {}
public function onError(ConnectionInterface $conn, \Exception $e): void { $conn->close(); }
+5
View File
@@ -10,4 +10,9 @@ class Utils
{
$conn->send("HTTP/1.1 {$head}\r\nContent-Type: application/json\r\n\r\n{$jsonData}");
}
static function respondHtml(ConnectionInterface $conn, string $html): void
{
$conn->send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n{$html}");
}
}