653 lines
30 KiB
HTML
653 lines
30 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Drug Interaction Check - Pharmacy{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="content">
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-header">
|
|
<div class="page-title">
|
|
<h4>Drug Interaction Checker</h4>
|
|
<h6>Comprehensive drug interaction analysis and clinical decision support</h6>
|
|
</div>
|
|
<div class="page-btn">
|
|
<button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#interactionGuideModal">
|
|
<i class="fa fa-question-circle"></i> Interaction Guide
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Patient Selection -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Patient Selection</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="post" id="interactionCheckForm">
|
|
{% csrf_token %}
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Select Patient *</label>
|
|
<select name="patient_id" class="form-select" id="patientSelect" required>
|
|
<option value="">Choose a patient...</option>
|
|
{% for patient in patients %}
|
|
<option value="{{ patient.id }}"
|
|
{% if selected_patient.id == patient.id %}selected{% endif %}>
|
|
{{ patient.get_full_name }} - {{ patient.medical_record_number }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Check Type</label>
|
|
<select name="check_type" class="form-select">
|
|
<option value="comprehensive">Comprehensive Check</option>
|
|
<option value="drug_drug">Drug-Drug Interactions</option>
|
|
<option value="drug_allergy">Drug-Allergy Check</option>
|
|
<option value="drug_condition">Drug-Condition Check</option>
|
|
<option value="duplicate_therapy">Duplicate Therapy</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if selected_patient %}
|
|
<!-- Patient Information -->
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Patient Information</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<strong>Name:</strong> {{ selected_patient.get_full_name }}<br>
|
|
<strong>MRN:</strong> {{ selected_patient.medical_record_number }}<br>
|
|
<strong>DOB:</strong> {{ selected_patient.date_of_birth|date:"M d, Y" }}<br>
|
|
<strong>Age:</strong> {{ selected_patient.age }} years
|
|
</div>
|
|
<div class="col-md-6">
|
|
<strong>Weight:</strong> {{ selected_patient.weight|default:"Not recorded" }} kg<br>
|
|
<strong>Height:</strong> {{ selected_patient.height|default:"Not recorded" }} cm<br>
|
|
<strong>Gender:</strong> {{ selected_patient.get_gender_display }}<br>
|
|
<strong>Pregnancy Status:</strong> {{ selected_patient.pregnancy_status|default:"N/A" }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Risk Factors</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-2">
|
|
<strong>Kidney Function:</strong><br>
|
|
<span class="badge bg-{{ selected_patient.kidney_function_color }}">
|
|
{{ selected_patient.kidney_function|default:"Normal" }}
|
|
</span>
|
|
</div>
|
|
<div class="mb-2">
|
|
<strong>Liver Function:</strong><br>
|
|
<span class="badge bg-{{ selected_patient.liver_function_color }}">
|
|
{{ selected_patient.liver_function|default:"Normal" }}
|
|
</span>
|
|
</div>
|
|
<div class="mb-2">
|
|
<strong>Age Category:</strong><br>
|
|
<span class="badge bg-info">{{ selected_patient.age_category }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Current Medications -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Current Medications</h5>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#addMedicationModal">
|
|
<i class="fa fa-plus"></i> Add Medication
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Medication</th>
|
|
<th>Strength</th>
|
|
<th>Dosage</th>
|
|
<th>Route</th>
|
|
<th>Frequency</th>
|
|
<th>Start Date</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="medicationsList">
|
|
{% for medication in current_medications %}
|
|
<tr data-medication-id="{{ medication.id }}">
|
|
<td>
|
|
<strong>{{ medication.name }}</strong><br>
|
|
<small class="text-muted">{{ medication.generic_name }}</small>
|
|
</td>
|
|
<td>{{ medication.strength }}</td>
|
|
<td>{{ medication.dosage }}</td>
|
|
<td>{{ medication.route|title }}</td>
|
|
<td>{{ medication.frequency }}</td>
|
|
<td>{{ medication.start_date|date:"M d, Y" }}</td>
|
|
<td>
|
|
<span class="badge bg-{{ medication.status_color }}">
|
|
{{ medication.status|title }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-outline-danger"
|
|
onclick="removeMedication({{ medication.id }})">
|
|
<i class="fa fa-times"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="8" class="text-center text-muted">
|
|
No current medications on file
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Interaction Check Results -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Interaction Analysis Results</h5>
|
|
<div class="card-tools">
|
|
<button type="button" class="btn btn-sm btn-success" onclick="runInteractionCheck()">
|
|
<i class="fa fa-sync"></i> Run Check
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="interactionResults">
|
|
<!-- Critical Interactions -->
|
|
<div class="alert alert-danger" id="criticalInteractions" style="display: none;">
|
|
<h6><i class="fa fa-exclamation-triangle"></i> Critical Interactions</h6>
|
|
<div id="criticalList"></div>
|
|
</div>
|
|
|
|
<!-- Major Interactions -->
|
|
<div class="alert alert-warning" id="majorInteractions" style="display: none;">
|
|
<h6><i class="fa fa-exclamation-circle"></i> Major Interactions</h6>
|
|
<div id="majorList"></div>
|
|
</div>
|
|
|
|
<!-- Moderate Interactions -->
|
|
<div class="alert alert-info" id="moderateInteractions" style="display: none;">
|
|
<h6><i class="fa fa-info-circle"></i> Moderate Interactions</h6>
|
|
<div id="moderateList"></div>
|
|
</div>
|
|
|
|
<!-- Minor Interactions -->
|
|
<div class="alert alert-secondary" id="minorInteractions" style="display: none;">
|
|
<h6><i class="fa fa-info"></i> Minor Interactions</h6>
|
|
<div id="minorList"></div>
|
|
</div>
|
|
|
|
<!-- No Interactions -->
|
|
<div class="alert alert-success" id="noInteractions" style="display: none;">
|
|
<h6><i class="fa fa-check-circle"></i> No Significant Interactions Found</h6>
|
|
<p>No clinically significant drug interactions were detected with the current medication regimen.</p>
|
|
</div>
|
|
|
|
<!-- Initial State -->
|
|
<div id="initialState" class="text-center text-muted">
|
|
<i class="fa fa-search fa-3x mb-3"></i>
|
|
<p>Click "Run Check" to analyze drug interactions for this patient</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Allergy Alerts -->
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Allergy Alerts</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if patient_allergies %}
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Allergen</th>
|
|
<th>Reaction</th>
|
|
<th>Severity</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for allergy in patient_allergies %}
|
|
<tr>
|
|
<td>{{ allergy.allergen }}</td>
|
|
<td>{{ allergy.reaction }}</td>
|
|
<td>
|
|
<span class="badge bg-{{ allergy.severity_color }}">
|
|
{{ allergy.severity|title }}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted">No known allergies on file</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Medical Conditions</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if patient_conditions %}
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Condition</th>
|
|
<th>Status</th>
|
|
<th>Onset</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for condition in patient_conditions %}
|
|
<tr>
|
|
<td>{{ condition.name }}</td>
|
|
<td>
|
|
<span class="badge bg-{{ condition.status_color }}">
|
|
{{ condition.status|title }}
|
|
</span>
|
|
</td>
|
|
<td>{{ condition.onset_date|date:"M Y"|default:"Unknown" }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted">No active medical conditions on file</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Clinical Decision Support -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title">Clinical Decision Support</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="clinicalRecommendations">
|
|
<div class="text-center text-muted">
|
|
<i class="fa fa-lightbulb fa-2x mb-3"></i>
|
|
<p>Clinical recommendations will appear here after running the interaction check</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Medication Modal -->
|
|
<div class="modal fade" id="addMedicationModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Add Medication for Interaction Check</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<form id="addMedicationForm">
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label class="form-label">Medication Name *</label>
|
|
<input type="text" name="medication_name" class="form-control" required>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Strength</label>
|
|
<input type="text" name="strength" class="form-control" placeholder="e.g., 10mg">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Route</label>
|
|
<select name="route" class="form-select">
|
|
<option value="oral">Oral</option>
|
|
<option value="iv">Intravenous</option>
|
|
<option value="im">Intramuscular</option>
|
|
<option value="topical">Topical</option>
|
|
<option value="inhaled">Inhaled</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Dosage</label>
|
|
<input type="text" name="dosage" class="form-control" placeholder="e.g., 1 tablet">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<label class="form-label">Frequency</label>
|
|
<select name="frequency" class="form-select">
|
|
<option value="once_daily">Once Daily</option>
|
|
<option value="twice_daily">Twice Daily</option>
|
|
<option value="three_times_daily">Three Times Daily</option>
|
|
<option value="four_times_daily">Four Times Daily</option>
|
|
<option value="as_needed">As Needed</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-primary">Add Medication</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Interaction Guide Modal -->
|
|
<div class="modal fade" id="interactionGuideModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Drug Interaction Severity Guide</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Severity</th>
|
|
<th>Description</th>
|
|
<th>Clinical Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr class="table-danger">
|
|
<td><strong>Critical</strong></td>
|
|
<td>Life-threatening interactions that should be avoided</td>
|
|
<td>Contraindicated - Do not use together</td>
|
|
</tr>
|
|
<tr class="table-warning">
|
|
<td><strong>Major</strong></td>
|
|
<td>Significant clinical effects requiring intervention</td>
|
|
<td>Monitor closely, consider alternatives</td>
|
|
</tr>
|
|
<tr class="table-info">
|
|
<td><strong>Moderate</strong></td>
|
|
<td>Clinically significant but manageable</td>
|
|
<td>Monitor patient, adjust dosing if needed</td>
|
|
</tr>
|
|
<tr class="table-secondary">
|
|
<td><strong>Minor</strong></td>
|
|
<td>Limited clinical significance</td>
|
|
<td>Minimal monitoring required</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Patient selection change handler
|
|
document.getElementById('patientSelect').addEventListener('change', function() {
|
|
if (this.value) {
|
|
document.getElementById('interactionCheckForm').submit();
|
|
}
|
|
});
|
|
|
|
// Add medication form handler
|
|
document.getElementById('addMedicationForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(this);
|
|
const medicationData = {
|
|
name: formData.get('medication_name'),
|
|
strength: formData.get('strength'),
|
|
route: formData.get('route'),
|
|
dosage: formData.get('dosage'),
|
|
frequency: formData.get('frequency')
|
|
};
|
|
|
|
addMedicationToList(medicationData);
|
|
|
|
// Close modal and reset form
|
|
bootstrap.Modal.getInstance(document.getElementById('addMedicationModal')).hide();
|
|
this.reset();
|
|
});
|
|
});
|
|
|
|
function addMedicationToList(medication) {
|
|
const tbody = document.getElementById('medicationsList');
|
|
const row = document.createElement('tr');
|
|
row.innerHTML = `
|
|
<td>
|
|
<strong>${medication.name}</strong><br>
|
|
<small class="text-muted">Generic name</small>
|
|
</td>
|
|
<td>${medication.strength || '-'}</td>
|
|
<td>${medication.dosage || '-'}</td>
|
|
<td>${medication.route}</td>
|
|
<td>${medication.frequency.replace('_', ' ')}</td>
|
|
<td>${new Date().toLocaleDateString()}</td>
|
|
<td><span class="badge bg-success">Active</span></td>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-outline-danger" onclick="removeMedication(this)">
|
|
<i class="fa fa-times"></i>
|
|
</button>
|
|
</td>
|
|
`;
|
|
|
|
// Remove "no medications" row if it exists
|
|
const noMedsRow = tbody.querySelector('td[colspan="8"]');
|
|
if (noMedsRow) {
|
|
noMedsRow.parentElement.remove();
|
|
}
|
|
|
|
tbody.appendChild(row);
|
|
}
|
|
|
|
function removeMedication(element) {
|
|
if (confirm('Remove this medication from the interaction check?')) {
|
|
element.closest('tr').remove();
|
|
|
|
// Check if list is empty
|
|
const tbody = document.getElementById('medicationsList');
|
|
if (tbody.children.length === 0) {
|
|
tbody.innerHTML = `
|
|
<tr>
|
|
<td colspan="8" class="text-center text-muted">
|
|
No current medications on file
|
|
</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
}
|
|
}
|
|
|
|
function runInteractionCheck() {
|
|
// Show loading state
|
|
const resultsDiv = document.getElementById('interactionResults');
|
|
resultsDiv.innerHTML = `
|
|
<div class="text-center">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
<p class="mt-2">Analyzing drug interactions...</p>
|
|
</div>
|
|
`;
|
|
|
|
// Simulate API call
|
|
setTimeout(() => {
|
|
displayInteractionResults();
|
|
}, 2000);
|
|
}
|
|
|
|
function displayInteractionResults() {
|
|
// Hide all alert sections first
|
|
document.querySelectorAll('#interactionResults .alert').forEach(alert => {
|
|
alert.style.display = 'none';
|
|
});
|
|
|
|
// Sample interaction data (in real implementation, this would come from API)
|
|
const interactions = {
|
|
critical: [
|
|
{
|
|
drugs: ['Warfarin', 'Aspirin'],
|
|
description: 'Increased risk of bleeding',
|
|
recommendation: 'Avoid combination or monitor INR closely'
|
|
}
|
|
],
|
|
major: [
|
|
{
|
|
drugs: ['Lisinopril', 'Potassium Supplement'],
|
|
description: 'Risk of hyperkalemia',
|
|
recommendation: 'Monitor serum potassium levels'
|
|
}
|
|
],
|
|
moderate: [
|
|
{
|
|
drugs: ['Metformin', 'Contrast Dye'],
|
|
description: 'Risk of lactic acidosis',
|
|
recommendation: 'Hold metformin before contrast procedures'
|
|
}
|
|
],
|
|
minor: []
|
|
};
|
|
|
|
// Display results
|
|
if (interactions.critical.length > 0) {
|
|
displayInteractionCategory('critical', interactions.critical, 'danger');
|
|
}
|
|
if (interactions.major.length > 0) {
|
|
displayInteractionCategory('major', interactions.major, 'warning');
|
|
}
|
|
if (interactions.moderate.length > 0) {
|
|
displayInteractionCategory('moderate', interactions.moderate, 'info');
|
|
}
|
|
if (interactions.minor.length > 0) {
|
|
displayInteractionCategory('minor', interactions.minor, 'secondary');
|
|
}
|
|
|
|
// Show no interactions if none found
|
|
if (interactions.critical.length === 0 && interactions.major.length === 0 &&
|
|
interactions.moderate.length === 0 && interactions.minor.length === 0) {
|
|
document.getElementById('noInteractions').style.display = 'block';
|
|
}
|
|
|
|
// Update clinical recommendations
|
|
updateClinicalRecommendations(interactions);
|
|
}
|
|
|
|
function displayInteractionCategory(category, interactions, alertClass) {
|
|
const categoryDiv = document.getElementById(`${category}Interactions`);
|
|
const listDiv = document.getElementById(`${category}List`);
|
|
|
|
let html = '';
|
|
interactions.forEach(interaction => {
|
|
html += `
|
|
<div class="interaction-item mb-2 p-2 border rounded">
|
|
<strong>${interaction.drugs.join(' + ')}</strong><br>
|
|
<small>${interaction.description}</small><br>
|
|
<em class="text-muted">Recommendation: ${interaction.recommendation}</em>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
listDiv.innerHTML = html;
|
|
categoryDiv.style.display = 'block';
|
|
}
|
|
|
|
function updateClinicalRecommendations(interactions) {
|
|
const recommendationsDiv = document.getElementById('clinicalRecommendations');
|
|
|
|
let html = '<h6>Clinical Recommendations:</h6>';
|
|
|
|
if (interactions.critical.length > 0) {
|
|
html += '<div class="alert alert-danger"><strong>Immediate Action Required:</strong> Critical interactions detected that require immediate attention.</div>';
|
|
}
|
|
|
|
if (interactions.major.length > 0) {
|
|
html += '<div class="alert alert-warning"><strong>Enhanced Monitoring:</strong> Implement close patient monitoring protocols.</div>';
|
|
}
|
|
|
|
html += `
|
|
<ul class="list-unstyled">
|
|
<li><i class="fa fa-check text-success"></i> Review all medication dosages</li>
|
|
<li><i class="fa fa-check text-success"></i> Consider therapeutic alternatives</li>
|
|
<li><i class="fa fa-check text-success"></i> Implement appropriate monitoring</li>
|
|
<li><i class="fa fa-check text-success"></i> Document clinical decision</li>
|
|
</ul>
|
|
`;
|
|
|
|
recommendationsDiv.innerHTML = html;
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|