hospital-management/templates/patients/consents/consent_template_detail.html
Marwan Alwali 610e165e17 update
2025-09-04 19:19:52 +03:00

587 lines
24 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}{{ template.name }} - Consent Template{% endblock %}
{% block extra_css %}
<style>
.template-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 15px;
padding: 2rem;
margin-bottom: 2rem;
}
.template-content {
background: #fff;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
padding: 2rem;
margin-bottom: 2rem;
}
.template-preview {
border: 2px dashed #dee2e6;
border-radius: 10px;
padding: 2rem;
background: #f8f9fa;
min-height: 400px;
}
.template-meta {
background: #f8f9fa;
border-radius: 10px;
padding: 1.5rem;
}
.version-badge {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
color: white;
padding: 0.5rem 1rem;
border-radius: 50px;
font-weight: bold;
}
.usage-chart {
height: 200px;
}
.action-buttons {
position: sticky;
top: 20px;
z-index: 100;
}
.template-variables {
background: #e3f2fd;
border-left: 4px solid #2196f3;
padding: 1rem;
border-radius: 0 10px 10px 0;
margin: 1rem 0;
}
.variable-tag {
background: #2196f3;
color: white;
padding: 0.25rem 0.5rem;
border-radius: 15px;
font-size: 0.75rem;
margin: 0.25rem;
display: inline-block;
}
.template-history {
max-height: 300px;
overflow-y: auto;
}
.history-item {
border-left: 3px solid #dee2e6;
padding-left: 1rem;
margin-bottom: 1rem;
position: relative;
}
.history-item::before {
content: '';
position: absolute;
left: -6px;
top: 0;
width: 10px;
height: 10px;
border-radius: 50%;
background: #007bff;
}
.template-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.stat-card {
background: white;
border-radius: 10px;
padding: 1.5rem;
text-align: center;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
border: 1px solid #e9ecef;
}
.stat-icon {
width: 50px;
height: 50px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 1rem;
font-size: 20px;
}
</style>
{% endblock %}
{% block content %}
<div id="content" class="app-content">
<!-- Page Header -->
<div class="d-flex align-items-center mb-4">
<div>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'patients:patient_list' %}">Patients</a></li>
<li class="breadcrumb-item"><a href="{% url 'patients:consent_template_list' %}">Consent Templates</a></li>
<li class="breadcrumb-item active">{{ template.name }}</li>
</ol>
</div>
</div>
<div class="row">
<!-- Main Content -->
<div class="col-lg-8">
<!-- Template Header -->
<div class="template-header">
<div class="d-flex justify-content-between align-items-start">
<div>
<h1 class="mb-2">
<i class="fas fa-file-contract me-3"></i>{{ template.name }}
</h1>
<p class="mb-3 opacity-75">{{ template.description }}</p>
<div class="d-flex align-items-center gap-3">
<span class="version-badge">
<i class="fas fa-code-branch me-1"></i>Version {{ template.version|default:"1.0" }}
</span>
<span class="badge bg-light text-dark">
<i class="fas fa-tag me-1"></i>{{ template.get_category_display }}
</span>
<span class="badge bg-light text-dark">
<i class="fas fa-language me-1"></i>{{ template.get_language_display }}
</span>
</div>
</div>
<div class="text-end">
{% if template.status == 'active' %}
<span class="badge bg-success fs-6 px-3 py-2">
<i class="fas fa-check-circle me-1"></i>Active
</span>
{% elif template.status == 'draft' %}
<span class="badge bg-warning fs-6 px-3 py-2">
<i class="fas fa-edit me-1"></i>Draft
</span>
{% elif template.status == 'archived' %}
<span class="badge bg-secondary fs-6 px-3 py-2">
<i class="fas fa-archive me-1"></i>Archived
</span>
{% else %}
<span class="badge bg-info fs-6 px-3 py-2">
<i class="fas fa-clock me-1"></i>{{ template.get_status_display }}
</span>
{% endif %}
</div>
</div>
</div>
<!-- Template Statistics -->
<div class="template-stats">
<div class="stat-card">
<div class="stat-icon bg-primary text-white">
<i class="fas fa-users"></i>
</div>
<h4 class="mb-1">{{ template.usage_count|default:0 }}</h4>
<small class="text-muted">Times Used</small>
</div>
<div class="stat-card">
<div class="stat-icon bg-success text-white">
<i class="fas fa-calendar-check"></i>
</div>
<h4 class="mb-1">{{ template.last_used|date:"M d"|default:"Never" }}</h4>
<small class="text-muted">Last Used</small>
</div>
<div class="stat-card">
<div class="stat-icon bg-info text-white">
<i class="fas fa-star"></i>
</div>
<h4 class="mb-1">{{ template.rating|floatformat:1|default:"N/A" }}</h4>
<small class="text-muted">Average Rating</small>
</div>
<div class="stat-card">
<div class="stat-icon bg-warning text-white">
<i class="fas fa-clock"></i>
</div>
<h4 class="mb-1">{{ template.avg_completion_time|default:"N/A" }}</h4>
<small class="text-muted">Avg. Completion</small>
</div>
</div>
<!-- Template Content Preview -->
<div class="template-content">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="mb-0">
<i class="fas fa-eye me-2"></i>Template Preview
</h5>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-outline-primary" onclick="togglePreviewMode('formatted')">
<i class="fas fa-file-alt"></i> Formatted
</button>
<button type="button" class="btn btn-outline-secondary" onclick="togglePreviewMode('raw')">
<i class="fas fa-code"></i> Raw
</button>
</div>
</div>
<div id="formattedPreview" class="template-preview">
<div class="mb-4">
<h3 class="text-center mb-4">{{ template.name }}</h3>
<div class="content">
{{ template.content|safe|default:"<p class='text-muted text-center'>No content available for preview.</p>" }}
</div>
</div>
{% if template.variables %}
<div class="template-variables">
<h6 class="mb-2">
<i class="fas fa-code me-2"></i>Template Variables
</h6>
<p class="small mb-2">The following variables will be replaced when the template is used:</p>
{% for variable in template.variables %}
<span class="variable-tag">{{ variable }}</span>
{% endfor %}
</div>
{% endif %}
</div>
<div id="rawPreview" class="template-preview d-none">
<pre class="mb-0"><code>{{ template.raw_content|default:"No raw content available." }}</code></pre>
</div>
</div>
<!-- Usage History -->
<div class="template-content">
<h5 class="mb-3">
<i class="fas fa-history me-2"></i>Recent Usage History
</h5>
<div class="template-history">
{% for usage in recent_usage %}
<div class="history-item">
<div class="d-flex justify-content-between align-items-start">
<div>
<h6 class="mb-1">{{ usage.patient_name }}</h6>
<p class="text-muted small mb-1">{{ usage.description }}</p>
<small class="text-muted">
<i class="fas fa-user me-1"></i>{{ usage.created_by }}
<i class="fas fa-clock ms-2 me-1"></i>{{ usage.created_at|timesince }} ago
</small>
</div>
<span class="badge bg-{{ usage.status_color }}">{{ usage.status }}</span>
</div>
</div>
{% empty %}
<div class="text-center py-4">
<i class="fas fa-history fa-3x text-muted mb-3"></i>
<h6 class="text-muted">No Usage History</h6>
<p class="text-muted">This template hasn't been used yet.</p>
</div>
{% endfor %}
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Action Buttons -->
<div class="action-buttons">
<div class="card mb-4">
<div class="card-header">
<h6 class="mb-0">
<i class="fas fa-tools me-2"></i>Actions
</h6>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<a href="{% url 'patients:consent_template_edit' template.id %}" class="btn btn-primary">
<i class="fas fa-edit me-2"></i>Edit Template
</a>
<button type="button" class="btn btn-success" onclick="useTemplate()">
<i class="fas fa-play me-2"></i>Use Template
</button>
<button type="button" class="btn btn-info" onclick="duplicateTemplate()">
<i class="fas fa-copy me-2"></i>Duplicate
</button>
<button type="button" class="btn btn-warning" onclick="exportTemplate()">
<i class="fas fa-download me-2"></i>Export
</button>
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-ellipsis-h me-2"></i>More Actions
</button>
<ul class="dropdown-menu w-100">
<li><a class="dropdown-item" href="#" onclick="shareTemplate()">
<i class="fas fa-share me-2"></i>Share Template
</a></li>
<li><a class="dropdown-item" href="#" onclick="printTemplate()">
<i class="fas fa-print me-2"></i>Print Preview
</a></li>
<li><a class="dropdown-item" href="#" onclick="viewVersionHistory()">
<i class="fas fa-code-branch me-2"></i>Version History
</a></li>
<li><hr class="dropdown-divider"></li>
{% if template.status != 'archived' %}
<li><a class="dropdown-item text-danger" href="#" onclick="archiveTemplate()">
<i class="fas fa-archive me-2"></i>Archive Template
</a></li>
{% else %}
<li><a class="dropdown-item text-success" href="#" onclick="restoreTemplate()">
<i class="fas fa-undo me-2"></i>Restore Template
</a></li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
<!-- Template Metadata -->
<div class="card mb-4">
<div class="card-header">
<h6 class="mb-0">
<i class="fas fa-info-circle me-2"></i>Template Information
</h6>
</div>
<div class="card-body">
<div class="template-meta">
<div class="row g-3">
<div class="col-12">
<label class="form-label small text-muted">Created By</label>
<div class="fw-bold">{{ template.created_by|default:"System" }}</div>
</div>
<div class="col-6">
<label class="form-label small text-muted">Created</label>
<div class="fw-bold">{{ template.created_at|date:"M d, Y" }}</div>
</div>
<div class="col-6">
<label class="form-label small text-muted">Updated</label>
<div class="fw-bold">{{ template.updated_at|date:"M d, Y" }}</div>
</div>
<div class="col-6">
<label class="form-label small text-muted">File Size</label>
<div class="fw-bold">{{ template.file_size|filesizeformat|default:"N/A" }}</div>
</div>
<div class="col-6">
<label class="form-label small text-muted">Checksum</label>
<div class="fw-bold small">{{ template.checksum|truncatechars:8|default:"N/A" }}</div>
</div>
{% if template.tags %}
<div class="col-12">
<label class="form-label small text-muted">Tags</label>
<div>
{% for tag in template.tags %}
<span class="badge bg-secondary me-1">{{ tag }}</span>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Usage Analytics -->
<div class="card mb-4">
<div class="card-header">
<h6 class="mb-0">
<i class="fas fa-chart-line me-2"></i>Usage Analytics
</h6>
</div>
<div class="card-body">
<canvas id="usageChart" class="usage-chart"></canvas>
<div class="mt-3">
<div class="row text-center">
<div class="col-4">
<div class="fw-bold text-primary">{{ analytics.this_week|default:0 }}</div>
<small class="text-muted">This Week</small>
</div>
<div class="col-4">
<div class="fw-bold text-success">{{ analytics.this_month|default:0 }}</div>
<small class="text-muted">This Month</small>
</div>
<div class="col-4">
<div class="fw-bold text-info">{{ analytics.total|default:0 }}</div>
<small class="text-muted">All Time</small>
</div>
</div>
</div>
</div>
</div>
<!-- Related Templates -->
{% if related_templates %}
<div class="card">
<div class="card-header">
<h6 class="mb-0">
<i class="fas fa-link me-2"></i>Related Templates
</h6>
</div>
<div class="card-body">
{% for related in related_templates %}
<div class="d-flex align-items-center mb-3">
<div class="me-3">
<i class="fas fa-file-contract text-primary"></i>
</div>
<div class="flex-grow-1">
<a href="{% url 'patients:consent_template_detail' related.id %}" class="text-decoration-none">
<div class="fw-bold">{{ related.name }}</div>
<small class="text-muted">{{ related.category }}</small>
</a>
</div>
<div>
<span class="badge bg-light text-dark">{{ related.usage_count|default:0 }}</span>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Usage Analytics Chart
const ctx = document.getElementById('usageChart').getContext('2d');
const usageChart = new Chart(ctx, {
type: 'line',
data: {
labels: {{ analytics.labels|safe|default:"[]" }},
datasets: [{
label: 'Usage Count',
data: {{ analytics.data|safe|default:"[]" }},
borderColor: '#007bff',
backgroundColor: 'rgba(0, 123, 255, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
function togglePreviewMode(mode) {
if (mode === 'formatted') {
document.getElementById('formattedPreview').classList.remove('d-none');
document.getElementById('rawPreview').classList.add('d-none');
} else {
document.getElementById('formattedPreview').classList.add('d-none');
document.getElementById('rawPreview').classList.remove('d-none');
}
}
function useTemplate() {
if (confirm('Are you sure you want to use this template for a new consent form?')) {
window.location.href = '{% url "patients:consent_create" %}?template={{ template.id }}';
}
}
function duplicateTemplate() {
if (confirm('Are you sure you want to duplicate this template?')) {
$.ajax({
url: '{% url "patients:consent_template_duplicate" template.id %}',
method: 'POST',
headers: {
'X-CSRFToken': $('[name=csrfmiddlewaretoken]').val()
},
success: function(response) {
if (response.success) {
window.location.href = response.redirect_url;
} else {
alert('Error duplicating template: ' + response.error);
}
},
error: function() {
alert('Error duplicating template.');
}
});
}
}
function exportTemplate() {
window.location.href = '{% url "patients:consent_template_export" template.id %}';
}
function shareTemplate() {
const shareUrl = window.location.href;
if (navigator.share) {
navigator.share({
title: '{{ template.name }}',
text: 'Check out this consent template',
url: shareUrl
});
} else {
navigator.clipboard.writeText(shareUrl).then(function() {
alert('Template URL copied to clipboard!');
});
}
}
function printTemplate() {
window.open('{% url "patients:consent_template_print" template.id %}', '_blank');
}
function viewVersionHistory() {
window.location.href = '{% url "patients:consent_template_versions" template.id %}';
}
function archiveTemplate() {
if (confirm('Are you sure you want to archive this template? It will no longer be available for use.')) {
$.ajax({
url: '{% url "patients:consent_template_archive" template.id %}',
method: 'POST',
headers: {
'X-CSRFToken': $('[name=csrfmiddlewaretoken]').val()
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error archiving template: ' + response.error);
}
},
error: function() {
alert('Error archiving template.');
}
});
}
}
function restoreTemplate() {
if (confirm('Are you sure you want to restore this template?')) {
$.ajax({
url: '{% url "patients:consent_template_restore" template.id %}',
method: 'POST',
headers: {
'X-CSRFToken': $('[name=csrfmiddlewaretoken]').val()
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error restoring template: ' + response.error);
}
},
error: function() {
alert('Error restoring template.');
}
});
}
}
</script>
{% endblock %}