Add admin panel page

This commit is contained in:
2026-06-17 16:38:05 +10:00
parent 5dbbefc032
commit f3c450092a
+147
View File
@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Newbury Nights — Admin</title>
<link rel="stylesheet" href="/css/app.css" />
<link rel="stylesheet" href="/css/admin.css" />
</head>
<body>
<!-- Login -->
<div id="login" class="login-wrap">
<div class="login-card">
<h1 class="login-title">Newbury<span>Nights</span></h1>
<div class="login-sub mono">ADMIN CONSOLE</div>
<label for="lg-user">Username</label>
<input id="lg-user" autocomplete="username" />
<label for="lg-pass">Password</label>
<input id="lg-pass" type="password" autocomplete="current-password" />
<button class="primary" id="lg-go" style="width:100%;margin-top:14px">Sign in</button>
<div id="lg-error" class="lg-error hidden"></div>
</div>
</div>
<!-- App -->
<div id="app" class="hidden">
<header class="topbar">
<div class="brand">Newbury<span>Nights</span> <span class="badge mono">ADMIN</span></div>
<nav class="tabs">
<button class="tab active" data-tab="ghosts">Ghosts</button>
<button class="tab" data-tab="sets">Sets</button>
<button class="tab" data-tab="account">Account</button>
</nav>
<button id="logout" class="small">Sign out</button>
</header>
<!-- GHOSTS -->
<section id="tab-ghosts" class="tab-panel">
<div class="panel-head">
<h2>Ghosts</h2>
<div class="head-actions">
<input id="ghost-search" placeholder="Search name / ability…" style="width:220px" />
<button class="primary" id="new-ghost">+ New ghost</button>
</div>
</div>
<div class="table-wrap">
<table id="ghosts-table">
<thead>
<tr><th></th><th>Name / Display</th><th>Type</th><th>Rarity</th><th>HP</th><th>DMG</th><th>Ability</th><th>Set</th><th>On</th><th></th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</section>
<!-- SETS -->
<section id="tab-sets" class="tab-panel hidden">
<div class="panel-head">
<h2>Sets</h2>
<button class="primary" id="new-set">+ New set</button>
</div>
<div id="sets-list" class="sets-list"></div>
</section>
<!-- ACCOUNT -->
<section id="tab-account" class="tab-panel hidden">
<div class="panel-head"><h2>Account</h2></div>
<div class="account-card">
<p class="muted">Signed in as <strong id="acct-user"></strong>. Change your password below.</p>
<label>Current password</label><input id="cp-current" type="password" />
<label>New password (min 8 chars)</label><input id="cp-new" type="password" />
<button class="primary" id="cp-go" style="margin-top:12px">Update password</button>
<div id="cp-msg" class="cp-msg hidden"></div>
</div>
</section>
</div>
<!-- Ghost editor modal -->
<div id="ghost-modal" class="modal hidden">
<div class="modal-card">
<h3 id="gm-title">Edit ghost</h3>
<div class="grid2">
<div><label>Name</label><input id="gm-name" /></div>
<div><label>Display name (lock-on label)</label><input id="gm-display" /></div>
<div><label>Type</label>
<select id="gm-type"><option value="red">Red</option><option value="yellow">Yellow</option><option value="blue">Blue</option></select>
</div>
<div><label>Rarity (14)</label><input id="gm-rarity" type="number" min="1" max="4" /></div>
<div><label>Health</label><input id="gm-health" type="number" /></div>
<div><label>Damage</label><input id="gm-damage" type="number" /></div>
<div><label>Speed (05)</label><input id="gm-speed" type="number" min="0" max="5" /></div>
<div><label>Range (05)</label><input id="gm-range" type="number" min="0" max="5" /></div>
<div><label>Charge shot (03)</label><input id="gm-charge" type="number" min="0" max="3" /></div>
<div><label>Ability</label><input id="gm-ability" /></div>
<div><label>Set number (ref)</label><input id="gm-setnum" /></div>
<div><label>Set name (ref)</label><input id="gm-setname" /></div>
</div>
<div class="checks">
<label class="chk"><input type="checkbox" id="gm-boss" /> Boss ghost</label>
<label class="chk"><input type="checkbox" id="gm-enabled" checked /> Enabled</label>
</div>
<div class="image-row">
<label>Billboard image (GIF / PNG)</label>
<div class="row">
<input id="gm-file" type="file" accept=".gif,.png,.jpg,.jpeg,.webp" />
<img id="gm-preview" class="gm-preview hidden" alt="" />
</div>
<div class="muted" style="font-size:11px;margin-top:4px">Upload happens after you save the ghost.</div>
</div>
<div class="modal-actions">
<button data-close>Cancel</button>
<button class="primary" id="gm-save">Save</button>
</div>
</div>
</div>
<!-- Set editor modal -->
<div id="set-modal" class="modal hidden">
<div class="modal-card">
<h3 id="sm-title">Edit set</h3>
<div class="grid2">
<div><label>Scan code (QR payload)</label><input id="sm-code" placeholder="NN-70419" /></div>
<div><label>Set number (ref)</label><input id="sm-setnum" /></div>
<div><label>Set name</label><input id="sm-setname" /></div>
<div><label>Boss ghost</label><select id="sm-boss"><option value="">— none —</option></select></div>
</div>
<label class="chk"><input type="checkbox" id="sm-enabled" checked /> Enabled</label>
<div class="roster-pick">
<label>Roster (ghosts returned on scan)</label>
<input id="sm-roster-search" placeholder="Filter ghosts…" />
<div id="sm-roster" class="roster-checklist"></div>
</div>
<div class="modal-actions">
<button data-close>Cancel</button>
<button class="primary" id="sm-save">Save set</button>
</div>
</div>
</div>
<div class="disclaimer">
Fan-made tribute. Not affiliated with, sponsored by, or endorsed by the LEGO Group.
LEGO® and Hidden Side™ are trademarks of the LEGO Group.
</div>
<script type="module" src="/js/admin.js"></script>
</body>
</html>