hospital-management/templates/analytics/metric_definition_list.html
2025-08-12 13:33:25 +03:00

592 lines
29 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Metric Definitions - Hospital 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>Metric Definitions</h4>
<h6>Manage and configure analytics metrics</h6>
</div>
<div class="page-btn">
<a href="{% url 'analytics:metric_definition_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Add Metric
</a>
</div>
</div>
</div>
</div>
<!-- Statistics Cards -->
<div class="row">
<div class="col-lg-3 col-sm-6">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-primary border-primary">
<i class="fas fa-chart-line"></i>
</span>
<div class="dash-count">
<h3>{{ total_metrics|default:"0" }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Total Metrics</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-primary" style="width: 100%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-success border-success">
<i class="fas fa-check-circle"></i>
</span>
<div class="dash-count">
<h3>{{ active_metrics|default:"0" }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Active Metrics</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-success" style="width: {{ active_percentage|default:0 }}%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-warning border-warning">
<i class="fas fa-calculator"></i>
</span>
<div class="dash-count">
<h3>{{ calculated_today|default:"0" }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Calculated Today</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-warning" style="width: 75%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-info border-info">
<i class="fas fa-database"></i>
</span>
<div class="dash-count">
<h3>{{ data_sources_used|default:"0" }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Data Sources</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-info" style="width: 60%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filters and Search -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-filter me-2"></i>Filters
</h5>
<div class="card-tools">
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="clearFilters()">
<i class="fas fa-times me-1"></i>Clear
</button>
</div>
</div>
<div class="card-body">
<form method="get" id="filterForm">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label for="search" class="form-label">Search</label>
<div class="input-group">
<input type="text" class="form-control" id="search" name="search"
value="{{ request.GET.search }}" placeholder="Search metrics...">
<button class="btn btn-outline-secondary" type="submit">
<i class="fas fa-search"></i>
</button>
</div>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label for="category" class="form-label">Category</label>
<select class="form-select" id="category" name="category">
<option value="">All Categories</option>
<option value="clinical" {% if request.GET.category == 'clinical' %}selected{% endif %}>Clinical</option>
<option value="financial" {% if request.GET.category == 'financial' %}selected{% endif %}>Financial</option>
<option value="operational" {% if request.GET.category == 'operational' %}selected{% endif %}>Operational</option>
<option value="quality" {% if request.GET.category == 'quality' %}selected{% endif %}>Quality</option>
<option value="patient_satisfaction" {% if request.GET.category == 'patient_satisfaction' %}selected{% endif %}>Patient Satisfaction</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label for="metric_type" class="form-label">Type</label>
<select class="form-select" id="metric_type" name="metric_type">
<option value="">All Types</option>
<option value="count" {% if request.GET.metric_type == 'count' %}selected{% endif %}>Count</option>
<option value="percentage" {% if request.GET.metric_type == 'percentage' %}selected{% endif %}>Percentage</option>
<option value="average" {% if request.GET.metric_type == 'average' %}selected{% endif %}>Average</option>
<option value="sum" {% if request.GET.metric_type == 'sum' %}selected{% endif %}>Sum</option>
<option value="ratio" {% if request.GET.metric_type == 'ratio' %}selected{% endif %}>Ratio</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label for="status" class="form-label">Status</label>
<select class="form-select" id="status" name="status">
<option value="">All Status</option>
<option value="active" {% if request.GET.status == 'active' %}selected{% endif %}>Active</option>
<option value="inactive" {% if request.GET.status == 'inactive' %}selected{% endif %}>Inactive</option>
<option value="draft" {% if request.GET.status == 'draft' %}selected{% endif %}>Draft</option>
</select>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label for="data_source" class="form-label">Data Source</label>
<select class="form-select" id="data_source" name="data_source">
<option value="">All Sources</option>
{% for source in data_sources %}
<option value="{{ source.id }}" {% if request.GET.data_source == source.id|stringformat:"s" %}selected{% endif %}>
{{ source.name }}
</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button type="submit" class="btn btn-primary me-2">
<i class="fas fa-filter me-1"></i>Apply Filters
</button>
<button type="button" class="btn btn-outline-secondary me-2" onclick="exportMetrics()">
<i class="fas fa-download me-1"></i>Export
</button>
<button type="button" class="btn btn-outline-info" onclick="bulkActions()">
<i class="fas fa-tasks me-1"></i>Bulk Actions
</button>
</div>
</div>
</form>
</div>
</div>
<!-- Metrics List -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-list me-2"></i>Metric Definitions
</h5>
<div class="card-tools">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary btn-sm active" onclick="toggleView('list')">
<i class="fas fa-list"></i>
</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="toggleView('grid')">
<i class="fas fa-th"></i>
</button>
</div>
</div>
</div>
<div class="card-body">
<!-- List View -->
<div id="listView" class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>
<input type="checkbox" id="selectAll" onchange="toggleSelectAll()">
</th>
<th>Metric Name</th>
<th>Category</th>
<th>Type</th>
<th>Data Source</th>
<th>Status</th>
<th>Last Calculated</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for metric in metrics %}
<tr>
<td>
<input type="checkbox" class="metric-checkbox" value="{{ metric.id }}">
</td>
<td>
<div class="metric-info">
<h6 class="mb-1">{{ metric.name }}</h6>
<p class="text-muted mb-0 small">{{ metric.description|truncatechars:50 }}</p>
</div>
</td>
<td>
<span class="badge bg-primary">{{ metric.get_category_display }}</span>
</td>
<td>
<span class="badge bg-info">{{ metric.get_metric_type_display }}</span>
</td>
<td>
<span class="text-muted">{{ metric.data_source.name|default:"N/A" }}</span>
</td>
<td>
{% if metric.status == 'active' %}
<span class="badge bg-success">Active</span>
{% elif metric.status == 'inactive' %}
<span class="badge bg-secondary">Inactive</span>
{% else %}
<span class="badge bg-warning">Draft</span>
{% endif %}
</td>
<td>
{% if metric.last_calculated %}
<span class="text-muted">{{ metric.last_calculated|timesince }} ago</span>
{% else %}
<span class="text-muted">Never</span>
{% endif %}
</td>
<td>
<div class="dropdown">
<button class="btn btn-outline-secondary btn-sm dropdown-toggle" type="button"
data-bs-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="{% url 'analytics:metric_definition_detail' metric.pk %}">
<i class="fas fa-eye me-2"></i>View
</a>
</li>
<li>
<a class="dropdown-item" href="{% url 'analytics:metric_definition_update' metric.pk %}">
<i class="fas fa-edit me-2"></i>Edit
</a>
</li>
<li>
<a class="dropdown-item" href="#" onclick="calculateMetric('{{ metric.id }}')">
<i class="fas fa-calculator me-2"></i>Calculate
</a>
</li>
<li>
<a class="dropdown-item" href="#" onclick="duplicateMetric('{{ metric.id }}')">
<i class="fas fa-copy me-2"></i>Duplicate
</a>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item text-danger" href="{% url 'analytics:metric_definition_delete' metric.pk %}">
<i class="fas fa-trash me-2"></i>Delete
</a>
</li>
</ul>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="8" class="text-center py-4">
<i class="fas fa-chart-line fa-3x text-muted mb-3"></i>
<h6 class="text-muted">No Metrics Found</h6>
<p class="text-muted">Create your first metric definition to get started.</p>
<a href="{% url 'analytics:metric_definition_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Create Metric
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Grid View -->
<div id="gridView" class="row" style="display: none;">
{% for metric in metrics %}
<div class="col-lg-4 col-md-6 mb-4">
<div class="card metric-card">
<div class="card-header d-flex justify-content-between align-items-center">
<div class="metric-status">
{% if metric.status == 'active' %}
<span class="badge bg-success">Active</span>
{% elif metric.status == 'inactive' %}
<span class="badge bg-secondary">Inactive</span>
{% else %}
<span class="badge bg-warning">Draft</span>
{% endif %}
</div>
<div class="dropdown">
<button class="btn btn-outline-secondary btn-sm dropdown-toggle" type="button"
data-bs-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="{% url 'analytics:metric_definition_detail' metric.pk %}">
<i class="fas fa-eye me-2"></i>View
</a>
</li>
<li>
<a class="dropdown-item" href="{% url 'analytics:metric_definition_update' metric.pk %}">
<i class="fas fa-edit me-2"></i>Edit
</a>
</li>
<li>
<a class="dropdown-item" href="#" onclick="calculateMetric('{{ metric.id }}')">
<i class="fas fa-calculator me-2"></i>Calculate
</a>
</li>
</ul>
</div>
</div>
<div class="card-body">
<h6 class="card-title">{{ metric.name }}</h6>
<p class="card-text text-muted small">{{ metric.description|truncatechars:80 }}</p>
<div class="metric-details">
<div class="detail-row">
<span class="detail-label">Category:</span>
<span class="badge bg-primary">{{ metric.get_category_display }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Type:</span>
<span class="badge bg-info">{{ metric.get_metric_type_display }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Source:</span>
<span class="text-muted">{{ metric.data_source.name|default:"N/A" }}</span>
</div>
<div class="detail-row">
<span class="detail-label">Last Calculated:</span>
<span class="text-muted">
{% if metric.last_calculated %}
{{ metric.last_calculated|timesince }} ago
{% else %}
Never
{% endif %}
</span>
</div>
</div>
</div>
<div class="card-footer">
<div class="d-flex justify-content-between">
<a href="{% url 'analytics:metric_definition_detail' metric.pk %}" class="btn btn-outline-primary btn-sm">
<i class="fas fa-eye me-1"></i>View
</a>
<button type="button" class="btn btn-outline-success btn-sm" onclick="calculateMetric('{{ metric.id }}')">
<i class="fas fa-calculator me-1"></i>Calculate
</button>
</div>
</div>
</div>
</div>
{% empty %}
<div class="col-12">
<div class="text-center py-5">
<i class="fas fa-chart-line fa-3x text-muted mb-3"></i>
<h6 class="text-muted">No Metrics Found</h6>
<p class="text-muted">Create your first metric definition to get started.</p>
<a href="{% url 'analytics:metric_definition_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Create Metric
</a>
</div>
</div>
{% endfor %}
</div>
<!-- Pagination -->
{% if is_paginated %}
<nav aria-label="Metrics pagination">
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">First</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">Previous</a>
</li>
{% endif %}
<li class="page-item active">
<span class="page-link">{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
</li>
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">Last</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
</div>
</div>
</div>
<script>
function toggleView(viewType) {
const listView = document.getElementById('listView');
const gridView = document.getElementById('gridView');
const buttons = document.querySelectorAll('.btn-group button');
buttons.forEach(btn => btn.classList.remove('active'));
if (viewType === 'list') {
listView.style.display = 'block';
gridView.style.display = 'none';
buttons[0].classList.add('active');
} else {
listView.style.display = 'none';
gridView.style.display = 'block';
buttons[1].classList.add('active');
}
}
function toggleSelectAll() {
const selectAll = document.getElementById('selectAll');
const checkboxes = document.querySelectorAll('.metric-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = selectAll.checked;
});
}
function clearFilters() {
document.getElementById('filterForm').reset();
window.location.href = window.location.pathname;
}
function exportMetrics() {
const selectedMetrics = Array.from(document.querySelectorAll('.metric-checkbox:checked'))
.map(cb => cb.value);
if (selectedMetrics.length === 0) {
alert('Please select metrics to export');
return;
}
alert(`Exporting ${selectedMetrics.length} metric(s)...`);
}
function bulkActions() {
const selectedMetrics = Array.from(document.querySelectorAll('.metric-checkbox:checked'))
.map(cb => cb.value);
if (selectedMetrics.length === 0) {
alert('Please select metrics for bulk actions');
return;
}
const action = prompt('Choose action:\n1. Activate\n2. Deactivate\n3. Delete\n\nEnter number:');
if (action) {
alert(`Performing bulk action on ${selectedMetrics.length} metric(s)...`);
}
}
function calculateMetric(metricId) {
if (confirm('Calculate this metric now?')) {
alert('Metric calculation started...');
}
}
function duplicateMetric(metricId) {
if (confirm('Create a copy of this metric?')) {
alert('Metric duplicated successfully!');
}
}
// Auto-submit form on filter change
document.querySelectorAll('#filterForm select').forEach(select => {
select.addEventListener('change', function() {
document.getElementById('filterForm').submit();
});
});
</script>
<style>
.metric-card {
transition: transform 0.2s, box-shadow 0.2s;
}
.metric-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.metric-details {
margin-top: 15px;
}
.detail-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.detail-label {
font-size: 0.875rem;
color: #6c757d;
font-weight: 500;
}
.metric-info h6 {
margin-bottom: 5px;
font-weight: 600;
}
@media (max-width: 768px) {
.page-btn {
margin-top: 15px;
}
.card-tools {
margin-top: 15px;
}
.metric-card {
margin-bottom: 20px;
}
.detail-row {
flex-direction: column;
align-items: flex-start;
gap: 5px;
}
}
</style>
{% endblock %}