// VV compare frontend (() => { const $ = (id) => document.getElementById(id); const sections = { upload: $("s-upload"), processing: $("s-processing"), result: $("s-result"), }; const show = (n) => { for (const [k, el] of Object.entries(sections)) el.classList.toggle("hidden", k !== n); }; let state = { jobId: null, result: null, origFile: null, newFile: null }; function attachDrop(zoneId, inputId, textId, which) { const zone = $(zoneId); const input = $(inputId); const text = $(textId); zone.addEventListener("click", () => input.click()); input.addEventListener("change", (e) => { if (e.target.files[0]) setFile(which, e.target.files[0], zone, text); }); ["dragenter", "dragover"].forEach((ev) => zone.addEventListener(ev, (e) => { e.preventDefault(); zone.classList.add("drag-over"); })); ["dragleave", "drop"].forEach((ev) => zone.addEventListener(ev, (e) => { e.preventDefault(); zone.classList.remove("drag-over"); })); zone.addEventListener("drop", (e) => { if (e.dataTransfer.files[0]) setFile(which, e.dataTransfer.files[0], zone, text); }); } function setFile(which, file, zone, textEl) { if (which === "orig") state.origFile = file; else state.newFile = file; zone.classList.add("has-file"); const size = file.size > 1024 * 1024 ? `${(file.size / 1024 / 1024).toFixed(1)} MB` : `${(file.size / 1024).toFixed(0)} kB`; textEl.innerHTML = `${escapeHtml(file.name)}
${size}`; updateRunBtn(); } attachDrop("drop-original", "orig-input", "orig-text", "orig"); attachDrop("drop-new", "new-input", "new-text", "new"); function updateRunBtn() { const btn = $("compare-btn"); const hint = $("compare-hint"); if (!state.origFile && !state.newFile) { btn.disabled = true; hint.textContent = "Nahrajte oba soubory."; } else if (!state.origFile) { btn.disabled = true; hint.textContent = "Chybí původní VV."; } else if (!state.newFile) { btn.disabled = true; hint.textContent = "Chybí nový VV."; } else { btn.disabled = false; hint.textContent = "Připraveno k porovnání."; } } $("compare-btn").addEventListener("click", async () => { if (!state.origFile || !state.newFile) return; show("processing"); try { const fd = new FormData(); fd.append("original", state.origFile); fd.append("new", state.newFile); const r = await fetch("/api/compare", { method: "POST", body: fd }); if (!r.ok) throw new Error((await r.json()).detail || r.statusText); const json = await r.json(); state.jobId = json.job_id; state.result = json.result; renderResult(); show("result"); } catch (err) { alert("Chyba: " + err.message); show("upload"); } }); function renderResult() { const r = state.result; const c = r.changes.length, a = r.added.length, d = r.removed.length; $("cnt-changed").textContent = c; $("cnt-added").textContent = a; $("cnt-removed").textContent = d; $("results-meta").textContent = `Porovnání ${r.per_sheet.length} listů — ${c + a + d} celkových rozdílů.`; const psHtml = r.per_sheet.map((ps) => ` ${escapeHtml(ps.sheet)} ${escapeHtml(ps.hala || "")} ${ps.orig_count} ${ps.new_count} ${ps.changes} ${ps.added} ${ps.removed} `).join(""); $("per-sheet").innerHTML = r.per_sheet.length ? ` ${psHtml}
ListHala Pol. původníPol. nový ZměněnéPřidanéOdebrané
` : `

Nepodařilo se najít listy VV v žádném ze souborů.

`; } $("download-btn").addEventListener("click", () => { if (state.jobId) window.location.href = `/api/report/${state.jobId}`; }); $("restart-btn").addEventListener("click", () => { state = { jobId: null, result: null, origFile: null, newFile: null }; $("orig-input").value = ""; $("new-input").value = ""; $("drop-original").classList.remove("has-file"); $("drop-new").classList.remove("has-file"); $("orig-text").textContent = "Přetáhněte soubor sem nebo klikněte"; $("new-text").textContent = "Přetáhněte soubor sem nebo klikněte"; updateRunBtn(); show("upload"); }); function escapeHtml(s) { return String(s ?? "").replace(/[&<>"']/g, (c) => ({"&":"&","<":"<",">":">",'"':""","'":"'"}[c])); } })();