document.addEventListener("DOMContentLoaded", () => { const convo = document.querySelector(".convo"); const input = document.querySelector(".qt input"); const sendBtn = document.querySelector(".sendingQA"); const fileBtn = document.querySelector(".fa-file"); const imageBtn = document.querySelector(".fa-image"); let selectedFile = null; let filePreviewBubble = null; // Create hidden file inputs for documents and images const fileUpload = document.createElement("input"); fileUpload.type = "file"; fileUpload.accept = ".pdf,.docx,.pptx,.xlsx"; fileUpload.style.display = "none"; document.body.appendChild(fileUpload); const imageUpload = document.createElement("input"); imageUpload.type = "file"; imageUpload.accept = "image/*"; imageUpload.style.display = "none"; document.body.appendChild(imageUpload); // Click on hidden inputs when buttons are clicked fileBtn.addEventListener("click", () => fileUpload.click()); imageBtn.addEventListener("click", () => imageUpload.click()); // Handle document file selection fileUpload.addEventListener("change", (e) => { handleFileSelection(e.target.files[0], "document"); }); // Handle image file selection imageUpload.addEventListener("change", (e) => { handleFileSelection(e.target.files[0], "image"); }); function handleFileSelection(file, type) { if (!file) return; const validDocTypes = [ 'application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ]; const validImageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; const isValid = type === "document" ? validDocTypes.includes(file.type) : validImageTypes.includes(file.type); if (!isValid) { alert(`Please select a valid ${type === "document" ? "document (PDF, DOCX, PPTX, XLSX)" : "image (JPEG, PNG, GIF, WEBP)"}`); if (type === "document") fileUpload.value = ''; else imageUpload.value = ''; return; } selectedFile = file; if (filePreviewBubble) filePreviewBubble.remove(); filePreviewBubble = document.createElement("div"); filePreviewBubble.className = "file-preview-bubble bubble right"; filePreviewBubble.textContent = `${type === "document" ? "📎" : "🖼️"} Selected: ${file.name}`; convo.appendChild(filePreviewBubble); convo.scrollTop = convo.scrollHeight; } function createMessageBubble(text, sender = "You", audioSrc = null, fileName = null) { const bubble = document.createElement("div"); bubble.className = `bubble ${sender === "You" ? "right" : "left"}`; const label = document.createElement("div"); label.className = "label"; label.innerText = sender; const message = document.createElement("div"); message.className = "text"; message.style.whiteSpace = "pre-wrap"; if (sender === "You") { let fileLine = fileName ? `📎 Selected file: ${fileName}\n` : ""; message.innerText = `${fileLine}❓ ${text}`; } else { message.style.display = "flex"; message.style.justifyContent = "space-between"; message.style.alignItems = "center"; const msgSpan = document.createElement("span"); msgSpan.innerText = text; message.appendChild(msgSpan); if (audioSrc) { const icon = document.createElement("i"); icon.className = "fa-solid fa-volume-high audio-toggle"; icon.title = "Click to mute"; icon.style.cursor = "pointer"; icon.style.fontSize = "18px"; const audio = new Audio(audioSrc); audio.play(); icon.addEventListener("click", () => { if (audio.muted) { audio.currentTime = 0; audio.muted = false; icon.classList.remove("fa-volume-xmark"); icon.classList.add("fa-volume-high"); icon.title = "Click to mute"; audio.play(); } else { audio.muted = true; icon.classList.remove("fa-volume-high"); icon.classList.add("fa-volume-xmark"); icon.title = "Click to unmute"; } }); message.appendChild(icon); } } bubble.appendChild(label); bubble.appendChild(message); convo.appendChild(bubble); convo.scrollTop = convo.scrollHeight; return bubble; } async function sendMessage() { const question = input.value.trim(); if (!question) return; if (!selectedFile) { alert("Please upload a document or image first."); return; } // Remove file preview bubble if (filePreviewBubble) { filePreviewBubble.remove(); filePreviewBubble = null; } // Create user's message bubble createMessageBubble(question, "You", null, selectedFile.name); // Thinking bubble const thinkingBubble = createMessageBubble("Wait, Let me think 🤔...", "Aidan"); const formData = new FormData(); formData.append("question", question); formData.append("file", selectedFile); try { const response = await fetch("/predict", { method: "POST", body: formData }); const result = await response.json(); const answerText = result.answer || "No response."; const audioSrc = result.audio || null; // Update the thinking bubble const message = thinkingBubble.querySelector(".text"); message.innerText = answerText; if (audioSrc) { const icon = document.createElement("i"); icon.className = "fa-solid fa-volume-high audio-toggle"; icon.title = "Click to mute"; icon.style.cursor = "pointer"; icon.style.fontSize = "18px"; icon.style.marginLeft = "10px"; const audio = new Audio(audioSrc); audio.play(); icon.addEventListener("click", () => { if (audio.muted) { audio.currentTime = 0; audio.muted = false; icon.classList.remove("fa-volume-xmark"); icon.classList.add("fa-volume-high"); icon.title = "Click to mute"; audio.play(); } else { audio.muted = true; icon.classList.remove("fa-volume-high"); icon.classList.add("fa-volume-xmark"); icon.title = "Click to unmute"; } }); message.style.display = "flex"; message.style.justifyContent = "space-between"; message.appendChild(icon); } } catch (err) { const message = thinkingBubble.querySelector(".text"); message.innerText = "⚠️ Aidan had trouble responding."; } input.value = ""; selectedFile = null; } sendBtn.addEventListener("click", sendMessage); input.addEventListener("keydown", (event) => { if (event.key === "Enter") { event.preventDefault(); sendMessage(); } }); });