mindfull / mindfull_client.html
IamSamk
Mindfull Gradio Space deploy
27caffe
Raw
History Blame Contribute Delete
17 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mindfull AI Avatar Chatbot</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.chat-container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 800px;
height: 90vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.chat-header {
background: #4a5568;
color: white;
padding: 20px;
text-align: center;
}
.chat-header h1 {
margin-bottom: 5px;
}
.chat-header p {
opacity: 0.8;
font-size: 14px;
}
.status-bar {
background: #f7fafc;
padding: 10px 20px;
border-bottom: 1px solid #e2e8f0;
font-size: 12px;
color: #4a5568;
}
.status-indicator {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 5px;
}
.status-connected {
background: #48bb78;
}
.status-disconnected {
background: #f56565;
}
.chat-messages {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #f8f9fa;
}
.message {
margin-bottom: 20px;
display: flex;
align-items: flex-start;
}
.message.user {
justify-content: flex-end;
}
.message-content {
max-width: 70%;
padding: 15px;
border-radius: 15px;
position: relative;
}
.message.user .message-content {
background: #4299e1;
color: white;
border-bottom-right-radius: 5px;
}
.message.bot .message-content {
background: white;
border: 1px solid #e2e8f0;
border-bottom-left-radius: 5px;
}
.message-meta {
font-size: 11px;
opacity: 0.7;
margin-top: 5px;
}
.emotion-tag {
display: inline-block;
background: #edf2f7;
color: #4a5568;
padding: 2px 8px;
border-radius: 10px;
font-size: 10px;
margin-left: 5px;
}
.media-content {
margin-top: 10px;
}
.audio-player {
width: 100%;
margin-top: 10px;
}
.video-player {
width: 100%;
max-width: 300px;
border-radius: 10px;
margin-top: 10px;
}
.chat-input {
padding: 20px;
background: white;
border-top: 1px solid #e2e8f0;
}
.input-container {
display: flex;
gap: 10px;
align-items: flex-end;
}
.message-input {
flex: 1;
border: 2px solid #e2e8f0;
border-radius: 25px;
padding: 15px 20px;
font-size: 14px;
resize: none;
max-height: 100px;
min-height: 50px;
outline: none;
transition: border-color 0.3s;
}
.message-input:focus {
border-color: #4299e1;
}
.send-button {
background: #4299e1;
color: white;
border: none;
border-radius: 50%;
width: 50px;
height: 50px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s;
}
.send-button:hover:not(:disabled) {
background: #3182ce;
}
.send-button:disabled {
background: #a0aec0;
cursor: not-allowed;
}
.loading {
display: none;
text-align: center;
padding: 20px;
color: #4a5568;
}
.loading.show {
display: block;
}
.spinner {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #e2e8f0;
border-radius: 50%;
border-top-color: #4299e1;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.controls {
display: flex;
gap: 10px;
margin-top: 10px;
flex-wrap: wrap;
}
.control-checkbox {
display: flex;
align-items: center;
gap: 5px;
font-size: 12px;
color: #4a5568;
}
.error-message {
background: #fed7d7;
color: #c53030;
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
font-size: 12px;
}
@media (max-width: 768px) {
.chat-container {
height: 100vh;
border-radius: 0;
}
.message-content {
max-width: 90%;
}
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">
<h1>🛡️ Mindfull</h1>
<p>AI Mental Wellness Assistant for Police Officers</p>
</div>
<div class="status-bar">
<span class="status-indicator status-disconnected" id="statusIndicator"></span>
<span id="statusText">Connecting...</span>
</div>
<div class="chat-messages" id="chatMessages">
<div class="message bot">
<div class="message-content">
<div>🙏 Namaskara! I'm Mindfull, your AI wellness assistant. I'm here to support you with any mental health concerns or stress you might be experiencing. How are you feeling today?</div>
<div class="message-meta">System message</div>
</div>
</div>
</div>
<div class="loading" id="loadingIndicator">
<div class="spinner"></div>
<span>Processing your message...</span>
</div>
<div class="chat-input">
<div class="error-message" id="errorMessage" style="display: none;"></div>
<div class="input-container">
<textarea
id="messageInput"
class="message-input"
placeholder="Share how you're feeling today..."
rows="1"
></textarea>
<button id="sendButton" class="send-button">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
</svg>
</button>
</div>
<div class="controls">
<label class="control-checkbox">
<input type="checkbox" id="enableVideo" checked>
Generate Avatar Video
</label>
<label class="control-checkbox">
<input type="checkbox" id="autoPlay" checked>
Auto-play Audio
</label>
</div>
</div>
</div>
<script>
class MindfullChat {
constructor() {
this.apiUrl = 'http://localhost:5000';
this.sessionId = null;
this.isConnected = false;
this.initializeElements();
this.setupEventListeners();
this.checkConnection();
this.createSession();
}
initializeElements() {
this.messagesContainer = document.getElementById('chatMessages');
this.messageInput = document.getElementById('messageInput');
this.sendButton = document.getElementById('sendButton');
this.loadingIndicator = document.getElementById('loadingIndicator');
this.statusIndicator = document.getElementById('statusIndicator');
this.statusText = document.getElementById('statusText');
this.errorMessage = document.getElementById('errorMessage');
this.enableVideo = document.getElementById('enableVideo');
this.autoPlay = document.getElementById('autoPlay');
}
setupEventListeners() {
this.sendButton.addEventListener('click', () => this.sendMessage());
this.messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
this.sendMessage();
}
});
// Auto-resize textarea
this.messageInput.addEventListener('input', () => {
this.messageInput.style.height = 'auto';
this.messageInput.style.height = this.messageInput.scrollHeight + 'px';
});
}
async checkConnection() {
try {
const response = await fetch(`${this.apiUrl}/health`);
if (response.ok) {
this.setConnectionStatus(true, 'Connected');
} else {
this.setConnectionStatus(false, 'API Error');
}
} catch (error) {
this.setConnectionStatus(false, 'Disconnected');
this.showError('Unable to connect to Mindfull API. Please ensure the server is running.');
}
}
async createSession() {
try {
const response = await fetch(`${this.apiUrl}/session`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
if (response.ok) {
const data = await response.json();
this.sessionId = data.session_id;
console.log('Session created:', this.sessionId);
}
} catch (error) {
console.error('Failed to create session:', error);
}
}
setConnectionStatus(connected, text) {
this.isConnected = connected;
this.statusIndicator.className = `status-indicator ${connected ? 'status-connected' : 'status-disconnected'}`;
this.statusText.textContent = text;
}
showError(message) {
this.errorMessage.textContent = message;
this.errorMessage.style.display = 'block';
setTimeout(() => {
this.errorMessage.style.display = 'none';
}, 5000);
}
addMessage(content, isUser = false, metadata = {}) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${isUser ? 'user' : 'bot'}`;
let metaInfo = '';
if (!isUser) {
const emotion = metadata.emotion ? `<span class="emotion-tag">${metadata.emotion}</span>` : '';
const processingTime = metadata.processingTime ? ` • ${metadata.processingTime}s` : '';
metaInfo = `<div class="message-meta">${new Date().toLocaleTimeString()}${emotion}${processingTime}</div>`;
}
let mediaContent = '';
if (metadata.audioUrl) {
mediaContent += `
<div class="media-content">
<audio controls class="audio-player" ${this.autoPlay.checked ? 'autoplay' : ''}>
<source src="${this.apiUrl}${metadata.audioUrl}" type="audio/wav">
Your browser does not support the audio element.
</audio>
</div>
`;
}
if (metadata.videoUrl) {
mediaContent += `
<div class="media-content">
<video controls class="video-player" ${this.autoPlay.checked ? 'autoplay' : ''}>
<source src="${this.apiUrl}${metadata.videoUrl}" type="video/mp4">
Your browser does not support the video element.
</video>
</div>
`;
}
messageDiv.innerHTML = `
<div class="message-content">
<div>${content}</div>
${metaInfo}
${mediaContent}
</div>
`;
this.messagesContainer.appendChild(messageDiv);
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
}
setLoading(loading) {
this.loadingIndicator.classList.toggle('show', loading);
this.sendButton.disabled = loading;
if (loading) {
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
}
}
async sendMessage() {
const message = this.messageInput.value.trim();
if (!message || !this.isConnected) return;
// Add user message
this.addMessage(message, true);
// Clear input
this.messageInput.value = '';
this.messageInput.style.height = 'auto';
// Show loading
this.setLoading(true);
try {
const response = await fetch(`${this.apiUrl}/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
session_id: this.sessionId,
include_video: this.enableVideo.checked
})
});
if (response.ok) {
const data = await response.json();
// Add bot response
this.addMessage(data.response_text, false, {
emotion: data.emotion_detected,
processingTime: data.processing_time?.toFixed(2),
audioUrl: data.audio_url,
videoUrl: data.video_url
});
if (data.warnings && data.warnings.length > 0) {
console.warn('Warnings:', data.warnings);
}
} else {
const errorData = await response.json();
this.showError(errorData.message || 'Failed to send message');
}
} catch (error) {
console.error('Send message error:', error);
this.showError('Network error. Please try again.');
} finally {
this.setLoading(false);
}
}
}
// Initialize chat when page loads
document.addEventListener('DOMContentLoaded', () => {
new MindfullChat();
});
</script>
</body>
</html>