Marwan Alwali b9b8c69129 update
2025-08-31 10:47:23 +03:00

558 lines
21 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}OR Equipment Management{% endblock %}
{% block css %}
<style>
.equipment-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 0.5rem;
padding: 2rem;
margin-bottom: 2rem;
}
.equipment-card {
border: 1px solid #dee2e6;
border-radius: 0.375rem;
margin-bottom: 1rem;
background: white;
transition: all 0.3s ease;
}
.equipment-card:hover {
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
transform: translateY(-2px);
}
.equipment-image {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 0.375rem 0.375rem 0 0;
}
.equipment-content {
padding: 1.5rem;
}
.equipment-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
margin-bottom: 1rem;
}
.info-item {
display: flex;
flex-direction: column;
}
.info-label {
font-size: 0.875rem;
color: #6c757d;
font-weight: 600;
margin-bottom: 0.25rem;
}
.info-value {
color: #495057;
font-weight: 500;
}
.status-indicator {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
margin-right: 0.5rem;
}
.status-available { background-color: #28a745; }
.status-in-use { background-color: #007bff; }
.status-maintenance { background-color: #ffc107; }
.status-out-of-order { background-color: #dc3545; }
.status-reserved { background-color: #6f42c1; }
.maintenance-alert {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 0.25rem;
padding: 0.75rem;
margin-bottom: 1rem;
}
.filter-section {
background: #f8f9fa;
border-radius: 0.375rem;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.stat-card {
background: white;
border: 1px solid #dee2e6;
border-radius: 0.375rem;
padding: 1.5rem;
text-align: center;
}
.stat-number {
font-size: 2rem;
font-weight: bold;
color: #007bff;
margin-bottom: 0.5rem;
}
.stat-label {
color: #6c757d;
font-size: 0.875rem;
}
.equipment-actions {
display: flex;
justify-content: between;
gap: 0.5rem;
margin-top: 1rem;
}
@media (max-width: 768px) {
.equipment-header {
padding: 1.5rem;
}
.equipment-info {
grid-template-columns: 1fr;
}
.equipment-actions {
flex-direction: column;
}
}
</style>
{% endblock %}
{% block content %}
<div id="content" class="app-content">
<!-- Page Header -->
<div class="d-flex align-items-center mb-3">
<div>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'operating_theatre:dashboard' %}">Operating Theatre</a></li>
<li class="breadcrumb-item active">Equipment</li>
</ol>
<h1 class="page-header mb-0">
<i class="fas fa-tools me-2"></i>OR Equipment Management
</h1>
</div>
<div class="ms-auto">
<div class="btn-group">
<a href="{% url 'operating_theatre:equipment_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Add Equipment
</a>
<button class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-download me-1"></i>Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="exportEquipment('pdf')">
<i class="fas fa-file-pdf me-2"></i>PDF
</a></li>
<li><a class="dropdown-item" href="#" onclick="exportEquipment('excel')">
<i class="fas fa-file-excel me-2"></i>Excel
</a></li>
</ul>
</div>
</div>
</div>
<!-- Equipment Header -->
<div class="equipment-header">
<div class="row">
<div class="col-md-8">
<h2 class="mb-3">Equipment Inventory</h2>
<div class="row">
<div class="col-md-4">
<div class="mb-2">
<strong>Total Equipment:</strong> {{ stats.total_equipment }}
</div>
<div class="mb-2">
<strong>Available:</strong> {{ stats.available_equipment }}
</div>
</div>
<div class="col-md-4">
<div class="mb-2">
<strong>In Use:</strong> {{ stats.in_use_equipment }}
</div>
<div class="mb-2">
<strong>Maintenance:</strong> {{ stats.maintenance_equipment }}
</div>
</div>
<div class="col-md-4">
<div class="mb-2">
<strong>Out of Order:</strong> {{ stats.out_of_order_equipment }}
</div>
<div class="mb-2">
<strong>Utilization:</strong> {{ stats.utilization_percentage }}%
</div>
</div>
</div>
</div>
<div class="col-md-4 text-end">
<div class="mb-3">
<button class="btn btn-outline-light" onclick="scheduleMaintenanceCheck()">
<i class="fas fa-wrench me-1"></i>Schedule Maintenance
</button>
</div>
<div class="mb-2">
<button class="btn btn-outline-light" onclick="generateQRCodes()">
<i class="fas fa-qrcode me-1"></i>Generate QR Codes
</button>
</div>
</div>
</div>
</div>
<!-- Maintenance Alerts -->
{% if maintenance_alerts %}
<div class="maintenance-alert">
<h6 class="mb-2">
<i class="fas fa-exclamation-triangle me-2"></i>Maintenance Alerts
</h6>
<ul class="mb-0">
{% for alert in maintenance_alerts %}
<li>{{ alert.equipment_name }} - {{ alert.message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<!-- Statistics -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-number text-success">{{ stats.available_equipment }}</div>
<div class="stat-label">Available</div>
</div>
<div class="stat-card">
<div class="stat-number text-primary">{{ stats.in_use_equipment }}</div>
<div class="stat-label">In Use</div>
</div>
<div class="stat-card">
<div class="stat-number text-warning">{{ stats.maintenance_equipment }}</div>
<div class="stat-label">Maintenance</div>
</div>
<div class="stat-card">
<div class="stat-number text-danger">{{ stats.out_of_order_equipment }}</div>
<div class="stat-label">Out of Order</div>
</div>
</div>
<!-- Filters -->
<div class="filter-section">
<form method="get" id="filterForm">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label class="form-label">Category</label>
<select class="form-select" name="category">
<option value="">All Categories</option>
{% for category in equipment_categories %}
<option value="{{ category.0 }}" {% if request.GET.category == category.0 %}selected{% endif %}>
{{ category.1 }}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label class="form-label">Status</label>
<select class="form-select" name="status">
<option value="">All Status</option>
<option value="available" {% if request.GET.status == 'available' %}selected{% endif %}>Available</option>
<option value="in_use" {% if request.GET.status == 'in_use' %}selected{% endif %}>In Use</option>
<option value="maintenance" {% if request.GET.status == 'maintenance' %}selected{% endif %}>Maintenance</option>
<option value="out_of_order" {% if request.GET.status == 'out_of_order' %}selected{% endif %}>Out of Order</option>
</select>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label class="form-label">Location</label>
<select class="form-select" name="location">
<option value="">All Locations</option>
{% for room in operating_rooms %}
<option value="{{ room.id }}" {% if request.GET.location == room.id|stringformat:"s" %}selected{% endif %}>
{{ room.name }}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label class="form-label">Search</label>
<input type="text" class="form-control" name="search"
value="{{ request.GET.search }}" placeholder="Search equipment...">
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-12">
<button type="submit" class="btn btn-primary me-2">
<i class="fas fa-filter me-1"></i>Apply Filters
</button>
<a href="{% url 'operating_theatre:equipment_list' %}" class="btn btn-outline-secondary">
<i class="fas fa-times me-1"></i>Clear
</a>
</div>
</div>
</form>
</div>
<!-- Equipment Grid -->
<div class="row">
{% for equipment in equipment_list %}
<div class="col-lg-4 col-md-6">
<div class="equipment-card">
{% if equipment.image %}
<img src="{{ equipment.image.url }}" alt="{{ equipment.name }}" class="equipment-image">
{% else %}
<div class="equipment-image bg-light d-flex align-items-center justify-content-center">
<i class="fas fa-tools fa-3x text-muted"></i>
</div>
{% endif %}
<div class="equipment-content">
<div class="d-flex justify-content-between align-items-start mb-2">
<h5 class="mb-1">{{ equipment.name }}</h5>
<div>
<span class="status-indicator status-{{ equipment.status }}"></span>
{% if equipment.status == 'available' %}
<span class="badge bg-success">Available</span>
{% elif equipment.status == 'in_use' %}
<span class="badge bg-primary">In Use</span>
{% elif equipment.status == 'maintenance' %}
<span class="badge bg-warning">Maintenance</span>
{% elif equipment.status == 'out_of_order' %}
<span class="badge bg-danger">Out of Order</span>
{% elif equipment.status == 'reserved' %}
<span class="badge bg-info">Reserved</span>
{% endif %}
</div>
</div>
<div class="equipment-info">
<div class="info-item">
<div class="info-label">Serial Number</div>
<div class="info-value">{{ equipment.serial_number }}</div>
</div>
<div class="info-item">
<div class="info-label">Category</div>
<div class="info-value">{{ equipment.get_category_display }}</div>
</div>
<div class="info-item">
<div class="info-label">Manufacturer</div>
<div class="info-value">{{ equipment.manufacturer }}</div>
</div>
<div class="info-item">
<div class="info-label">Model</div>
<div class="info-value">{{ equipment.model }}</div>
</div>
<div class="info-item">
<div class="info-label">Location</div>
<div class="info-value">
{% if equipment.current_location %}
{{ equipment.current_location.name }}
{% else %}
<span class="text-muted">Not assigned</span>
{% endif %}
</div>
</div>
<div class="info-item">
<div class="info-label">Last Maintenance</div>
<div class="info-value">
{% if equipment.last_maintenance_date %}
{{ equipment.last_maintenance_date|date:"M d, Y" }}
{% else %}
<span class="text-muted">Never</span>
{% endif %}
</div>
</div>
</div>
{% if equipment.next_maintenance_due %}
<div class="mb-2">
<small class="text-muted">
<i class="fas fa-calendar-alt me-1"></i>
Next maintenance: {{ equipment.next_maintenance_due|date:"M d, Y" }}
</small>
</div>
{% endif %}
<div class="equipment-actions">
<div class="btn-group flex-fill">
<a href="{% url 'operating_theatre:equipment_detail' equipment.pk %}"
class="btn btn-outline-primary btn-sm">
<i class="fas fa-eye me-1"></i>View
</a>
<a href="{% url 'operating_theatre:equipment_edit' equipment.pk %}"
class="btn btn-outline-secondary btn-sm">
<i class="fas fa-edit me-1"></i>Edit
</a>
</div>
<div class="btn-group">
{% if equipment.status == 'available' %}
<button class="btn btn-success btn-sm" onclick="reserveEquipment('{{ equipment.pk }}')">
<i class="fas fa-lock me-1"></i>Reserve
</button>
{% elif equipment.status == 'reserved' %}
<button class="btn btn-warning btn-sm" onclick="releaseEquipment('{{ equipment.pk }}')">
<i class="fas fa-unlock me-1"></i>Release
</button>
{% endif %}
<div class="dropdown">
<button class="btn btn-outline-secondary btn-sm dropdown-toggle"
data-bs-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#" onclick="scheduleMaintenance('{{ equipment.pk }}')">
<i class="fas fa-wrench me-2"></i>Schedule Maintenance
</a>
</li>
<li>
<a class="dropdown-item" href="#" onclick="generateQR('{{ equipment.pk }}')">
<i class="fas fa-qrcode me-2"></i>Generate QR Code
</a>
</li>
<li>
<a class="dropdown-item" href="#" onclick="viewHistory('{{ equipment.pk }}')">
<i class="fas fa-history me-2"></i>View History
</a>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item text-danger" href="#" onclick="reportIssue('{{ equipment.pk }}')">
<i class="fas fa-exclamation-triangle me-2"></i>Report Issue
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
{% empty %}
<div class="col-12">
<div class="text-center py-5">
<i class="fas fa-tools fa-3x text-muted mb-3"></i>
<h5 class="text-muted">No equipment found</h5>
<p class="text-muted">No equipment matches the selected filters.</p>
<a href="{% url 'operating_theatre:equipment_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Add First Equipment
</a>
</div>
</div>
{% endfor %}
</div>
<!-- Pagination -->
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
</div>
{% endblock %}
{% block js %}
<script>
function reserveEquipment(equipmentId) {
if (confirm('Reserve this equipment?')) {
$.ajax({
url: `/operating-theatre/equipment/${equipmentId}/reserve/`,
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error reserving equipment: ' + response.error);
}
},
error: function() {
alert('Error reserving equipment');
}
});
}
}
function releaseEquipment(equipmentId) {
if (confirm('Release this equipment reservation?')) {
$.ajax({
url: `/operating-theatre/equipment/${equipmentId}/release/`,
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error releasing equipment: ' + response.error);
}
},
error: function() {
alert('Error releasing equipment');
}
});
}
}
function scheduleMaintenance(equipmentId) {
window.location.href = `/operating-theatre/equipment/${equipmentId}/maintenance/schedule/`;
}
function generateQR(equipmentId) {
window.open(`/operating-theatre/equipment/${equipmentId}/qr-code/`, '_blank');
}
function viewHistory(equipmentId) {
window.location.href = `/operating-theatre/equipment/${equipmentId}/history/`;
}
function reportIssue(equipmentId) {
window.location.href = `/operating-theatre/equipment/${equipmentId}/report-issue/`;
}
function scheduleMaintenanceCheck() {
window.location.href = '/operating-theatre/maintenance/schedule/';
}
function generateQRCodes() {
window.open('/operating-theatre/equipment/qr-codes/bulk/', '_blank');
}
function exportEquipment(format) {
window.location.href = `/operating-theatre/equipment/export/?format=${format}`;
}
// Auto-submit form on filter change
$('#filterForm select').on('change', function() {
$('#filterForm').submit();
});
</script>
{% endblock %}