803 lines
36 KiB
HTML
803 lines
36 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Quality Metrics - Quality Management{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="content">
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-header">
|
|
<div class="page-title">
|
|
<h4>Quality Metrics Dashboard</h4>
|
|
<h6>Monitor and analyze healthcare quality indicators and performance metrics</h6>
|
|
</div>
|
|
<div class="page-btn">
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-primary" onclick="refreshMetrics()">
|
|
<i class="fa fa-sync"></i> Refresh
|
|
</button>
|
|
<button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#exportMetricsModal">
|
|
<i class="fa fa-download"></i> Export
|
|
</button>
|
|
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#addMetricModal">
|
|
<i class="fa fa-plus"></i> Add Metric
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Key Performance Indicators -->
|
|
<div class="row">
|
|
<div class="col-xl-3 col-sm-6 col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="dash-widget-header">
|
|
<span class="dash-widget-icon text-primary border-primary">
|
|
<i class="fa fa-heart"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ metrics.patient_satisfaction|default:4.2 }}/5</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Patient Satisfaction</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-primary" style="width: {{ metrics.satisfaction_percentage|default:84 }}%"></div>
|
|
</div>
|
|
<small class="text-success">
|
|
<i class="fa fa-arrow-up"></i> +2.3% from last month
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-sm-6 col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="dash-widget-header">
|
|
<span class="dash-widget-icon text-success border-success">
|
|
<i class="fa fa-shield-alt"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ metrics.safety_score|default:96.8 }}%</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Safety Score</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-success" style="width: {{ metrics.safety_score|default:96.8 }}%"></div>
|
|
</div>
|
|
<small class="text-success">
|
|
<i class="fa fa-arrow-up"></i> +1.2% from last month
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-sm-6 col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="dash-widget-header">
|
|
<span class="dash-widget-icon text-warning border-warning">
|
|
<i class="fa fa-clock"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ metrics.avg_wait_time|default:18 }} min</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Average Wait Time</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-warning" style="width: 65%"></div>
|
|
</div>
|
|
<small class="text-danger">
|
|
<i class="fa fa-arrow-down"></i> -3 min from last month
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-sm-6 col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="dash-widget-header">
|
|
<span class="dash-widget-icon text-info border-info">
|
|
<i class="fa fa-chart-line"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ metrics.quality_index|default:87.5 }}%</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Overall Quality Index</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-info" style="width: {{ metrics.quality_index|default:87.5 }}%"></div>
|
|
</div>
|
|
<small class="text-success">
|
|
<i class="fa fa-arrow-up"></i> +4.1% from last month
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quality Metrics Charts -->
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Quality Trends</h5>
|
|
<div class="card-tools">
|
|
<select class="form-select form-select-sm" id="trendPeriod">
|
|
<option value="7">Last 7 days</option>
|
|
<option value="30" selected>Last 30 days</option>
|
|
<option value="90">Last 90 days</option>
|
|
<option value="365">Last year</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<canvas id="qualityTrendsChart" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Quality Score Distribution</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<canvas id="qualityDistributionChart" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clinical Quality Indicators -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Clinical Quality Indicators</h5>
|
|
<div class="card-tools">
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-sm btn-outline-primary active" data-category="all">All</button>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" data-category="safety">Safety</button>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" data-category="effectiveness">Effectiveness</button>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" data-category="efficiency">Efficiency</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped" id="qualityIndicatorsTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Indicator</th>
|
|
<th>Category</th>
|
|
<th>Current Value</th>
|
|
<th>Target</th>
|
|
<th>Benchmark</th>
|
|
<th>Trend</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr data-category="safety">
|
|
<td>
|
|
<strong>Hospital-Acquired Infection Rate</strong><br>
|
|
<small class="text-muted">Per 1,000 patient days</small>
|
|
</td>
|
|
<td><span class="badge bg-danger">Safety</span></td>
|
|
<td>{{ indicators.hai_rate|default:2.1 }}</td>
|
|
<td>< 2.0</td>
|
|
<td>1.8</td>
|
|
<td>
|
|
<span class="text-warning">
|
|
<i class="fa fa-arrow-up"></i> +0.2
|
|
</span>
|
|
</td>
|
|
<td><span class="badge bg-warning">Needs Attention</span></td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewDetails('hai_rate')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr data-category="safety">
|
|
<td>
|
|
<strong>Medication Error Rate</strong><br>
|
|
<small class="text-muted">Per 1,000 doses</small>
|
|
</td>
|
|
<td><span class="badge bg-danger">Safety</span></td>
|
|
<td>{{ indicators.med_error_rate|default:0.8 }}</td>
|
|
<td>< 1.0</td>
|
|
<td>0.6</td>
|
|
<td>
|
|
<span class="text-success">
|
|
<i class="fa fa-arrow-down"></i> -0.1
|
|
</span>
|
|
</td>
|
|
<td><span class="badge bg-success">On Target</span></td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewDetails('med_error_rate')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr data-category="effectiveness">
|
|
<td>
|
|
<strong>30-Day Readmission Rate</strong><br>
|
|
<small class="text-muted">Percentage of discharges</small>
|
|
</td>
|
|
<td><span class="badge bg-primary">Effectiveness</span></td>
|
|
<td>{{ indicators.readmission_rate|default:8.2 }}%</td>
|
|
<td>< 10%</td>
|
|
<td>7.5%</td>
|
|
<td>
|
|
<span class="text-success">
|
|
<i class="fa fa-arrow-down"></i> -1.1%
|
|
</span>
|
|
</td>
|
|
<td><span class="badge bg-success">Exceeds Target</span></td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewDetails('readmission_rate')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr data-category="effectiveness">
|
|
<td>
|
|
<strong>Mortality Rate</strong><br>
|
|
<small class="text-muted">Risk-adjusted</small>
|
|
</td>
|
|
<td><span class="badge bg-primary">Effectiveness</span></td>
|
|
<td>{{ indicators.mortality_rate|default:1.2 }}%</td>
|
|
<td>< 1.5%</td>
|
|
<td>1.1%</td>
|
|
<td>
|
|
<span class="text-success">
|
|
<i class="fa fa-minus"></i> 0.0
|
|
</span>
|
|
</td>
|
|
<td><span class="badge bg-success">On Target</span></td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewDetails('mortality_rate')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr data-category="efficiency">
|
|
<td>
|
|
<strong>Average Length of Stay</strong><br>
|
|
<small class="text-muted">Days</small>
|
|
</td>
|
|
<td><span class="badge bg-info">Efficiency</span></td>
|
|
<td>{{ indicators.avg_los|default:4.8 }}</td>
|
|
<td>< 5.0</td>
|
|
<td>4.2</td>
|
|
<td>
|
|
<span class="text-success">
|
|
<i class="fa fa-arrow-down"></i> -0.3
|
|
</span>
|
|
</td>
|
|
<td><span class="badge bg-success">On Target</span></td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewDetails('avg_los')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<tr data-category="efficiency">
|
|
<td>
|
|
<strong>Emergency Department Wait Time</strong><br>
|
|
<small class="text-muted">Minutes to provider</small>
|
|
</td>
|
|
<td><span class="badge bg-info">Efficiency</span></td>
|
|
<td>{{ indicators.ed_wait_time|default:32 }}</td>
|
|
<td>< 30</td>
|
|
<td>25</td>
|
|
<td>
|
|
<span class="text-warning">
|
|
<i class="fa fa-arrow-up"></i> +5
|
|
</span>
|
|
</td>
|
|
<td><span class="badge bg-warning">Needs Attention</span></td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewDetails('ed_wait_time')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quality Improvement Initiatives -->
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Active Quality Initiatives</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% for initiative in quality_initiatives %}
|
|
<div class="initiative-item mb-3">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div>
|
|
<h6 class="mb-1">{{ initiative.title }}</h6>
|
|
<p class="text-muted small mb-2">{{ initiative.description|truncatewords:15 }}</p>
|
|
<div class="d-flex align-items-center">
|
|
<span class="badge bg-{{ initiative.status_color }} me-2">{{ initiative.status|title }}</span>
|
|
<small class="text-muted">Due: {{ initiative.due_date|date:"M d, Y" }}</small>
|
|
</div>
|
|
</div>
|
|
<div class="text-end">
|
|
<div class="progress" style="width: 60px; height: 6px;">
|
|
<div class="progress-bar bg-{{ initiative.status_color }}"
|
|
style="width: {{ initiative.progress }}%"></div>
|
|
</div>
|
|
<small class="text-muted">{{ initiative.progress }}%</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<div class="text-center text-muted py-4">
|
|
<i class="fa fa-clipboard-list fa-2x mb-2"></i>
|
|
<p>No active quality initiatives</p>
|
|
<button class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#addInitiativeModal">
|
|
<i class="fa fa-plus"></i> Add Initiative
|
|
</button>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Quality Alerts</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% for alert in quality_alerts %}
|
|
<div class="alert alert-{{ alert.severity }} alert-sm mb-2">
|
|
<div class="d-flex justify-content-between">
|
|
<div>
|
|
<strong>{{ alert.title }}</strong><br>
|
|
<small>{{ alert.message }}</small>
|
|
</div>
|
|
<div class="text-end">
|
|
<small class="text-muted">{{ alert.created_at|timesince }} ago</small><br>
|
|
<button class="btn btn-sm btn-outline-secondary" onclick="dismissAlert({{ alert.id }})">
|
|
<i class="fa fa-times"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<div class="text-center text-muted py-4">
|
|
<i class="fa fa-check-circle fa-2x mb-2 text-success"></i>
|
|
<p>No active quality alerts</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Benchmarking -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Benchmarking Comparison</h5>
|
|
<div class="card-tools">
|
|
<select class="form-select form-select-sm" id="benchmarkType">
|
|
<option value="national">National Average</option>
|
|
<option value="regional">Regional Average</option>
|
|
<option value="peer">Peer Hospitals</option>
|
|
<option value="top_decile">Top 10%</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<canvas id="benchmarkChart" height="200"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Export Metrics Modal -->
|
|
<div class="modal fade" id="exportMetricsModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Export Quality Metrics</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<form id="exportForm">
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Date Range</label>
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<input type="date" name="start_date" class="form-control" required>
|
|
</div>
|
|
<div class="col-6">
|
|
<input type="date" name="end_date" class="form-control" required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Metrics to Include</label>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="metrics" value="all" id="allMetrics" checked>
|
|
<label class="form-check-label" for="allMetrics">All Metrics</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="metrics" value="safety" id="safetyMetrics">
|
|
<label class="form-check-label" for="safetyMetrics">Safety Indicators</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="metrics" value="effectiveness" id="effectivenessMetrics">
|
|
<label class="form-check-label" for="effectivenessMetrics">Effectiveness Indicators</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="metrics" value="efficiency" id="efficiencyMetrics">
|
|
<label class="form-check-label" for="efficiencyMetrics">Efficiency Indicators</label>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Export Format</label>
|
|
<select name="format" class="form-select" required>
|
|
<option value="pdf">PDF Report</option>
|
|
<option value="excel">Excel Spreadsheet</option>
|
|
<option value="csv">CSV Data</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-primary">Export</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Metric Modal -->
|
|
<div class="modal fade" id="addMetricModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Add Quality Metric</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<form id="addMetricForm">
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Metric Name</label>
|
|
<input type="text" name="metric_name" class="form-control" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Category</label>
|
|
<select name="category" class="form-select" required>
|
|
<option value="">Select category...</option>
|
|
<option value="safety">Safety</option>
|
|
<option value="effectiveness">Effectiveness</option>
|
|
<option value="efficiency">Efficiency</option>
|
|
<option value="patient_experience">Patient Experience</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Target Value</label>
|
|
<input type="number" name="target_value" class="form-control" step="0.01" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Unit of Measurement</label>
|
|
<input type="text" name="unit" class="form-control" placeholder="e.g., %, per 1000, days" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Description</label>
|
|
<textarea name="description" class="form-control" rows="3"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-success">Add Metric</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialize charts
|
|
initializeQualityTrendsChart();
|
|
initializeQualityDistributionChart();
|
|
initializeBenchmarkChart();
|
|
|
|
// Category filter functionality
|
|
const categoryButtons = document.querySelectorAll('[data-category]');
|
|
categoryButtons.forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
const category = this.getAttribute('data-category');
|
|
filterIndicators(category);
|
|
|
|
// Update active button
|
|
categoryButtons.forEach(btn => btn.classList.remove('active'));
|
|
this.classList.add('active');
|
|
});
|
|
});
|
|
|
|
// Export form handler
|
|
document.getElementById('exportForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
handleExport();
|
|
});
|
|
|
|
// Add metric form handler
|
|
document.getElementById('addMetricForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
handleAddMetric();
|
|
});
|
|
|
|
// Set default dates for export
|
|
const today = new Date();
|
|
const thirtyDaysAgo = new Date(today.getTime() - (30 * 24 * 60 * 60 * 1000));
|
|
|
|
document.querySelector('input[name="start_date"]').value = thirtyDaysAgo.toISOString().split('T')[0];
|
|
document.querySelector('input[name="end_date"]').value = today.toISOString().split('T')[0];
|
|
});
|
|
|
|
function initializeQualityTrendsChart() {
|
|
const ctx = document.getElementById('qualityTrendsChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
|
|
datasets: [{
|
|
label: 'Patient Satisfaction',
|
|
data: [4.1, 4.0, 4.2, 4.2],
|
|
borderColor: '#007bff',
|
|
backgroundColor: 'rgba(0, 123, 255, 0.1)',
|
|
tension: 0.4
|
|
}, {
|
|
label: 'Safety Score',
|
|
data: [95.5, 96.2, 96.8, 96.8],
|
|
borderColor: '#28a745',
|
|
backgroundColor: 'rgba(40, 167, 69, 0.1)',
|
|
tension: 0.4
|
|
}, {
|
|
label: 'Quality Index',
|
|
data: [85.2, 86.1, 87.0, 87.5],
|
|
borderColor: '#17a2b8',
|
|
backgroundColor: 'rgba(23, 162, 184, 0.1)',
|
|
tension: 0.4
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
y: {
|
|
beginAtZero: false,
|
|
min: 80
|
|
}
|
|
},
|
|
plugins: {
|
|
legend: {
|
|
position: 'top'
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function initializeQualityDistributionChart() {
|
|
const ctx = document.getElementById('qualityDistributionChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'doughnut',
|
|
data: {
|
|
labels: ['Excellent (90-100%)', 'Good (80-89%)', 'Fair (70-79%)', 'Poor (<70%)'],
|
|
datasets: [{
|
|
data: [45, 35, 15, 5],
|
|
backgroundColor: ['#28a745', '#17a2b8', '#ffc107', '#dc3545']
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
position: 'bottom'
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function initializeBenchmarkChart() {
|
|
const ctx = document.getElementById('benchmarkChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'radar',
|
|
data: {
|
|
labels: ['Safety', 'Effectiveness', 'Efficiency', 'Patient Experience', 'Timeliness'],
|
|
datasets: [{
|
|
label: 'Our Hospital',
|
|
data: [96.8, 87.5, 82.3, 84.0, 78.5],
|
|
borderColor: '#007bff',
|
|
backgroundColor: 'rgba(0, 123, 255, 0.2)',
|
|
pointBackgroundColor: '#007bff'
|
|
}, {
|
|
label: 'National Average',
|
|
data: [92.1, 85.2, 79.8, 81.5, 75.2],
|
|
borderColor: '#6c757d',
|
|
backgroundColor: 'rgba(108, 117, 125, 0.2)',
|
|
pointBackgroundColor: '#6c757d'
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
r: {
|
|
beginAtZero: true,
|
|
max: 100
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function filterIndicators(category) {
|
|
const rows = document.querySelectorAll('#qualityIndicatorsTable tbody tr');
|
|
|
|
rows.forEach(row => {
|
|
if (category === 'all' || row.getAttribute('data-category') === category) {
|
|
row.style.display = '';
|
|
} else {
|
|
row.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
function viewDetails(indicator) {
|
|
console.log(`Viewing details for indicator: ${indicator}`);
|
|
alert(`Detailed view for ${indicator} would be displayed here.`);
|
|
}
|
|
|
|
function refreshMetrics() {
|
|
console.log('Refreshing quality metrics...');
|
|
|
|
// Show loading state
|
|
const refreshBtn = document.querySelector('button[onclick="refreshMetrics()"]');
|
|
const originalContent = refreshBtn.innerHTML;
|
|
refreshBtn.innerHTML = '<i class="fa fa-spinner fa-spin"></i> Refreshing...';
|
|
refreshBtn.disabled = true;
|
|
|
|
// Simulate API call
|
|
setTimeout(() => {
|
|
refreshBtn.innerHTML = originalContent;
|
|
refreshBtn.disabled = false;
|
|
alert('Quality metrics refreshed successfully!');
|
|
}, 2000);
|
|
}
|
|
|
|
function handleExport() {
|
|
const formData = new FormData(document.getElementById('exportForm'));
|
|
|
|
console.log('Exporting quality metrics with parameters:', Object.fromEntries(formData));
|
|
|
|
// Close modal
|
|
bootstrap.Modal.getInstance(document.getElementById('exportMetricsModal')).hide();
|
|
|
|
// Simulate export
|
|
alert('Quality metrics export started. You will receive an email when the report is ready.');
|
|
}
|
|
|
|
function handleAddMetric() {
|
|
const formData = new FormData(document.getElementById('addMetricForm'));
|
|
|
|
console.log('Adding new quality metric:', Object.fromEntries(formData));
|
|
|
|
// Close modal
|
|
bootstrap.Modal.getInstance(document.getElementById('addMetricModal')).hide();
|
|
|
|
// Reset form
|
|
document.getElementById('addMetricForm').reset();
|
|
|
|
alert('Quality metric added successfully!');
|
|
}
|
|
|
|
function dismissAlert(alertId) {
|
|
console.log(`Dismissing alert: ${alertId}`);
|
|
|
|
// Find and remove the alert element
|
|
const alertElement = event.target.closest('.alert');
|
|
if (alertElement) {
|
|
alertElement.remove();
|
|
}
|
|
}
|
|
|
|
// Auto-refresh functionality
|
|
setInterval(() => {
|
|
console.log('Auto-refreshing quality metrics...');
|
|
// In real implementation, this would update the metrics without full page reload
|
|
}, 300000); // Refresh every 5 minutes
|
|
</script>
|
|
|
|
<style>
|
|
.dash-widget-header {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.dash-widget-icon {
|
|
width: 60px;
|
|
height: 60px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.5rem;
|
|
margin-right: 1rem;
|
|
border: 2px solid;
|
|
}
|
|
|
|
.dash-count h3 {
|
|
margin: 0;
|
|
font-size: 2rem;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.initiative-item {
|
|
border-left: 3px solid #dee2e6;
|
|
padding-left: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.alert-sm {
|
|
padding: 0.5rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.card-tools {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.progress {
|
|
height: 6px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.dash-widget-header {
|
|
flex-direction: column;
|
|
text-align: center;
|
|
}
|
|
|
|
.dash-widget-icon {
|
|
margin-right: 0;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|