533 lines
24 KiB
HTML
533 lines
24 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}{% if object %}Edit Equipment - {{ object.name }}{% else %}Add New Equipment{% endif %}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="d-flex align-items-center mb-3">
|
|
<div>
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{% url 'radiology:dashboard' %}">Radiology</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'radiology:equipment_list' %}">Equipment</a></li>
|
|
{% if object %}
|
|
<li class="breadcrumb-item"><a href="{% url 'radiology:equipment_detail' object.pk %}">{{ object.name }}</a></li>
|
|
<li class="breadcrumb-item active">Edit</li>
|
|
{% else %}
|
|
<li class="breadcrumb-item active">Add Equipment</li>
|
|
{% endif %}
|
|
</ol>
|
|
<h1 class="page-header mb-0">
|
|
{% if object %}Edit Equipment{% else %}Add New Equipment{% endif %}
|
|
</h1>
|
|
</div>
|
|
<div class="ms-auto">
|
|
{% if object %}
|
|
<a href="{% url 'radiology:equipment_detail' object.pk %}" class="btn btn-secondary">
|
|
<i class="fas fa-times me-2"></i>Cancel
|
|
</a>
|
|
{% else %}
|
|
<a href="{% url 'radiology:equipment_list' %}" class="btn btn-secondary">
|
|
<i class="fas fa-times me-2"></i>Cancel
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<form method="post" id="equipmentForm" novalidate>
|
|
{% csrf_token %}
|
|
|
|
<div class="row">
|
|
<div class="col-xl-8">
|
|
<!-- Basic Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
Basic Information
|
|
</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Equipment Name <span class="text-danger">*</span></label>
|
|
{{ form.name }}
|
|
{% if form.name.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.name.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Descriptive name for the equipment</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Modality <span class="text-danger">*</span></label>
|
|
{{ form.modality }}
|
|
{% if form.modality.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.modality.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Manufacturer</label>
|
|
{{ form.manufacturer }}
|
|
{% if form.manufacturer.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.manufacturer.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Model</label>
|
|
{{ form.model }}
|
|
{% if form.model.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.model.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Serial Number</label>
|
|
{{ form.serial_number }}
|
|
{% if form.serial_number.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.serial_number.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Asset Tag</label>
|
|
{{ form.asset_tag }}
|
|
{% if form.asset_tag.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.asset_tag.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Hospital asset tracking number</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Location <span class="text-danger">*</span></label>
|
|
{{ form.location }}
|
|
{% if form.location.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.location.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Room Number</label>
|
|
{{ form.room_number }}
|
|
{% if form.room_number.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.room_number.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Description</label>
|
|
{{ form.description }}
|
|
{% if form.description.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.description.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Additional details about the equipment</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Purchase and Warranty Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">
|
|
<i class="fas fa-receipt me-2"></i>
|
|
Purchase and Warranty Information
|
|
</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Purchase Date</label>
|
|
{{ form.purchase_date }}
|
|
{% if form.purchase_date.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.purchase_date.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Installation Date</label>
|
|
{{ form.installation_date }}
|
|
{% if form.installation_date.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.installation_date.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Purchase Cost</label>
|
|
{{ form.purchase_cost }}
|
|
{% if form.purchase_cost.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.purchase_cost.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Vendor</label>
|
|
{{ form.vendor }}
|
|
{% if form.vendor.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.vendor.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Warranty Start Date</label>
|
|
{{ form.warranty_start }}
|
|
{% if form.warranty_start.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.warranty_start.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Warranty Expiry Date</label>
|
|
{{ form.warranty_expiry }}
|
|
{% if form.warranty_expiry.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.warranty_expiry.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Technical Specifications -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">
|
|
<i class="fas fa-cogs me-2"></i>
|
|
Technical Specifications
|
|
</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Power Requirements</label>
|
|
{{ form.power_requirements }}
|
|
{% if form.power_requirements.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.power_requirements.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">e.g., 220V, 50Hz, 30A</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Dimensions</label>
|
|
{{ form.dimensions }}
|
|
{% if form.dimensions.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.dimensions.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Length x Width x Height</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Weight</label>
|
|
{{ form.weight }}
|
|
{% if form.weight.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.weight.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Equipment weight in kg</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Software Version</label>
|
|
{{ form.software_version }}
|
|
{% if form.software_version.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.software_version.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Additional Specifications</label>
|
|
{{ form.additional_specs }}
|
|
{% if form.additional_specs.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.additional_specs.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Any other technical specifications or notes</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-4">
|
|
<!-- Equipment Status -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Equipment Status</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Current Status</label>
|
|
{{ form.status }}
|
|
{% if form.status.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.status.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
{{ form.is_active }}
|
|
<label class="form-check-label" for="{{ form.is_active.id_for_label }}">
|
|
Equipment is active
|
|
</label>
|
|
</div>
|
|
<div class="form-text">Active equipment can be scheduled for studies</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
{{ form.requires_contrast }}
|
|
<label class="form-check-label" for="{{ form.requires_contrast.id_for_label }}">
|
|
Requires contrast capability
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
{{ form.portable }}
|
|
<label class="form-check-label" for="{{ form.portable.id_for_label }}">
|
|
Portable equipment
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Service Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Service Information</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Service Provider</label>
|
|
{{ form.service_provider }}
|
|
{% if form.service_provider.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.service_provider.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Service Contract Number</label>
|
|
{{ form.service_contract_number }}
|
|
{% if form.service_contract_number.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.service_contract_number.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Service Interval (days)</label>
|
|
{{ form.service_interval_days }}
|
|
{% if form.service_interval_days.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.service_interval_days.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">How often service is required</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Last Service Date</label>
|
|
{{ form.last_service_date }}
|
|
{% if form.last_service_date.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.last_service_date.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Contact Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Contact Information</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Technical Support Contact</label>
|
|
{{ form.tech_support_contact }}
|
|
{% if form.tech_support_contact.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.tech_support_contact.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Technical Support Phone</label>
|
|
{{ form.tech_support_phone }}
|
|
{% if form.tech_support_phone.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.tech_support_phone.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Emergency Contact</label>
|
|
{{ form.emergency_contact }}
|
|
{% if form.emergency_contact.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.emergency_contact.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Emergency Phone</label>
|
|
{{ form.emergency_phone }}
|
|
{% if form.emergency_phone.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.emergency_phone.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Actions</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-save me-2"></i>Save Equipment
|
|
</button>
|
|
{% if object %}
|
|
<button type="button" class="btn btn-outline-info" onclick="generateQRCode()">
|
|
<i class="fas fa-qrcode me-2"></i>Generate QR Code
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary" onclick="duplicateEquipment()">
|
|
<i class="fas fa-copy me-2"></i>Duplicate
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Form validation
|
|
const form = document.getElementById('equipmentForm');
|
|
form.addEventListener('submit', function(e) {
|
|
if (!validateForm()) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
// Auto-calculate next service date
|
|
const lastServiceInput = document.querySelector('input[name="last_service_date"]');
|
|
const serviceIntervalInput = document.querySelector('input[name="service_interval_days"]');
|
|
|
|
if (lastServiceInput && serviceIntervalInput) {
|
|
function calculateNextService() {
|
|
const lastService = new Date(lastServiceInput.value);
|
|
const interval = parseInt(serviceIntervalInput.value);
|
|
|
|
if (lastService && interval) {
|
|
const nextService = new Date(lastService);
|
|
nextService.setDate(nextService.getDate() + interval);
|
|
|
|
// Display calculated date (if there's a field for it)
|
|
console.log('Next service due:', nextService.toDateString());
|
|
}
|
|
}
|
|
|
|
lastServiceInput.addEventListener('change', calculateNextService);
|
|
serviceIntervalInput.addEventListener('change', calculateNextService);
|
|
}
|
|
|
|
// Modality-specific field handling
|
|
const modalitySelect = document.querySelector('select[name="modality"]');
|
|
if (modalitySelect) {
|
|
modalitySelect.addEventListener('change', function() {
|
|
handleModalityChange(this.value);
|
|
});
|
|
|
|
// Initialize on page load
|
|
handleModalityChange(modalitySelect.value);
|
|
}
|
|
});
|
|
|
|
function validateForm() {
|
|
const requiredFields = ['name', 'modality', 'location'];
|
|
let isValid = true;
|
|
|
|
requiredFields.forEach(field => {
|
|
const input = document.querySelector(`[name="${field}"]`);
|
|
if (input && !input.value.trim()) {
|
|
isValid = false;
|
|
input.classList.add('is-invalid');
|
|
|
|
// Show error message
|
|
let errorDiv = input.parentNode.querySelector('.invalid-feedback');
|
|
if (!errorDiv) {
|
|
errorDiv = document.createElement('div');
|
|
errorDiv.className = 'invalid-feedback d-block';
|
|
input.parentNode.appendChild(errorDiv);
|
|
}
|
|
errorDiv.textContent = 'This field is required.';
|
|
} else if (input) {
|
|
input.classList.remove('is-invalid');
|
|
}
|
|
});
|
|
|
|
return isValid;
|
|
}
|
|
|
|
function handleModalityChange(modality) {
|
|
// Show/hide fields based on modality
|
|
const contrastField = document.querySelector('input[name="requires_contrast"]').closest('.form-check');
|
|
|
|
if (modality === 'ct' || modality === 'mri') {
|
|
contrastField.style.display = 'block';
|
|
} else {
|
|
contrastField.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function generateQRCode() {
|
|
if (confirm('Generate QR code for this equipment?')) {
|
|
window.open('{% url "radiology:equipment_detail" object.pk %}?action=qr_code', '_blank');
|
|
}
|
|
}
|
|
|
|
function duplicateEquipment() {
|
|
if (confirm('Create a copy of this equipment?')) {
|
|
window.location.href = '{% url "radiology:equipment_create" %}?duplicate={{ object.pk }}';
|
|
}
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|