741 lines
35 KiB
HTML
741 lines
35 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}{% if object %}Edit Vital Signs{% else %}Record Vital Signs{% endif %} - {{ 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">
|
|
{% if object %}
|
|
<i class="fas fa-edit me-2"></i>Edit Vital Signs
|
|
{% else %}
|
|
<i class="fas fa-heartbeat me-2"></i>Record Vital Signs
|
|
{% endif %}
|
|
</h1>
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb mb-0">
|
|
<li class="breadcrumb-item"><a href="{% url 'emr:dashboard' %}">EMR</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'emr:vital_signs_list' %}">Vital Signs</a></li>
|
|
{% if object %}
|
|
<li class="breadcrumb-item active">Edit</li>
|
|
{% else %}
|
|
<li class="breadcrumb-item active">New</li>
|
|
{% endif %}
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
<div class="btn-group">
|
|
<a href="{% url 'emr:vital_signs_list' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-arrow-left me-2"></i>Back to List
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<form method="post" novalidate>
|
|
{% csrf_token %}
|
|
|
|
<div class="row">
|
|
<!-- Main Form -->
|
|
<div class="col-lg-8">
|
|
<!-- Patient Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-user me-2"></i>Patient Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="{{ form.patient.id_for_label }}" class="form-label">
|
|
Patient <span class="text-danger">*</span>
|
|
</label>
|
|
{{ form.patient }}
|
|
{% if form.patient.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.patient.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="{{ form.encounter.id_for_label }}" class="form-label">
|
|
Encounter
|
|
</label>
|
|
{{ form.encounter }}
|
|
{% if form.encounter.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.encounter.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
<div class="form-text">Optional: Associate with specific encounter</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="{{ form.measured_datetime.id_for_label }}" class="form-label">
|
|
Measurement Date & Time <span class="text-danger">*</span>
|
|
</label>
|
|
{{ form.measured_datetime }}
|
|
{% if form.measured_datetime.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.measured_datetime.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="{{ form.measured_by.id_for_label }}" class="form-label">
|
|
Measured By
|
|
</label>
|
|
{{ form.measured_by }}
|
|
{% if form.measured_by.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.measured_by.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Vital Signs Measurements -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-thermometer-half me-2"></i>Vital Signs Measurements
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<!-- Blood Pressure -->
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<h6 class="text-primary mb-3">
|
|
<i class="fas fa-heart me-2"></i>Blood Pressure
|
|
</h6>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.systolic_bp.id_for_label }}" class="form-label">
|
|
Systolic (mmHg)
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.systolic_bp }}
|
|
<span class="input-group-text">mmHg</span>
|
|
</div>
|
|
{% if form.systolic_bp.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.systolic_bp.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.diastolic_bp.id_for_label }}" class="form-label">
|
|
Diastolic (mmHg)
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.diastolic_bp }}
|
|
<span class="input-group-text">mmHg</span>
|
|
</div>
|
|
{% if form.diastolic_bp.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.diastolic_bp.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.bp_position.id_for_label }}" class="form-label">
|
|
Position
|
|
</label>
|
|
{{ form.bp_position }}
|
|
{% if form.bp_position.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.bp_position.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.bp_cuff_size.id_for_label }}" class="form-label">
|
|
Cuff Size
|
|
</label>
|
|
{{ form.bp_cuff_size }}
|
|
{% if form.bp_cuff_size.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.bp_cuff_size.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Heart Rate and Temperature -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.heart_rate.id_for_label }}" class="form-label">
|
|
<i class="fas fa-heartbeat me-1"></i>Heart Rate
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.heart_rate }}
|
|
<span class="input-group-text">bpm</span>
|
|
</div>
|
|
{% if form.heart_rate.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.heart_rate.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.temperature.id_for_label }}" class="form-label">
|
|
<i class="fas fa-thermometer-half me-1"></i>Temperature
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.temperature }}
|
|
<span class="input-group-text">°F</span>
|
|
</div>
|
|
{% if form.temperature.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.temperature.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.temperature_route.id_for_label }}" class="form-label">
|
|
Temperature Route
|
|
</label>
|
|
{{ form.temperature_route }}
|
|
{% if form.temperature_route.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.temperature_route.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.respiratory_rate.id_for_label }}" class="form-label">
|
|
<i class="fas fa-lungs me-1"></i>Respiratory Rate
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.respiratory_rate }}
|
|
<span class="input-group-text">rpm</span>
|
|
</div>
|
|
{% if form.respiratory_rate.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.respiratory_rate.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Oxygen and Physical Measurements -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.oxygen_saturation.id_for_label }}" class="form-label">
|
|
<i class="fas fa-lungs me-1"></i>Oxygen Saturation
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.oxygen_saturation }}
|
|
<span class="input-group-text">%</span>
|
|
</div>
|
|
{% if form.oxygen_saturation.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.oxygen_saturation.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.height.id_for_label }}" class="form-label">
|
|
<i class="fas fa-ruler-vertical me-1"></i>Height
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.height }}
|
|
<span class="input-group-text">cm</span>
|
|
</div>
|
|
{% if form.height.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.height.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label for="{{ form.weight.id_for_label }}" class="form-label">
|
|
<i class="fas fa-weight me-1"></i>Weight
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.weight }}
|
|
<span class="input-group-text">kg</span>
|
|
</div>
|
|
{% if form.weight.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.weight.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="mb-3">
|
|
<label class="form-label">
|
|
<i class="fas fa-calculator me-1"></i>BMI
|
|
</label>
|
|
<div class="input-group">
|
|
<input type="text" class="form-control" id="bmi_display" readonly placeholder="Auto-calculated">
|
|
<span class="input-group-text">kg/m²</span>
|
|
</div>
|
|
<div class="form-text">Automatically calculated from height and weight</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Pain and Additional Measurements -->
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="mb-3">
|
|
<label for="{{ form.pain_scale.id_for_label }}" class="form-label">
|
|
<i class="fas fa-exclamation-triangle me-1"></i>Pain Scale (0-10)
|
|
</label>
|
|
{{ form.pain_scale }}
|
|
{% if form.pain_scale.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.pain_scale.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
<div class="form-text">0 = No pain, 10 = Worst possible pain</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="mb-3">
|
|
<label for="{{ form.blood_glucose.id_for_label }}" class="form-label">
|
|
<i class="fas fa-tint me-1"></i>Blood Glucose
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.blood_glucose }}
|
|
<span class="input-group-text">mg/dL</span>
|
|
</div>
|
|
{% if form.blood_glucose.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.blood_glucose.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="mb-3">
|
|
<label for="{{ form.head_circumference.id_for_label }}" class="form-label">
|
|
<i class="fas fa-circle me-1"></i>Head Circumference
|
|
</label>
|
|
<div class="input-group">
|
|
{{ form.head_circumference }}
|
|
<span class="input-group-text">cm</span>
|
|
</div>
|
|
{% if form.head_circumference.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.head_circumference.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
<div class="form-text">Typically for pediatric patients</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Additional Information -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-notes-medical me-2"></i>Additional Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label for="{{ form.notes.id_for_label }}" class="form-label">
|
|
Clinical Notes
|
|
</label>
|
|
{{ form.notes }}
|
|
{% if form.notes.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.notes.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
<div class="form-text">Any additional observations or notes about the vital signs</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="{{ form.device_used.id_for_label }}" class="form-label">
|
|
Device Used
|
|
</label>
|
|
{{ form.device_used }}
|
|
{% if form.device_used.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.device_used.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label for="{{ form.location.id_for_label }}" class="form-label">
|
|
Location
|
|
</label>
|
|
{{ form.location }}
|
|
{% if form.location.errors %}
|
|
<div class="invalid-feedback d-block">
|
|
{{ form.location.errors.0 }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="col-lg-4">
|
|
<!-- Critical Values Alert -->
|
|
<div class="card mb-4" id="critical-values-card" style="display: none;">
|
|
<div class="card-header bg-danger text-white">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>Critical Values Detected
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="critical-values-list"></div>
|
|
<div class="alert alert-warning mt-3 mb-0">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
<small>Please verify these values and notify the physician immediately if confirmed.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Normal Ranges Reference -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-chart-line me-2"></i>Normal Ranges
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="accordion" id="normalRangesAccordion">
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#adultRanges">
|
|
Adult Normal Ranges
|
|
</button>
|
|
</h2>
|
|
<div id="adultRanges" class="accordion-collapse collapse" data-bs-parent="#normalRangesAccordion">
|
|
<div class="accordion-body">
|
|
<ul class="list-unstyled mb-0">
|
|
<li><strong>Blood Pressure:</strong> 90-120/60-80 mmHg</li>
|
|
<li><strong>Heart Rate:</strong> 60-100 bpm</li>
|
|
<li><strong>Temperature:</strong> 97.8-99.1°F</li>
|
|
<li><strong>Respiratory Rate:</strong> 12-20 rpm</li>
|
|
<li><strong>Oxygen Saturation:</strong> 95-100%</li>
|
|
<li><strong>BMI:</strong> 18.5-24.9 kg/m²</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#pediatricRanges">
|
|
Pediatric Ranges
|
|
</button>
|
|
</h2>
|
|
<div id="pediatricRanges" class="accordion-collapse collapse" data-bs-parent="#normalRangesAccordion">
|
|
<div class="accordion-body">
|
|
<p class="text-muted mb-2">Ranges vary by age. Consult pediatric reference charts.</p>
|
|
<ul class="list-unstyled mb-0">
|
|
<li><strong>Newborn HR:</strong> 120-160 bpm</li>
|
|
<li><strong>Infant HR:</strong> 80-140 bpm</li>
|
|
<li><strong>Child HR:</strong> 70-120 bpm</li>
|
|
<li><strong>Adolescent HR:</strong> 60-90 bpm</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">
|
|
<i class="fas fa-cog me-2"></i>Actions
|
|
</h5>
|
|
</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>
|
|
{% if object %}Update Vital Signs{% else %}Record Vital Signs{% endif %}
|
|
</button>
|
|
<a href="{% url 'emr:vital_signs_list' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-times me-2"></i>Cancel
|
|
</a>
|
|
<button type="button" class="btn btn-outline-info" onclick="clearForm()">
|
|
<i class="fas fa-eraser me-2"></i>Clear Form
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<script>
|
|
// Vital signs form functionality
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Add Bootstrap classes to form elements
|
|
const form = document.querySelector('form');
|
|
const inputs = form.querySelectorAll('input, select, textarea');
|
|
|
|
inputs.forEach(input => {
|
|
if (!input.classList.contains('form-control') && !input.classList.contains('form-select')) {
|
|
if (input.tagName === 'SELECT') {
|
|
input.classList.add('form-select');
|
|
} else {
|
|
input.classList.add('form-control');
|
|
}
|
|
}
|
|
});
|
|
|
|
// Set default measurement time to now if creating new record
|
|
{% if not object %}
|
|
const measuredDatetime = document.getElementById('{{ form.measured_datetime.id_for_label }}');
|
|
if (measuredDatetime && !measuredDatetime.value) {
|
|
const now = new Date();
|
|
const localISOTime = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString().slice(0, 16);
|
|
measuredDatetime.value = localISOTime;
|
|
}
|
|
{% endif %}
|
|
|
|
// BMI calculation
|
|
const heightInput = document.getElementById('{{ form.height.id_for_label }}');
|
|
const weightInput = document.getElementById('{{ form.weight.id_for_label }}');
|
|
const bmiDisplay = document.getElementById('bmi_display');
|
|
|
|
function calculateBMI() {
|
|
const height = parseFloat(heightInput.value);
|
|
const weight = parseFloat(weightInput.value);
|
|
|
|
if (height && weight && height > 0) {
|
|
const heightInMeters = height / 100;
|
|
const bmi = weight / (heightInMeters * heightInMeters);
|
|
bmiDisplay.value = bmi.toFixed(1);
|
|
|
|
// Add BMI category
|
|
let category = '';
|
|
if (bmi < 18.5) category = ' (Underweight)';
|
|
else if (bmi < 25) category = ' (Normal)';
|
|
else if (bmi < 30) category = ' (Overweight)';
|
|
else category = ' (Obese)';
|
|
|
|
bmiDisplay.value += category;
|
|
} else {
|
|
bmiDisplay.value = '';
|
|
}
|
|
}
|
|
|
|
if (heightInput && weightInput) {
|
|
heightInput.addEventListener('input', calculateBMI);
|
|
weightInput.addEventListener('input', calculateBMI);
|
|
calculateBMI(); // Calculate on page load
|
|
}
|
|
|
|
// Critical values monitoring
|
|
const criticalRanges = {
|
|
systolic_bp: { min: 90, max: 180, unit: 'mmHg' },
|
|
diastolic_bp: { min: 60, max: 110, unit: 'mmHg' },
|
|
heart_rate: { min: 60, max: 100, unit: 'bpm' },
|
|
temperature: { min: 97.0, max: 100.4, unit: '°F' },
|
|
respiratory_rate: { min: 12, max: 20, unit: 'rpm' },
|
|
oxygen_saturation: { min: 95, max: 100, unit: '%' }
|
|
};
|
|
|
|
function checkCriticalValues() {
|
|
const criticalValues = [];
|
|
|
|
Object.keys(criticalRanges).forEach(fieldName => {
|
|
const input = document.getElementById(`id_${fieldName}`);
|
|
if (input && input.value) {
|
|
const value = parseFloat(input.value);
|
|
const range = criticalRanges[fieldName];
|
|
|
|
if (value < range.min || value > range.max) {
|
|
criticalValues.push({
|
|
field: fieldName.replace('_', ' ').toUpperCase(),
|
|
value: value,
|
|
unit: range.unit,
|
|
range: `${range.min}-${range.max} ${range.unit}`
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
const criticalCard = document.getElementById('critical-values-card');
|
|
const criticalList = document.getElementById('critical-values-list');
|
|
|
|
if (criticalValues.length > 0) {
|
|
criticalList.innerHTML = criticalValues.map(cv =>
|
|
`<div class="alert alert-danger py-2 mb-2">
|
|
<strong>${cv.field}:</strong> ${cv.value} ${cv.unit}<br>
|
|
<small>Normal: ${cv.range}</small>
|
|
</div>`
|
|
).join('');
|
|
criticalCard.style.display = 'block';
|
|
} else {
|
|
criticalCard.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// Add event listeners for critical value checking
|
|
Object.keys(criticalRanges).forEach(fieldName => {
|
|
const input = document.getElementById(`id_${fieldName}`);
|
|
if (input) {
|
|
input.addEventListener('input', checkCriticalValues);
|
|
}
|
|
});
|
|
|
|
// Check on page load
|
|
checkCriticalValues();
|
|
});
|
|
|
|
function clearForm() {
|
|
if (confirm('Are you sure you want to clear all form data?')) {
|
|
const form = document.querySelector('form');
|
|
const inputs = form.querySelectorAll('input, select, textarea');
|
|
|
|
inputs.forEach(input => {
|
|
if (input.type !== 'hidden' && input.name !== 'csrfmiddlewaretoken') {
|
|
if (input.type === 'checkbox') {
|
|
input.checked = false;
|
|
} else {
|
|
input.value = '';
|
|
}
|
|
}
|
|
});
|
|
|
|
// Reset BMI display
|
|
document.getElementById('bmi_display').value = '';
|
|
|
|
// Hide critical values card
|
|
document.getElementById('critical-values-card').style.display = 'none';
|
|
|
|
// Set default measurement time
|
|
{% if not object %}
|
|
const measuredDatetime = document.getElementById('{{ form.measured_datetime.id_for_label }}');
|
|
if (measuredDatetime) {
|
|
const now = new Date();
|
|
const localISOTime = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString().slice(0, 16);
|
|
measuredDatetime.value = localISOTime;
|
|
}
|
|
{% endif %}
|
|
}
|
|
}
|
|
|
|
// Form submission with loading state
|
|
document.querySelector('form').addEventListener('submit', function() {
|
|
const submitBtn = document.querySelector('button[type="submit"]');
|
|
const originalText = submitBtn.innerHTML;
|
|
|
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Saving...';
|
|
submitBtn.disabled = true;
|
|
|
|
// Re-enable if form validation fails
|
|
setTimeout(() => {
|
|
if (document.querySelector('.is-invalid')) {
|
|
submitBtn.innerHTML = originalText;
|
|
submitBtn.disabled = false;
|
|
}
|
|
}, 100);
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.input-group-text {
|
|
background-color: #f8f9fa;
|
|
border-color: #ced4da;
|
|
}
|
|
|
|
.is-invalid {
|
|
border-color: #dc3545;
|
|
}
|
|
|
|
.invalid-feedback {
|
|
display: block;
|
|
width: 100%;
|
|
margin-top: 0.25rem;
|
|
font-size: 0.875em;
|
|
color: #dc3545;
|
|
}
|
|
|
|
.accordion-button:not(.collapsed) {
|
|
background-color: #e7f1ff;
|
|
color: #0d6efd;
|
|
}
|
|
|
|
.card-header.bg-danger {
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.alert-danger {
|
|
border-left: 4px solid #dc3545;
|
|
}
|
|
|
|
.alert-warning {
|
|
border-left: 4px solid #ffc107;
|
|
}
|
|
|
|
#bmi_display {
|
|
background-color: #f8f9fa;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.text-primary {
|
|
color: #0d6efd !important;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.row.mb-4 .col-md-3,
|
|
.row.mb-4 .col-md-4,
|
|
.row.mb-4 .col-md-6 {
|
|
margin-bottom: 1rem;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|