Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>MyPharma AI - Your Study Companion</title> | |
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
<style> | |
/* Indian Traditional Theme CSS */ | |
:root { | |
--saffron: #FF9933; | |
--maroon: #800000; | |
--gold: #FFD700; | |
--peacock-blue: #005F9E; | |
--cream: #FFF8E7; | |
--dark-gold: #B8860B; | |
--light-saffron: #FFE4B5; | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
body { | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
background: linear-gradient(135deg, var(--cream) 0%, var(--light-saffron) 100%); | |
min-height: 100vh; | |
position: relative; | |
overflow-x: hidden; | |
} | |
/* Indian pattern background */ | |
body::before { | |
content: ""; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
opacity: 0.05; | |
background-image: | |
radial-gradient(circle at 25% 25%, var(--saffron) 2px, transparent 2px), | |
radial-gradient(circle at 75% 75%, var(--maroon) 1px, transparent 1px); | |
background-size: 50px 50px; | |
z-index: -1; | |
} | |
.container { | |
max-width: 1200px; | |
margin: 0 auto; | |
padding: 20px; | |
min-height: 100vh; | |
display: flex; | |
flex-direction: column; | |
} | |
/* Header */ | |
.header { | |
background: linear-gradient(135deg, var(--maroon) 0%, var(--peacock-blue) 100%); | |
color: white; | |
padding: 20px; | |
border-radius: 15px; | |
margin-bottom: 20px; | |
box-shadow: 0 8px 25px rgba(0,0,0,0.15); | |
position: relative; | |
overflow: hidden; | |
} | |
.header::before { | |
content: "🕉️"; | |
position: absolute; | |
top: 10px; | |
right: 20px; | |
font-size: 30px; | |
opacity: 0.3; | |
} | |
.header h1 { | |
font-size: 2.5em; | |
margin-bottom: 10px; | |
text-shadow: 2px 2px 4px rgba(0,0,0,0.3); | |
} | |
.header .subtitle { | |
font-size: 1.2em; | |
opacity: 0.9; | |
font-weight: 300; | |
} | |
.quote-container { | |
background: var(--gold); | |
color: var(--maroon); | |
padding: 15px; | |
border-radius: 10px; | |
margin-bottom: 20px; | |
text-align: center; | |
font-style: italic; | |
font-weight: 500; | |
box-shadow: 0 4px 15px rgba(255,215,0,0.3); | |
} | |
/* Chat Container */ | |
.chat-container { | |
flex: 1; | |
background: white; | |
border-radius: 15px; | |
box-shadow: 0 8px 25px rgba(0,0,0,0.1); | |
display: flex; | |
flex-direction: column; | |
overflow: hidden; | |
border: 3px solid var(--gold); | |
} | |
.chat-header { | |
background: linear-gradient(135deg, var(--saffron) 0%, var(--gold) 100%); | |
padding: 15px 20px; | |
color: var(--maroon); | |
font-weight: bold; | |
font-size: 1.1em; | |
} | |
.chat-messages { | |
flex: 1; | |
padding: 20px; | |
overflow-y: auto; | |
max-height: 500px; | |
min-height: 300px; | |
} | |
.message { | |
margin-bottom: 20px; | |
animation: fadeIn 0.3s ease-in; | |
} | |
@keyframes fadeIn { | |
from { opacity: 0; transform: translateY(10px); } | |
to { opacity: 1; transform: translateY(0); } | |
} | |
.message.user { | |
text-align: right; | |
} | |
.message.bot { | |
text-align: left; | |
} | |
.message-bubble { | |
display: inline-block; | |
max-width: 80%; | |
padding: 15px 20px; | |
border-radius: 20px; | |
position: relative; | |
word-wrap: break-word; | |
} | |
.message.user .message-bubble { | |
background: linear-gradient(135deg, var(--peacock-blue) 0%, var(--maroon) 100%); | |
color: white; | |
border-bottom-right-radius: 5px; | |
} | |
.message.bot .message-bubble { | |
background: linear-gradient(135deg, var(--light-saffron) 0%, var(--cream) 100%); | |
color: var(--maroon); | |
border: 2px solid var(--saffron); | |
border-bottom-left-radius: 5px; | |
} | |
.agent-badge { | |
display: inline-block; | |
background: var(--gold); | |
color: var(--maroon); | |
padding: 3px 8px; | |
border-radius: 12px; | |
font-size: 0.8em; | |
font-weight: bold; | |
margin-bottom: 5px; | |
} | |
/* Input Area */ | |
.input-area { | |
padding: 20px; | |
background: var(--cream); | |
border-top: 3px solid var(--gold); | |
} | |
.input-container { | |
display: flex; | |
gap: 10px; | |
align-items: center; | |
} | |
#messageInput { | |
flex: 1; | |
padding: 15px 20px; | |
border: 2px solid var(--saffron); | |
border-radius: 25px; | |
font-size: 16px; | |
outline: none; | |
background: white; | |
transition: all 0.3s ease; | |
} | |
#messageInput:focus { | |
border-color: var(--peacock-blue); | |
box-shadow: 0 0 15px rgba(0,95,158,0.2); | |
} | |
#sendBtn { | |
background: linear-gradient(135deg, var(--saffron) 0%, var(--gold) 100%); | |
color: var(--maroon); | |
border: none; | |
padding: 15px 25px; | |
border-radius: 25px; | |
cursor: pointer; | |
font-weight: bold; | |
transition: all 0.3s ease; | |
font-size: 16px; | |
} | |
#sendBtn:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 5px 15px rgba(255,153,51,0.4); | |
} | |
#sendBtn:disabled { | |
opacity: 0.6; | |
cursor: not-allowed; | |
} | |
/* --- CSS FOR THE LOADING INDICATOR --- */ | |
.loading { | |
display: none; /* Hidden by default */ | |
text-align: center; | |
margin-top: 15px; | |
color: var(--maroon); | |
font-weight: bold; | |
} | |
.loading.show { | |
display: block; /* Visible when .show class is added */ | |
} | |
/* Quick Actions */ | |
.quick-actions { | |
display: flex; | |
gap: 10px; | |
margin-bottom: 15px; | |
flex-wrap: wrap; | |
} | |
.quick-btn { | |
background: white; | |
color: var(--peacock-blue); | |
border: 2px solid var(--peacock-blue); | |
padding: 8px 15px; | |
border-radius: 20px; | |
cursor: pointer; | |
font-size: 14px; | |
transition: all 0.3s ease; | |
} | |
.quick-btn:hover { | |
background: var(--peacock-blue); | |
color: white; | |
} | |
/* Responsive Design */ | |
@media (max-width: 768px) { | |
.container { | |
padding: 10px; | |
} | |
.header h1 { | |
font-size: 2em; | |
} | |
.message-bubble { | |
max-width: 95%; | |
} | |
.input-container { | |
flex-direction: column; | |
} | |
#messageInput { | |
width: 100%; | |
margin-bottom: 10px; | |
} | |
.quick-actions { | |
justify-content: center; | |
} | |
} | |
/* Error Messages */ | |
.error-message { | |
background: #ffebee; | |
color: #c62828; | |
border: 1px solid #ef5350; | |
padding: 10px; | |
border-radius: 5px; | |
margin: 10px 0; | |
} | |
/* Success Messages */ | |
.success-message { | |
background: #e8f5e8; | |
color: #2e7d32; | |
border: 1px solid #4caf50; | |
padding: 10px; | |
border-radius: 5px; | |
margin: 10px 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="header"> | |
<h1>🇮🇳 MyPharma AI</h1> | |
<div class="subtitle">{{ greeting or "नमस्ते! Your Intelligent Pharmacy Study Companion" }}</div> | |
</div> | |
<div class="quote-container" id="quoteContainer"> | |
📿 {{ daily_quote or "विद्या धनं सर्व धन प्रधानम् - Knowledge is the supreme wealth" }} | |
</div> | |
<div class="chat-container"> | |
<div class="chat-header"> | |
💬 Chat with Your AI Study Buddy | |
</div> | |
<div class="chat-messages" id="chatMessages"> | |
<div class="message bot"> | |
<div class="message-bubble"> | |
<div class="agent-badge">🤖 Academic Agent</div> | |
🙏 <strong>Namaste!</strong> I'm your AI study companion for pharmacy subjects!<br><br> | |
I can help you with:<br> | |
📚 <strong>Academic Questions</strong> - Pharmacology, chemistry, biology concepts<br> | |
💊 <strong>Drug Information</strong> - Mechanisms, side effects, interactions<br> | |
❓ <strong>Quiz Generation</strong> - Practice questions and tests<br> | |
🧠 <strong>Memory Aids</strong> - Mnemonics and memory tricks<br> | |
🗣️ <strong>Viva Practice</strong> - Mock interview sessions<br><br> | |
<em>आपका अध्ययन साथी (Your Study Companion)</em> ✨ | |
</div> | |
</div> | |
</div> | |
<div class="input-area"> | |
<div class="quick-actions"> | |
<button class="quick-btn" onclick="populateInput('Explain ')">📊 Explain Topic</button> | |
<button class="quick-btn" onclick="populateInput('What are the side effects of ')">⚗️ Drug Info</button> | |
<button class="quick-btn" onclick="populateInput('Make a quiz on ')">❓ Create Quiz</button> | |
<button class="quick-btn" onclick="populateInput('Mnemonic for ')">🧠 Mnemonics</button> | |
</div> | |
<div class="input-container"> | |
<input type="text" | |
id="messageInput" | |
placeholder="Ask me anything about pharmacy... (e.g., 'Explain the Krebs cycle')" | |
onkeypress="handleKeyPress(event)"> | |
<button id="sendBtn" onclick="sendMessage()">Send 📨</button> | |
</div> | |
<div class="loading" id="loading"> | |
🔄 Processing your query... | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
let isProcessing = false; | |
async function sendMessage() { | |
const input = document.getElementById('messageInput'); | |
const message = input.value.trim(); | |
if (!message || isProcessing) return; | |
addMessage(message, 'user'); | |
input.value = ''; | |
showLoading(true); | |
try { | |
const response = await fetch('/chat', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ query: message }) | |
}); | |
const data = await response.json(); | |
showLoading(false); // Remove loading indicator *before* adding new message | |
if (data.success) { | |
addMessage(data.message, 'bot', data.agent_used); | |
} else { | |
addMessage(`❌ Error: ${data.error || 'Something went wrong'}`, 'bot', 'error'); | |
} | |
} catch (error) { | |
showLoading(false); | |
addMessage(`❌ Connection error: ${error.message}`, 'bot', 'error'); | |
} | |
} | |
function addMessage(text, sender, agentType = '') { | |
const messagesContainer = document.getElementById('chatMessages'); | |
const messageDiv = document.createElement('div'); | |
messageDiv.className = `message ${sender}`; | |
// This dictionary now includes all agent types | |
const agentIcons = { | |
'academic': '📚 Academic Agent', | |
'drug_info': '💊 Drug Info Agent', | |
'quiz_generation': '❓ Quiz Master', | |
'mnemonic_creation': '🧠 Memory Master', | |
'viva_practice': '🗣️ Viva Coach', | |
'error': '⚠️ System' | |
}; | |
const agentBadge = sender === 'bot' ? `<div class="agent-badge">${agentIcons[agentType] || '🤖 AI Assistant'}</div>` : ''; | |
const formattedText = marked.parse(text || 'Sorry, I received an empty response.'); | |
messageDiv.innerHTML = `<div class="message-bubble">${agentBadge}${formattedText}</div>`; | |
messagesContainer.appendChild(messageDiv); | |
messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
} | |
// This is the correct "typing indicator" loading function | |
function showLoading(show) { | |
isProcessing = show; | |
document.getElementById('sendBtn').disabled = show; | |
const loadingElement = document.getElementById('loading'); | |
if (show) { | |
loadingElement.classList.add('show'); | |
} else { | |
loadingElement.classList.remove('show'); | |
} | |
} | |
function handleKeyPress(event) { | |
if (event.key === 'Enter' && !event.shiftKey) { | |
event.preventDefault(); | |
sendMessage(); | |
} | |
} | |
function populateInput(templateText) { | |
const input = document.getElementById('messageInput'); | |
input.value = templateText; | |
input.focus(); | |
} | |
document.addEventListener('DOMContentLoaded', () => { | |
document.getElementById('messageInput').focus(); | |
}); | |
</script> | |
</body> | |
</html> | |
<!--<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>MyPharma AI - Your Study Companion</title> | |
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
<style> | |
/* Indian Traditional Theme CSS */ | |
:root { | |
--saffron: #FF9933; --maroon: #800000; --gold: #FFD700; | |
--peacock-blue: #005F9E; --cream: #FFF8E7; --light-saffron: #FFE4B5; | |
} | |
* { margin: 0; padding: 0; box-sizing: border-box; } | |
body { | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
background: linear-gradient(135deg, var(--cream) 0%, var(--light-saffron) 100%); | |
min-height: 100vh; | |
display: flex; align-items: center; justify-content: center; padding: 20px; | |
} | |
.container { | |
max-width: 800px; margin: 0 auto; width: 100%; | |
height: 90vh; max-height: 850px; display: flex; flex-direction: column; | |
background: white; border-radius: 15px; box-shadow: 0 8px 25px rgba(0,0,0,0.1); | |
border: 3px solid var(--gold); overflow: hidden; | |
} | |
.header { | |
background: linear-gradient(135deg, var(--maroon) 0%, var(--peacock-blue) 100%); | |
color: white; padding: 20px; text-align: center; | |
} | |
.header h1 { font-size: 2em; margin-bottom: 5px; } | |
.header .subtitle { font-size: 1.1em; opacity: 0.9; } | |
.quote-container { | |
background: var(--gold); color: var(--maroon); padding: 15px; | |
border-radius: 10px; margin: 20px; text-align: center; font-style: italic; | |
} | |
.chat-container { flex: 1; display: flex; flex-direction: column; overflow: hidden; } | |
.chat-messages { flex: 1; padding: 20px; overflow-y: auto; } | |
.message { margin-bottom: 20px; display: flex; max-width: 85%; animation: fadeIn 0.3s ease-in; } | |
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } | |
.message.user { margin-left: auto; flex-direction: row-reverse; } | |
.message-bubble { | |
padding: 12px 18px; border-radius: 20px; word-wrap: break-word; line-height: 1.6; | |
} | |
.message.user .message-bubble { | |
background: linear-gradient(135deg, var(--peacock-blue) 0%, var(--maroon) 100%); | |
color: white; border-bottom-right-radius: 5px; | |
} | |
.message.bot .message-bubble { | |
background: linear-gradient(135deg, var(--light-saffron) 0%, var(--cream) 100%); | |
color: var(--maroon); border: 2px solid var(--saffron); border-bottom-left-radius: 5px; | |
} | |
.agent-badge { | |
display: inline-block; background: var(--gold); color: var(--maroon); | |
padding: 3px 8px; border-radius: 12px; font-size: 0.8em; font-weight: bold; margin-bottom: 8px; | |
} | |
.input-area { padding: 20px; background: var(--cream); border-top: 3px solid var(--gold); } | |
.quick-actions { display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap; } | |
.quick-btn { | |
background: white; color: var(--peacock-blue); border: 2px solid var(--peacock-blue); | |
padding: 8px 15px; border-radius: 20px; cursor: pointer; font-size: 14px; transition: all 0.3s ease; | |
} | |
.quick-btn:hover { background: var(--peacock-blue); color: white; } | |
.input-container { display: flex; gap: 10px; align-items: center; } | |
#messageInput { | |
flex: 1; padding: 15px 20px; border: 2px solid var(--saffron); | |
border-radius: 25px; font-size: 16px; outline: none; | |
} | |
#sendBtn { | |
background: linear-gradient(135deg, var(--saffron) 0%, var(--gold) 100%); | |
color: var(--maroon); border: none; padding: 15px 25px; border-radius: 25px; | |
cursor: pointer; font-weight: bold; font-size: 16px; transition: all 0.3s ease; | |
} | |
#sendBtn:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(255,153,51,0.4); } | |
.typing-indicator span { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background-color: #aaa; margin: 0 2px; animation: bounce 1s infinite; } | |
.typing-indicator span:nth-child(2) { animation-delay: 0.1s; } | |
.typing-indicator span:nth-child(3) { animation-delay: 0.2s; } | |
@keyframes bounce { 0%, 60%, 100% { transform: translateY(0); } 30% { transform: translateY(-6px); } } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="header"> | |
<h1>🇮🇳 MyPharma AI</h1> | |
<div class="subtitle">{{ greeting or "नमस्ते! Your Intelligent Pharmacy Study Companion" }}</div> | |
</div> | |
<div class="quote-container" id="quoteContainer"> | |
📿 {{ daily_quote or "विद्या धनं सर्व धन प्रधानम् - Knowledge is the supreme wealth" }} | |
</div> | |
<div class="chat-container"> | |
<div class="chat-messages" id="chatMessages"> | |
<div class="message bot"> | |
<div class="message-bubble"> | |
<div class="agent-badge">🤖 AI Study Buddy</div> | |
🙏 <strong>Namaste!</strong> I have studied the documents in the knowledge library. Ask me anything about your subjects, and I will find the answer for you. | |
</div> | |
</div> | |
</div> | |
<div class="input-area"> | |
<div class="quick-actions"> | |
<button class="quick-btn" onclick="populateInput('Explain ')">📊 Explain Topic</button> | |
<button class="quick-btn" onclick="populateInput('What are the side effects of ')">⚗️ Drug Info</button> | |
<button class="quick-btn" onclick="populateInput('Make a quiz on ')">❓ Create Quiz</button> | |
</div> | |
<div class="input-container"> | |
<input type="text" | |
id="messageInput" | |
placeholder="Ask about your documents..." | |
onkeypress="handleKeyPress(event)"> | |
<button id="sendBtn" onclick="sendMessage()">Send 📨</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
let isProcessing = false; | |
async function sendMessage() { | |
const input = document.getElementById('messageInput'); | |
const message = input.value.trim(); | |
if (!message || isProcessing) return; | |
addMessage(message, 'user'); | |
input.value = ''; | |
showLoading(true); | |
try { | |
const response = await fetch('/chat', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ query: message }) | |
}); | |
const data = await response.json(); | |
showLoading(false); | |
if (data.success) { | |
addMessage(data.message, 'bot', data.agent_used); | |
} else { | |
addMessage(`❌ Error: ${data.error || 'Something went wrong'}`, 'bot', 'error'); | |
} | |
} catch (error) { | |
showLoading(false); | |
addMessage(`❌ Connection error: ${error.message}`, 'bot', 'error'); | |
} | |
} | |
function addMessage(text, sender, agentType = '') { | |
const messagesContainer = document.getElementById('chatMessages'); | |
const messageDiv = document.createElement('div'); | |
messageDiv.className = `message ${sender}`; | |
const agentIcons = { 'academic': '📚 Academic Agent', 'drug_info': '💊 Drug Info Agent', 'quiz_generation': '❓ Quiz Master', 'mnemonic_creation': '🧠 Memory Master', 'viva_practice': '🗣️ Viva Coach', 'error': '⚠️ System' }; | |
const agentBadge = sender === 'bot' ? `<div class="agent-badge">${agentIcons[agentType] || '🤖 AI Assistant'}</div>` : ''; | |
const formattedText = marked.parse(text || 'Sorry, I received an empty response.'); | |
messageDiv.innerHTML = `<div class="message-bubble">${agentBadge}${formattedText}</div>`; | |
messagesContainer.appendChild(messageDiv); | |
messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
} | |
function showLoading(show) { | |
document.getElementById('sendBtn').disabled = show; | |
const existingLoading = document.getElementById('loading-indicator'); | |
if (existingLoading) existingLoading.remove(); | |
if (show) { | |
const messagesContainer = document.getElementById('chatMessages'); | |
const loadingDiv = document.createElement('div'); | |
loadingDiv.className = 'message bot'; | |
loadingDiv.id = 'loading-indicator'; | |
loadingDiv.innerHTML = `<div class="message-bubble"><div class="typing-indicator"><span></span><span></span><span></span></div></div>`; | |
messagesContainer.appendChild(loadingDiv); | |
messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
} | |
} | |
function handleKeyPress(event) { | |
if (event.key === 'Enter' && !event.shiftKey) { | |
event.preventDefault(); | |
sendMessage(); | |
} | |
} | |
function populateInput(templateText) { | |
const input = document.getElementById('messageInput'); | |
input.value = templateText; | |
input.focus(); | |
} | |
async function getNewQuote() { | |
try { | |
const response = await fetch('/quote'); | |
const data = await response.json(); | |
document.getElementById('quoteContainer').innerHTML = `📿 ${data.quote}`; | |
} catch (error) { | |
console.error('Failed to fetch new quote:', error); | |
} | |
} | |
document.addEventListener('DOMContentLoaded', () => { | |
document.getElementById('messageInput').focus(); | |
setInterval(getNewQuote, 5 * 60 * 1000); // Update quote every 5 mins | |
}); | |
</script> | |
old | |
<script> | |
// Global variables | |
let isProcessing = false; | |
// In templates/index.html, inside the <script> tag | |
// --- File Management Functions --- | |
async function uploadFile() { | |
const fileInput = document.getElementById('fileInput'); | |
const file = fileInput.files[0]; | |
if (!file) { | |
addMessage('Please select a file to upload first.', 'bot', 'error'); | |
return; | |
} | |
const formData = new FormData(); | |
formData.append('file', file); | |
showLoading(true); | |
isProcessing = true; | |
try { | |
const response = await fetch('/upload', { | |
method: 'POST', | |
body: formData, | |
}); | |
const data = await response.json(); | |
if (data.success) { | |
addMessage(`✅ ${data.message}`, 'bot', 'academic'); | |
updateFileList(data.files); | |
} else { | |
addMessage(`❌ Upload Error: ${data.error}`, 'bot', 'error'); | |
} | |
} catch (error) { | |
addMessage(`❌ Connection Error: ${error.message}`, 'bot', 'error'); | |
} finally { | |
showLoading(false); | |
isProcessing = false; | |
fileInput.value = ''; // Clear the file input | |
} | |
} | |
function updateFileList(files = []) { | |
const fileListDiv = document.getElementById('fileList'); | |
if (files.length > 0) { | |
let fileLinks = files.map(f => `<span>${f.original_name}</span>`).join(', '); | |
fileListDiv.innerHTML = `<div style="font-size: 0.9em; margin-top: 10px;"><strong>Active Files:</strong> ${fileLinks} <button onclick="clearFiles()" style="margin-left: 10px; background: #800000; color: white; border: none; border-radius: 5px; cursor: pointer; padding: 2px 8px;">Clear All</button></div>`; | |
} else { | |
fileListDiv.innerHTML = ''; | |
} | |
} | |
async function clearFiles() { | |
showLoading(true); | |
isProcessing = true; | |
try { | |
const response = await fetch('/clear_files', { method: 'POST' }); | |
const data = await response.json(); | |
if (data.success) { | |
addMessage('🧹 All uploaded files and sessions have been cleared.', 'bot', 'academic'); | |
updateFileList([]); | |
} else { | |
addMessage(`❌ Error: ${data.error}`, 'bot', 'error'); | |
} | |
} catch (error) { | |
addMessage(`❌ Connection Error: ${error.message}`, 'bot', 'error'); | |
} finally { | |
showLoading(false); | |
isProcessing = false; | |
} | |
} | |
// Update the file list on page load | |
document.addEventListener('DOMContentLoaded', function() { | |
fetch('/files').then(res => res.json()).then(data => { | |
updateFileList(data.files); | |
}); | |
}); | |
// Send message function | |
async function sendMessage() { | |
const input = document.getElementById('messageInput'); | |
const message = input.value.trim(); | |
if (!message || isProcessing) return; | |
// Add user message to chat | |
addMessage(message, 'user'); | |
input.value = ''; | |
// Show loading | |
showLoading(true); | |
isProcessing = true; | |
try { | |
const response = await fetch('/chat', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ query: message }) | |
}); | |
const data = await response.json(); | |
if (data.success) { | |
addMessage(data.message, 'bot', data.agent_used); | |
} else { | |
addMessage(`❌ Error: ${data.error || 'Something went wrong'}`, 'bot', 'error'); | |
} | |
} catch (error) { | |
addMessage(`❌ Connection error: ${error.message}`, 'bot', 'error'); | |
} finally { | |
showLoading(false); | |
isProcessing = false; | |
} | |
} | |
// Add message to chat | |
function addMessage(text, sender, agentType = '') { | |
const messagesContainer = document.getElementById('chatMessages'); | |
const messageDiv = document.createElement('div'); | |
messageDiv.className = `message ${sender}`; | |
let agentBadge = ''; | |
if (sender === 'bot' && agentType) { | |
const agentIcons = { | |
'academic': '📚 Academic Agent', | |
'drug_info': '💊 Drug Info Agent', | |
'quiz_generation': '❓ Quiz Master', | |
'mnemonic_creation': '🧠 Memory Master', | |
'viva_practice': '🗣️ Viva Coach', | |
'error': '⚠️ System' | |
}; | |
agentBadge = `<div class="agent-badge">${agentIcons[agentType] || '🤖 AI Assistant'}</div>`; | |
} | |
// THE FIX: Use marked.parse() to convert markdown to HTML | |
// instead of a simple replace. | |
const formattedText = marked.parse(text || 'Sorry, I received an empty response.'); | |
messageDiv.innerHTML = ` | |
<div class="message-bubble"> | |
${agentBadge} | |
${formattedText} | |
</div> | |
`; | |
messagesContainer.appendChild(messageDiv); | |
messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
} | |
// Show/hide loading | |
function showLoading(show) { | |
const loading = document.getElementById('loading'); | |
const sendBtn = document.getElementById('sendBtn'); | |
loading.classList.toggle('show', show); | |
sendBtn.disabled = show; | |
} | |
// Handle Enter key press | |
function handleKeyPress(event) { | |
if (event.key === 'Enter' && !event.shiftKey) { | |
event.preventDefault(); | |
sendMessage(); | |
} | |
} | |
// Quick message function | |
function populateInput(templateText) { | |
const input = document.getElementById('messageInput'); | |
input.value = templateText; | |
input.focus(); // This handily puts the cursor in the text box for you! | |
} | |
// Get new quote function | |
async function getNewQuote() { | |
try { | |
const response = await fetch('/quote'); | |
const data = await response.json(); | |
document.getElementById('quoteContainer').innerHTML = `📿 ${data.quote}`; | |
} catch (error) { | |
console.error('Failed to fetch new quote:', error); | |
} | |
} | |
// Initialize app | |
document.addEventListener('DOMContentLoaded', function() { | |
// Focus on input | |
document.getElementById('messageInput').focus(); | |
// Get new quote every 5 minutes | |
setInterval(getNewQuote, 5 * 60 * 1000); | |
}); | |
</script> | |
</body> | |
</html>--> |