class HealeoApp {
constructor() {
this.currentPatient = null;
this.currentTab = 'overview';
this.currentFilter = 'all';
this.recommendations = [];
this.approvalHistory = [];
this.patients = [
{
id: 1,
name: "John Doe",
age: 58,
gender: "Male",
avatar: "JD",
conditions: ["Type 2 Diabetes", "Hypertension"],
lastVisit: "2024-01-15",
nextFollowup: "2024-02-01",
adherence: 87,
risk: "Moderate",
status: "active",
carePlan: {
activeConditions: [
{ condition: "Type 2 Diabetes", severity: "moderate", status: "managed" },
{ condition: "Hypertension", severity: "mild", status: "improving" }
],
medications: [
{ name: "Metformin", dosage: "1000mg", frequency: "Twice daily", adherence: 95 },
{ name: "Lisinopril", dosage: "10mg", frequency: "Once daily", adherence: 82 }
],
goals: [
{ text: "Reduce HbA1c to <7%", target: "6 months", progress: 65 },
{ text: "Blood pressure <130/80", target: "3 months", progress: 45 }
],
lifestyle: [
"Mediterranean diet - strict adherence",
"30min walking 5x/week",
"Sleep hygiene protocol"
]
},
labs: [
{ date: "2024-01-15", type: "HbA1c", value: "7.2", unit: "%", trend: "down" },
{ date: "2024-01-15", type: "Blood Pressure", value: "138/85", unit: "mmHg", trend: "stable" }
]
},
{
id: 2,
name: "Sarah Chen",
age: 34,
gender: "Female",
avatar: "SC",
conditions: ["Asthma", "Anxiety Disorder"],
lastVisit: "2024-01-10",
nextFollowup: "2024-01-25",
adherence: 92,
risk: "Low",
status: "stable",
carePlan: {
activeConditions: [
{ condition: "Asthma", severity: "moderate", status: "controlled" },
{ condition: "Anxiety Disorder", severity: "mild", status: "managed" }
],
medications: [
{ name: "Albuterol", dosage: "90mcg", frequency: "As needed", adherence: 88 },
{ name: "Sertraline", dosage: "50mg", frequency: "Once daily", adherence: 98 }
],
goals: [
{ text: "Reduce anxiety attacks to <2/month", target: "Ongoing", progress: 80 },
{ text: "Peak flow >350 L/min", target: "Maintenance", progress: 90 }
],
lifestyle: [
"Daily meditation practice",
"Yoga 3x/week",
"Air quality monitoring"
]
},
labs: [
{ date: "2024-01-10", type: "Spirometry", value: "85%", unit: "predicted", trend: "up" }
]
},
{
id: 3,
name: "Robert Martinez",
age: 67,
gender: "Male",
avatar: "RM",
conditions: ["COPD", "Heart Failure"],
lastVisit: "2024-01-08",
nextFollowup: "2024-01-22",
adherence: 73,
risk: "High",
status: "critical",
carePlan: {
activeConditions: [
{ condition: "COPD", severity: "severe", status: "worsening" },
{ condition: "Heart Failure", severity: "moderate", status: "stable" }
],
medications: [
{ name: "Furosemide", dosage: "40mg", frequency: "Once daily", adherence: 65 },
{ name: "Spironolactone", dosage: "25mg", frequency: "Once daily", adherence: 70 }
],
goals: [
{ text: "Reduce ED visits", target: "6 months", progress: 30 },
{ text: "Weight stability ±2lbs", target: "Monthly", progress: 60 }
],
lifestyle: [
"Sodium restriction <2g/day",
"Daily weight monitoring",
"Pulmonary rehab 2x/week"
]
},
labs: [
{ date: "2024-01-08", type: "BNP", value: "450", unit: "pg/mL", trend: "up" },
{ date: "2024-01-08", type: "eGFR", value: "45", unit: "mL/min", trend: "down" }
]
},
{
id: 4,
name: "Emily Watson",
age: 45,
gender: "Female",
avatar: "EW",
conditions: ["Rheumatoid Arthritis"],
lastVisit: "2024-01-12",
nextFollowup: "2024-02-12",
adherence: 96,
risk: "Low",
status: "review",
carePlan: {
activeConditions: [
{ condition: "Rheumatoid Arthritis", severity: "moderate", status: "improving" }
],
medications: [
{ name: "Methotrexate", dosage: "15mg", frequency: "Weekly", adherence: 96 },
{ name: "Folic Acid", dosage: "1mg", frequency: "Daily", adherence: 100 }
],
goals: [
{ text: "DAS28 <3.2", target: "3 months", progress: 75 },
{ text: "Pain score <4/10", target: "Ongoing", progress: 60 }
],
lifestyle: [
"Joint protection techniques",
"Aquatic therapy",
"Anti-inflammatory diet"
]
},
labs: [
{ date: "2024-01-12", type: "CRP", value: "8.5", unit: "mg/L", trend: "down" }
]
}
];
this.aiRecommendations = [
{
id: 1,
patientId: 1,
type: "medication",
title: "Dosage Adjustment Suggested",
description: "Increase Metformin to 1500mg based on current HbA1c trending and BMI.",
rationale: "Current HbA1c of 7.2% suggests suboptimal glycemic control. Patient BMI 32 indicates insulin resistance.",
confidence: 92,
action: "Adjust prescription",
timestamp: "10 mins ago"
},
{
id: 2,
patientId: 1,
type: "followup",
title: "Follow-up Timeline Update",
description: "Move next visit from 2/1 to 1/28 for earlier intervention.",
rationale: "Recent lab trends show glucose variability. Earlier assessment recommended.",
confidence: 87,
action: "Reschedule visit",
timestamp: "15 mins ago"
},
{
id: 3,
patientId: 1,
type: "monitoring",
title: "Add Continuous Glucose Monitor",
description: "Recommend CGM for 2 weeks to assess glycemic patterns.",
rationale: "Identifying fasting vs post-prandial spikes will optimize medication timing.",
confidence: 95,
action: "Order device",
timestamp: "20 mins ago"
}
];
this.timeline = [
{ date: "2024-01-15", type: "visit", title: "Routine Visit", description: "HbA1c discussed, adherence reviewed", icon: "stethoscope" },
{ date: "2024-01-10", type: "medication", title: "Medication Refill", description: "Metformin 90-day supply issued", icon: "pill" },
{ date: "2024-01-05", type: "lab", title: "Lab Results", description: "HbA1c: 7.2% (down from 7.8%)", icon: "flask-conical", highlight: true },
{ date: "2023-12-20", type: "therapy", title: "Nutritionist Consult", description: "Mediterranean diet counseling", icon: "apple" },
{ date: "2023-12-01", type: "visit", title: "Emergency Visit", description: "Hypoglycemic episode resolved", icon: "alert-circle", highlight: true }
];
this.init();
}
init() {
this.renderPatientList();
this.selectPatient(this.patients[0]);
lucide.createIcons();
}
filterPatients(query) {
const filtered = this.patients.filter(p =>
p.name.toLowerCase().includes(query.toLowerCase()) ||
p.conditions.some(c => c.toLowerCase().includes(query.toLowerCase()))
);
this.renderPatientList(filtered);
}
setFilter(filter) {
this.currentFilter = filter;
document.querySelectorAll('.filter-btn').forEach(btn => {
if(btn.dataset.filter === filter) {
btn.classList.remove('bg-gray-100', 'text-gray-600', 'border-gray-200');
btn.classList.add('bg-blue-100', 'text-blue-700', 'border-blue-200');
} else {
btn.classList.add('bg-gray-100', 'text-gray-600', 'border-gray-200');
btn.classList.remove('bg-blue-100', 'text-blue-700', 'border-blue-200');
}
});
let filtered = this.patients;
if(filter === 'critical') filtered = this.patients.filter(p => p.status === 'critical');
if(filter === 'review') filtered = this.patients.filter(p => p.status === 'review');
this.renderPatientList(filtered);
}
renderPatientList(patients = this.patients) {
const container = document.getElementById('patientList');
container.innerHTML = '';
patients.forEach(patient => {
const card = document.createElement('div');
card.className = `p-3 rounded-lg border cursor-pointer transition-all hover:shadow-md ${this.currentPatient?.id === patient.id ? 'bg-blue-50 border-blue-300 shadow-sm' : 'bg-white border-gray-200 hover:border-blue-300'}`;
card.onclick = () => this.selectPatient(patient);
const statusColor = patient.status === 'critical' ? 'bg-red-100 text-red-700' : patient.status === 'review' ? 'bg-amber-100 text-amber-700' : 'bg-green-100 text-green-700';
card.innerHTML = `
${patient.avatar}
${patient.name}
${patient.status}
${patient.age}y • ${patient.gender}
${patient.conditions.slice(0, 2).map(c => `${c}`).join('')}
${patient.conditions.length > 2 ? `+${patient.conditions.length - 2}` : ''}
${patient.adherence}% adherence
`;
container.appendChild(card);
});
document.getElementById('patientCount').textContent = patients.length;
lucide.createIcons();
}
selectPatient(patient) {
this.currentPatient = patient;
this.renderPatientList();
this.updatePatientHeader();
this.renderTabContent();
this.renderRecommendations();
this.showToast(`Loaded care plan for ${patient.name}`, 'success');
}
updatePatientHeader() {
const p = this.currentPatient;
document.getElementById('patientAvatar').textContent = p.avatar;
document.getElementById('patientName').textContent = p.name;
document.getElementById('patientMeta').textContent = `${p.age} years old • ${p.gender} • MRN: 00${p.id}2345`;
document.getElementById('lastVisit').textContent = p.lastVisit;
document.getElementById('nextFollowup').textContent = p.nextFollowup;
document.getElementById('adherenceScore').textContent = p.adherence + '%';
const riskColors = { 'Low': 'text-green-600', 'Moderate': 'text-yellow-600', 'High': 'text-red-600' };
const riskEl = document.getElementById('riskLevel');
riskEl.textContent = p.risk;
riskEl.className = `text-sm font-semibold ${riskColors[p.risk] || 'text-gray-600'}`;
const tagsContainer = document.getElementById('patientTags');
tagsContainer.innerHTML = p.conditions.map(c =>
`${c}`
).join('');
}
setTab(tab) {
this.currentTab = tab;
document.querySelectorAll('.tab-btn').forEach(btn => {
if(btn.dataset.tab === tab) {
btn.classList.add('border-blue-600', 'text-blue-600', 'active');
btn.classList.remove('border-transparent', 'text-gray-600');
} else {
btn.classList.remove('border-blue-600', 'text-blue-600', 'active');
btn.classList.add('border-transparent', 'text-gray-600');
}
});
this.renderTabContent();
}
renderTabContent() {
const container = document.getElementById('tabContent');
container.innerHTML = '';
if(this.currentTab === 'overview') this.renderOverview(container);
else if(this.currentTab === 'timeline') this.renderTimeline(container);
else if(this.currentTab === 'history') this.renderHistory(container);
else if(this.currentTab === 'labs') this.renderLabs(container);
lucide.createIcons();
}
renderOverview(container) {
const plan = this.currentPatient.carePlan;
const sections = [
{ id: 'conditions', title: 'Active Conditions', icon: 'activity', content: this.renderConditions(plan.activeConditions) },
{ id: 'medications', title: 'Medication Plan', icon: 'pill', content: this.renderMedications(plan.medications) },
{ id: 'goals', title: 'Treatment Goals', icon: 'target', content: this.renderGoals(plan.goals) },
{ id: 'lifestyle', title: 'Lifestyle Recommendations', icon: 'heart', content: this.renderLifestyle(plan.lifestyle) }
];
sections.forEach(section => {
const card = document.createElement('div');
card.className = 'bg-white rounded-xl border border-gray-200 overflow-hidden';
card.innerHTML = `
${section.content}
`;
container.appendChild(card);
});
}
renderConditions(conditions) {
return `
${conditions.map(c => `
${c.condition}
Severity: ${c.severity} • Status: ${c.status}
`).join('')}
`;
}
renderMedications(medications) {
return `
${medications.map(m => `
${m.name}
${m.adherence}% adherence
${m.dosage}
${m.frequency}
`).join('')}
`;
}
renderGoals(goals) {
return `
${goals.map(g => `
`).join('')}
`;
}
renderLifestyle(items) {
return `
${items.map((item, idx) => `
${item}
`).join('')}
`;
}
renderTimeline(container) {
const timelineHtml = `
${this.timeline.map((event, idx) => `
${event.title}
${event.date}
${event.highlight ? '
Key Event' : ''}
${event.description}
`).join('')}
`;
container.innerHTML = timelineHtml;
}
renderHistory(container) {
container.innerHTML = `
Care Plan Revisions
Medication dosage updated
By Dr. Smith • Jan 15, 2024 • 10:30 AM
Metformin: 500mg → 1000mg
AI Recommendation Approved
By Dr. Smith • Jan 14, 2024 • 3:45 PM
Added CGM monitoring for 14 days
`;
}
renderLabs(container) {
const labs = this.currentPatient.labs || [];
container.innerHTML = `
${labs.map(lab => `
${lab.value} ${lab.unit}
${lab.trend === 'up' ? 'Increased' : lab.trend === 'down' ? 'Decreased' : 'Stable'}
`).join('')}
`;
}
renderRecommendations() {
const container = document.getElementById('recommendationList');
const recs = this.aiRecommendations.filter(r => r.patientId === this.currentPatient?.id);
document.getElementById('pendingCount').textContent = recs.length;
if(recs.length === 0) {
container.innerHTML = `
All recommendations reviewed
No pending AI suggestions
`;
lucide.createIcons();
return;
}
container.innerHTML = recs.map(rec => `
${rec.title}
${rec.description}
AI Rationale:
${rec.rationale}
`).join('');
// Update confidence based on pending recommendations
const avgConfidence = recs.reduce((acc, r) => acc + r.confidence, 0) / recs.length;
this.updateConfidence(avgConfidence);
lucide.createIcons();
}
approveRecommendation(id) {
const rec = this.aiRecommendations.find(r => r.id === id);
if(!rec) return;
// Add to history
this.approvalHistory.unshift({
...rec,
status: 'approved',
timestamp: new Date().toLocaleTimeString()
});
// Remove from pending
this.aiRecommendations = this.aiRecommendations.filter(r => r.id !== id);
// Update UI
const card = document.getElementById(`rec-${id}`);
if(card) {
card.style.transform = 'translateX(100%)';
card.style.opacity = '0';
setTimeout(() => this.renderRecommendations(), 300);
}
this.showToast('Recommendation approved and applied to care plan', 'success');
this.updateApprovalHistory();
}
rejectRecommendation(id) {
const rec = this.aiRecommendations.find(r => r.id === id);
if(!rec) return;
this.approvalHistory.unshift({
...rec,
status: 'rejected',
timestamp: new Date().toLocaleTimeString()
});
this.aiRecommendations = this.aiRecommendations.filter(r => r.id !== id);
const card = document.getElementById(`rec-${id}`);
if(card) {
card.style.transform = 'translateX(100%)';
card.style.opacity = '0';
setTimeout(() => this.renderRecommendations(), 300);
}
this.showToast('Recommendation rejected', 'info');
this.updateApprovalHistory();
}
updateApprovalHistory() {
const container = document.getElementById('approvalHistory');
container.innerHTML = this.approvalHistory.slice(0, 3).map(h => `
${h.title}
${h.status}
${h.timestamp}
`).join('');
}
updateConfidence(score) {
document.getElementById('confidenceValue').textContent = Math.round(score) + '%';
document.getElementById('confidenceBar').style.width = score + '%';
document.getElementById('lastUpdated').textContent = 'Just now';
}
regenerateAI() {
const btn = document.getElementById('regenerateBtn');
const originalContent = btn.innerHTML;
btn.innerHTML = 'Analyzing...';
btn.disabled = true;
lucide.createIcons();
// Simulate AI processing
setTimeout(() => {
// Add new random recommendation
const newRec = {
id: Date.now(),
patientId: this.currentPatient.id,
type: 'monitoring',
title: 'New Symptom Pattern Detected',
description: 'AI detected irregular glucose patterns during sleep hours.',
rationale: 'Continuous monitoring data analysis reveals dawn phenomenon requiring adjustment.',
confidence: Math.floor(Math.random() * 15) + 85,
action: 'Review data',
timestamp: 'Just now'
};
this.aiRecommendations.push(newRec);
this.renderRecommendations();
btn.innerHTML = originalContent;
btn.disabled = false;
lucide.createIcons();
this.showToast('AI analysis complete. New recommendations available.', 'success');
}, 2000);
}
saveCarePlan() {
this.showToast('Care plan saved successfully', 'success');
}
addTimelineEvent() {
const today = new Date().toISOString().split('T')[0];
this.timeline.unshift({
date: today,
type: 'note',
title: 'New Clinical Note',
description: 'Added via care plan engine',
icon: 'file-text'
});
this.renderTabContent();
this.showToast('Timeline event added', 'success');
}
requestLab() {
this.showToast('Lab order submitted to LIS', 'info');
}
openAIChat() {
this.showToast('AI Assistant coming soon', 'info');
}
showToast(message, type = 'info') {
const container = document.getElementById('toastContainer');
const toast = document.createElement('div');
const colors = {
success: 'bg-green-500',
error: 'bg-red-500',
info: 'bg-blue-500',
warning: 'bg-amber-500'
};
const icons = {
success: 'check-circle',
error: 'x-circle',
info: 'info',
warning: 'alert-triangle'
};
toast.className = `${colors[type]} text-white px-4 py-3 rounded-lg shadow-lg flex items-center gap-3 min-w-[300px] toast-enter`;
toast.innerHTML = `
`;
container.appendChild(toast);
lucide.createIcons();
setTimeout(() => toast.remove(), 5000);
}
}
// Initialize app
const app = new HealeoApp();