874 lines
40 KiB
HTML
874 lines
40 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Incident Reporting - 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>Incident Reporting System</h4>
|
|
<h6>Report, track, and analyze safety incidents and near misses</h6>
|
|
</div>
|
|
<div class="page-btn">
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#reportIncidentModal">
|
|
<i class="fa fa-plus"></i> Report Incident
|
|
</button>
|
|
<button type="button" class="btn btn-info" onclick="exportIncidents()">
|
|
<i class="fa fa-download"></i> Export
|
|
</button>
|
|
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#incidentAnalyticsModal">
|
|
<i class="fa fa-chart-bar"></i> Analytics
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Incident Statistics -->
|
|
<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-danger border-danger">
|
|
<i class="fa fa-exclamation-triangle"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ stats.total_incidents|default:47 }}</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Total Incidents (This Month)</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-danger" style="width: 75%"></div>
|
|
</div>
|
|
<small class="text-danger">
|
|
<i class="fa fa-arrow-up"></i> +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-warning border-warning">
|
|
<i class="fa fa-clock"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ stats.pending_review|default:12 }}</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Pending Review</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-warning" style="width: 60%"></div>
|
|
</div>
|
|
<small class="text-warning">
|
|
<i class="fa fa-clock"></i> Avg review time: 2.3 days
|
|
</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-search"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ stats.under_investigation|default:8 }}</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Under Investigation</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-info" style="width: 40%"></div>
|
|
</div>
|
|
<small class="text-info">
|
|
<i class="fa fa-search"></i> Avg investigation: 7.5 days
|
|
</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-check-circle"></i>
|
|
</span>
|
|
<div class="dash-count">
|
|
<h3>{{ stats.resolved|default:27 }}</h3>
|
|
</div>
|
|
</div>
|
|
<div class="dash-widget-info">
|
|
<h6 class="text-muted">Resolved</h6>
|
|
<div class="progress progress-sm">
|
|
<div class="progress-bar bg-success" style="width: 85%"></div>
|
|
</div>
|
|
<small class="text-success">
|
|
<i class="fa fa-check"></i> 85% resolution rate
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Incident Filters and Search -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Incident Management</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
<div class="col-md-3">
|
|
<label class="form-label">Status Filter</label>
|
|
<select class="form-select" id="statusFilter">
|
|
<option value="">All Statuses</option>
|
|
<option value="reported">Reported</option>
|
|
<option value="under_review">Under Review</option>
|
|
<option value="investigating">Investigating</option>
|
|
<option value="resolved">Resolved</option>
|
|
<option value="closed">Closed</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">Severity Filter</label>
|
|
<select class="form-select" id="severityFilter">
|
|
<option value="">All Severities</option>
|
|
<option value="low">Low</option>
|
|
<option value="moderate">Moderate</option>
|
|
<option value="high">High</option>
|
|
<option value="critical">Critical</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">Category Filter</label>
|
|
<select class="form-select" id="categoryFilter">
|
|
<option value="">All Categories</option>
|
|
<option value="medication_error">Medication Error</option>
|
|
<option value="patient_fall">Patient Fall</option>
|
|
<option value="equipment_failure">Equipment Failure</option>
|
|
<option value="infection_control">Infection Control</option>
|
|
<option value="communication">Communication</option>
|
|
<option value="other">Other</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">Search</label>
|
|
<div class="input-group">
|
|
<input type="text" class="form-control" id="searchInput" placeholder="Search incidents...">
|
|
<button class="btn btn-outline-primary" type="button" onclick="searchIncidents()">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Incidents Table -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Recent Incidents</h5>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="refreshIncidents()">
|
|
<i class="fa fa-sync"></i> Refresh
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped" id="incidentsTable">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Date/Time</th>
|
|
<th>Type</th>
|
|
<th>Severity</th>
|
|
<th>Location</th>
|
|
<th>Reporter</th>
|
|
<th>Status</th>
|
|
<th>Assigned To</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>INC-2024-001</strong></td>
|
|
<td>{{ incident.date_reported|default:"Jan 15, 2024 14:30"|date:"M d, Y H:i" }}</td>
|
|
<td><span class="badge bg-danger">Medication Error</span></td>
|
|
<td><span class="badge bg-warning">Moderate</span></td>
|
|
<td>ICU - Room 302</td>
|
|
<td>Dr. Sarah Johnson</td>
|
|
<td><span class="badge bg-info">Under Review</span></td>
|
|
<td>Quality Team</td>
|
|
<td>
|
|
<div class="btn-group">
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewIncident('INC-2024-001')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-warning" onclick="editIncident('INC-2024-001')">
|
|
<i class="fa fa-edit"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-success" onclick="updateStatus('INC-2024-001')">
|
|
<i class="fa fa-check"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>INC-2024-002</strong></td>
|
|
<td>Jan 15, 2024 09:15</td>
|
|
<td><span class="badge bg-warning">Patient Fall</span></td>
|
|
<td><span class="badge bg-danger">High</span></td>
|
|
<td>Ward 3B - Room 315</td>
|
|
<td>Nurse Mary Wilson</td>
|
|
<td><span class="badge bg-warning">Investigating</span></td>
|
|
<td>Risk Manager</td>
|
|
<td>
|
|
<div class="btn-group">
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewIncident('INC-2024-002')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-warning" onclick="editIncident('INC-2024-002')">
|
|
<i class="fa fa-edit"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-success" onclick="updateStatus('INC-2024-002')">
|
|
<i class="fa fa-check"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>INC-2024-003</strong></td>
|
|
<td>Jan 14, 2024 16:45</td>
|
|
<td><span class="badge bg-info">Equipment Failure</span></td>
|
|
<td><span class="badge bg-success">Low</span></td>
|
|
<td>OR 2</td>
|
|
<td>Tech Mike Davis</td>
|
|
<td><span class="badge bg-success">Resolved</span></td>
|
|
<td>Biomedical Eng.</td>
|
|
<td>
|
|
<div class="btn-group">
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewIncident('INC-2024-003')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-secondary" onclick="generateReport('INC-2024-003')">
|
|
<i class="fa fa-file-alt"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>INC-2024-004</strong></td>
|
|
<td>Jan 14, 2024 11:20</td>
|
|
<td><span class="badge bg-secondary">Communication</span></td>
|
|
<td><span class="badge bg-warning">Moderate</span></td>
|
|
<td>Emergency Dept.</td>
|
|
<td>Dr. Robert Chen</td>
|
|
<td><span class="badge bg-primary">Reported</span></td>
|
|
<td>Unassigned</td>
|
|
<td>
|
|
<div class="btn-group">
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewIncident('INC-2024-004')">
|
|
<i class="fa fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-warning" onclick="assignIncident('INC-2024-004')">
|
|
<i class="fa fa-user-plus"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
<nav aria-label="Incidents pagination">
|
|
<ul class="pagination justify-content-center">
|
|
<li class="page-item disabled">
|
|
<a class="page-link" href="#" tabindex="-1">Previous</a>
|
|
</li>
|
|
<li class="page-item active">
|
|
<a class="page-link" href="#">1</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="#">2</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="#">3</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="#">Next</a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Incident Trends -->
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Incident Trends</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<canvas id="incidentTrendsChart" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Incident Categories</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<canvas id="incidentCategoriesChart" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Report Incident Modal -->
|
|
<div class="modal fade" id="reportIncidentModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Report New Incident</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<form id="reportIncidentForm">
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Incident Type *</label>
|
|
<select name="incident_type" class="form-select" required>
|
|
<option value="">Select type...</option>
|
|
<option value="medication_error">Medication Error</option>
|
|
<option value="patient_fall">Patient Fall</option>
|
|
<option value="equipment_failure">Equipment Failure</option>
|
|
<option value="infection_control">Infection Control</option>
|
|
<option value="communication">Communication Issue</option>
|
|
<option value="documentation">Documentation Error</option>
|
|
<option value="security">Security Incident</option>
|
|
<option value="other">Other</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Severity Level *</label>
|
|
<select name="severity" class="form-select" required>
|
|
<option value="">Select severity...</option>
|
|
<option value="low">Low - No harm, minimal impact</option>
|
|
<option value="moderate">Moderate - Minor harm or potential for harm</option>
|
|
<option value="high">High - Significant harm or high potential</option>
|
|
<option value="critical">Critical - Severe harm or death</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Date and Time of Incident *</label>
|
|
<input type="datetime-local" name="incident_datetime" class="form-control" required>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Location *</label>
|
|
<input type="text" name="location" class="form-control"
|
|
placeholder="e.g., ICU Room 302, OR 1, Emergency Dept." required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Patient Involved</label>
|
|
<input type="text" name="patient_id" class="form-control"
|
|
placeholder="Patient MRN (if applicable)">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Staff Involved</label>
|
|
<input type="text" name="staff_involved" class="form-control"
|
|
placeholder="Names or IDs of involved staff">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Incident Description *</label>
|
|
<textarea name="description" class="form-control" rows="4"
|
|
placeholder="Provide a detailed description of what happened..." required></textarea>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Contributing Factors</label>
|
|
<textarea name="contributing_factors" class="form-control" rows="3"
|
|
placeholder="What factors may have contributed to this incident?"></textarea>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Immediate Actions Taken</label>
|
|
<textarea name="immediate_actions" class="form-control" rows="3"
|
|
placeholder="What immediate actions were taken to address the incident?"></textarea>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Witnesses</label>
|
|
<input type="text" name="witnesses" class="form-control"
|
|
placeholder="Names of any witnesses">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Equipment Involved</label>
|
|
<input type="text" name="equipment" class="form-control"
|
|
placeholder="Equipment model/serial numbers">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="anonymous" id="anonymousReport">
|
|
<label class="form-check-label" for="anonymousReport">
|
|
Submit as anonymous report
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="notify_management" id="notifyManagement" checked>
|
|
<label class="form-check-label" for="notifyManagement">
|
|
Notify management immediately (for high/critical severity)
|
|
</label>
|
|
</div>
|
|
</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-danger">Report Incident</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Incident Analytics Modal -->
|
|
<div class="modal fade" id="incidentAnalyticsModal" tabindex="-1">
|
|
<div class="modal-dialog modal-xl">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Incident Analytics Dashboard</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Incidents by Department</h6>
|
|
<canvas id="departmentChart" height="200"></canvas>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Resolution Time Analysis</h6>
|
|
<canvas id="resolutionTimeChart" height="200"></canvas>
|
|
</div>
|
|
</div>
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<h6>Root Cause Analysis Summary</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Root Cause</th>
|
|
<th>Frequency</th>
|
|
<th>Percentage</th>
|
|
<th>Trend</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Communication Breakdown</td>
|
|
<td>15</td>
|
|
<td>32%</td>
|
|
<td><span class="text-danger"><i class="fa fa-arrow-up"></i> +5%</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Inadequate Training</td>
|
|
<td>12</td>
|
|
<td>26%</td>
|
|
<td><span class="text-success"><i class="fa fa-arrow-down"></i> -3%</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>System/Process Issues</td>
|
|
<td>10</td>
|
|
<td>21%</td>
|
|
<td><span class="text-warning"><i class="fa fa-minus"></i> 0%</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Equipment Malfunction</td>
|
|
<td>8</td>
|
|
<td>17%</td>
|
|
<td><span class="text-success"><i class="fa fa-arrow-down"></i> -2%</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Environmental Factors</td>
|
|
<td>2</td>
|
|
<td>4%</td>
|
|
<td><span class="text-warning"><i class="fa fa-minus"></i> 0%</span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Initialize charts
|
|
initializeIncidentTrendsChart();
|
|
initializeIncidentCategoriesChart();
|
|
initializeDepartmentChart();
|
|
initializeResolutionTimeChart();
|
|
|
|
// Set current datetime for incident reporting
|
|
const now = new Date();
|
|
const localDateTime = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString().slice(0, 16);
|
|
document.querySelector('input[name="incident_datetime"]').value = localDateTime;
|
|
|
|
// Form submission handler
|
|
document.getElementById('reportIncidentForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
handleIncidentReport();
|
|
});
|
|
|
|
// Filter change handlers
|
|
document.getElementById('statusFilter').addEventListener('change', applyFilters);
|
|
document.getElementById('severityFilter').addEventListener('change', applyFilters);
|
|
document.getElementById('categoryFilter').addEventListener('change', applyFilters);
|
|
});
|
|
|
|
function initializeIncidentTrendsChart() {
|
|
const ctx = document.getElementById('incidentTrendsChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
|
|
datasets: [{
|
|
label: 'Total Incidents',
|
|
data: [12, 15, 8, 12],
|
|
borderColor: '#dc3545',
|
|
backgroundColor: 'rgba(220, 53, 69, 0.1)',
|
|
tension: 0.4
|
|
}, {
|
|
label: 'High Severity',
|
|
data: [2, 4, 1, 3],
|
|
borderColor: '#fd7e14',
|
|
backgroundColor: 'rgba(253, 126, 20, 0.1)',
|
|
tension: 0.4
|
|
}, {
|
|
label: 'Resolved',
|
|
data: [10, 12, 7, 9],
|
|
borderColor: '#28a745',
|
|
backgroundColor: 'rgba(40, 167, 69, 0.1)',
|
|
tension: 0.4
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function initializeIncidentCategoriesChart() {
|
|
const ctx = document.getElementById('incidentCategoriesChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'doughnut',
|
|
data: {
|
|
labels: ['Medication Error', 'Patient Fall', 'Equipment Failure', 'Communication', 'Other'],
|
|
datasets: [{
|
|
data: [15, 12, 8, 7, 5],
|
|
backgroundColor: ['#dc3545', '#fd7e14', '#ffc107', '#17a2b8', '#6c757d']
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
position: 'bottom'
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function initializeDepartmentChart() {
|
|
const ctx = document.getElementById('departmentChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['ICU', 'Emergency', 'Surgery', 'Medical Ward', 'Pharmacy'],
|
|
datasets: [{
|
|
label: 'Incidents',
|
|
data: [12, 10, 8, 6, 4],
|
|
backgroundColor: '#dc3545'
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function initializeResolutionTimeChart() {
|
|
const ctx = document.getElementById('resolutionTimeChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: ['< 1 day', '1-3 days', '4-7 days', '1-2 weeks', '> 2 weeks'],
|
|
datasets: [{
|
|
label: 'Number of Incidents',
|
|
data: [8, 15, 12, 7, 3],
|
|
backgroundColor: ['#28a745', '#17a2b8', '#ffc107', '#fd7e14', '#dc3545']
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function handleIncidentReport() {
|
|
const formData = new FormData(document.getElementById('reportIncidentForm'));
|
|
|
|
console.log('Reporting incident:', Object.fromEntries(formData));
|
|
|
|
// Close modal
|
|
bootstrap.Modal.getInstance(document.getElementById('reportIncidentModal')).hide();
|
|
|
|
// Reset form
|
|
document.getElementById('reportIncidentForm').reset();
|
|
|
|
// Show success message
|
|
alert('Incident reported successfully! Incident ID: INC-2024-' + Math.floor(Math.random() * 1000).toString().padStart(3, '0'));
|
|
|
|
// Refresh the incidents table
|
|
refreshIncidents();
|
|
}
|
|
|
|
function viewIncident(incidentId) {
|
|
console.log(`Viewing incident: ${incidentId}`);
|
|
alert(`Detailed view for incident ${incidentId} would be displayed here.`);
|
|
}
|
|
|
|
function editIncident(incidentId) {
|
|
console.log(`Editing incident: ${incidentId}`);
|
|
alert(`Edit form for incident ${incidentId} would be displayed here.`);
|
|
}
|
|
|
|
function updateStatus(incidentId) {
|
|
const newStatus = prompt('Enter new status:\n1. Under Review\n2. Investigating\n3. Resolved\n4. Closed\n\nEnter number:');
|
|
|
|
if (newStatus && ['1', '2', '3', '4'].includes(newStatus)) {
|
|
const statuses = {
|
|
'1': 'Under Review',
|
|
'2': 'Investigating',
|
|
'3': 'Resolved',
|
|
'4': 'Closed'
|
|
};
|
|
|
|
console.log(`Updating incident ${incidentId} status to: ${statuses[newStatus]}`);
|
|
alert(`Incident ${incidentId} status updated to: ${statuses[newStatus]}`);
|
|
refreshIncidents();
|
|
}
|
|
}
|
|
|
|
function assignIncident(incidentId) {
|
|
const assignee = prompt('Assign incident to:\n1. Quality Team\n2. Risk Manager\n3. Department Head\n4. Biomedical Engineering\n\nEnter number:');
|
|
|
|
if (assignee && ['1', '2', '3', '4'].includes(assignee)) {
|
|
const assignees = {
|
|
'1': 'Quality Team',
|
|
'2': 'Risk Manager',
|
|
'3': 'Department Head',
|
|
'4': 'Biomedical Engineering'
|
|
};
|
|
|
|
console.log(`Assigning incident ${incidentId} to: ${assignees[assignee]}`);
|
|
alert(`Incident ${incidentId} assigned to: ${assignees[assignee]}`);
|
|
refreshIncidents();
|
|
}
|
|
}
|
|
|
|
function generateReport(incidentId) {
|
|
console.log(`Generating report for incident: ${incidentId}`);
|
|
alert(`Incident report for ${incidentId} is being generated. You will receive an email when ready.`);
|
|
}
|
|
|
|
function searchIncidents() {
|
|
const searchTerm = document.getElementById('searchInput').value;
|
|
console.log(`Searching incidents for: ${searchTerm}`);
|
|
applyFilters();
|
|
}
|
|
|
|
function applyFilters() {
|
|
const status = document.getElementById('statusFilter').value;
|
|
const severity = document.getElementById('severityFilter').value;
|
|
const category = document.getElementById('categoryFilter').value;
|
|
const search = document.getElementById('searchInput').value;
|
|
|
|
console.log('Applying filters:', { status, severity, category, search });
|
|
|
|
// In real implementation, this would filter the table rows
|
|
alert('Filters applied successfully!');
|
|
}
|
|
|
|
function refreshIncidents() {
|
|
console.log('Refreshing incidents table...');
|
|
|
|
// Show loading state
|
|
const refreshBtn = document.querySelector('button[onclick="refreshIncidents()"]');
|
|
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('Incidents table refreshed!');
|
|
}, 1500);
|
|
}
|
|
|
|
function exportIncidents() {
|
|
const format = prompt('Export format:\n1. PDF Report\n2. Excel Spreadsheet\n3. CSV Data\n\nEnter number:');
|
|
|
|
if (format && ['1', '2', '3'].includes(format)) {
|
|
const formats = {
|
|
'1': 'PDF Report',
|
|
'2': 'Excel Spreadsheet',
|
|
'3': 'CSV Data'
|
|
};
|
|
|
|
console.log(`Exporting incidents as: ${formats[format]}`);
|
|
alert(`Incident export started as ${formats[format]}. You will receive an email when ready.`);
|
|
}
|
|
}
|
|
</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;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
|
|
.btn-group {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.btn-group .btn {
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|