754 lines
36 KiB
HTML
754 lines
36 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}{% if object %}Edit{% else %}New{% endif %} Medication - Pharmacy{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- BEGIN breadcrumb -->
|
|
<ol class="breadcrumb float-xl-end">
|
|
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'pharmacy:dashboard' %}">Pharmacy</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'pharmacy:medication_list' %}">Medications</a></li>
|
|
{% if object %}
|
|
<li class="breadcrumb-item"><a href="{% url 'pharmacy:medication_detail' object.pk %}">{{ object.name }}</a></li>
|
|
<li class="breadcrumb-item active">Edit</li>
|
|
{% else %}
|
|
<li class="breadcrumb-item active">New</li>
|
|
{% endif %}
|
|
</ol>
|
|
<!-- END breadcrumb -->
|
|
|
|
<!-- BEGIN page-header -->
|
|
<h1 class="page-header">
|
|
{% if object %}Edit Medication{% else %}New Medication{% endif %}
|
|
<small>{% if object %}{{ object.name }}{% else %}Add new medication to formulary{% endif %}</small>
|
|
</h1>
|
|
<!-- END page-header -->
|
|
|
|
<div class="row">
|
|
<div class="col-xl-8">
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Medication Details</h4>
|
|
<div class="panel-heading-btn">
|
|
<button type="button" class="btn btn-xs btn-info me-2" onclick="validateNDC()">
|
|
<i class="fa fa-check"></i> Validate NDC
|
|
</button>
|
|
<button type="button" class="btn btn-xs btn-secondary me-2" onclick="saveDraft()">
|
|
<i class="fa fa-save"></i> Save Draft
|
|
</button>
|
|
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
|
</div>
|
|
</div>
|
|
<div class="panel-body">
|
|
<form method="post" id="medication-form" novalidate>
|
|
{% csrf_token %}
|
|
|
|
<!-- Basic Information -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
{{ form.generic_name }}
|
|
<label for="{{ form.generic_name.id_for_label }}">Generic Name <span class="text-danger">*</span></label>
|
|
{% if form.generic_name.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.generic_name.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Official generic name of the medication.</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
{{ form.brand_name }}
|
|
<label for="{{ form.brand_name.id_for_label }}">Brand Name</label>
|
|
{% if form.brand_name.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.brand_name.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Commercial brand name (if applicable).</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Identification -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-4">
|
|
<div class="form-floating">
|
|
{{ form.ndc_number }}
|
|
<label for="{{ form.ndc_number.id_for_label }}">NDC Number</label>
|
|
{% if form.ndc_number.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.ndc_number.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">National Drug Code number.</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-floating">
|
|
{{ form.manufacturer }}
|
|
<label for="{{ form.manufacturer.id_for_label }}">Manufacturer</label>
|
|
{% if form.manufacturer.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.manufacturer.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Medication manufacturer.</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-floating">
|
|
{{ form.barcode }}
|
|
<label for="{{ form.barcode.id_for_label }}">Barcode</label>
|
|
{% if form.barcode.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.barcode.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Product barcode for scanning.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Classification -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-4">
|
|
<div class="form-floating">
|
|
{{ form.category }}
|
|
<label for="{{ form.category.id_for_label }}">Category <span class="text-danger">*</span></label>
|
|
{% if form.category.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.category.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Therapeutic category.</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-floating">
|
|
{{ form.dosage_form }}
|
|
<label for="{{ form.dosage_form.id_for_label }}">Dosage Form <span class="text-danger">*</span></label>
|
|
{% if form.dosage_form.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.dosage_form.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Physical form of medication.</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-floating">
|
|
{{ form.route }}
|
|
<label for="{{ form.route.id_for_label }}">Route <span class="text-danger">*</span></label>
|
|
{% if form.route.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.route.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Route of administration.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Strength and Units -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
{{ form.strength }}
|
|
<label for="{{ form.strength.id_for_label }}">Strength <span class="text-danger">*</span></label>
|
|
{% if form.strength.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.strength.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Medication strength (e.g., 500mg, 10mg/ml).</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
{{ form.unit_of_measure }}
|
|
<label for="{{ form.unit_of_measure.id_for_label }}">Unit of Measure</label>
|
|
{% if form.unit_of_measure.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.unit_of_measure.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">Unit for dispensing (tablets, ml, etc.).</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Special Properties -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-3">
|
|
<div class="form-check">
|
|
{{ form.is_controlled }}
|
|
<label class="form-check-label" for="{{ form.is_controlled.id_for_label }}">
|
|
<i class="fa fa-shield text-warning me-1"></i>Controlled substance
|
|
</label>
|
|
{% if form.is_controlled.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_controlled.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">DEA controlled substance.</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-check">
|
|
{{ form.is_high_alert }}
|
|
<label class="form-check-label" for="{{ form.is_high_alert.id_for_label }}">
|
|
<i class="fa fa-exclamation-triangle text-danger me-1"></i>High alert medication
|
|
</label>
|
|
{% if form.is_high_alert.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_high_alert.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Requires extra caution.</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-check">
|
|
{{ form.requires_refrigeration }}
|
|
<label class="form-check-label" for="{{ form.requires_refrigeration.id_for_label }}">
|
|
<i class="fa fa-snowflake text-info me-1"></i>Requires refrigeration
|
|
</label>
|
|
{% if form.requires_refrigeration.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.requires_refrigeration.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Cold storage required.</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-check">
|
|
{{ form.is_generic }}
|
|
<label class="form-check-label" for="{{ form.is_generic.id_for_label }}">
|
|
<i class="fa fa-check text-success me-1"></i>Generic available
|
|
</label>
|
|
{% if form.is_generic.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_generic.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Generic version available.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Controlled Substance Information -->
|
|
<div id="controlled-info" class="card border-warning mb-3" style="display: none;">
|
|
<div class="card-header bg-warning text-dark">
|
|
<h6 class="card-title mb-0">
|
|
<i class="fa fa-shield me-2"></i>Controlled Substance Information
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.controlled_schedule }}
|
|
<label for="{{ form.controlled_schedule.id_for_label }}">Schedule</label>
|
|
{% if form.controlled_schedule.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.controlled_schedule.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.dea_class }}
|
|
<label for="{{ form.dea_class.id_for_label }}">DEA Class</label>
|
|
{% if form.dea_class.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.dea_class.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="alert alert-warning">
|
|
<i class="fa fa-exclamation-triangle me-2"></i>
|
|
This medication is classified as a controlled substance and requires special handling.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clinical Information -->
|
|
<div class="card border-primary mb-3">
|
|
<div class="card-header bg-primary text-white">
|
|
<h6 class="card-title mb-0">
|
|
<i class="fa fa-stethoscope me-2"></i>Clinical Information
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label for="{{ form.indications.id_for_label }}" class="form-label">Indications</label>
|
|
{{ form.indications }}
|
|
{% if form.indications.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.indications.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Approved uses and indications.</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.contraindications.id_for_label }}" class="form-label">Contraindications</label>
|
|
{{ form.contraindications }}
|
|
{% if form.contraindications.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.contraindications.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Conditions where medication should not be used.</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.side_effects.id_for_label }}" class="form-label">Side Effects</label>
|
|
{{ form.side_effects }}
|
|
{% if form.side_effects.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.side_effects.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Common and serious side effects.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dosage Information -->
|
|
<div class="card border-success mb-3">
|
|
<div class="card-header bg-success text-white">
|
|
<h6 class="card-title mb-0">
|
|
<i class="fa fa-calculator me-2"></i>Dosage Information
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="form-floating mb-3">
|
|
{{ form.usual_adult_dose }}
|
|
<label for="{{ form.usual_adult_dose.id_for_label }}">Usual Adult Dose</label>
|
|
{% if form.usual_adult_dose.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.usual_adult_dose.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-floating mb-3">
|
|
{{ form.usual_pediatric_dose }}
|
|
<label for="{{ form.usual_pediatric_dose.id_for_label }}">Usual Pediatric Dose</label>
|
|
{% if form.usual_pediatric_dose.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.usual_pediatric_dose.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-floating mb-3">
|
|
{{ form.maximum_dose }}
|
|
<label for="{{ form.maximum_dose.id_for_label }}">Maximum Dose</label>
|
|
{% if form.maximum_dose.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.maximum_dose.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Storage Information -->
|
|
<div class="card border-warning mb-3">
|
|
<div class="card-header bg-warning text-dark">
|
|
<h6 class="card-title mb-0">
|
|
<i class="fa fa-warehouse me-2"></i>Storage and Handling
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.storage_temperature }}
|
|
<label for="{{ form.storage_temperature.id_for_label }}">Storage Temperature</label>
|
|
{% if form.storage_temperature.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.storage_temperature.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.shelf_life }}
|
|
<label for="{{ form.shelf_life.id_for_label }}">Shelf Life</label>
|
|
{% if form.shelf_life.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.shelf_life.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.storage_conditions.id_for_label }}" class="form-label">Storage Conditions</label>
|
|
{{ form.storage_conditions }}
|
|
{% if form.storage_conditions.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.storage_conditions.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Special storage requirements.</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.special_handling.id_for_label }}" class="form-label">Special Handling</label>
|
|
{{ form.special_handling }}
|
|
{% if form.special_handling.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.special_handling.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Special handling instructions.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Status and Notes -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-check">
|
|
{{ form.is_active }}
|
|
<label class="form-check-label" for="{{ form.is_active.id_for_label }}">
|
|
<i class="fa fa-check text-success me-1"></i>Active medication
|
|
</label>
|
|
{% if form.is_active.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_active.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Available for prescribing.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.notes.id_for_label }}" class="form-label">Notes</label>
|
|
{{ form.notes }}
|
|
{% if form.notes.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.notes.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Additional notes or comments.</div>
|
|
</div>
|
|
|
|
<!-- Form Actions -->
|
|
<div class="d-flex justify-content-between">
|
|
<div>
|
|
<a href="{% if object %}{% url 'pharmacy:medication_detail' object.pk %}{% else %}{% url 'pharmacy:medication_list' %}{% endif %}" class="btn btn-secondary">
|
|
<i class="fa fa-arrow-left me-2"></i>Cancel
|
|
</a>
|
|
</div>
|
|
<div>
|
|
<button type="button" class="btn btn-info me-2" onclick="saveDraft()">
|
|
<i class="fa fa-save me-2"></i>Save Draft
|
|
</button>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fa fa-check me-2"></i>{% if object %}Update{% else %}Create{% endif %} Medication
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
</div>
|
|
|
|
<div class="col-xl-4">
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Medication Guidelines</h4>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div class="alert alert-info">
|
|
<h6 class="alert-heading">Best Practices</h6>
|
|
<ul class="mb-0 small">
|
|
<li>Use official generic names</li>
|
|
<li>Verify NDC numbers</li>
|
|
<li>Include complete dosage information</li>
|
|
<li>Specify storage requirements</li>
|
|
<li>Document contraindications</li>
|
|
<li>Mark controlled substances</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card border-warning mb-3">
|
|
<div class="card-header bg-warning text-dark">
|
|
<h6 class="card-title mb-0">Validation Checks</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<ul class="list-unstyled mb-0 small">
|
|
<li id="name-check"><i class="fa fa-times text-danger me-2"></i>Generic name validation pending</li>
|
|
<li id="ndc-check"><i class="fa fa-times text-danger me-2"></i>NDC validation pending</li>
|
|
<li id="strength-check"><i class="fa fa-times text-danger me-2"></i>Strength format pending</li>
|
|
<li id="controlled-check"><i class="fa fa-times text-danger me-2"></i>Controlled substance check pending</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Quick Actions</h4>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div class="d-grid gap-2">
|
|
<button type="button" class="btn btn-outline-info" onclick="validateNDC()">
|
|
<i class="fa fa-check me-2"></i>Validate NDC
|
|
</button>
|
|
<button type="button" class="btn btn-outline-warning" onclick="checkDuplicates()">
|
|
<i class="fa fa-search me-2"></i>Check Duplicates
|
|
</button>
|
|
<button type="button" class="btn btn-outline-primary" onclick="loadTemplate()">
|
|
<i class="fa fa-copy me-2"></i>Load Template
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary" onclick="clearForm()">
|
|
<i class="fa fa-refresh me-2"></i>Clear Form
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Form Status</h4>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div id="form-status">
|
|
<div class="alert alert-secondary">
|
|
<i class="fa fa-info-circle me-2"></i>
|
|
<span id="status-text">Draft medication</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="small text-muted">
|
|
<div>Last saved: <span id="last-saved">Never</span></div>
|
|
<div>Auto-save: <span class="text-success">Enabled</span></div>
|
|
<div>Validation: <span id="validation-status" class="text-warning">Pending</span></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script>
|
|
var autoSaveTimer;
|
|
|
|
$(document).ready(function() {
|
|
// Initialize form behavior
|
|
initializeFormBehavior();
|
|
|
|
// Auto-save functionality
|
|
$('#medication-form input, #medication-form select, #medication-form textarea').on('change input', function() {
|
|
clearTimeout(autoSaveTimer);
|
|
autoSaveTimer = setTimeout(function() {
|
|
saveDraft();
|
|
}, 5000);
|
|
});
|
|
|
|
// Form validation
|
|
$('#medication-form').on('submit', function(e) {
|
|
if (!validateForm()) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
});
|
|
|
|
function initializeFormBehavior() {
|
|
// Controlled substance checkbox
|
|
$('#{{ form.is_controlled.id_for_label }}').on('change', function() {
|
|
if ($(this).is(':checked')) {
|
|
$('#controlled-info').show();
|
|
} else {
|
|
$('#controlled-info').hide();
|
|
}
|
|
});
|
|
|
|
// Initial state
|
|
if ($('#{{ form.is_controlled.id_for_label }}').is(':checked')) {
|
|
$('#controlled-info').show();
|
|
}
|
|
|
|
// Generic name change
|
|
$('#{{ form.generic_name.id_for_label }}').on('change', function() {
|
|
checkDuplicates();
|
|
validateGenericName();
|
|
});
|
|
|
|
// NDC number change
|
|
$('#{{ form.ndc_number.id_for_label }}').on('change', function() {
|
|
validateNDC();
|
|
});
|
|
|
|
// Strength change
|
|
$('#{{ form.strength.id_for_label }}').on('change', function() {
|
|
validateStrength();
|
|
});
|
|
}
|
|
|
|
function validateForm() {
|
|
var isValid = true;
|
|
var errors = [];
|
|
|
|
// Required field validation
|
|
var requiredFields = [
|
|
'{{ form.generic_name.id_for_label }}',
|
|
'{{ form.category.id_for_label }}',
|
|
'{{ form.dosage_form.id_for_label }}',
|
|
'{{ form.route.id_for_label }}',
|
|
'{{ form.strength.id_for_label }}'
|
|
];
|
|
|
|
requiredFields.forEach(function(fieldId) {
|
|
var field = $('#' + fieldId);
|
|
if (!field.val()) {
|
|
field.addClass('is-invalid');
|
|
errors.push(field.closest('.form-floating, .mb-3').find('label').text().replace(' *', '') + ' is required');
|
|
isValid = false;
|
|
} else {
|
|
field.removeClass('is-invalid');
|
|
}
|
|
});
|
|
|
|
// NDC format validation
|
|
var ndcNumber = $('#{{ form.ndc_number.id_for_label }}').val();
|
|
if (ndcNumber && !isValidNDC(ndcNumber)) {
|
|
$('#{{ form.ndc_number.id_for_label }}').addClass('is-invalid');
|
|
errors.push('NDC number format is invalid');
|
|
isValid = false;
|
|
}
|
|
|
|
// Controlled substance validation
|
|
if ($('#{{ form.is_controlled.id_for_label }}').is(':checked')) {
|
|
var schedule = $('#{{ form.controlled_schedule.id_for_label }}').val();
|
|
if (!schedule) {
|
|
$('#{{ form.controlled_schedule.id_for_label }}').addClass('is-invalid');
|
|
errors.push('Controlled schedule is required for controlled substances');
|
|
isValid = false;
|
|
}
|
|
}
|
|
|
|
if (!isValid) {
|
|
toastr.error('Please fix the following errors:\n' + errors.join('\n'));
|
|
$('#validation-status').text('Failed').removeClass('text-success text-warning').addClass('text-danger');
|
|
} else {
|
|
$('#validation-status').text('Passed').removeClass('text-danger text-warning').addClass('text-success');
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
|
|
function validateNDC() {
|
|
var ndcNumber = $('#{{ form.ndc_number.id_for_label }}').val();
|
|
|
|
if (!ndcNumber) {
|
|
$('#ndc-check').html('<i class="fa fa-times text-danger me-2"></i>NDC number not provided');
|
|
return;
|
|
}
|
|
|
|
if (isValidNDC(ndcNumber)) {
|
|
$('#ndc-check').html('<i class="fa fa-check text-success me-2"></i>NDC format valid');
|
|
|
|
// Check NDC in database
|
|
$.ajax({
|
|
url: '{% url "pharmacy:validate_ndc" %}',
|
|
method: 'POST',
|
|
data: {
|
|
'ndc_number': ndcNumber,
|
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
|
},
|
|
success: function(response) {
|
|
if (response.exists) {
|
|
toastr.warning('NDC number already exists in database');
|
|
} else {
|
|
toastr.success('NDC number is available');
|
|
}
|
|
},
|
|
error: function() {
|
|
toastr.error('Failed to validate NDC number');
|
|
}
|
|
});
|
|
} else {
|
|
$('#ndc-check').html('<i class="fa fa-times text-danger me-2"></i>Invalid NDC format');
|
|
toastr.error('NDC number format is invalid. Use format: 12345-678-90');
|
|
}
|
|
}
|
|
|
|
function isValidNDC(ndc) {
|
|
// NDC format: 5-4-2 or 5-3-2 digits with hyphens
|
|
var ndcPattern = /^\d{4,5}-\d{3,4}-\d{1,2}$/;
|
|
return ndcPattern.test(ndc);
|
|
}
|
|
|
|
function validateGenericName() {
|
|
var genericName = $('#{{ form.generic_name.id_for_label }}').val();
|
|
|
|
if (genericName && genericName.length >= 3) {
|
|
$('#name-check').html('<i class="fa fa-check text-success me-2"></i>Generic name format valid');
|
|
} else {
|
|
$('#name-check').html('<i class="fa fa-times text-danger me-2"></i>Generic name too short');
|
|
}
|
|
}
|
|
|
|
function validateStrength() {
|
|
var strength = $('#{{ form.strength.id_for_label }}').val();
|
|
|
|
if (strength) {
|
|
// Basic strength format validation
|
|
var strengthPattern = /^\d+(\.\d+)?\s*(mg|g|ml|mcg|units?|iu|mEq)/i;
|
|
if (strengthPattern.test(strength)) {
|
|
$('#strength-check').html('<i class="fa fa-check text-success me-2"></i>Strength format valid');
|
|
} else {
|
|
$('#strength-check').html('<i class="fa fa-exclamation-triangle text-warning me-2"></i>Check strength format');
|
|
}
|
|
} else {
|
|
$('#strength-check').html('<i class="fa fa-times text-danger me-2"></i>Strength not provided');
|
|
}
|
|
}
|
|
|
|
function checkDuplicates() {
|
|
var genericName = $('#{{ form.generic_name.id_for_label }}').val();
|
|
var strength = $('#{{ form.strength.id_for_label }}').val();
|
|
|
|
if (!genericName) {
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: '{% url "pharmacy:check_medication_duplicates" %}',
|
|
method: 'POST',
|
|
data: {
|
|
'generic_name': genericName,
|
|
'strength': strength,
|
|
{% if object %}'exclude_id': {{ object.pk }},{% endif %}
|
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
|
},
|
|
success: function(response) {
|
|
if (response.duplicates.length > 0) {
|
|
var message = 'Similar medications found:\n';
|
|
response.duplicates.forEach(function(med) {
|
|
message += '- ' + med.name + ' (' + med.strength + ')\n';
|
|
});
|
|
toastr.warning(message);
|
|
}
|
|
},
|
|
error: function() {
|
|
toastr.error('Failed to check for duplicates');
|
|
}
|
|
});
|
|
}
|
|
|
|
function saveDraft() {
|
|
var formData = $('#medication-form').serialize();
|
|
|
|
$.ajax({
|
|
url: '{% url "pharmacy:save_medication_draft" %}',
|
|
method: 'POST',
|
|
data: formData,
|
|
success: function(response) {
|
|
updateFormStatus('Draft saved', 'success');
|
|
$('#last-saved').text(new Date().toLocaleTimeString());
|
|
},
|
|
error: function() {
|
|
updateFormStatus('Failed to save draft', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
function updateFormStatus(message, type) {
|
|
var alertClass = 'alert-' + type;
|
|
$('#form-status').html('<div class="alert ' + alertClass + '"><i class="fa fa-info-circle me-2"></i>' + message + '</div>');
|
|
}
|
|
|
|
function loadTemplate() {
|
|
// Implementation for loading medication templates
|
|
toastr.info('Template loading feature coming soon');
|
|
}
|
|
|
|
function clearForm() {
|
|
if (confirm('Are you sure you want to clear all form data?')) {
|
|
$('#medication-form')[0].reset();
|
|
$('#controlled-info').hide();
|
|
updateFormStatus('Form cleared', 'info');
|
|
}
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|