import gradio as gr
import logging
from datetime import datetime
import time
from typing import Dict, Any, Optional, Tuple
import json
import os
from PIL import Image
from .enhanced_ai_processor import EnhancedAIProcessor
from .dashboard_database_manager import DashboardDatabaseManager
from .dashboard_api import DashboardIntegrationManager
from .auth import AuthManager
class EnhancedUIComponents:
"""Enhanced UI components with dashboard integration and analytics tracking"""
def __init__(self, auth_manager: AuthManager, database_manager: DashboardDatabaseManager,
ai_processor: EnhancedAIProcessor):
"""Initialize enhanced UI components"""
self.auth_manager = auth_manager
self.database_manager = database_manager
self.ai_processor = ai_processor
self.dashboard_integration = DashboardIntegrationManager(database_manager)
# Start dashboard integration
self.dashboard_integration.start_integration()
# UI styling
self.theme = gr.themes.Soft()
self.custom_css = self._load_custom_css()
# Session tracking
self.current_session = {}
logging.info("✅ Enhanced UI Components initialized with dashboard integration")
def _load_custom_css(self):
"""Load custom CSS for the application"""
return """
/* =================== SMARTHEAL CSS =================== */
/* Global Styling */
body, html {
margin: 0 !important;
padding: 0 !important;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif !important;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important;
color: #1A202C !important;
line-height: 1.6 !important;
}
/* Professional Header with Logo */
.medical-header {
background: linear-gradient(135deg, #3182ce 0%, #2c5aa0 100%) !important;
color: white !important;
padding: 32px 40px !important;
border-radius: 20px 20px 0 0 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
margin-bottom: 0 !important;
box-shadow: 0 10px 40px rgba(49, 130, 206, 0.3) !important;
border: none !important;
position: relative !important;
overflow: hidden !important;
}
.logo {
width: 80px !important;
height: 80px !important;
border-radius: 50% !important;
margin-right: 24px !important;
border: 4px solid rgba(255, 255, 255, 0.3) !important;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2) !important;
background: white !important;
padding: 4px !important;
}
.medical-header h1 {
font-size: 3.5rem !important;
font-weight: 800 !important;
margin: 0 !important;
text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3) !important;
background: linear-gradient(45deg, #ffffff, #f8f9fa) !important;
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent !important;
background-clip: text !important;
filter: drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.3)) !important;
}
.medical-header p {
font-size: 1.3rem !important;
margin: 8px 0 0 0 !important;
opacity: 0.95 !important;
font-weight: 500 !important;
text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2) !important;
}
/* Enhanced Form Styling */
.gr-form {
background: linear-gradient(145deg, #ffffff 0%, #f8f9fa 100%) !important;
border-radius: 20px !important;
padding: 32px !important;
margin: 24px 0 !important;
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.1) !important;
border: 1px solid rgba(229, 62, 62, 0.1) !important;
backdrop-filter: blur(10px) !important;
position: relative !important;
overflow: hidden !important;
}
/* Professional Input Fields */
.gr-textbox, .gr-number {
border-radius: 12px !important;
border: 2px solid #E2E8F0 !important;
background: #FFFFFF !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05) !important;
font-size: 1rem !important;
color: #1A202C !important;
padding: 16px 20px !important;
}
.gr-textbox:focus, .gr-number:focus, .gr-textbox input:focus, .gr-number input:focus {
border-color: #E53E3E !important;
box-shadow: 0 0 0 4px rgba(229, 62, 62, 0.1) !important;
background: #FFFFFF !important;
outline: none !important;
transform: translateY(-1px) !important;
}
/* Enhanced Button Styling */
button.gr-button, button.gr-button-primary {
background: linear-gradient(135deg, #E53E3E 0%, #C53030 100%) !important;
color: #FFFFFF !important;
border: none !important;
border-radius: 12px !important;
font-weight: 700 !important;
padding: 16px 32px !important;
font-size: 1.1rem !important;
letter-spacing: 0.5px !important;
text-align: center !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
box-shadow: 0 4px 16px rgba(229, 62, 62, 0.3) !important;
position: relative !important;
overflow: hidden !important;
text-transform: uppercase !important;
cursor: pointer !important;
}
button.gr-button:hover, button.gr-button-primary:hover {
background: linear-gradient(135deg, #C53030 0%, #9C2A2A 100%) !important;
box-shadow: 0 8px 32px rgba(229, 62, 62, 0.4) !important;
transform: translateY(-3px) !important;
}
/* Professional Status Messages */
.status-success {
background: linear-gradient(135deg, #F0FFF4 0%, #E6FFFA 100%) !important;
border: 2px solid #38A169 !important;
color: #22543D !important;
padding: 20px 24px !important;
border-radius: 16px !important;
font-weight: 600 !important;
margin: 16px 0 !important;
box-shadow: 0 8px 24px rgba(56, 161, 105, 0.2) !important;
backdrop-filter: blur(10px) !important;
}
.status-error {
background: linear-gradient(135deg, #FFF5F5 0%, #FED7D7 100%) !important;
border: 2px solid #E53E3E !important;
color: #742A2A !important;
padding: 20px 24px !important;
border-radius: 16px !important;
font-weight: 600 !important;
margin: 16px 0 !important;
box-shadow: 0 8px 24px rgba(229, 62, 62, 0.2) !important;
backdrop-filter: blur(10px) !important;
}
.status-warning {
background: linear-gradient(135deg, #FFFAF0 0%, #FEEBC8 100%) !important;
border: 2px solid #DD6B20 !important;
color: #9C4221 !important;
padding: 20px 24px !important;
border-radius: 16px !important;
font-weight: 600 !important;
margin: 16px 0 !important;
box-shadow: 0 8px 24px rgba(221, 107, 32, 0.2) !important;
backdrop-filter: blur(10px) !important;
}
/* Image gallery styling for better visualization */
.image-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin: 20px 0;
}
.image-item {
background: #f8f9fa;
border-radius: 12px;
padding: 15px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
text-align: center;
}
.image-item img {
max-width: 100%;
height: auto;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
.image-item h4 {
margin: 15px 0 5px 0;
color: #2d3748;
font-weight: 600;
}
.image-item p {
margin: 0;
color: #666;
font-size: 0.9em;
}
/* Analyze button special styling */
#analyze-btn {
background: linear-gradient(135deg, #1B5CF3 0%, #1E3A8A 100%) !important;
color: #FFFFFF !important;
border: none !important;
border-radius: 8px !important;
font-weight: 700 !important;
padding: 14px 28px !important;
font-size: 1.1rem !important;
letter-spacing: 0.5px !important;
text-align: center !important;
transition: all 0.2s ease-in-out !important;
}
#analyze-btn:hover {
background: linear-gradient(135deg, #174ea6 0%, #123b82 100%) !important;
box-shadow: 0 4px 14px rgba(27, 95, 193, 0.4) !important;
transform: translateY(-2px) !important;
}
/* Responsive design */
@media (max-width: 768px) {
.medical-header {
padding: 16px !important;
text-align: center !important;
}
.medical-header h1 {
font-size: 2rem !important;
}
.logo {
width: 48px !important;
height: 48px !important;
margin-right: 16px !important;
}
.gr-form {
padding: 16px !important;
margin: 8px 0 !important;
}
.image-gallery {
grid-template-columns: 1fr;
}
}
"""
def create_interface(self):
"""Create the enhanced Gradio interface with dashboard integration"""
with gr.Blocks(theme=self.theme, css=self.custom_css, title="SmartHeal AI - Enhanced") as interface:
# Header
gr.HTML("""
🏥 SmartHeal AI - Enhanced Edition
Advanced Wound Care Analysis with Real-time Dashboard Integration
""")
# Integration status display
integration_status = gr.HTML(self._get_integration_status_html())
# Session info
session_info = gr.HTML(self._get_session_info_html())
with gr.Tabs():
# Authentication Tab
with gr.Tab("🔐 Authentication"):
with gr.Row():
with gr.Column():
gr.HTML("""
""")
username_input = gr.Textbox(
label="Username",
placeholder="Enter your username",
interactive=True
)
password_input = gr.Textbox(
label="Password",
type="password",
placeholder="Enter your password",
interactive=True
)
login_btn = gr.Button("Login", variant="primary")
logout_btn = gr.Button("Logout", variant="secondary")
auth_status = gr.HTML(value="Please login to continue
")
# Enhanced Analysis Tab
with gr.Tab("🔬 Wound Analysis"):
with gr.Row():
with gr.Column(scale=1):
gr.HTML("""
""")
# Patient Information
patient_name = gr.Textbox(label="Patient Name", placeholder="Enter patient name")
patient_age = gr.Number(label="Patient Age", value=0, minimum=0, maximum=120)
patient_gender = gr.Dropdown(
label="Gender",
choices=["Male", "Female", "Other"],
value="Male"
)
# Wound Details
gr.HTML("""
""")
wound_location = gr.Textbox(label="Wound Location", placeholder="e.g., Left heel, Right forearm")
wound_duration = gr.Textbox(label="Wound Duration", placeholder="e.g., 2 weeks, 1 month")
pain_level = gr.Slider(label="Pain Level (0-10)", minimum=0, maximum=10, value=0, step=1)
# Clinical Assessment
moisture_level = gr.Dropdown(
label="Moisture Level",
choices=["Dry", "Moist", "Wet", "Macerated"],
value="Moist"
)
infection_signs = gr.Dropdown(
label="Signs of Infection",
choices=["None", "Mild", "Moderate", "Severe"],
value="None"
)
diabetic_status = gr.Dropdown(
label="Diabetic Status",
choices=["No", "Type 1", "Type 2", "Unknown"],
value="No"
)
# Medical History
gr.HTML("""
""")
previous_treatment = gr.Textbox(
label="Previous Treatment",
placeholder="Describe any previous treatments",
lines=2
)
medical_history = gr.Textbox(
label="Medical History",
placeholder="Relevant medical conditions",
lines=2
)
medications = gr.Textbox(
label="Current Medications",
placeholder="List current medications",
lines=2
)
allergies = gr.Textbox(
label="Known Allergies",
placeholder="List any known allergies",
lines=2
)
additional_notes = gr.Textbox(
label="Additional Notes",
placeholder="Any additional relevant information",
lines=3
)
with gr.Column(scale=1):
gr.HTML("""
""")
# Image Upload
wound_image = gr.Image(
label="Wound Image",
type="pil",
height=400
)
# Analysis Controls
analyze_btn = gr.Button("🔍 Analyze Wound", variant="primary", size="lg")
# Processing indicator
processing_status = gr.HTML(visible=False)
# Analysis Metrics
analysis_metrics = gr.HTML(visible=False)
# Results Section
with gr.Row():
with gr.Column():
gr.HTML("""
""")
# Visual Analysis Results
with gr.Row():
detection_image = gr.Image(label="Wound Detection", visible=False)
segmentation_image = gr.Image(label="Wound Segmentation", visible=False)
# Analysis Report
analysis_report = gr.Markdown(visible=False)
# Download Options
with gr.Row():
download_report = gr.File(label="Download Report", visible=False)
download_images = gr.File(label="Download Analysis Images", visible=False)
# Dashboard Integration Tab
with gr.Tab("📊 Dashboard Integration"):
gr.HTML("""
""")
dashboard_status = gr.HTML()
with gr.Row():
refresh_status_btn = gr.Button("🔄 Refresh Status", variant="secondary")
view_analytics_btn = gr.Button("📈 View Analytics", variant="primary")
# Analytics Summary
analytics_summary = gr.HTML()
# Recent Activity
recent_activity = gr.HTML()
# Event Handlers
# Authentication
login_btn.click(
fn=self._handle_login,
inputs=[username_input, password_input],
outputs=[auth_status, session_info]
)
logout_btn.click(
fn=self._handle_logout,
outputs=[auth_status, session_info]
)
# Analysis
analyze_btn.click(
fn=self._start_analysis,
inputs=[],
outputs=[processing_status, analysis_metrics]
).then(
fn=self._perform_enhanced_analysis,
inputs=[
patient_name, patient_age, patient_gender, wound_location, wound_duration,
pain_level, moisture_level, infection_signs, diabetic_status,
previous_treatment, medical_history, medications, allergies,
additional_notes, wound_image
],
outputs=[
analysis_report, detection_image, segmentation_image,
download_report, download_images, processing_status,
analysis_metrics, session_info
]
)
# Dashboard Integration
refresh_status_btn.click(
fn=self._refresh_dashboard_status,
outputs=[dashboard_status, analytics_summary]
)
view_analytics_btn.click(
fn=self._get_analytics_summary,
outputs=[analytics_summary, recent_activity]
)
# Auto-refresh integration status on load
interface.load(
fn=self._refresh_dashboard_status,
outputs=[dashboard_status, analytics_summary]
)
return interface
def _get_integration_status_html(self) -> str:
"""Get HTML for integration status display"""
status = self.dashboard_integration.get_integration_status()
if status['api_running'] and status['database_connected']:
return """
✅ Dashboard Integration Active
API Server: Running | Database: Connected | Real-time Analytics: Enabled
"""
else:
return """
❌ Dashboard Integration Issues
Please check API server and database connection
"""
def _get_session_info_html(self) -> str:
"""Get HTML for session information display"""
if self.current_session:
user_info = self.current_session.get('user_info', {})
return f"""
👤 Active Session
User: {user_info.get('name', 'Unknown')} |
Role: {user_info.get('role', 'Unknown')} |
Session Started: {self.current_session.get('start_time', 'Unknown')}
"""
else:
return """
⚠️ No Active Session
Please login to start tracking your analysis session
"""
def _handle_login(self, username: str, password: str) -> Tuple[str, str]:
"""Handle user login with session tracking"""
try:
if not username or not password:
return (
"❌ Please enter both username and password
",
self._get_session_info_html()
)
# Authenticate user
user_info = self.auth_manager.authenticate_user(username, password)
if user_info:
# Start session tracking
self.current_session = {
'user_info': user_info,
'start_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'session_id': f"session_{int(time.time())}",
'analyses_count': 0
}
return (
f"✅ Welcome, {user_info.get('name', username)}! You are now logged in.
",
self._get_session_info_html()
)
else:
return (
"❌ Invalid username or password
",
self._get_session_info_html()
)
except Exception as e:
logging.error(f"Login error: {e}")
return (
f"❌ Login failed: {str(e)}
",
self._get_session_info_html()
)
def _handle_logout(self) -> Tuple[str, str]:
"""Handle user logout"""
try:
if self.current_session:
# Log session end
session_duration = time.time() - datetime.strptime(
self.current_session['start_time'], '%Y-%m-%d %H:%M:%S'
).timestamp()
session_data = {
'user_id': self.current_session['user_info'].get('id'),
'session_duration': round(session_duration / 60, 2), # Convert to minutes
'analyses_count': self.current_session.get('analyses_count', 0)
}
# Clear session
self.current_session = {}
return (
"👋 You have been logged out successfully
",
self._get_session_info_html()
)
else:
return (
"⚠️ No active session to logout
",
self._get_session_info_html()
)
except Exception as e:
logging.error(f"Logout error: {e}")
return (
f"❌ Logout error: {str(e)}
",
self._get_session_info_html()
)
def _start_analysis(self) -> Tuple[str, str]:
"""Start analysis process with status indicators"""
return (
"""
🔄 Analysis in Progress...
Please wait while we process your wound image and patient data
""",
"""
Analysis Metrics:
Status: Initializing...
Processing Time: 0.0s
Models Loading: ⏳
"""
)
def _perform_enhanced_analysis(self, patient_name: str, patient_age: int, patient_gender: str,
wound_location: str, wound_duration: str, pain_level: int,
moisture_level: str, infection_signs: str, diabetic_status: str,
previous_treatment: str, medical_history: str, medications: str,
allergies: str, additional_notes: str, wound_image) -> Tuple:
"""Perform enhanced analysis with dashboard integration"""
start_time = time.time()
try:
# Check authentication
if not self.current_session:
return (
"❌ **Authentication Required**\n\nPlease login before performing analysis.",
None, None, None, None,
"❌ Authentication required
",
"Please login to continue
",
self._get_session_info_html()
)
# Validate inputs
if not wound_image:
return (
"❌ **Image Required**\n\nPlease upload a wound image for analysis.",
None, None, None, None,
"❌ Wound image required
",
"Please upload an image
",
self._get_session_info_html()
)
if not patient_name.strip():
return (
"❌ **Patient Name Required**\n\nPlease enter the patient's name.",
None, None, None, None,
"❌ Patient name required
",
"Please enter patient name
",
self._get_session_info_html()
)
# Prepare patient information
patient_info = {
'patient_name': patient_name,
'patient_age': patient_age,
'patient_gender': patient_gender,
'wound_location': wound_location,
'wound_duration': wound_duration,
'pain_level': pain_level,
'moisture_level': moisture_level,
'infection_signs': infection_signs,
'diabetic_status': diabetic_status,
'previous_treatment': previous_treatment,
'medical_history': medical_history,
'medications': medications,
'allergies': allergies,
'additional_notes': additional_notes
}
# Save questionnaire response to dashboard database
user_id = self.current_session['user_info'].get('id')
questionnaire_id = self.database_manager.save_questionnaire_response(patient_info, user_id)
if not questionnaire_id:
logging.warning("Failed to save questionnaire response")
# Save wound image
image_id = None
if questionnaire_id:
image_id = self.database_manager.save_wound_image(questionnaire_id, wound_image, "wound_analysis.jpg")
# Perform comprehensive AI analysis
analysis_results = self.ai_processor.perform_comprehensive_analysis(wound_image, patient_info)
processing_time = analysis_results.get('processing_time', 0)
# Save AI analysis results to dashboard database
analysis_data = {
'questionnaire_id': questionnaire_id,
'image_id': image_id,
'analysis_data': analysis_results,
'summary': analysis_results.get('report', '')[:1000], # First 1000 chars as summary
'recommendations': analysis_results.get('report', ''),
'risk_score': analysis_results.get('risk_score', 0),
'processing_time': processing_time,
'model_version': analysis_results.get('model_version', 'v1.0'),
'visual_results': analysis_results.get('visual_results', {})
}
analysis_id = self.database_manager.save_ai_analysis(analysis_data)
# Log analysis session
session_data = {
'user_id': user_id,
'questionnaire_id': questionnaire_id,
'image_id': image_id,
'analysis_id': analysis_id,
'session_duration': processing_time
}
self.dashboard_integration.log_analysis_session(session_data)
# Log bot interaction
interaction_data = {
'patient_id': None, # Would need to get from patients table
'practitioner_id': user_id,
'input_text': f"Wound analysis for {patient_name}",
'output_text': analysis_results.get('report', '')[:500], # First 500 chars
'wound_image_url': f"uploads/wound_analysis_{int(time.time())}.jpg",
'interaction_type': 'wound_analysis'
}
self.dashboard_integration.log_bot_interaction(interaction_data)
# Update session count
self.current_session['analyses_count'] = self.current_session.get('analyses_count', 0) + 1
# Prepare results for display
visual_results = analysis_results.get('visual_results', {})
report = analysis_results.get('report', 'Analysis completed but no report generated.')
# Get analysis images
detection_image = visual_results.get('detection_image_pil')
segmentation_image = visual_results.get('segmentation_image_pil')
# Create downloadable report
report_file = self._create_report_file(analysis_results, patient_info)
# Create metrics display
metrics_html = f"""
Analysis Completed Successfully!
Processing Time: {processing_time}s
Risk Score: {analysis_results.get('risk_score', 0)}/100
Wound Type: {visual_results.get('wound_type', 'Unknown')}
Surface Area: {visual_results.get('surface_area_cm2', 0)} cm²
Model Version: {analysis_results.get('model_version', 'v1.0')}
Dashboard Integration: ✅ Active
"""
success_status = f"""
✅ Analysis Completed Successfully!
Processing Time: {processing_time}s | Risk Score: {analysis_results.get('risk_score', 0)}/100
Results saved to dashboard for real-time analytics
"""
return (
report,
detection_image,
segmentation_image,
report_file,
None, # Images download placeholder
success_status,
metrics_html,
self._get_session_info_html()
)
except Exception as e:
processing_time = time.time() - start_time
error_message = str(e)
logging.error(f"Analysis error: {error_message}")
error_status = f"""
❌ Analysis Failed
Error: {error_message}
Processing Time: {processing_time:.2f}s
"""
error_metrics = f"""
Analysis Error:
Status: Failed
Processing Time: {processing_time:.2f}s
Error: {error_message}
"""
return (
f"❌ **Analysis Failed**\n\n**Error:** {error_message}\n\nPlease check your inputs and try again.",
None, None, None, None,
error_status,
error_metrics,
self._get_session_info_html()
)
def _create_report_file(self, analysis_results: Dict[str, Any], patient_info: Dict[str, Any]) -> str:
"""Create downloadable report file"""
try:
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f"wound_analysis_report_{timestamp}.md"
filepath = os.path.join("uploads", filename)
# Ensure uploads directory exists
os.makedirs("uploads", exist_ok=True)
# Create comprehensive report
report_content = f"""# SmartHeal AI Wound Analysis Report
**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
**Patient:** {patient_info.get('patient_name', 'N/A')}
**Analysis ID:** {timestamp}
## Patient Information
- **Name:** {patient_info.get('patient_name', 'N/A')}
- **Age:** {patient_info.get('patient_age', 'N/A')} years
- **Gender:** {patient_info.get('patient_gender', 'N/A')}
- **Wound Location:** {patient_info.get('wound_location', 'N/A')}
- **Wound Duration:** {patient_info.get('wound_duration', 'N/A')}
- **Pain Level:** {patient_info.get('pain_level', 'N/A')}/10
## Analysis Results
{analysis_results.get('report', 'No report generated')}
## Technical Details
- **Processing Time:** {analysis_results.get('processing_time', 0)}s
- **Risk Score:** {analysis_results.get('risk_score', 0)}/100
- **Model Version:** {analysis_results.get('model_version', 'Unknown')}
- **Analysis Timestamp:** {analysis_results.get('analysis_timestamp', 'Unknown')}
---
*Generated by SmartHeal AI Enhanced Edition with Dashboard Integration*
"""
with open(filepath, 'w', encoding='utf-8') as f:
f.write(report_content)
return filepath
except Exception as e:
logging.error(f"Error creating report file: {e}")
return None
def _refresh_dashboard_status(self) -> Tuple[str, str]:
"""Refresh dashboard integration status"""
try:
status = self.dashboard_integration.get_integration_status()
analytics_data = self.database_manager.get_analytics_data()
if status['api_running'] and status['database_connected']:
status_html = f"""
✅
Dashboard Integration Active
API Server: Running on port 5001
Database: Connected
Last Updated: {status['timestamp']}
🔗 Test API Health
"""
else:
status_html = f"""
❌ Dashboard Integration Issues
API Running: {status['api_running']}
Database Connected: {status['database_connected']}
Last Checked: {status['timestamp']}
"""
analytics_html = f"""
📊 Analytics Summary
Total Analyses: {analytics_data.get('total_analyses', 0)}
Average Processing Time: {analytics_data.get('avg_processing_time', 0)}s
High Risk Cases: {analytics_data.get('high_risk_count', 0)}
Average Risk Score: {analytics_data.get('avg_risk_score', 0)}
Analyses Today: {analytics_data.get('analyses_today', 0)}
"""
return status_html, analytics_html
except Exception as e:
logging.error(f"Error refreshing dashboard status: {e}")
return (
f"❌ Error refreshing status: {str(e)}
",
"❌ Unable to load analytics
"
)
def _get_analytics_summary(self) -> Tuple[str, str]:
"""Get comprehensive analytics summary"""
try:
analytics_data = self.database_manager.get_analytics_data()
interaction_history = self.database_manager.get_interaction_history(10)
# Create detailed analytics HTML
analytics_html = f"""
📈 Comprehensive Analytics
Analysis Statistics:
• Total Analyses: {analytics_data.get('total_analyses', 0)}
• Analyses Today: {analytics_data.get('analyses_today', 0)}
• Analyses This Week: {analytics_data.get('analyses_this_week', 0)}
• Average Processing Time: {analytics_data.get('avg_processing_time', 0)}s
• Average Risk Score: {analytics_data.get('avg_risk_score', 0)}/100
Risk Distribution:
• High Risk Cases: {analytics_data.get('high_risk_count', 0)}
• Unique Questionnaires: {analytics_data.get('unique_questionnaires', 0)}
• Analyses with Images: {analytics_data.get('analyses_with_images', 0)}
"""
# Create recent activity HTML
activity_html = "🕒 Recent Activity
"
if interaction_history:
activity_html += "
"
for interaction in interaction_history[:5]:
timestamp = interaction.get('interacted_at', 'Unknown')
if isinstance(timestamp, str):
try:
timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M')
except:
pass
activity_html += f"""
- {timestamp} - {interaction.get('interaction_type', 'Unknown')}
(Patient: {interaction.get('patient_name', 'Unknown')})
"""
activity_html += "
"
else:
activity_html += "
No recent activity found.
"
activity_html += "
"
return analytics_html, activity_html
except Exception as e:
logging.error(f"Error getting analytics summary: {e}")
return (
f"❌ Error loading analytics: {str(e)}
",
"❌ Unable to load recent activity
"
)