(() => { const messagesEl = document.getElementById("messages"); const composer = document.getElementById("composer"); const input = document.getElementById("message-input"); const convIdEl = document.getElementById("conv-id"); const slotsBox = document.getElementById("slots-box"); let conversationId = null; let busy = false; function addBubble(role, text) { const div = document.createElement("div"); div.className = `bubble ${role}`; div.textContent = text; messagesEl.appendChild(div); messagesEl.scrollTop = messagesEl.scrollHeight; } function renderLead(lead) { document.getElementById("lead-name").textContent = (lead && lead.name) || "—"; document.getElementById("lead-need").textContent = (lead && lead.need) || "—"; document.getElementById("lead-budget").textContent = (lead && lead.budget) || "—"; document.getElementById("lead-contact").textContent = (lead && (lead.contact_channel || lead.email || lead.phone)) || "—"; } function renderSlots(slots) { slotsBox.innerHTML = ""; if (!slots || !slots.length) { slotsBox.innerHTML = '
—
'; return; } slots.forEach((slot) => { const btn = document.createElement("button"); btn.type = "button"; btn.className = "slot-btn"; btn.textContent = slot.label || slot.start; btn.addEventListener("click", () => bookSlot(slot)); slotsBox.appendChild(btn); }); } async function bookSlot(slot) { if (!conversationId) return; const res = await fetch("/api/appointments/book", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ conversation_id: conversationId, slot_start: slot.start, slot_end: slot.end, }), }); const data = await res.json(); if (!res.ok) { addBubble("assistant", data.detail || "Booking failed"); return; } addBubble( "assistant", data.message || "Appointment booked" ); renderSlots([]); } async function loadHealth() { try { const res = await fetch("/api/health"); const data = await res.json(); document.getElementById("h-openai").textContent = data.openai ? "on" : "demo"; document.getElementById("h-calcom").textContent = data.calcom ? "on" : "demo"; document.getElementById("h-whatsapp").textContent = data.whatsapp ? "on" : "demo"; document.getElementById("h-chunks").textContent = data.knowledge_chunks; } catch (_) { /* ignore */ } } async function startChat() { messagesEl.innerHTML = ""; const res = await fetch( "/api/chat/start?ui_language=en", { method: "POST" } ); const data = await res.json(); conversationId = data.conversation_id; convIdEl.textContent = `#${conversationId}`; addBubble("assistant", data.greeting); renderLead(null); renderSlots([]); } composer.addEventListener("submit", async (event) => { event.preventDefault(); if (busy || !conversationId) return; const text = input.value.trim(); if (!text) return; input.value = ""; addBubble("user", text); busy = true; try { const res = await fetch("/api/chat/message", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ conversation_id: conversationId, message: text, ui_language: "en", }), }); const data = await res.json(); addBubble("assistant", data.reply); renderLead(data.lead); renderSlots(data.suggested_slots); } catch (err) { addBubble("assistant", "Network error. Please retry."); } finally { busy = false; } }); loadHealth(); startChat(); })();