document.addEventListener("DOMContentLoaded", () => { // --- Element Selectors --- const userInput = document.getElementById("user-input"); const sendButton = document.getElementById("send-button"); const chatHistory = document.getElementById("chat-history"); const menuItems = document.querySelectorAll(".menu-item"); const convoRecord = document.getElementById("convo-record"); // Modal Elements const patientModal = document.getElementById("patient-modal"); const patientForm = document.getElementById("patient-form"); const patientIdInput = document.getElementById("patient-id-input"); // Track session for backend context let currentSessionId = window.activeSessionId || null; let similarSearchActive = false; // --- NEW: Toggle state for similar search // --- NEW: Function to control chat input state --- function setChatInputDisabled(disabled) { if (userInput) { userInput.disabled = disabled; userInput.placeholder = disabled ? "Please start a patient session first..." : "Ask Swift Query AI..."; } if (sendButton) { sendButton.disabled = disabled; sendButton.classList.toggle('bg-gray-400', disabled); sendButton.classList.toggle('bg-primary', !disabled); sendButton.classList.toggle('hover:bg-orange-600', !disabled); } } // --- Feature Handlers (MODIFIED) --- const featureHandlers = { "chat-feature": () => { if (similarSearchActive) { // If similar search was active, turn it off toggleSimilarSearch(document.getElementById('similar-cases-feature')); } if (userInput) userInput.focus(); }, "similar-cases-feature": (event) => { if (!window.activePatientId) { appendMessage("Please start a patient session to find similar cases.", "ai", new Date()); return; } // NEW: Toggle the similar search mode toggleSimilarSearch(event.currentTarget); }, "patient-search-feature": () => { if (patientModal) { patientModal.classList.remove("hidden"); if (patientIdInput) setTimeout(() => patientIdInput.focus(), 100); } }, "clear-chat-feature": () => { const greeting = chatHistory.firstChild; chatHistory.innerHTML = ''; if(greeting) chatHistory.appendChild(greeting); appendMessage("Local chat view cleared.", "ai", new Date()); }, "history-feature": () => { loadHistoryList(); } }; // --- NEW: Toggle function for Similar Search --- function toggleSimilarSearch(buttonElement) { similarSearchActive = !similarSearchActive; if (!userInput || !buttonElement) return; if (similarSearchActive) { userInput.value = "/similar "; userInput.focus(); buttonElement.classList.add("active"); // Add visual indicator appendMessage("**Similar Case Search Activated.**\nPlease describe the symptoms or conditions to find matching cases.", "ai", new Date()); } else { if (userInput.value.startsWith("/similar ")) { userInput.value = ""; } buttonElement.classList.remove("active"); appendMessage("**Similar Case Search Deactivated.**", "ai", new Date()); } } // --- Event Listeners --- menuItems.forEach(item => { if (item.tagName === 'A' && !item.href.includes('logout')) { item.addEventListener("click", (e) => { if (featureHandlers[item.id]) { e.preventDefault(); // Don't deactivate similar search button when it's clicked if (item.id !== 'similar-cases-feature') { const activeItem = document.querySelector(".menu-item.active"); if (activeItem) activeItem.classList.remove("active"); item.classList.add("active"); } featureHandlers[item.id](e); } }); } }); if (patientForm) { patientForm.addEventListener("submit", (e) => { e.preventDefault(); const pid = patientIdInput.value.trim(); if (pid) { if (patientModal) patientModal.classList.add("hidden"); startPatientSession(pid); } }); } // --- Recording Logic --- let mediaRecorder = null; let audioChunks = []; window.startRecording = async function () { if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) return; try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream); audioChunks = []; mediaRecorder.ondataavailable = (event) => { if (event.data.size > 0) audioChunks.push(event.data); }; mediaRecorder.onstop = async () => { const audioBlob = new Blob(audioChunks, { type: 'audio/mp3' }); appendMessage("Processing recording... âŗ", "ai", new Date()); const formData = new FormData(); formData.append("audio", audioBlob, "recording.mp3"); formData.append("patient_id", window.activePatientId); try { const response = await fetch("/doctor/upload_recording", { method: "POST", body: formData }); const result = await response.json(); if (result.success) { appendMessage(`### đī¸ Recording Saved\n\n**Processed Note:**\n${result.data.processed_note}`, "ai", new Date()); } else { appendMessage(`â Recording failed: ${result.error}`, "ai", new Date()); } } catch (err) { console.error(err); appendMessage("â Error uploading recording.", "ai", new Date()); } stream.getTracks().forEach(track => track.stop()); }; mediaRecorder.start(); appendMessage("đī¸ **Recording Started...**", "ai", new Date()); if (convoRecord) convoRecord.checked = true; } catch (err) { console.error("Microphone access denied:", err); if (convoRecord) convoRecord.checked = false; alert("Microphone access is required to record."); } }; window.stopRecording = function () { if (mediaRecorder && mediaRecorder.state !== "inactive") { mediaRecorder.stop(); appendMessage("âšī¸ **Recording Stopped.** Processing...", "ai", new Date()); if (convoRecord) convoRecord.checked = false; } }; if (convoRecord) { convoRecord.addEventListener("change", async () => { if (!window.activePatientId) { convoRecord.checked = false; alert("Please start a patient session before starting a recording."); return; } if (convoRecord.checked) await window.startRecording(); else window.stopRecording(); }); } // --- Core Chat Functions --- if (sendButton) sendButton.addEventListener("click", sendMessage); if (userInput) { userInput.addEventListener("keypress", (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); sendMessage(); } }); userInput.addEventListener("input", function () { this.style.height = "50px"; this.style.height = `${Math.min(this.scrollHeight, 200)}px`; }); } function startPatientSession(patientId) { setChatInputDisabled(true); if (chatHistory) chatHistory.innerHTML = ''; appendMessage(`Starting session for Patient ID: ${patientId}... This may take a moment.`, "ai", new Date()); fetch(`/doctor/start_session/${patientId}`, { method: "POST", headers: { "Content-Type": "application/json" }, }) .then(res => res.json()) .then(data => { if (data.success) { appendMessage(`Session for patient ${data.patient_id} is ready. Reloading dashboard...`, "ai", new Date()); setTimeout(() => window.location.reload(), 500); } else { console.error("Error starting session:", data.error); appendMessage(`Failed to start session: ${data.error}`, "ai", new Date()); setChatInputDisabled(false); } }) .catch(err => { console.error("Network error starting session:", err); appendMessage("A network error occurred while starting the session.", "ai", new Date()); setChatInputDisabled(false); }); } function loadHistoryList() { chatHistory.innerHTML = ''; appendMessage("Loading history sessions...", "ai", new Date()); fetch("/api/history") .then(res => res.json()) .then(data => { chatHistory.innerHTML = ''; if (data.history && data.history.length > 0) { appendMessage("### Select a Past Session to Resume:", "ai", new Date()); const list = document.createElement("div"); list.className = "flex flex-col gap-2 mt-2"; data.history.forEach(item => { const btn = document.createElement("button"); btn.className = "bg-white p-3 rounded-lg shadow-sm hover:bg-orange-50 text-left border border-gray-200 transition-colors w-full group"; btn.innerHTML = `