/** * ClauseGuard — Popup Script v4.3 * Shows user status (logged in / guest), scan results, usage. * * FIXED v4.3: sidePanel.open() is properly awaited. * FIXED v4.3: CRITICAL severity is now counted and displayed. * FIXED v4.3: Shows scan source ("Legal-BERT" / "Local") accurately. */ document.addEventListener("DOMContentLoaded", async () => { const resultsView = document.getElementById("results-view"); const emptyView = document.getElementById("empty-view"); const limitBanner = document.getElementById("limit-banner"); const userBar = document.getElementById("user-bar"); const userEmail = document.getElementById("user-email"); const userPlan = document.getElementById("user-plan"); const guestBar = document.getElementById("guest-bar"); let tab; try { const [t] = await chrome.tabs.query({ active: true, currentWindow: true }); tab = t; } catch { return; } if (!tab?.id) return; // Load user info let auth = null; try { auth = await chrome.runtime.sendMessage({ type: "GET_USER" }); } catch {} if (auth?.isLoggedIn) { if (userBar) userBar.style.display = "flex"; if (guestBar) guestBar.style.display = "none"; if (userEmail) userEmail.textContent = auth.email || "User"; if (userPlan) { userPlan.textContent = auth.plan?.toUpperCase() || "FREE"; userPlan.className = "plan-badge plan-" + (auth.plan || "free"); } } else { if (userBar) userBar.style.display = "none"; if (guestBar) guestBar.style.display = "flex"; } // Check usage let usage = null; try { usage = await chrome.runtime.sendMessage({ type: "CHECK_USAGE" }); } catch {} updateUsage(usage); if (usage && !usage.allowed && limitBanner) limitBanner.style.display = "block"; // Load results let results = null; try { results = await chrome.runtime.sendMessage({ type: "GET_RESULTS", tabId: tab.id }); } catch {} if (results && results.risk_score !== undefined) { showResults(results); } else { if (emptyView) emptyView.style.display = "block"; if (resultsView) resultsView.style.display = "none"; } // Scan button const btnScan = document.getElementById("btn-scan"); if (btnScan) { btnScan.addEventListener("click", async () => { if (usage && !usage.allowed) { if (limitBanner) limitBanner.style.display = "block"; return; } btnScan.textContent = "Scanning..."; btnScan.disabled = true; try { await chrome.tabs.sendMessage(tab.id, { type: "TRIGGER_SCAN" }); setTimeout(async () => { try { const r = await chrome.runtime.sendMessage({ type: "GET_RESULTS", tabId: tab.id }); if (r?.risk_score !== undefined) showResults(r); } catch {} try { usage = await chrome.runtime.sendMessage({ type: "CHECK_USAGE" }); updateUsage(usage); } catch {} btnScan.textContent = "Scan this page"; btnScan.disabled = false; }, 3000); } catch { btnScan.textContent = "Error — refresh page"; btnScan.disabled = false; } }); } // Re-scan const btnRescan = document.getElementById("btn-rescan"); if (btnRescan) btnRescan.addEventListener("click", async () => { if (usage && !usage.allowed) { if (limitBanner) limitBanner.style.display = "block"; return; } try { await chrome.tabs.sendMessage(tab.id, { type: "TRIGGER_SCAN" }); } catch {} window.close(); }); // FIX v4.3: Properly await async sidePanel.open() so errors are caught const btnDetails = document.getElementById("btn-details"); if (btnDetails) btnDetails.addEventListener("click", async () => { try { await chrome.sidePanel.open({ tabId: tab.id }); } catch(e) { console.warn("sidePanel.open failed:", e); } window.close(); }); // Login button const btnLogin = document.getElementById("btn-login"); if (btnLogin) btnLogin.addEventListener("click", () => { chrome.tabs.create({ url: "https://clauseguardweb.netlify.app/auth/login" }); }); }); function showResults(results) { const rv = document.getElementById("results-view"); const ev = document.getElementById("empty-view"); if (rv) rv.style.display = "block"; if (ev) ev.style.display = "none"; const el = (id) => document.getElementById(id); if (el("risk-score")) el("risk-score").textContent = results.risk_score; const grade = results.grade || "C"; const badge = el("grade-badge"); if (badge) { badge.className = "grade grade-" + grade.toLowerCase(); badge.textContent = "Grade " + grade; } const bar = el("bar-fill"); if (bar) { bar.style.width = results.risk_score + "%"; bar.className = "bar-fill " + (results.risk_score >= 60 ? "bar-red" : results.risk_score >= 30 ? "bar-amber" : "bar-green"); } // FIX v4.3: Count CRITICAL severity too (backend can return it) const counts = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 }; (results.results || []).forEach(r => (r.categories || []).forEach(c => { if (counts[c.severity] !== undefined) counts[c.severity]++; else counts.MEDIUM++; // Unknown severities default to MEDIUM })); // Merge CRITICAL into HIGH for display (popup only has 3 columns) if (el("c-high")) el("c-high").textContent = counts.CRITICAL + counts.HIGH; if (el("c-med")) el("c-med").textContent = counts.MEDIUM; if (el("c-low")) el("c-low").textContent = counts.LOW; // Show source indicator const src = el("scan-source"); if (src) src.textContent = results.source === "api" ? "Legal-BERT" : results.source === "local" ? "Local (offline)" : ""; } function updateUsage(usage) { if (!usage) return; const text = document.getElementById("usage-text"); const fill = document.getElementById("usage-fill"); if (!text || !fill) return; if (usage.plan === "free") { text.textContent = usage.used + "/" + usage.limit + " scans"; const pct = Math.min(100, (usage.used / usage.limit) * 100); fill.style.width = pct + "%"; if (pct >= 100) fill.style.background = "#ef4444"; else if (pct >= 70) fill.style.background = "#f59e0b"; } else { text.textContent = "Unlimited"; fill.style.width = "100%"; fill.style.background = "#22c55e"; } }