(() => { async function loadStats() { const res = await fetch("/api/dashboard/stats"); const data = await res.json(); document.getElementById("s-total").textContent = data.total_conversations; document.getElementById("s-rate").textContent = `${data.resolution_rate}%`; document.getElementById("s-appt").textContent = data.appointments_booked; document.getElementById("s-hand").textContent = data.handed_off; document.getElementById("s-unans").textContent = data.unanswered_count; document.getElementById("s-leads").textContent = data.leads_complete; const unansBody = document.getElementById("unans-body"); unansBody.innerHTML = ""; (data.recent_unanswered || []).forEach((q) => { const tr = document.createElement("tr"); tr.innerHTML = ` ${q.id} #${q.conversation_id} ${escapeHtml(q.question)} ${formatWhen(q.created_at)} `; unansBody.appendChild(tr); }); } async function loadConversations() { const res = await fetch("/api/conversations"); const rows = await res.json(); const body = document.getElementById("conv-body"); body.innerHTML = ""; rows.forEach((c) => { const status = c.handed_off ? 'handoff' : c.appointment_booked ? 'booked' : `${c.status}`; const tr = document.createElement("tr"); tr.innerHTML = ` #${c.id} ${c.channel} ${c.language} ${escapeHtml(c.lead_name || "—")} ${status} ${c.message_count} ${formatWhen(c.created_at)} Open · Export CSV `; body.appendChild(tr); }); } function formatWhen(value) { try { return new Date(value).toLocaleString(); } catch (_) { return value; } } function escapeHtml(text) { return String(text) .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">"); } loadStats(); loadConversations(); })();