const $ = (sel) => document.querySelector(sel); const $$ = (sel) => document.querySelectorAll(sel); let libraries = []; async function api(path, opts = {}) { const resp = await fetch(path, { headers: { "Content-Type": "application/json" }, ...opts, }); if (!resp.ok) { let msg = resp.statusText; try { msg = (await resp.json()).detail || msg; } catch {} throw new Error(msg); } return resp.json(); } function toast(msg, isError = false) { const t = $("#toast"); t.textContent = msg; t.className = isError ? "error" : ""; t.hidden = false; setTimeout(() => (t.hidden = true), 4000); } function esc(s) { const d = document.createElement("div"); d.textContent = s ?? ""; return d.innerHTML; } // ---- navigation ---- $$("nav button").forEach((btn) => btn.addEventListener("click", () => { $$("nav button").forEach((b) => b.classList.remove("active")); btn.classList.add("active"); $$("main > section").forEach((s) => (s.hidden = true)); $("#view-" + btn.dataset.view).hidden = false; if (btn.dataset.view === "missing") loadRequests("missing"); if (btn.dataset.view === "imported") loadRequests("imported"); if (btn.dataset.view === "settings") loadLibraries(); }) ); // ---- libraries ---- async function loadLibraries() { libraries = await api("/api/libraries"); const tbody = $("#lib-table tbody"); tbody.innerHTML = libraries .map( (l) => `
Suche läuft…
"; try { const results = await api(`/api/search?media_type=${type}&q=${encodeURIComponent(q)}`); if (!results.length) { box.innerHTML = "Keine Treffer.
"; return; } const opts = libOptions(type); box.innerHTML = results .map( (r, i) => `Nichts hier.
"; return; } box.innerHTML = reqs .map( (r) => `✓ ${esc(r.path)} → ${esc(r.dest)}
` : `✗ ${esc(r.path)}: ${esc(r.error)}
` ) .join(""); $("#scan-btn").click(); } catch (err) { toast(err.message, true); } }); // ---- init ---- loadLibraries();