2025-08-12 13:33:25 +03:00

524 lines
25 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Operating Theatre Dashboard - {{ block.super }}{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Page Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h1 class="h3 mb-1">
<i class="fas fa-procedures me-2"></i>Operating Theatre Dashboard
</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item active">Operating Theatre</li>
</ol>
</nav>
</div>
<div class="btn-group">
<a href="{% url 'operating_theatre:surgical_case_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-2"></i>New Case
</a>
<a href="{% url 'operating_theatre:surgical_note_create' %}" class="btn btn-success">
<i class="fas fa-file-medical me-2"></i>New Note
</a>
</div>
</div>
<!-- Statistics Cards -->
<div class="row mb-4" hx-get="{% url 'operating_theatre:operating_theatre_stats' %}" hx-trigger="load, every 30s">
<!-- Room Status Stats -->
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-success text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ rooms_available|default:0 }}</div>
<div class="small">Rooms Available</div>
</div>
<div class="fa-2x">
<i class="fas fa-door-open"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-warning text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ rooms_in_use|default:0 }}</div>
<div class="small">Rooms In Use</div>
</div>
<div class="fa-2x">
<i class="fas fa-user-md"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-info text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ rooms_maintenance|default:0 }}</div>
<div class="small">Maintenance</div>
</div>
<div class="fa-2x">
<i class="fas fa-tools"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-primary text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ total_rooms|default:0 }}</div>
<div class="small">Total Rooms</div>
</div>
<div class="fa-2x">
<i class="fas fa-hospital"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Case Statistics -->
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-secondary text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ cases_today|default:0 }}</div>
<div class="small">Cases Today</div>
</div>
<div class="fa-2x">
<i class="fas fa-calendar-day"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-warning text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ cases_in_progress|default:0 }}</div>
<div class="small">Cases In Progress</div>
</div>
<div class="fa-2x">
<i class="fas fa-play-circle"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-success text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ cases_completed_today|default:0 }}</div>
<div class="small">Completed Today</div>
</div>
<div class="fa-2x">
<i class="fas fa-check-circle"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card bg-gradient-danger text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="h4 mb-1">{{ emergency_cases_today|default:0 }}</div>
<div class="small">Emergency Cases</div>
</div>
<div class="fa-2x">
<i class="fas fa-exclamation-triangle"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Today's Schedule -->
<div class="col-lg-8 mb-4">
<div class="card h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-calendar-alt me-2"></i>Today's Schedule
</h5>
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-primary" onclick="refreshSchedule()">
<i class="fas fa-sync-alt"></i>
</button>
<a href="{% url 'operating_theatre:surgical_case_list' %}" class="btn btn-sm btn-outline-primary">
View All
</a>
</div>
</div>
<div class="card-body">
{% if todays_schedule %}
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>Time</th>
<th>Patient</th>
<th>Procedure</th>
<th>Room</th>
<th>Surgeon</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for case in todays_schedule %}
<tr>
<td>
<div class="fw-semibold">{{ case.scheduled_start_time|date:"H:i" }}</div>
<div class="small text-muted">{{ case.estimated_duration }} min</div>
</td>
<td>
<div class="fw-semibold">{{ case.patient.get_full_name }}</div>
<div class="small text-muted">{{ case.patient.mrn }}</div>
</td>
<td>
<div>{{ case.primary_procedure|truncatechars:30 }}</div>
{% if case.case_type == 'EMERGENCY' %}
<span class="badge bg-danger">Emergency</span>
{% elif case.case_type == 'URGENT' %}
<span class="badge bg-warning">Urgent</span>
{% endif %}
</td>
<td>
{% if case.operating_room %}
<span class="badge bg-info">{{ case.operating_room.room_number }}</span>
{% else %}
<span class="text-muted">TBD</span>
{% endif %}
</td>
<td>
{% if case.primary_surgeon %}
<div class="small">{{ case.primary_surgeon.get_full_name }}</div>
{% else %}
<span class="text-muted">N/A</span>
{% endif %}
</td>
<td>
<span class="badge bg-{% if case.status == 'SCHEDULED' %}secondary{% elif case.status == 'IN_PROGRESS' %}warning{% elif case.status == 'COMPLETED' %}success{% elif case.status == 'CANCELLED' %}danger{% else %}info{% endif %}">
{{ case.get_status_display }}
</span>
</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{% url 'operating_theatre:surgical_case_detail' case.pk %}" class="btn btn-outline-primary" title="View Details">
<i class="fas fa-eye"></i>
</a>
{% if case.status == 'SCHEDULED' %}
<button type="button" class="btn btn-outline-success" onclick="startCase({{ case.pk }})" title="Start Case">
<i class="fas fa-play"></i>
</button>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="fas fa-calendar-times fa-3x text-muted mb-3"></i>
<p class="text-muted">No cases scheduled for today.</p>
<a href="{% url 'operating_theatre:surgical_case_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-2"></i>Schedule a Case
</a>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Room Status Overview -->
<div class="col-lg-4 mb-4">
<div class="card h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-door-open me-2"></i>Room Status
</h5>
<a href="{% url 'operating_theatre:operating_room_list' %}" class="btn btn-sm btn-outline-primary">
Manage
</a>
</div>
<div class="card-body">
{% if room_utilization %}
{% for room in room_utilization %}
<div class="d-flex align-items-center mb-3 p-3 rounded {% if room.status == 'AVAILABLE' %}bg-light-success{% elif room.status == 'OCCUPIED' %}bg-light-warning{% elif room.status == 'MAINTENANCE' %}bg-light-danger{% else %}bg-light-info{% endif %}">
<div class="me-3">
<div class="bg-{% if room.status == 'AVAILABLE' %}success{% elif room.status == 'OCCUPIED' %}warning{% elif room.status == 'MAINTENANCE' %}danger{% else %}info{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="fas fa-{% if room.status == 'AVAILABLE' %}check{% elif room.status == 'OCCUPIED' %}user-md{% elif room.status == 'MAINTENANCE' %}tools{% else %}clock{% endif %} text-white"></i>
</div>
</div>
<div class="flex-grow-1">
<div class="fw-semibold">{{ room.room_number }} - {{ room.room_name }}</div>
<div class="small text-muted">
{{ room.get_status_display }}
{% if room.current_case %}
- {{ room.current_case.patient.get_full_name }}
{% endif %}
</div>
<div class="small text-muted">{{ room.cases_today|default:0 }} case{{ room.cases_today|pluralize }} today</div>
</div>
<div>
<a href="{% url 'operating_theatre:operating_room_detail' room.pk %}" class="btn btn-sm btn-outline-primary">
<i class="fas fa-eye"></i>
</a>
</div>
</div>
{% endfor %}
{% else %}
<div class="text-center py-4">
<i class="fas fa-door-closed fa-3x text-muted mb-3"></i>
<p class="text-muted">No operating rooms configured.</p>
<a href="{% url 'operating_theatre:operating_room_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-2"></i>Add Room
</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="row">
<!-- Recent Activity -->
<div class="col-lg-6 mb-4">
<div class="card h-100">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-history me-2"></i>Recent Activity
</h5>
<a href="{% url 'operating_theatre:surgical_case_list' %}" class="btn btn-sm btn-outline-primary">
View All
</a>
</div>
<div class="card-body">
{% if recent_cases %}
{% for case in recent_cases %}
<div class="d-flex align-items-center mb-3">
<div class="bg-{% if case.status == 'COMPLETED' %}success{% elif case.status == 'IN_PROGRESS' %}warning{% elif case.status == 'CANCELLED' %}danger{% else %}secondary{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center me-3" style="width: 32px; height: 32px;">
<i class="fas fa-{% if case.status == 'COMPLETED' %}check{% elif case.status == 'IN_PROGRESS' %}play{% elif case.status == 'CANCELLED' %}times{% else %}clock{% endif %} text-white small"></i>
</div>
<div class="flex-grow-1">
<div class="fw-semibold">{{ case.patient.get_full_name }}</div>
<div class="small text-muted">{{ case.primary_procedure|truncatechars:40 }}</div>
<div class="small text-muted">{{ case.scheduled_start_time|date:"M d, H:i" }}</div>
</div>
<div>
<span class="badge bg-{% if case.status == 'COMPLETED' %}success{% elif case.status == 'IN_PROGRESS' %}warning{% elif case.status == 'CANCELLED' %}danger{% else %}secondary{% endif %}">
{{ case.get_status_display }}
</span>
</div>
</div>
{% endfor %}
{% else %}
<div class="text-center py-4">
<i class="fas fa-history fa-3x text-muted mb-3"></i>
<p class="text-muted">No recent activity.</p>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="col-lg-6 mb-4">
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-bolt me-2"></i>Quick Actions
</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-6">
<a href="{% url 'operating_theatre:surgical_case_list' %}" class="btn btn-outline-primary w-100 h-100 d-flex flex-column align-items-center justify-content-center">
<i class="fas fa-list-alt fa-2x mb-2"></i>
<span>View Cases</span>
</a>
</div>
<div class="col-6">
<a href="{% url 'operating_theatre:operating_room_list' %}" class="btn btn-outline-info w-100 h-100 d-flex flex-column align-items-center justify-content-center">
<i class="fas fa-door-open fa-2x mb-2"></i>
<span>Manage Rooms</span>
</a>
</div>
<div class="col-6">
<a href="{% url 'operating_theatre:or_block_list' %}" class="btn btn-outline-success w-100 h-100 d-flex flex-column align-items-center justify-content-center">
<i class="fas fa-calendar-alt fa-2x mb-2"></i>
<span>OR Blocks</span>
</a>
</div>
<div class="col-6">
<a href="{% url 'operating_theatre:surgical_note_list' %}" class="btn btn-outline-warning w-100 h-100 d-flex flex-column align-items-center justify-content-center">
<i class="fas fa-file-medical fa-2x mb-2"></i>
<span>Surgical Notes</span>
</a>
</div>
<div class="col-6">
<a href="{% url 'operating_theatre:equipment_usage_list' %}" class="btn btn-outline-secondary w-100 h-100 d-flex flex-column align-items-center justify-content-center">
<i class="fas fa-tools fa-2x mb-2"></i>
<span>Equipment</span>
</a>
</div>
<div class="col-6">
<a href="{% url 'operating_theatre:surgical_note_template_list' %}" class="btn btn-outline-dark w-100 h-100 d-flex flex-column align-items-center justify-content-center">
<i class="fas fa-file-alt fa-2x mb-2"></i>
<span>Templates</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Performance Metrics -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-chart-line me-2"></i>Performance Metrics
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3 text-center">
<div class="h4 text-primary">{{ performance_metrics.utilization_rate|default:0 }}%</div>
<div class="small text-muted">OR Utilization Rate</div>
</div>
<div class="col-md-3 text-center">
<div class="h4 text-success">{{ performance_metrics.on_time_starts|default:0 }}%</div>
<div class="small text-muted">On-Time Starts</div>
</div>
<div class="col-md-3 text-center">
<div class="h4 text-info">{{ performance_metrics.avg_turnover|default:0 }} min</div>
<div class="small text-muted">Avg Turnover Time</div>
</div>
<div class="col-md-3 text-center">
<div class="h4 text-warning">{{ performance_metrics.cancellation_rate|default:0 }}%</div>
<div class="small text-muted">Cancellation Rate</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Auto-refresh functionality
function refreshSchedule() {
location.reload();
}
// Start case function
function startCase(caseId) {
if (confirm('Start this surgical case?')) {
fetch(`/operating_theatre/cases/${caseId}/start/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error starting case: ' + data.error);
}
})
.catch(error => {
console.error('Error:', error);
alert('Error starting case');
});
}
}
// Auto-refresh every 30 seconds
setInterval(function() {
const statsContainer = document.querySelector('[hx-get]');
if (statsContainer) {
htmx.trigger(statsContainer, 'refresh');
}
}, 30000);
</script>
<style>
.bg-light-success {
background-color: rgba(25, 135, 84, 0.1) !important;
}
.bg-light-warning {
background-color: rgba(255, 193, 7, 0.1) !important;
}
.bg-light-danger {
background-color: rgba(220, 53, 69, 0.1) !important;
}
.bg-light-info {
background-color: rgba(13, 202, 240, 0.1) !important;
}
.bg-gradient {
background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
}
.card-body .btn {
transition: all 0.2s ease-in-out;
}
.card-body .btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.table-hover tbody tr:hover {
background-color: rgba(0, 0, 0, 0.025);
}
@media (max-width: 768px) {
.btn-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.col-xl-3, .col-md-6 {
margin-bottom: 1rem;
}
}
</style>
{% endblock %}