ui: loading states, player failure overlay + retry, toasts, back nav, full history page with delete

Bundle 1-4+7 from PLAN.md: skeleton loaders, player Loading/Buffering/fatal overlay with Retry, action toasts, back-to-home crumb + logo fix, ?history full-history view with per-entry delete (GET /api/history?all=1, DELETE /api/history). 14/14 tests green.
This commit is contained in:
jozamudi committed 2026-08-19 18:20:42 +00:00
1 parent 19e878800c
commit 2ec0f8a034
10 files changed
+414 -20

No files matched your search

+9
View File
@@ -16,9 +16,13 @@ input { width:100%; box-sizing:border-box; padding:.55rem .8rem; border-radius:8
button { width:100%; margin-top:.4rem; padding:.55rem; border:0; border-radius:8px;
background:var(--acc); color:#000; font-weight:600; cursor:pointer; }
.err { color:#f87171; font-size:.85rem; margin:.6rem 0 0; min-height:1.2em; }
.banner { position:fixed; top:1rem; left:50%; transform:translateX(-50%); background:var(--card);
border:1px solid var(--bd); border-radius:8px; padding:.4rem .9rem; color:var(--muted);
font-size:.85rem; }
</style>
</head>
<body>
<p class="banner" id="banner" hidden></p>
<form onsubmit="event.preventDefault(); login()">
<h1>ani-web</h1>
<input id="user" placeholder="username" autocomplete="username">
@@ -35,6 +39,11 @@ const BASE = (() => {
})();
const $ = id => document.getElementById(id);
const next = new URLSearchParams(location.search).get("next");
(() => { // one-shot confirmations for logout / account delete
const s = new URLSearchParams(location.search);
const note = s.get("signedout") ? "Signed out." : s.get("deleted") ? "Account deleted." : null;
if (note) { const b = $("banner"); b.textContent = note; b.hidden = false; }
})();
async function login() {
$("err").textContent = "";
const r = await fetch(BASE + "login", {method: "POST",