Marwan Alwali 193ee7f34a update
2025-08-24 12:00:10 +03:00

605 lines
27 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Admission Management - {{ 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-user-injured me-2"></i>Admission Management
</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{% url 'inpatients:dashboard' %}">Inpatients</a></li>
<li class="breadcrumb-item active">Admissions</li>
</ol>
</nav>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary" onclick="refreshAdmissions()">
<i class="fas fa-sync-alt me-2"></i>Refresh
</button>
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-download me-2"></i>Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="exportData('csv')">
<i class="fas fa-file-csv me-2"></i>Export as CSV
</a></li>
<li><a class="dropdown-item" href="#" onclick="exportData('excel')">
<i class="fas fa-file-excel me-2"></i>Export as Excel
</a></li>
<li><a class="dropdown-item" href="#" onclick="exportData('pdf')">
<i class="fas fa-file-pdf me-2"></i>Export as PDF
</a></li>
</ul>
</div>
<a href="{% url 'inpatients:admission_create' %}" class="btn btn-primary">
<i class="fas fa-user-plus me-2"></i>New Admission
</a>
</div>
</div>
<!-- Statistics Cards -->
<div class="row mb-4">
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Total Admissions</h6>
<h3 class="mb-0 text-primary">{{ total_admissions }}</h3>
<small class="text-muted">All time</small>
</div>
<div class="bg-primary bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-user-injured fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Active Admissions</h6>
<h3 class="mb-0 text-success">{{ active_admissions }}</h3>
<small class="text-muted">Currently admitted</small>
</div>
<div class="bg-success bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-bed fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Today's Admissions</h6>
<h3 class="mb-0 text-info">{{ todays_admissions }}</h3>
<small class="text-muted">New today</small>
</div>
<div class="bg-info bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-calendar-day fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title text-muted mb-1">Pending Discharges</h6>
<h3 class="mb-0 text-warning">{{ pending_discharges }}</h3>
<small class="text-muted">Ready for discharge</small>
</div>
<div class="bg-warning bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-sign-out-alt fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filters and Search -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-filter me-2"></i>Filters and Search
</h5>
</div>
<div class="card-body">
<form method="get" id="filterForm">
<div class="row">
<div class="col-md-2">
<label for="status" class="form-label">Status</label>
<select name="status" id="status" class="form-select">
<option value="">All Status</option>
{% for value, label in admission_statuses %}
<option value="{{ value }}" {% if request.GET.status == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-2">
<label for="ward" class="form-label">Ward</label>
<select name="ward" id="ward" class="form-select">
<option value="">All Wards</option>
{% for ward in wards %}
<option value="{{ ward.id }}" {% if request.GET.ward == ward.id|stringformat:"s" %}selected{% endif %}>{{ ward.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-2">
<label for="admission_type" class="form-label">Type</label>
<select name="admission_type" id="admission_type" class="form-select">
<option value="">All Types</option>
{% for value, label in admission_types %}
<option value="{{ value }}" {% if request.GET.admission_type == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-3">
<label for="search" class="form-label">Search</label>
<input type="text" name="search" id="search" class="form-control"
placeholder="Patient name, MRN, diagnosis..." value="{{ request.GET.search }}">
</div>
<div class="col-md-2">
<label for="date_range" class="form-label">Date Range</label>
<select name="date_range" id="date_range" class="form-select">
<option value="">All Dates</option>
<option value="today" {% if request.GET.date_range == 'today' %}selected{% endif %}>Today</option>
<option value="week" {% if request.GET.date_range == 'week' %}selected{% endif %}>This Week</option>
<option value="month" {% if request.GET.date_range == 'month' %}selected{% endif %}>This Month</option>
</select>
</div>
<div class="col-md-1 d-flex align-items-end">
<button type="submit" class="btn btn-primary w-100">
<i class="fas fa-search"></i>
</button>
</div>
</div>
<div class="row mt-3">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<div>
{% if request.GET %}
<a href="{% url 'inpatients:admission_list' %}" class="btn btn-outline-secondary btn-sm">
<i class="fas fa-times me-1"></i>Clear Filters
</a>
{% endif %}
</div>
<div>
<span class="text-muted">{{ admissions.count }} admission{{ admissions.count|pluralize }} found</span>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<!-- Admissions Table -->
<div class="card">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-list me-2"></i>Admissions List
</h5>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-outline-secondary" onclick="selectAll()">
<i class="fas fa-check-square me-1"></i>Select All
</button>
<button type="button" class="btn btn-outline-secondary" onclick="clearSelection()">
<i class="fas fa-square me-1"></i>Clear
</button>
<div class="btn-group">
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown" id="bulkActions" disabled>
<i class="fas fa-cogs me-1"></i>Bulk Actions
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="bulkAction('transfer')">
<i class="fas fa-exchange-alt me-2"></i>Transfer Selected
</a></li>
<li><a class="dropdown-item" href="#" onclick="bulkAction('discharge')">
<i class="fas fa-sign-out-alt me-2"></i>Discharge Selected
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="bulkAction('export')">
<i class="fas fa-download me-2"></i>Export Selected
</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th width="40">
<input type="checkbox" class="form-check-input" id="selectAllCheckbox" onchange="toggleSelectAll()">
</th>
<th>Patient</th>
<th>Ward/Bed</th>
<th>Admission Date</th>
<th>Type</th>
<th>Attending Physician</th>
<th>Primary Diagnosis</th>
<th>Status</th>
<th>Length of Stay</th>
<th width="120">Actions</th>
</tr>
</thead>
<tbody>
{% for admission in admissions %}
<tr>
<td>
<input type="checkbox" class="form-check-input admission-checkbox" value="{{ admission.id }}" onchange="updateBulkActions()">
</td>
<td>
<div class="d-flex align-items-center">
<div class="avatar-sm bg-primary bg-gradient rounded-circle d-flex align-items-center justify-content-center me-2">
<span class="text-white small fw-bold">
{{ admission.patient.first_name.0 }}{{ admission.patient.last_name.0 }}
</span>
</div>
<div>
<div class="fw-semibold">{{ admission.patient.get_full_name }}</div>
<small class="text-muted">{{ admission.patient.mrn }}</small>
</div>
</div>
</td>
<td>
<div>{{ admission.current_ward.name }}</div>
<small class="text-muted">Bed {{ admission.current_bed.bed_number }}</small>
</td>
<td>
<div>{{ admission.admission_datetime|date:"M d, Y" }}</div>
<small class="text-muted ">{{ admission.admission_datetime|time:"H:i" }}</small>
</td>
<td>
<div class="badge
bg-{% if admission.admission_type == 'EMERGENCY' %}danger
{% elif admission.admission_type == 'ELECTIVE' %}primary
{% elif admission.admission_type == 'TRANSFER' %}info
{% elif admission.admission_type == 'URGENT' %}yellow
{% elif admission.admission_type == 'OBSERVATION' %}indego
{% elif admission.admission_type == 'DAY_SURGERY' %}purple
{% elif admission.admission_type == 'DIRECT' %}red
{% else %}secondary
{% endif %}">
{{ admission.get_admission_type_display }}
</div>
</td>
<td>
{% if admission.attending_physician %}
<div>{{ admission.attending_physician.get_full_name }}</div>
<small class="text-muted">{{ admission.attending_physician.specialization|default:"Physician" }}</small>
{% else %}
<span class="text-muted">Not assigned</span>
{% endif %}
</td>
<td>
{% if admission.primary_diagnosis %}
<div title="{{ admission.primary_diagnosis }}">
{{ admission.primary_diagnosis|truncatechars:30 }}
</div>
{% else %}
<span class="text-muted">Not specified</span>
{% endif %}
</td>
<td>
<span class="badge bg-{% if admission.status == 'ADMITTED' %}success{% elif admission.status == 'PENDING' %}warning{% elif admission.status == 'DISCHARGED' %}secondary{% else %}info{% endif %}">
{{ admission.get_status_display }}
</span>
</td>
<td>
<div>{{ admission.length_of_stay }} day{{ admission.length_of_stay|pluralize }}</div>
{% if admission.anticipated_discharge_date %}
<small class="text-muted">Est. {{ admission.anticipated_discharge_date|date:"M d" }}</small>
{% endif %}
</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{% url 'inpatients:admission_detail' admission.pk %}"
class="btn btn-outline-primary btn-sm" title="View Details">
<i class="fas fa-eye"></i>
</a>
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown">
<span class="visually-hidden">Toggle Dropdown</span>
<i class="fas fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="{% url 'inpatients:admission_update' admission.pk %}">
<i class="fas fa-edit me-2"></i>Edit
</a></li>
{% if admission.status == 'ADMITTED' %}
<li><a class="dropdown-item" href="{% url 'inpatients:transfer_patient' admission.pk %}">
<i class="fas fa-exchange-alt me-2"></i>Transfer
</a></li>
<li><a class="dropdown-item" href="{% url 'inpatients:discharge_patient' admission.pk %}">
<i class="fas fa-sign-out-alt me-2"></i>Discharge
</a></li>
{% endif %}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">
<i class="fas fa-notes-medical me-2"></i>Add Note
</a></li>
<li><a class="dropdown-item" href="#">
<i class="fas fa-print me-2"></i>Print Summary
</a></li>
</ul>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="10" class="text-center py-4">
<i class="fas fa-user-injured fa-3x text-muted mb-3"></i>
<h6 class="text-muted">No admissions found</h6>
<p class="text-muted">
{% if request.GET %}
Try adjusting your search criteria or
<a href="{% url 'inpatients:admission_list' %}">clear filters</a>
{% else %}
Patient admissions will appear here
{% endif %}
</p>
<a href="{% url 'inpatients:admission_create' %}" class="btn btn-primary">
<i class="fas fa-user-plus me-2"></i>Add First Admission
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Pagination -->
{% if is_paginated %}
{% include 'partial/pagination.html'%}
{% endif %}
</div>
</div>
<script>
// Admission list functionality
document.addEventListener('DOMContentLoaded', function() {
// Auto-submit form on filter change
const filterForm = document.getElementById('filterForm');
const filterInputs = filterForm.querySelectorAll('select, input[type="text"]');
filterInputs.forEach(input => {
if (input.type === 'text') {
// Debounce text input
let timeout;
input.addEventListener('input', function() {
clearTimeout(timeout);
timeout = setTimeout(() => {
filterForm.submit();
}, 500);
});
} else {
input.addEventListener('change', function() {
filterForm.submit();
});
}
});
});
function refreshAdmissions() {
location.reload();
}
function selectAll() {
const checkboxes = document.querySelectorAll('.admission-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = true;
});
updateBulkActions();
}
function clearSelection() {
const checkboxes = document.querySelectorAll('.admission-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = false;
});
document.getElementById('selectAllCheckbox').checked = false;
updateBulkActions();
}
function toggleSelectAll() {
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
const checkboxes = document.querySelectorAll('.admission-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
updateBulkActions();
}
function updateBulkActions() {
const checkboxes = document.querySelectorAll('.admission-checkbox:checked');
const bulkActionsBtn = document.getElementById('bulkActions');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
bulkActionsBtn.disabled = checkboxes.length === 0;
// Update select all checkbox state
const allCheckboxes = document.querySelectorAll('.admission-checkbox');
if (checkboxes.length === 0) {
selectAllCheckbox.indeterminate = false;
selectAllCheckbox.checked = false;
} else if (checkboxes.length === allCheckboxes.length) {
selectAllCheckbox.indeterminate = false;
selectAllCheckbox.checked = true;
} else {
selectAllCheckbox.indeterminate = true;
}
}
function bulkAction(action) {
const checkboxes = document.querySelectorAll('.admission-checkbox:checked');
const admissionIds = Array.from(checkboxes).map(cb => cb.value);
if (admissionIds.length === 0) {
alert('Please select at least one admission.');
return;
}
switch (action) {
case 'transfer':
if (confirm(`Transfer ${admissionIds.length} selected patient(s)?`)) {
// Implement bulk transfer
console.log('Bulk transfer:', admissionIds);
}
break;
case 'discharge':
if (confirm(`Discharge ${admissionIds.length} selected patient(s)?`)) {
// Implement bulk discharge
console.log('Bulk discharge:', admissionIds);
}
break;
case 'export':
exportSelectedAdmissions(admissionIds);
break;
}
}
function exportData(format) {
const form = document.createElement('form');
form.method = 'POST';
form.action = '';
const csrfToken = document.createElement('input');
csrfToken.type = 'hidden';
csrfToken.name = 'csrfmiddlewaretoken';
csrfToken.value = document.querySelector('[name=csrfmiddlewaretoken]').value;
const formatInput = document.createElement('input');
formatInput.type = 'hidden';
formatInput.name = 'format';
formatInput.value = format;
// Add current filters
const filterForm = document.getElementById('filterForm');
const formData = new FormData(filterForm);
for (let [key, value] of formData.entries()) {
if (value) {
const input = document.createElement('input');
input.type = 'hidden';
input.name = key;
input.value = value;
form.appendChild(input);
}
}
form.appendChild(csrfToken);
form.appendChild(formatInput);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
function exportSelectedAdmissions(admissionIds) {
const form = document.createElement('form');
form.method = 'POST';
form.action = '';
const csrfToken = document.createElement('input');
csrfToken.type = 'hidden';
csrfToken.name = 'csrfmiddlewaretoken';
csrfToken.value = document.querySelector('[name=csrfmiddlewaretoken]').value;
admissionIds.forEach(id => {
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'admission_ids';
input.value = id;
form.appendChild(input);
});
form.appendChild(csrfToken);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
</script>
<style>
.avatar-sm {
width: 32px;
height: 32px;
font-size: 0.75rem;
}
.bg-gradient {
background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
}
.table th {
border-top: none;
font-weight: 600;
color: #6c757d;
font-size: 0.875rem;
}
.table td {
vertical-align: middle;
font-size: 0.875rem;
}
.badge {
font-size: 0.75em;
}
.form-check-input:indeterminate {
background-color: #0d6efd;
border-color: #0d6efd;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e");
}
@media (max-width: 768px) {
.d-flex.justify-content-between {
flex-direction: column;
gap: 1rem;
}
.btn-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table-responsive {
font-size: 0.8rem;
}
.avatar-sm {
width: 28px;
height: 28px;
font-size: 0.7rem;
}
}
</style>
{% endblock %}