Spaces:
Sleeping
Sleeping
| <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>--> |