Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>LawChatbot Panel</title> | |
<link rel="stylesheet" href="/static/style.css"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
</head> | |
<body> | |
<div class="chat-container"> | |
<h2>LawChatbot</h2> | |
<div id="chat-box" class="chat-box"></div> | |
<form id="chat-form"> | |
<input type="text" id="user-input" placeholder="Type your legal question..." autocomplete="off" required> | |
<button type="submit">Send</button> | |
</form> | |
</div> | |
<script> | |
const chatForm = document.getElementById('chat-form'); | |
const userInput = document.getElementById('user-input'); | |
const chatBox = document.getElementById('chat-box'); | |
chatForm.addEventListener('submit', async (e) => { | |
e.preventDefault(); | |
const question = userInput.value.trim(); | |
if (!question) return; | |
appendMessage('user', question); | |
userInput.value = ''; | |
appendBotMessage('...'); | |
const response = await fetch('/chat', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ question }) | |
}); | |
const data = await response.json(); | |
// data.answer, data.context (if present) | |
updateBotMessage(data.answer, data.context || []); | |
}); | |
function appendMessage(sender, text) { | |
const msg = document.createElement('div'); | |
msg.className = sender === 'user' ? 'user-msg' : 'bot-msg'; | |
msg.textContent = text; | |
chatBox.appendChild(msg); | |
chatBox.scrollTop = chatBox.scrollHeight; | |
} | |
function appendBotMessage(text) { | |
// Add a placeholder for bot message with icon and context | |
const msg = document.createElement('div'); | |
msg.className = 'bot-msg'; | |
msg.innerHTML = `<span class="bot-answer">${text}</span>`; | |
chatBox.appendChild(msg); | |
chatBox.scrollTop = chatBox.scrollHeight; | |
} | |
function updateBotMessage(answer, contextArr) { | |
// Update the last bot message with answer and icon | |
const lastMsg = chatBox.querySelector('.bot-msg:last-child'); | |
if (!lastMsg) return; | |
lastMsg.innerHTML = `<span class="bot-answer">${answer}</span>`; | |
if (contextArr && contextArr.length > 0) { | |
// Add source icon | |
const icon = document.createElement('span'); | |
icon.className = 'source-icon'; | |
icon.title = 'Show source documents'; | |
icon.innerHTML = ` | |
<svg width="18" height="18" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" style="vertical-align:middle;cursor:pointer;"> | |
<circle cx="10" cy="10" r="9" stroke="#2b6cb0" stroke-width="2" fill="#e3e7ed"/> | |
<rect x="8.5" y="6" width="3" height="6" rx="1.5" fill="#2b6cb0"/> | |
<circle cx="10" cy="14.5" r="1" fill="#2b6cb0"/> | |
</svg> | |
`; | |
icon.onclick = function() { | |
let ctx = lastMsg.querySelector('.context-box'); | |
if (ctx) { | |
ctx.style.display = ctx.style.display === 'none' ? 'block' : 'none'; | |
} else { | |
ctx = document.createElement('div'); | |
ctx.className = 'context-box'; | |
ctx.innerHTML = contextArr.map((c, i) => `<div class='context-doc'><b>Source ${i+1}:</b><br>${c}</div>`).join(''); | |
lastMsg.appendChild(ctx); | |
} | |
}; | |
lastMsg.appendChild(icon); | |
} | |
chatBox.scrollTop = chatBox.scrollHeight; | |
} | |
</script> | |
</body> | |
<style> | |
.source-icon { margin-left: 8px; cursor: pointer; vertical-align: middle; } | |
.context-box { | |
background: #f1f5fa; | |
border: 1px solid #cbd5e1; | |
border-radius: 6px; | |
margin-top: 8px; | |
padding: 10px; | |
font-size: 0.97em; | |
color: #333; | |
display: block; | |
} | |
.context-doc { margin-bottom: 10px; } | |
</style> | |
</html> | |