Download app/static/js/chat.js from nvikou/ReplyFlow: direct link, hf CLI and curl.
- Browser
- Download file 4.56 kB
-
https://huggingface.co/spaces/nvikou/ReplyFlow/resolve/main/app/static/js/chat.js
- Command line
-
hf download hf://spaces/nvikou/ReplyFlow/app/static/js/chat.js
-
curl -L -o chat.js https://huggingface.co/spaces/nvikou/ReplyFlow/resolve/main/app/static/js/chat.js
4.56 kB
| (() => { | |
| 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 = | |
| '<div style="color:var(--muted);font-size:0.9rem">—</div>'; | |
| 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(); | |
| })(); | |