← back to Patterndesignlab

public/admin-login.html

40 lines

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<title>Admin sign in · Pattern Design Lab</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<header class="top"><div class="wrap">
  <a class="brand" href="/">Pattern Design<span class="dot">.</span>Lab</a>
</div></header>

<div class="wrap" style="max-width:380px;padding:60px 20px">
  <h1 style="font-size:22px;margin-bottom:4px">Admin sign in</h1>
  <p style="color:#6b6b6b;font-size:14px;margin-bottom:18px">Curation &amp; catalog controls.</p>
  <form id="f">
    <input id="u" placeholder="username" autocomplete="username" style="width:100%;height:42px;border:1px solid var(--line);border-radius:10px;padding:0 12px;margin-bottom:10px;font-size:14px">
    <input id="p" type="password" placeholder="password" autocomplete="current-password" style="width:100%;height:42px;border:1px solid var(--line);border-radius:10px;padding:0 12px;margin-bottom:10px;font-size:14px">
    <button class="buy" type="submit" style="width:100%">Sign in</button>
    <p id="msg" class="note" style="margin-top:10px"></p>
  </form>
</div>

<script>
document.getElementById('f').onsubmit = async (e) => {
  e.preventDefault();
  const msg = document.getElementById('msg');
  const r = await fetch('/api/admin/login', { method:'POST', headers:{'Content-Type':'application/json'},
    body: JSON.stringify({ user: document.getElementById('u').value, pass: document.getElementById('p').value }) });
  if (r.ok) {
    const next = new URLSearchParams(location.search).get('next');
    location.href = (next && /^\/(?!\/)/.test(next)) ? next : '/admin'; // "/x" only — "//host" is an open redirect
  } else { msg.textContent = 'Invalid credentials.'; msg.style.color = '#b3261e'; }
};
</script>
</body>
</html>