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

718 lines
30 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}{{ metric.name }} - Metric Definition{% 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.name }}</h4>
<h6>Metric definition details and configuration</h6>
</div>
<div class="page-btn">
<a href="{% url 'analytics:metric_definition_list' %}" class="btn btn-secondary me-2">
<i class="fas fa-arrow-left me-1"></i>Back to Metrics
</a>
<a href="{% url 'analytics:metric_definition_update' metric.pk %}" class="btn btn-primary">
<i class="fas fa-edit me-1"></i>Edit Metric
</a>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Main Content -->
<div class="col-lg-8">
<!-- Metric Overview -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-chart-line me-2"></i>Metric Overview
</h5>
<div class="card-tools">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="calculateMetric()">
<i class="fas fa-calculator me-1"></i>Calculate Now
</button>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-8">
<div class="metric-info">
<h4 class="text-primary">{{ metric.name }}</h4>
<p class="text-muted mb-3">{{ metric.description|default:"No description provided" }}</p>
<div class="row">
<div class="col-sm-6">
<div class="info-item">
<label class="form-label">Category:</label>
<span class="badge bg-primary">{{ metric.get_category_display }}</span>
</div>
</div>
<div class="col-sm-6">
<div class="info-item">
<label class="form-label">Type:</label>
<span class="badge bg-info">{{ metric.get_metric_type_display }}</span>
</div>
</div>
<div class="col-sm-6">
<div class="info-item">
<label class="form-label">Unit:</label>
<span class="text-muted">{{ metric.unit|default:"N/A" }}</span>
</div>
</div>
<div class="col-sm-6">
<div class="info-item">
<label class="form-label">Format:</label>
<span class="text-muted">{{ metric.format|default:"Default" }}</span>
</div>
</div>
<div class="col-sm-6">
<div class="info-item">
<label class="form-label">Data Source:</label>
<span class="text-muted">
{% if metric.data_source %}
<a href="{% url 'analytics:data_source_detail' metric.data_source.pk %}">
{{ metric.data_source.name }}
</a>
{% else %}
Not specified
{% endif %}
</span>
</div>
</div>
<div class="col-sm-6">
<div class="info-item">
<label class="form-label">Calculation Frequency:</label>
<span class="text-muted">{{ metric.get_calculation_frequency_display|default:"Manual" }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="metric-status-card">
<div class="status-header">
<div class="status-icon">
{% if metric.status == 'active' %}
<i class="fas fa-check-circle fa-2x text-success"></i>
{% elif metric.status == 'inactive' %}
<i class="fas fa-pause-circle fa-2x text-secondary"></i>
{% else %}
<i class="fas fa-edit fa-2x text-warning"></i>
{% endif %}
</div>
<h6>
{% if metric.status == 'active' %}
Active
{% elif metric.status == 'inactive' %}
Inactive
{% else %}
Draft
{% endif %}
</h6>
</div>
<div class="status-stats">
<div class="stat-item">
<span class="stat-value">{{ metric.calculation_count|default:"0" }}</span>
<span class="stat-label">Calculations</span>
</div>
<div class="stat-item">
<span class="stat-value">{{ metric.widget_count|default:"0" }}</span>
<span class="stat-label">Widgets</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Formula and Configuration -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-code me-2"></i>Formula & Configuration
</h5>
</div>
<div class="card-body">
<div class="formula-section">
<h6>Calculation Formula:</h6>
{% if metric.formula %}
<div class="formula-display">
<pre class="bg-light p-3 rounded"><code>{{ metric.formula }}</code></pre>
</div>
{% else %}
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle me-2"></i>
No formula defined for this metric.
</div>
{% endif %}
</div>
{% if metric.sql_query %}
<div class="sql-section mt-4">
<h6>SQL Query:</h6>
<div class="sql-display">
<pre class="bg-dark text-light p-3 rounded"><code>{{ metric.sql_query }}</code></pre>
</div>
</div>
{% endif %}
{% if metric.parameters %}
<div class="parameters-section mt-4">
<h6>Parameters:</h6>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Default Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{% for param in metric.parameters %}
<tr>
<td><code>{{ param.name }}</code></td>
<td><span class="badge bg-secondary">{{ param.type }}</span></td>
<td>{{ param.default_value|default:"N/A" }}</td>
<td>{{ param.description|default:"No description" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
</div>
</div>
<!-- Current Value and Trends -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-chart-area me-2"></i>Current Value & Trends
</h5>
<div class="card-tools">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary btn-sm active" onclick="changePeriod('7d')">7D</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="changePeriod('30d')">30D</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="changePeriod('90d')">90D</button>
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<div class="current-value-card">
<div class="value-header">
<h6 class="text-muted">Current Value</h6>
</div>
<div class="value-display">
<h2 class="text-primary">{{ metric.current_value|default:"N/A" }}</h2>
{% if metric.unit %}
<span class="unit">{{ metric.unit }}</span>
{% endif %}
</div>
<div class="value-change">
{% if metric.change_percentage %}
<span class="change-indicator {% if metric.change_percentage > 0 %}text-success{% else %}text-danger{% endif %}">
<i class="fas fa-arrow-{% if metric.change_percentage > 0 %}up{% else %}down{% endif %} me-1"></i>
{{ metric.change_percentage|floatformat:1 }}%
</span>
<span class="text-muted">vs last period</span>
{% endif %}
</div>
</div>
</div>
<div class="col-md-8">
<div class="trend-chart">
<canvas id="trendChart" width="400" height="200"></canvas>
</div>
</div>
</div>
{% if metric.last_calculated %}
<div class="calculation-info mt-3">
<div class="row">
<div class="col-md-6">
<small class="text-muted">
<i class="fas fa-clock me-1"></i>
Last calculated: {{ metric.last_calculated|timesince }} ago
</small>
</div>
<div class="col-md-6 text-end">
<small class="text-muted">
<i class="fas fa-stopwatch me-1"></i>
Calculation time: {{ metric.calculation_duration|default:"N/A" }}
</small>
</div>
</div>
</div>
{% endif %}
</div>
</div>
<!-- Calculation History -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-history me-2"></i>Calculation History
</h5>
</div>
<div class="card-body">
{% if metric.calculation_history %}
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>Date</th>
<th>Value</th>
<th>Status</th>
<th>Duration</th>
<th>Triggered By</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for calculation in metric.calculation_history %}
<tr>
<td>{{ calculation.calculated_at|date:"M d, Y H:i" }}</td>
<td>
<strong>{{ calculation.value }}</strong>
{% if metric.unit %}<span class="text-muted"> {{ metric.unit }}</span>{% endif %}
</td>
<td>
{% if calculation.status == 'success' %}
<span class="badge bg-success">Success</span>
{% elif calculation.status == 'error' %}
<span class="badge bg-danger">Error</span>
{% else %}
<span class="badge bg-warning">Pending</span>
{% endif %}
</td>
<td>{{ calculation.duration|default:"N/A" }}</td>
<td>{{ calculation.triggered_by|default:"System" }}</td>
<td>
<button type="button" class="btn btn-outline-secondary btn-sm"
onclick="viewCalculationDetails('{{ calculation.id }}')">
<i class="fas fa-eye"></i>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="fas fa-history fa-3x text-muted mb-3"></i>
<h6 class="text-muted">No Calculation History</h6>
<p class="text-muted">Calculation history will appear here after the first calculation.</p>
<button type="button" class="btn btn-primary" onclick="calculateMetric()">
<i class="fas fa-calculator me-1"></i>Calculate Now
</button>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Quick Actions -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-tools me-2"></i>Quick Actions
</h5>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button type="button" class="btn btn-primary" onclick="calculateMetric()">
<i class="fas fa-calculator me-1"></i>Calculate Now
</button>
<a href="{% url 'analytics:metric_definition_update' metric.pk %}" class="btn btn-outline-primary">
<i class="fas fa-edit me-1"></i>Edit Metric
</a>
<button type="button" class="btn btn-outline-secondary" onclick="duplicateMetric()">
<i class="fas fa-copy me-1"></i>Duplicate
</button>
<button type="button" class="btn btn-outline-info" onclick="exportData()">
<i class="fas fa-download me-1"></i>Export Data
</button>
<hr>
{% if metric.status == 'active' %}
<button type="button" class="btn btn-outline-warning" onclick="toggleStatus('inactive')">
<i class="fas fa-pause me-1"></i>Deactivate
</button>
{% else %}
<button type="button" class="btn btn-outline-success" onclick="toggleStatus('active')">
<i class="fas fa-play me-1"></i>Activate
</button>
{% endif %}
<a href="{% url 'analytics:metric_definition_delete' metric.pk %}" class="btn btn-outline-danger">
<i class="fas fa-trash me-1"></i>Delete
</a>
</div>
</div>
</div>
<!-- Metric Information -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-info-circle me-2"></i>Metric Information
</h5>
</div>
<div class="card-body">
<div class="metric-details">
<div class="detail-item">
<label class="form-label">Created By:</label>
<span class="detail-value">{{ metric.created_by|default:"System" }}</span>
</div>
<div class="detail-item">
<label class="form-label">Created Date:</label>
<span class="detail-value">{{ metric.created_at|date:"M d, Y H:i" }}</span>
</div>
<div class="detail-item">
<label class="form-label">Last Updated:</label>
<span class="detail-value">{{ metric.updated_at|date:"M d, Y H:i" }}</span>
</div>
<div class="detail-item">
<label class="form-label">Version:</label>
<span class="detail-value">{{ metric.version|default:"1.0" }}</span>
</div>
{% if metric.tags %}
<div class="detail-item">
<label class="form-label">Tags:</label>
<div class="tags-container">
{% for tag in metric.tags %}
<span class="badge bg-secondary me-1">{{ tag }}</span>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Related Widgets -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-chart-bar me-2"></i>Related Widgets
</h5>
</div>
<div class="card-body">
{% if metric.related_widgets %}
<div class="widgets-list">
{% for widget in metric.related_widgets %}
<div class="widget-item">
<div class="widget-info">
<h6 class="mb-1">{{ widget.name }}</h6>
<p class="text-muted mb-0 small">{{ widget.dashboard.name }}</p>
</div>
<a href="{% url 'analytics:dashboard_widget_detail' widget.pk %}" class="btn btn-outline-primary btn-sm">
<i class="fas fa-eye"></i>
</a>
</div>
{% endfor %}
</div>
{% else %}
<div class="text-center py-3">
<i class="fas fa-chart-bar fa-2x text-muted mb-2"></i>
<p class="text-muted mb-0">No widgets using this metric</p>
</div>
{% endif %}
</div>
</div>
<!-- Performance Stats -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-tachometer-alt me-2"></i>Performance
</h5>
</div>
<div class="card-body">
<div class="performance-stats">
<div class="stat-item">
<div class="stat-value">{{ metric.avg_calculation_time|default:"N/A" }}</div>
<div class="stat-label">Avg Calculation Time</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ metric.success_rate|default:"N/A" }}%</div>
<div class="stat-label">Success Rate</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ metric.data_freshness|default:"N/A" }}</div>
<div class="stat-label">Data Freshness</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function calculateMetric() {
if (confirm('Calculate this metric now? This may take some time.')) {
const btn = event.target;
const originalText = btn.innerHTML;
btn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Calculating...';
btn.disabled = true;
setTimeout(() => {
btn.innerHTML = originalText;
btn.disabled = false;
alert('Metric calculated successfully!');
window.location.reload();
}, 3000);
}
}
function duplicateMetric() {
if (confirm('Create a copy of this metric?')) {
alert('Metric duplicated successfully!');
}
}
function exportData() {
alert('Exporting metric data...');
}
function toggleStatus(newStatus) {
const action = newStatus === 'active' ? 'activate' : 'deactivate';
if (confirm(`Are you sure you want to ${action} this metric?`)) {
alert(`Metric ${action}d successfully!`);
window.location.reload();
}
}
function changePeriod(period) {
const buttons = document.querySelectorAll('.btn-group button');
buttons.forEach(btn => btn.classList.remove('active'));
event.target.classList.add('active');
// Update chart with new period data
updateTrendChart(period);
}
function updateTrendChart(period) {
// Placeholder for chart update logic
console.log('Updating chart for period:', period);
}
function viewCalculationDetails(calculationId) {
alert(`Viewing details for calculation: ${calculationId}`);
}
// Initialize trend chart
document.addEventListener('DOMContentLoaded', function() {
const ctx = document.getElementById('trendChart');
if (ctx) {
// Placeholder for Chart.js initialization
ctx.getContext('2d').fillText('Trend Chart Placeholder', 50, 100);
}
});
</script>
<style>
.info-item {
margin-bottom: 15px;
}
.info-item label {
font-weight: 600;
margin-bottom: 5px;
display: block;
color: #2c3e50;
}
.metric-status-card {
border: 1px solid #e9ecef;
border-radius: 8px;
background: white;
overflow: hidden;
height: 100%;
}
.status-header {
background: #f8f9fa;
padding: 20px;
text-align: center;
border-bottom: 1px solid #e9ecef;
}
.status-icon {
margin-bottom: 10px;
}
.status-header h6 {
margin: 0;
font-weight: 600;
color: #2c3e50;
}
.status-stats {
padding: 20px;
display: flex;
justify-content: space-around;
}
.stat-item {
text-align: center;
}
.stat-value {
display: block;
font-size: 1.5rem;
font-weight: 700;
color: #2c3e50;
margin-bottom: 5px;
}
.stat-label {
font-size: 0.875rem;
color: #6c757d;
}
.formula-display, .sql-display {
position: relative;
}
.formula-display pre, .sql-display pre {
margin: 0;
font-size: 0.875rem;
line-height: 1.4;
}
.current-value-card {
text-align: center;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
height: 100%;
}
.value-display h2 {
margin: 10px 0;
font-weight: 700;
}
.unit {
font-size: 1rem;
color: #6c757d;
margin-left: 5px;
}
.change-indicator {
font-weight: 600;
margin-right: 10px;
}
.detail-item {
margin-bottom: 15px;
}
.detail-item label {
font-weight: 600;
margin-bottom: 5px;
display: block;
color: #2c3e50;
}
.detail-value {
color: #6c757d;
}
.tags-container {
margin-top: 5px;
}
.widget-item {
display: flex;
justify-content: between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #e9ecef;
}
.widget-item:last-child {
border-bottom: none;
}
.widget-info {
flex: 1;
}
.widget-info h6 {
margin: 0;
font-weight: 600;
}
.performance-stats {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
.performance-stats .stat-item {
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
text-align: center;
}
.performance-stats .stat-value {
font-size: 1.25rem;
}
@media (max-width: 768px) {
.page-btn {
margin-top: 15px;
}
.card-tools {
margin-top: 15px;
}
.current-value-card {
margin-bottom: 20px;
}
.status-stats {
flex-direction: column;
gap: 15px;
}
.widget-item {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.performance-stats {
grid-template-columns: 1fr;
}
}
</style>
{% endblock %}