payparse / static /app.js
NabilHzs's picture
Upload folder using huggingface_hub
20e9e63 verified
Raw History Blame Contribute Delete
3.63 kB
// PayParse — minimal vanilla-JS chat client for the /api/chat endpoint.
const chatWindow = document.getElementById("chatWindow");
const composerForm = document.getElementById("composerForm");
const messageInput = document.getElementById("messageInput");
const sendButton = document.getElementById("sendButton");
const resetButton = document.getElementById("resetButton");
const engineBadge = document.getElementById("engineBadge");
const quickReplies = document.getElementById("quickReplies");
let sessionId = crypto.randomUUID();
function scrollToBottom() {
chatWindow.scrollTop = chatWindow.scrollHeight;
}
function appendMessage(text, sender) {
const row = document.createElement("div");
row.className = `msg msg-${sender}`;
const bubble = document.createElement("div");
bubble.className = "bubble";
bubble.textContent = text;
row.appendChild(bubble);
chatWindow.appendChild(row);
scrollToBottom();
return row;
}
function appendPayload(payload) {
const row = document.createElement("div");
row.className = "msg msg-bot";
const bubble = document.createElement("div");
bubble.className = "bubble payload";
bubble.textContent = JSON.stringify(payload, null, 2);
row.appendChild(bubble);
chatWindow.appendChild(row);
scrollToBottom();
}
function showTyping() {
const row = document.createElement("div");
row.className = "msg msg-bot typing";
row.id = "typingIndicator";
row.innerHTML = `<div class="bubble"><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>`;
chatWindow.appendChild(row);
scrollToBottom();
}
function hideTyping() {
const el = document.getElementById("typingIndicator");
if (el) el.remove();
}
async function loadHealth() {
try {
const res = await fetch("/health");
const data = await res.json();
engineBadge.textContent = data.offline_mode ? "Mode: Offline (Mock)" : "Mode: Gemini Live";
} catch {
engineBadge.textContent = "Tidak terhubung";
}
}
async function sendMessage(text) {
appendMessage(text, "user");
messageInput.value = "";
sendButton.disabled = true;
showTyping();
try {
const res = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ session_id: sessionId, message: text }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
hideTyping();
appendMessage(data.reply, "bot");
if (data.is_complete && data.payload) {
appendPayload(data.payload);
// Transaction finished server-side; start a fresh session for the next one.
sessionId = crypto.randomUUID();
}
} catch (err) {
hideTyping();
appendMessage("Maaf, terjadi kendala koneksi ke server. Coba lagi ya.", "bot");
console.error(err);
} finally {
sendButton.disabled = false;
messageInput.focus();
}
}
composerForm.addEventListener("submit", (e) => {
e.preventDefault();
const text = messageInput.value.trim();
if (!text) return;
sendMessage(text);
});
quickReplies.addEventListener("click", (e) => {
const chip = e.target.closest(".chip");
if (!chip) return;
sendMessage(chip.dataset.text);
});
resetButton.addEventListener("click", async () => {
try {
await fetch(`/api/session/${sessionId}`, { method: "DELETE" });
} catch {
/* session may already be gone; ignore */
}
sessionId = crypto.randomUUID();
chatWindow.innerHTML = "";
appendMessage(
'Oke, mulai dari awal. Mau dibantu transfer, beli pulsa, atau bayar listrik?',
"bot"
);
});
loadHealth();
messageInput.focus();