Files
2026-06-19 01:21:26 +00:00

149 lines
6.4 KiB
HTML
Raw Permalink 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" />
<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 (GIF / PNG / WebP, or MP4 / WebM video)</label>
<div class="row">
<input id="gm-file" type="file" accept=".gif,.png,.jpg,.jpeg,.webp,.webm,.mp4" />
<img id="gm-preview" class="gm-preview hidden" alt="" />
<video id="gm-preview-vid" class="gm-preview hidden" muted loop playsinline></video>
</div>
<div class="muted" style="font-size:11px;margin-top:4px">Upload happens after you save the ghost. MP4 files are converted to a transparent WebM (with a WebP fallback) on the server.</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>