// static/js/design.js // ── Marked.js config ────────────────────────────────────────────────────────── marked.setOptions({ breaks: true, gfm: true, highlight: (code, lang) => { if (lang && hljs.getLanguage(lang)) { return hljs.highlight(code, { language: lang }).value; } return hljs.highlightAuto(code).value; } }); // ── DOM refs ────────────────────────────────────────────────────────────────── const chatWindow = document.getElementById("chatWindow"); const queryInput = document.getElementById("queryInput"); const sendBtn = document.getElementById("sendBtn"); const topicInput = document.getElementById("topicInput"); const clearBtn = document.getElementById("clearBtn"); const menuBtn = document.getElementById("menuBtn"); const sidebar = document.getElementById("sidebar"); const overlay = document.getElementById("overlay"); const sidebarClose = document.getElementById("sidebarClose"); const quickBtns = document.querySelectorAll(".quick-btn"); // ── Conversation history ────────────────────────────────────────────────────── let history = []; // ── Sidebar toggle ──────────────────────────────────────────────────────────── function openSidebar() { sidebar.classList.add("open"); overlay.classList.add("show"); } function closeSidebar() { sidebar.classList.remove("open"); overlay.classList.remove("show"); } menuBtn.addEventListener("click", openSidebar); sidebarClose.addEventListener("click", closeSidebar); overlay.addEventListener("click", closeSidebar); // ── Auto-resize textarea ────────────────────────────────────────────────────── function autoResize() { queryInput.style.height = "auto"; queryInput.style.height = Math.min(queryInput.scrollHeight, 200) + "px"; } queryInput.addEventListener("input", autoResize); // ── Quick prompt buttons ────────────────────────────────────────────────────── quickBtns.forEach(btn => { btn.addEventListener("click", () => { queryInput.value = btn.dataset.prompt; autoResize(); queryInput.focus(); closeSidebar(); }); }); // ── Clear chat ──────────────────────────────────────────────────────────────── clearBtn.addEventListener("click", () => { history = []; const welcome = document.getElementById("welcomeMsg"); chatWindow.innerHTML = ""; if (welcome) chatWindow.appendChild(welcome); }); // ── Scroll to bottom ────────────────────────────────────────────────────────── function scrollToBottom() { chatWindow.scrollTo({ top: chatWindow.scrollHeight, behavior: "smooth" }); } // ── Add message bubble ──────────────────────────────────────────────────────── function addMessage(role, content) { const msg = document.createElement("div"); msg.className = `message ${role}`; const avatar = document.createElement("div"); avatar.className = "avatar"; avatar.textContent = role === "user" ? "YOU" : "SS"; const bubble = document.createElement("div"); bubble.className = "bubble"; if (role === "assistant") { bubble.innerHTML = marked.parse(content); bubble.querySelectorAll("pre code").forEach(el => hljs.highlightElement(el)); } else { // user bubble: preserve newlines and show code syntax as plain text bubble.style.whiteSpace = "pre-wrap"; bubble.textContent = content; } msg.appendChild(avatar); msg.appendChild(bubble); chatWindow.appendChild(msg); scrollToBottom(); } // ── Typing indicator ────────────────────────────────────────────────────────── function showTyping() { const msg = document.createElement("div"); msg.className = "message assistant"; msg.id = "typingIndicator"; const avatar = document.createElement("div"); avatar.className = "avatar"; avatar.textContent = "SS"; const bubble = document.createElement("div"); bubble.className = "bubble"; bubble.innerHTML = `
`; msg.appendChild(avatar); msg.appendChild(bubble); chatWindow.appendChild(msg); scrollToBottom(); } function hideTyping() { const indicator = document.getElementById("typingIndicator"); if (indicator) indicator.remove(); } // ── Send message ────────────────────────────────────────────────────────────── async function sendMessage() { const query = queryInput.value.trim(); if (!query) return; const topic = topicInput.value.trim() || null; addMessage("user", query); history.push({ role: "user", content: query }); // reset input queryInput.value = ""; queryInput.style.height = "auto"; sendBtn.disabled = true; showTyping(); try { const res = await fetch("/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, topic, history }) }); const data = await res.json(); hideTyping(); if (data.error) { addMessage("assistant", `⚠️ **Error:** ${data.error}`); } else { addMessage("assistant", data.response); history.push({ role: "assistant", content: data.response }); } } catch (err) { hideTyping(); addMessage("assistant", "⚠️ **Network error.** Flask server se connect nahi ho saka."); } finally { sendBtn.disabled = false; queryInput.focus(); } } // ── Keyboard handling ───────────────────────────────────────────────────────── queryInput.addEventListener("keydown", (e) => { if (e.key === "Enter") { if (e.shiftKey) { // Shift+Enter — insert a real newline and resize // let the browser insert \n naturally, then resize setTimeout(autoResize, 0); return; // do NOT send } // plain Enter — send e.preventDefault(); sendMessage(); } }); // ── Send button ─────────────────────────────────────────────────────────────── sendBtn.addEventListener("click", sendMessage);