update
This commit is contained in:
parent
2780a2dc7c
commit
2b4c58aa34
Binary file not shown.
@ -27,6 +27,19 @@ def add_class(field, css_class):
|
||||
return field.as_widget(attrs={"class": css_class})
|
||||
|
||||
|
||||
@register.filter(name="attr")
|
||||
def attr(field, args):
|
||||
attrs = {}
|
||||
definitions = args.split(",")
|
||||
for definition in definitions:
|
||||
if ":" in definition:
|
||||
key, val = definition.split(":")
|
||||
attrs[key.strip()] = val.strip()
|
||||
else:
|
||||
attrs[definition.strip()] = True
|
||||
return field.as_widget(attrs=attrs)
|
||||
|
||||
|
||||
@register.filter
|
||||
def sum_values(queryset, field_names):
|
||||
"""
|
||||
|
||||
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
38
emr/forms.py
38
emr/forms.py
@ -210,25 +210,25 @@ class CarePlanForm(forms.ModelForm):
|
||||
'approved', 'approved_by'
|
||||
]
|
||||
widgets = {
|
||||
'start_date': forms.DateInput(attrs={'type': 'date'}),
|
||||
'end_date': forms.DateInput(attrs={'type': 'date'}),
|
||||
'target_completion_date': forms.DateInput(attrs={'type': 'date'}),
|
||||
'last_reviewed': forms.DateInput(attrs={'type': 'date'}),
|
||||
'next_review_date': forms.DateInput(attrs={'type': 'date'}),
|
||||
'description': forms.Textarea(attrs={'rows': 3}),
|
||||
'patient_goals': forms.Textarea(attrs={'rows': 3}),
|
||||
'patient_preferences': forms.Textarea(attrs={'rows': 3}),
|
||||
'patient_barriers': forms.Textarea(attrs={'rows': 3}),
|
||||
'progress_notes': forms.Textarea(attrs={'rows': 3}),
|
||||
'goals': forms.Textarea(attrs={'rows': 3}),
|
||||
'objectives': forms.Textarea(attrs={'rows': 3}),
|
||||
'interventions': forms.Textarea(attrs={'rows': 3}),
|
||||
'activities': forms.Textarea(attrs={'rows': 3}),
|
||||
'monitoring_parameters': forms.Textarea(attrs={'rows': 3}),
|
||||
'evaluation_criteria': forms.Textarea(attrs={'rows': 3}),
|
||||
'resources_needed': forms.Textarea(attrs={'rows': 3}),
|
||||
'support_systems': forms.Textarea(attrs={'rows': 3}),
|
||||
'outcomes_achieved': forms.Textarea(attrs={'rows': 3}),
|
||||
'start_date': forms.DateInput(attrs={'type': 'date', 'class':'form-control form control-sm'}),
|
||||
'end_date': forms.DateInput(attrs={'type': 'date', 'class':'form-control form control-sm'}),
|
||||
'target_completion_date': forms.DateInput(attrs={'type': 'date', 'class':'form-control form control-sm'}),
|
||||
'last_reviewed': forms.DateInput(attrs={'type': 'date', 'class':'form-control form control-sm'}),
|
||||
'next_review_date': forms.DateInput(attrs={'type': 'date', 'class':'form-control form control-sm'}),
|
||||
'description': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'patient_goals': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'patient_preferences': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'patient_barriers': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'progress_notes': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'goals': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'objectives': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'interventions': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'activities': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'monitoring_parameters': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'evaluation_criteria': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'resources_needed': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'support_systems': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
'outcomes_achieved': forms.Textarea(attrs={'rows': 3, 'class':'form-control form control-sm'}),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@ -1,799 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{{ care_plan.title }} | Care Plan Detail{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link href="{% static 'plugins/timeline/timeline.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/bootstrap-icons/font/bootstrap-icons.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/chart.js/dist/Chart.min.css' %}" rel="stylesheet" />
|
||||
<style>
|
||||
.care-plan-badge {
|
||||
font-size: 0.85rem;
|
||||
padding: 0.35em 0.65em;
|
||||
}
|
||||
.care-plan-header {
|
||||
background: linear-gradient(45deg, var(--bs-blue), var(--bs-indigo));
|
||||
color: white;
|
||||
padding: 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.care-plan-status-active {
|
||||
background-color: var(--bs-success);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-status-completed {
|
||||
background-color: var(--bs-secondary);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-status-draft {
|
||||
background-color: var(--bs-warning);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-status-on-hold {
|
||||
background-color: var(--bs-info);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-priority-high {
|
||||
background-color: var(--bs-danger);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-priority-medium {
|
||||
background-color: var(--bs-warning);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-priority-low {
|
||||
background-color: var(--bs-info);
|
||||
color: white;
|
||||
}
|
||||
.timeline-item {
|
||||
padding: 1rem;
|
||||
border-left: 3px solid var(--bs-primary);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.related-item {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.related-item:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.goal-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-success);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.objective-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-info);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.intervention-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-warning);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.activity-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-purple);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.outcome-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-teal);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.monitoring-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-cyan);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.nav-tabs .nav-link.active {
|
||||
font-weight: bold;
|
||||
border-bottom: 3px solid var(--bs-primary);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- begin breadcrumb -->
|
||||
<ol class="breadcrumb float-xl-end">
|
||||
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'emr:dashboard' %}">EMR</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'emr:care_plan_list' %}">Care Plans</a></li>
|
||||
<li class="breadcrumb-item active">{{ care_plan.title }}</li>
|
||||
</ol>
|
||||
<!-- end breadcrumb -->
|
||||
|
||||
<!-- begin page-header -->
|
||||
<h1 class="page-header">Care Plan Detail <small>Comprehensive care plan information</small></h1>
|
||||
<!-- end page-header -->
|
||||
|
||||
<!-- begin row -->
|
||||
<div class="row">
|
||||
<!-- begin col-12 -->
|
||||
<div class="col-xl-12">
|
||||
<!-- begin care plan header -->
|
||||
<div class="care-plan-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h2 class="mb-1">{{ care_plan.title }}</h2>
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="me-3">
|
||||
<i class="bi bi-person-fill me-1"></i> {{ care_plan.patient.get_full_name }}
|
||||
</span>
|
||||
<span class="me-3">
|
||||
<i class="bi bi-calendar-event me-1"></i> Start: {{ care_plan.start_date }}
|
||||
{% if care_plan.end_date %}
|
||||
- End: {{ care_plan.end_date }}
|
||||
{% endif %}
|
||||
</span>
|
||||
<span>
|
||||
<i class="bi bi-person-badge me-1"></i> {{ care_plan.primary_provider.get_full_name }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<span class="badge care-plan-status-{{ care_plan.status|lower }} me-2">{{ care_plan.get_status_display }}</span>
|
||||
<span class="badge care-plan-priority-{{ care_plan.priority|lower }}">{{ care_plan.get_priority_display }} Priority</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end care plan header -->
|
||||
|
||||
<!-- begin progress panel -->
|
||||
<div class="panel panel-inverse">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Progress</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Completion Progress</h5>
|
||||
<div class="progress" style="height: 25px;">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated bg-success"
|
||||
role="progressbar"
|
||||
style="width: {{ care_plan.completion_percentage }}%;"
|
||||
aria-valuenow="{{ care_plan.completion_percentage }}"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100">
|
||||
{{ care_plan.completion_percentage }}% Complete
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-3">Plan Timeline</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="30%">Start Date</th>
|
||||
<td>{{ care_plan.start_date }}</td>
|
||||
</tr>
|
||||
{% if care_plan.target_completion_date %}
|
||||
<tr>
|
||||
<th>Target Completion</th>
|
||||
<td>{{ care_plan.target_completion_date }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if care_plan.end_date %}
|
||||
<tr>
|
||||
<th>End Date</th>
|
||||
<td>{{ care_plan.end_date }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if care_plan.last_reviewed %}
|
||||
<tr>
|
||||
<th>Last Reviewed</th>
|
||||
<td>{{ care_plan.last_reviewed }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if care_plan.next_review_date %}
|
||||
<tr>
|
||||
<th>Next Review</th>
|
||||
<td>
|
||||
{{ care_plan.next_review_date }}
|
||||
{% if care_plan.is_overdue %}
|
||||
<span class="badge bg-danger ms-2">Overdue</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Activity Chart</h5>
|
||||
<canvas id="activityChart" height="200"></canvas>
|
||||
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-3">Approval Status</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="30%">Status</th>
|
||||
<td>
|
||||
{% if care_plan.approved %}
|
||||
<span class="badge bg-success">Approved</span>
|
||||
{% else %}
|
||||
<span class="badge bg-warning">Pending Approval</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if care_plan.approved %}
|
||||
<tr>
|
||||
<th>Approved By</th>
|
||||
<td>{{ care_plan.approved_by.get_full_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Approved Date</th>
|
||||
<td>{{ care_plan.approved_date }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end progress panel -->
|
||||
|
||||
<!-- begin care plan details panel -->
|
||||
<div class="panel panel-inverse">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Care Plan Details</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<!-- begin nav tabs -->
|
||||
<ul class="nav nav-tabs" id="carePlanTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="overview-tab" data-bs-toggle="tab" data-bs-target="#overview" type="button" role="tab" aria-controls="overview" aria-selected="true">Overview</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="goals-tab" data-bs-toggle="tab" data-bs-target="#goals" type="button" role="tab" aria-controls="goals" aria-selected="false">Goals & Objectives</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="interventions-tab" data-bs-toggle="tab" data-bs-target="#interventions" type="button" role="tab" aria-controls="interventions" aria-selected="false">Interventions</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="monitoring-tab" data-bs-toggle="tab" data-bs-target="#monitoring" type="button" role="tab" aria-controls="monitoring" aria-selected="false">Monitoring</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="patient-tab" data-bs-toggle="tab" data-bs-target="#patient" type="button" role="tab" aria-controls="patient" aria-selected="false">Patient Involvement</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="outcomes-tab" data-bs-toggle="tab" data-bs-target="#outcomes" type="button" role="tab" aria-controls="outcomes" aria-selected="false">Outcomes</button>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- end nav tabs -->
|
||||
|
||||
<!-- begin tab content -->
|
||||
<div class="tab-content" id="carePlanTabsContent">
|
||||
<!-- Overview Tab -->
|
||||
<div class="tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="overview-tab">
|
||||
<div class="p-3">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Basic Information</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="30%">Care Plan ID</th>
|
||||
<td>{{ care_plan.care_plan_id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Plan Type</th>
|
||||
<td>{{ care_plan.get_plan_type_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<td>{{ care_plan.get_category_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td>{{ care_plan.get_status_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Priority</th>
|
||||
<td>{{ care_plan.get_priority_display }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h5 class="mb-3 mt-4">Description</h5>
|
||||
<div class="p-3 bg-light rounded">
|
||||
{{ care_plan.description|linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Provider Information</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="30%">Primary Provider</th>
|
||||
<td>{{ care_plan.primary_provider.get_full_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Care Team</th>
|
||||
<td>
|
||||
{% if care_plan.care_team.all %}
|
||||
<ul class="mb-0 ps-3">
|
||||
{% for provider in care_plan.care_team.all %}
|
||||
<li>{{ provider.get_full_name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
No additional care team members
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h5 class="mb-3 mt-4">Related Problems</h5>
|
||||
{% if care_plan.related_problems.all %}
|
||||
<div class="list-group">
|
||||
{% for problem in care_plan.related_problems.all %}
|
||||
<a href="{% url 'emr:problem_detail' problem.id %}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
|
||||
{{ problem.problem_name }}
|
||||
<span class="badge bg-{{ problem.status|lower }} rounded-pill">{{ problem.get_status_display }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No problems are associated with this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Goals & Objectives Tab -->
|
||||
<div class="tab-pane fade" id="goals" role="tabpanel" aria-labelledby="goals-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Goals</h5>
|
||||
{% if care_plan.goals %}
|
||||
<div class="goals-list">
|
||||
{% for goal in care_plan.goals %}
|
||||
<div class="goal-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ goal.title }}</h6>
|
||||
<span class="badge bg-{{ goal.status|default:'secondary'|lower }}">{{ goal.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ goal.description }}</p>
|
||||
{% if goal.target_date %}
|
||||
<small class="text-muted">Target Date: {{ goal.target_date }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No goals have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3 mt-4">Objectives</h5>
|
||||
{% if care_plan.objectives %}
|
||||
<div class="objectives-list">
|
||||
{% for objective in care_plan.objectives %}
|
||||
<div class="objective-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ objective.title }}</h6>
|
||||
<span class="badge bg-{{ objective.status|default:'secondary'|lower }}">{{ objective.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ objective.description }}</p>
|
||||
{% if objective.measure %}
|
||||
<small class="text-muted">Measure: {{ objective.measure }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No objectives have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Interventions Tab -->
|
||||
<div class="tab-pane fade" id="interventions" role="tabpanel" aria-labelledby="interventions-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Interventions</h5>
|
||||
{% if care_plan.interventions %}
|
||||
<div class="interventions-list">
|
||||
{% for intervention in care_plan.interventions %}
|
||||
<div class="intervention-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ intervention.title }}</h6>
|
||||
<span class="badge bg-{{ intervention.status|default:'secondary'|lower }}">{{ intervention.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ intervention.description }}</p>
|
||||
{% if intervention.frequency %}
|
||||
<small class="text-muted">Frequency: {{ intervention.frequency }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No interventions have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3 mt-4">Activities</h5>
|
||||
{% if care_plan.activities %}
|
||||
<div class="activities-list">
|
||||
{% for activity in care_plan.activities %}
|
||||
<div class="activity-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ activity.title }}</h6>
|
||||
<span class="badge bg-{{ activity.status|default:'secondary'|lower }}">{{ activity.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ activity.description }}</p>
|
||||
{% if activity.assigned_to %}
|
||||
<small class="text-muted">Assigned to: {{ activity.assigned_to }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No activities have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Monitoring Tab -->
|
||||
<div class="tab-pane fade" id="monitoring" role="tabpanel" aria-labelledby="monitoring-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Monitoring Parameters</h5>
|
||||
{% if care_plan.monitoring_parameters %}
|
||||
<div class="monitoring-list">
|
||||
{% for parameter in care_plan.monitoring_parameters %}
|
||||
<div class="monitoring-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ parameter.title }}</h6>
|
||||
<span class="badge bg-{{ parameter.status|default:'secondary'|lower }}">{{ parameter.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ parameter.description }}</p>
|
||||
{% if parameter.frequency %}
|
||||
<small class="text-muted">Frequency: {{ parameter.frequency }}</small>
|
||||
{% endif %}
|
||||
{% if parameter.target_range %}
|
||||
<small class="text-muted d-block">Target Range: {{ parameter.target_range }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No monitoring parameters have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3 mt-4">Evaluation Criteria</h5>
|
||||
{% if care_plan.evaluation_criteria %}
|
||||
<div class="evaluation-list">
|
||||
{% for criteria in care_plan.evaluation_criteria %}
|
||||
<div class="monitoring-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ criteria.title }}</h6>
|
||||
<span class="badge bg-{{ criteria.status|default:'secondary'|lower }}">{{ criteria.status|default:'Not Evaluated' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ criteria.description }}</p>
|
||||
{% if criteria.measure %}
|
||||
<small class="text-muted">Measure: {{ criteria.measure }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No evaluation criteria have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if care_plan.progress_notes %}
|
||||
<h5 class="mb-3 mt-4">Progress Notes</h5>
|
||||
<div class="p-3 bg-light rounded">
|
||||
{{ care_plan.progress_notes|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Patient Involvement Tab -->
|
||||
<div class="tab-pane fade" id="patient" role="tabpanel" aria-labelledby="patient-tab">
|
||||
<div class="p-3">
|
||||
{% if care_plan.patient_goals %}
|
||||
<h5 class="mb-3">Patient Goals</h5>
|
||||
<div class="p-3 bg-light rounded mb-4">
|
||||
{{ care_plan.patient_goals|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if care_plan.patient_preferences %}
|
||||
<h5 class="mb-3">Patient Preferences</h5>
|
||||
<div class="p-3 bg-light rounded mb-4">
|
||||
{{ care_plan.patient_preferences|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if care_plan.patient_barriers %}
|
||||
<h5 class="mb-3">Identified Barriers</h5>
|
||||
<div class="p-3 bg-light rounded mb-4">
|
||||
{{ care_plan.patient_barriers|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3">Resources Needed</h5>
|
||||
{% if care_plan.resources_needed %}
|
||||
<div class="list-group mb-4">
|
||||
{% for resource in care_plan.resources_needed %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ resource.name }}</h6>
|
||||
<span class="badge bg-{{ resource.status|default:'secondary'|lower }}">{{ resource.status|default:'Pending' }}</span>
|
||||
</div>
|
||||
{% if resource.description %}
|
||||
<p class="mb-1">{{ resource.description }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info mb-4">
|
||||
<i class="fa fa-info-circle me-2"></i> No resources have been identified for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3">Support Systems</h5>
|
||||
{% if care_plan.support_systems %}
|
||||
<div class="list-group">
|
||||
{% for support in care_plan.support_systems %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ support.name }}</h6>
|
||||
<span class="badge bg-{{ support.type|default:'secondary'|lower }}">{{ support.type|default:'Other' }}</span>
|
||||
</div>
|
||||
{% if support.description %}
|
||||
<p class="mb-1">{{ support.description }}</p>
|
||||
{% endif %}
|
||||
{% if support.contact %}
|
||||
<small class="text-muted">Contact: {{ support.contact }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No support systems have been identified for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Outcomes Tab -->
|
||||
<div class="tab-pane fade" id="outcomes" role="tabpanel" aria-labelledby="outcomes-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Outcomes Achieved</h5>
|
||||
{% if care_plan.outcomes_achieved %}
|
||||
<div class="outcomes-list">
|
||||
{% for outcome in care_plan.outcomes_achieved %}
|
||||
<div class="outcome-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ outcome.title }}</h6>
|
||||
<span class="badge bg-{{ outcome.status|default:'success'|lower }}">{{ outcome.status|default:'Achieved' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ outcome.description }}</p>
|
||||
{% if outcome.date_achieved %}
|
||||
<small class="text-muted">Date Achieved: {{ outcome.date_achieved }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No outcomes have been recorded for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end tab content -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- end care plan details panel -->
|
||||
|
||||
<!-- begin clinical notes panel -->
|
||||
<div class="panel panel-inverse">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Related Clinical Notes</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% if care_plan.clinical_notes.all %}
|
||||
<div class="timeline">
|
||||
{% for note in care_plan.clinical_notes.all %}
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-time">
|
||||
{{ note.note_datetime|date:"M d, Y" }} <small>{{ note.note_datetime|time:"h:i A" }}</small>
|
||||
</div>
|
||||
<div class="timeline-icon">
|
||||
<a href="javascript:;"> </a>
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h5>{{ note.title }}</h5>
|
||||
<span class="badge bg-{{ note.status|lower }}">{{ note.get_status_display }}</span>
|
||||
</div>
|
||||
<p class="mb-2">{{ note.content|truncatechars:200 }}</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<small class="text-muted">{{ note.get_note_type_display }} by {{ note.author.get_full_name }}</small>
|
||||
<a href="{% url 'emr:clinical_note_detail' note.id %}" class="btn btn-sm btn-primary">View Note</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No clinical notes are associated with this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- end clinical notes panel -->
|
||||
|
||||
<!-- begin action buttons -->
|
||||
<div class="d-flex justify-content-between mt-3">
|
||||
<div>
|
||||
<a href="{% url 'emr:care_plan_list' %}" class="btn btn-secondary me-2">
|
||||
<i class="fa fa-arrow-left me-1"></i> Back to Care Plans
|
||||
</a>
|
||||
<a href="{% url 'emr:patient_detail' care_plan.patient.id %}" class="btn btn-info">
|
||||
<i class="fa fa-user me-1"></i> Patient Profile
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
{% if not care_plan.approved %}
|
||||
<a href="#" class="btn btn-success me-2" data-bs-toggle="modal" data-bs-target="#approveModal">
|
||||
<i class="fa fa-check-circle me-1"></i> Approve Plan
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'emr:care_plan_update' care_plan.id %}" class="btn btn-primary me-2">
|
||||
<i class="fa fa-edit me-1"></i> Edit Care Plan
|
||||
</a>
|
||||
<a href="{% url 'emr:care_plan_delete' care_plan.id %}" class="btn btn-danger">
|
||||
<i class="fa fa-trash me-1"></i> Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end action buttons -->
|
||||
</div>
|
||||
<!-- end col-12 -->
|
||||
</div>
|
||||
<!-- end row -->
|
||||
|
||||
<!-- begin approve modal -->
|
||||
<div class="modal fade" id="approveModal" tabindex="-1" aria-labelledby="approveModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="approveModalLabel">Approve Care Plan</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{% url 'emr:care_plan_approve' care_plan.id %}" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="modal-body">
|
||||
<p>You are about to approve this care plan. This action will mark the plan as officially approved and ready for implementation.</p>
|
||||
<div class="mb-3">
|
||||
<label for="approval_notes" class="form-label">Approval Notes (Optional)</label>
|
||||
<textarea class="form-control" id="approval_notes" name="approval_notes" rows="3"></textarea>
|
||||
</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-success">Approve Care Plan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end approve modal -->
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'plugins/moment/min/moment.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/chart.js/dist/Chart.min.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize tooltips
|
||||
$('[data-bs-toggle="tooltip"]').tooltip();
|
||||
|
||||
// Initialize activity chart
|
||||
var ctx = document.getElementById('activityChart').getContext('2d');
|
||||
var activityChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Initial', 'Week 1', 'Week 2', 'Week 3', 'Week 4', 'Current'],
|
||||
datasets: [{
|
||||
label: 'Completion Progress',
|
||||
data: [0, 15, 30, 45, 60, {{ care_plan.completion_percentage }}],
|
||||
backgroundColor: 'rgba(40, 167, 69, 0.2)',
|
||||
borderColor: 'rgba(40, 167, 69, 1)',
|
||||
borderWidth: 2,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
return value + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(context) {
|
||||
return context.dataset.label + ': ' + context.raw + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle HTMX events
|
||||
document.body.addEventListener('htmx:afterSwap', function(evt) {
|
||||
if (evt.detail.target.id === 'clinical-notes-container') {
|
||||
// Reinitialize any components in the clinical notes container
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
804
emr/templates/emr/care_plans/care_plan_detail.html
Normal file
804
emr/templates/emr/care_plans/care_plan_detail.html
Normal file
@ -0,0 +1,804 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{{ care_plan.title }} | Care Plan Detail{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{#<link href="{% static 'plugins/timeline/timeline.css' %}" rel="stylesheet" />#}
|
||||
<link href="{% static 'plugins/bootstrap-icons/font/bootstrap-icons.css' %}" rel="stylesheet" />
|
||||
{#<link href="{% static 'plugins/chart.js/dist/' %}" rel="stylesheet" />#}
|
||||
<style>
|
||||
.care-plan-badge {
|
||||
font-size: 0.85rem;
|
||||
padding: 0.35em 0.65em;
|
||||
}
|
||||
.care-plan-header {
|
||||
background: linear-gradient(90deg, var(--bs-black), var(--bs-gray));
|
||||
color: white;
|
||||
padding: 1.5rem;
|
||||
border-radius: 0.25rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.care-plan-status-active {
|
||||
background-color: var(--bs-success);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-status-completed {
|
||||
background-color: var(--bs-secondary);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-status-draft {
|
||||
background-color: var(--bs-warning);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-status-on-hold {
|
||||
background-color: var(--bs-info);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-priority-high {
|
||||
background-color: var(--bs-danger);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-priority-medium {
|
||||
background-color: var(--bs-warning);
|
||||
color: white;
|
||||
}
|
||||
.care-plan-priority-low {
|
||||
background-color: var(--bs-info);
|
||||
color: white;
|
||||
}
|
||||
.timeline-item {
|
||||
padding: 1rem;
|
||||
border-left: 3px solid var(--bs-primary);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.related-item {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.related-item:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.goal-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-success);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.objective-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-info);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.intervention-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-warning);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.activity-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-purple);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.outcome-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-teal);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.monitoring-item {
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--bs-cyan);
|
||||
margin-bottom: 1rem;
|
||||
background-color: rgba(var(--bs-light-rgb), 0.5);
|
||||
}
|
||||
.nav-tabs .nav-link.active {
|
||||
font-weight: bold;
|
||||
border-bottom: 3px solid var(--bs-primary);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- begin page-header -->
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<div>
|
||||
<h1 class="h2">
|
||||
<i class="fas fa-tachometer-alt"></i>Care Plan<span class="fw-light">Detail</span>
|
||||
</h1>
|
||||
<p class="text-muted">Comprehensive care plan information</p>
|
||||
</div>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<div class="btn-group me-2">
|
||||
<a href="{% url 'emr:care_plan_list' %}" class="btn btn-secondary me-2">
|
||||
<i class="fa fa-arrow-left me-1"></i> Back to the list
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end page-header -->
|
||||
|
||||
<!-- begin row -->
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<!-- begin col-12 -->
|
||||
<div class="col-xl-12">
|
||||
<!-- begin care plan header -->
|
||||
<div class="care-plan-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h2 class="mb-1">{{ care_plan.title }}</h2>
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="me-3">
|
||||
<i class="bi bi-person-fill me-1"></i> {{ care_plan.patient.get_full_name }}
|
||||
</span>
|
||||
<span class="me-3">
|
||||
<i class="bi bi-calendar-event me-1"></i> Start: {{ care_plan.start_date }}
|
||||
{% if care_plan.end_date %}
|
||||
- End: {{ care_plan.end_date }}
|
||||
{% endif %}
|
||||
</span>
|
||||
<span>
|
||||
<i class="bi bi-person-badge me-1"></i> {{ care_plan.primary_provider.get_full_name }}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<span class="badge care-plan-status-{{ care_plan.status|lower }} me-2">{{ care_plan.get_status_display }}</span>
|
||||
<span class="badge care-plan-priority-{{ care_plan.priority|lower }}">{{ care_plan.get_priority_display }} Priority</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end care plan header -->
|
||||
|
||||
<!-- begin progress panel -->
|
||||
<div class="panel panel-inverse">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Progress</h4>
|
||||
|
||||
<div class="panel-heading-btn">
|
||||
<a href="{% url 'patients:patient_detail' care_plan.patient.id %}" class="btn btn-xs btn-outline-secondary me-2">
|
||||
<i class="fa fa-user me-1"></i> Patient Profile
|
||||
</a>
|
||||
{% if not care_plan.approved %}
|
||||
<a href="#" class="btn btn-xs btn-outline-success me-2" data-bs-toggle="modal" data-bs-target="#approveModal">
|
||||
<i class="fa fa-check-circle me-1"></i> Approve Plan
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'emr:care_plan_update' care_plan.id %}" class="btn btn-xs btn-outline-warning me-2">
|
||||
<i class="fa fa-edit me-1"></i> Edit
|
||||
</a>
|
||||
<a href="{% url 'emr:care_plan_delete' care_plan.id %}" class="btn btn-xs btn-outline-danger me-2">
|
||||
<i class="fa fa-trash me-1"></i> Delete
|
||||
</a>
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Completion Progress</h5>
|
||||
<div class="progress" style="height: 25px;">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated bg-success"
|
||||
role="progressbar"
|
||||
style="width: {{ care_plan.completion_percentage }}%;"
|
||||
aria-valuenow="{{ care_plan.completion_percentage }}"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100">
|
||||
{{ care_plan.completion_percentage }}% Complete
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-3">Plan Timeline</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="30%">Start Date</th>
|
||||
<td>{{ care_plan.start_date }}</td>
|
||||
</tr>
|
||||
{% if care_plan.target_completion_date %}
|
||||
<tr>
|
||||
<th>Target Completion</th>
|
||||
<td>{{ care_plan.target_completion_date }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if care_plan.end_date %}
|
||||
<tr>
|
||||
<th>End Date</th>
|
||||
<td>{{ care_plan.end_date }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if care_plan.last_reviewed %}
|
||||
<tr>
|
||||
<th>Last Reviewed</th>
|
||||
<td>{{ care_plan.last_reviewed }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if care_plan.next_review_date %}
|
||||
<tr>
|
||||
<th>Next Review</th>
|
||||
<td>
|
||||
{{ care_plan.next_review_date }}
|
||||
{% if care_plan.is_overdue %}
|
||||
<span class="badge bg-danger ms-2">Overdue</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Activity Chart</h5>
|
||||
<canvas id="activityChart" height="200"></canvas>
|
||||
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-3">Approval Status</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="30%">Status</th>
|
||||
<td>
|
||||
{% if care_plan.approved %}
|
||||
<span class="badge bg-success">Approved</span>
|
||||
{% else %}
|
||||
<span class="badge bg-warning">Pending Approval</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if care_plan.approved %}
|
||||
<tr>
|
||||
<th>Approved By</th>
|
||||
<td>{{ care_plan.approved_by.get_full_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Approved Date</th>
|
||||
<td>{{ care_plan.approved_date }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end progress panel -->
|
||||
|
||||
<!-- begin care plan details panel -->
|
||||
<div class="panel panel-inverse">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Care Plan Details</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<!-- begin nav tabs -->
|
||||
<ul class="nav nav-tabs" id="carePlanTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="overview-tab" data-bs-toggle="tab" data-bs-target="#overview" type="button" role="tab" aria-controls="overview" aria-selected="true">Overview</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="goals-tab" data-bs-toggle="tab" data-bs-target="#goals" type="button" role="tab" aria-controls="goals" aria-selected="false">Goals & Objectives</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="interventions-tab" data-bs-toggle="tab" data-bs-target="#interventions" type="button" role="tab" aria-controls="interventions" aria-selected="false">Interventions</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="monitoring-tab" data-bs-toggle="tab" data-bs-target="#monitoring" type="button" role="tab" aria-controls="monitoring" aria-selected="false">Monitoring</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="patient-tab" data-bs-toggle="tab" data-bs-target="#patient" type="button" role="tab" aria-controls="patient" aria-selected="false">Patient Involvement</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="outcomes-tab" data-bs-toggle="tab" data-bs-target="#outcomes" type="button" role="tab" aria-controls="outcomes" aria-selected="false">Outcomes</button>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- end nav tabs -->
|
||||
|
||||
<!-- begin tab content -->
|
||||
<div class="tab-content" id="carePlanTabsContent">
|
||||
<!-- Overview Tab -->
|
||||
<div class="tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="overview-tab">
|
||||
<div class="p-3">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Basic Information</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="30%">Care Plan ID</th>
|
||||
<td>{{ care_plan.care_plan_id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Plan Type</th>
|
||||
<td>{{ care_plan.get_plan_type_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<td>{{ care_plan.get_category_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td>{{ care_plan.get_status_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Priority</th>
|
||||
<td>{{ care_plan.get_priority_display }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h5 class="mb-3 mt-4">Description</h5>
|
||||
<div class="p-3 bg-light rounded">
|
||||
{{ care_plan.description|linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h5 class="mb-3">Provider Information</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="30%">Primary Provider</th>
|
||||
<td>{{ care_plan.primary_provider.get_full_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Care Team</th>
|
||||
<td>
|
||||
{% if care_plan.care_team.all %}
|
||||
<ul class="mb-0 ps-3">
|
||||
{% for provider in care_plan.care_team.all %}
|
||||
<li>{{ provider.get_full_name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
No additional care team members
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h5 class="mb-3 mt-4">Related Problems</h5>
|
||||
{% if care_plan.related_problems.all %}
|
||||
<div class="list-group">
|
||||
{% for problem in care_plan.related_problems.all %}
|
||||
<a href="{% url 'emr:problem_detail' problem.id %}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
|
||||
{{ problem.problem_name }}
|
||||
<span class="badge bg-{{ problem.status|lower }} rounded-pill">{{ problem.get_status_display }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No problems are associated with this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Goals & Objectives Tab -->
|
||||
<div class="tab-pane fade" id="goals" role="tabpanel" aria-labelledby="goals-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Goals</h5>
|
||||
{% if care_plan.goals %}
|
||||
<div class="goals-list">
|
||||
{% for goal in care_plan.goals %}
|
||||
<div class="goal-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ goal.title }}</h6>
|
||||
<span class="badge bg-{{ goal.status|default:'secondary'|lower }}">{{ goal.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ goal.description }}</p>
|
||||
{% if goal.target_date %}
|
||||
<small class="text-muted">Target Date: {{ goal.target_date }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No goals have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3 mt-4">Objectives</h5>
|
||||
{% if care_plan.objectives %}
|
||||
<div class="objectives-list">
|
||||
{% for objective in care_plan.objectives %}
|
||||
<div class="objective-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ objective.title }}</h6>
|
||||
<span class="badge bg-{{ objective.status|default:'secondary'|lower }}">{{ objective.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ objective.description }}</p>
|
||||
{% if objective.measure %}
|
||||
<small class="text-muted">Measure: {{ objective.measure }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No objectives have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Interventions Tab -->
|
||||
<div class="tab-pane fade" id="interventions" role="tabpanel" aria-labelledby="interventions-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Interventions</h5>
|
||||
{% if care_plan.interventions %}
|
||||
<div class="interventions-list">
|
||||
{% for intervention in care_plan.interventions %}
|
||||
<div class="intervention-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ intervention.title }}</h6>
|
||||
<span class="badge bg-{{ intervention.status|default:'secondary'|lower }}">{{ intervention.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ intervention.description }}</p>
|
||||
{% if intervention.frequency %}
|
||||
<small class="text-muted">Frequency: {{ intervention.frequency }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No interventions have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3 mt-4">Activities</h5>
|
||||
{% if care_plan.activities %}
|
||||
<div class="activities-list">
|
||||
{% for activity in care_plan.activities %}
|
||||
<div class="activity-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ activity.title }}</h6>
|
||||
<span class="badge bg-{{ activity.status|default:'secondary'|lower }}">{{ activity.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ activity.description }}</p>
|
||||
{% if activity.assigned_to %}
|
||||
<small class="text-muted">Assigned to: {{ activity.assigned_to }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No activities have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Monitoring Tab -->
|
||||
<div class="tab-pane fade" id="monitoring" role="tabpanel" aria-labelledby="monitoring-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Monitoring Parameters</h5>
|
||||
{% if care_plan.monitoring_parameters %}
|
||||
<div class="monitoring-list">
|
||||
{% for parameter in care_plan.monitoring_parameters %}
|
||||
<div class="monitoring-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ parameter.title }}</h6>
|
||||
<span class="badge bg-{{ parameter.status|default:'secondary'|lower }}">{{ parameter.status|default:'Not Started' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ parameter.description }}</p>
|
||||
{% if parameter.frequency %}
|
||||
<small class="text-muted">Frequency: {{ parameter.frequency }}</small>
|
||||
{% endif %}
|
||||
{% if parameter.target_range %}
|
||||
<small class="text-muted d-block">Target Range: {{ parameter.target_range }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No monitoring parameters have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3 mt-4">Evaluation Criteria</h5>
|
||||
{% if care_plan.evaluation_criteria %}
|
||||
<div class="evaluation-list">
|
||||
{% for criteria in care_plan.evaluation_criteria %}
|
||||
<div class="monitoring-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ criteria.title }}</h6>
|
||||
<span class="badge bg-{{ criteria.status|default:'secondary'|lower }}">{{ criteria.status|default:'Not Evaluated' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ criteria.description }}</p>
|
||||
{% if criteria.measure %}
|
||||
<small class="text-muted">Measure: {{ criteria.measure }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No evaluation criteria have been defined for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if care_plan.progress_notes %}
|
||||
<h5 class="mb-3 mt-4">Progress Notes</h5>
|
||||
<div class="p-3 bg-light rounded">
|
||||
{{ care_plan.progress_notes|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Patient Involvement Tab -->
|
||||
<div class="tab-pane fade" id="patient" role="tabpanel" aria-labelledby="patient-tab">
|
||||
<div class="p-3">
|
||||
{% if care_plan.patient_goals %}
|
||||
<h5 class="mb-3">Patient Goals</h5>
|
||||
<div class="p-3 bg-light rounded mb-4">
|
||||
{{ care_plan.patient_goals|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if care_plan.patient_preferences %}
|
||||
<h5 class="mb-3">Patient Preferences</h5>
|
||||
<div class="p-3 bg-light rounded mb-4">
|
||||
{{ care_plan.patient_preferences|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if care_plan.patient_barriers %}
|
||||
<h5 class="mb-3">Identified Barriers</h5>
|
||||
<div class="p-3 bg-light rounded mb-4">
|
||||
{{ care_plan.patient_barriers|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3">Resources Needed</h5>
|
||||
{% if care_plan.resources_needed %}
|
||||
<div class="list-group mb-4">
|
||||
{% for resource in care_plan.resources_needed %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ resource.name }}</h6>
|
||||
<span class="badge bg-{{ resource.status|default:'secondary'|lower }}">{{ resource.status|default:'Pending' }}</span>
|
||||
</div>
|
||||
{% if resource.description %}
|
||||
<p class="mb-1">{{ resource.description }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info mb-4">
|
||||
<i class="fa fa-info-circle me-2"></i> No resources have been identified for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="mb-3">Support Systems</h5>
|
||||
{% if care_plan.support_systems %}
|
||||
<div class="list-group">
|
||||
{% for support in care_plan.support_systems %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ support.name }}</h6>
|
||||
<span class="badge bg-{{ support.type|default:'secondary'|lower }}">{{ support.type|default:'Other' }}</span>
|
||||
</div>
|
||||
{% if support.description %}
|
||||
<p class="mb-1">{{ support.description }}</p>
|
||||
{% endif %}
|
||||
{% if support.contact %}
|
||||
<small class="text-muted">Contact: {{ support.contact }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No support systems have been identified for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Outcomes Tab -->
|
||||
<div class="tab-pane fade" id="outcomes" role="tabpanel" aria-labelledby="outcomes-tab">
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Outcomes Achieved</h5>
|
||||
{% if care_plan.outcomes_achieved %}
|
||||
<div class="outcomes-list">
|
||||
{% for outcome in care_plan.outcomes_achieved %}
|
||||
<div class="outcome-item">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ outcome.title }}</h6>
|
||||
<span class="badge bg-{{ outcome.status|default:'success'|lower }}">{{ outcome.status|default:'Achieved' }}</span>
|
||||
</div>
|
||||
<p class="mb-1">{{ outcome.description }}</p>
|
||||
{% if outcome.date_achieved %}
|
||||
<small class="text-muted">Date Achieved: {{ outcome.date_achieved }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No outcomes have been recorded for this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end tab content -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- end care plan details panel -->
|
||||
|
||||
<!-- begin clinical notes panel -->
|
||||
<div class="panel panel-inverse">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Related Clinical Notes</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% if care_plan.clinical_notes.all %}
|
||||
<div class="timeline">
|
||||
{% for note in care_plan.clinical_notes.all %}
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-time">
|
||||
{{ note.note_datetime|date:"M d, Y" }} <small>{{ note.note_datetime|time:"h:i A" }}</small>
|
||||
</div>
|
||||
<div class="timeline-icon">
|
||||
<a href="javascript:;"> </a>
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h5>{{ note.title }}</h5>
|
||||
<span class="badge bg-{{ note.status|lower }}">{{ note.get_status_display }}</span>
|
||||
</div>
|
||||
<p class="mb-2">{{ note.content|truncatechars:200 }}</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<small class="text-muted">{{ note.get_note_type_display }} by {{ note.author.get_full_name }}</small>
|
||||
<a href="{% url 'emr:clinical_note_detail' note.id %}" class="btn btn-sm btn-primary">View Note</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle me-2"></i> No clinical notes are associated with this care plan.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- end clinical notes panel -->
|
||||
|
||||
</div>
|
||||
<!-- end col-12 -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- end row -->
|
||||
|
||||
<!-- begin approve modal -->
|
||||
<div class="modal fade" id="approveModal" tabindex="-1" aria-labelledby="approveModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="approveModalLabel">Approve Care Plan</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="modal-body">
|
||||
<p>You are about to approve this care plan. This action will mark the plan as officially approved and ready for implementation.</p>
|
||||
<div class="mb-3">
|
||||
<label for="approval_notes" class="form-label">Approval Notes (Optional)</label>
|
||||
<textarea class="form-control" id="approval_notes" name="approval_notes" rows="3"></textarea>
|
||||
</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-success">Approve Care Plan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end approve modal -->
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'plugins/moment/min/moment.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/chart.js/dist/chart.umd.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize tooltips
|
||||
$('[data-bs-toggle="tooltip"]').tooltip();
|
||||
|
||||
// Initialize activity chart
|
||||
var ctx = document.getElementById('activityChart').getContext('2d');
|
||||
var activityChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Initial', 'Week 1', 'Week 2', 'Week 3', 'Week 4', 'Current'],
|
||||
datasets: [{
|
||||
label: 'Completion Progress',
|
||||
data: [0, 15, 30, 45, 60, {{ care_plan.completion_percentage }}],
|
||||
backgroundColor: 'rgba(40, 167, 69, 0.2)',
|
||||
borderColor: 'rgba(40, 167, 69, 1)',
|
||||
borderWidth: 2,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: 100,
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
return value + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(context) {
|
||||
return context.dataset.label + ': ' + context.raw + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Handle HTMX events
|
||||
document.body.addEventListener('htmx:afterSwap', function(evt) {
|
||||
if (evt.detail.target.id === 'clinical-notes-container') {
|
||||
// Reinitialize any components in the clinical notes container
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@ -88,16 +88,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- begin breadcrumb -->
|
||||
<ol class="breadcrumb float-xl-end">
|
||||
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'emr:dashboard' %}">EMR</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'emr:care_plan_list' %}">Care Plans</a></li>
|
||||
<li class="breadcrumb-item active">
|
||||
{% if form.instance.id %}Edit Care Plan{% else %}New Care Plan{% endif %}
|
||||
</li>
|
||||
</ol>
|
||||
<!-- end breadcrumb -->
|
||||
|
||||
|
||||
<!-- begin page-header -->
|
||||
<h1 class="page-header">
|
||||
|
||||
@ -4,17 +4,30 @@
|
||||
{% block title %}Care Plans - {{ block.super }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<div>
|
||||
<h1 class="h2">
|
||||
<i class="fas fa-clipboard-list me-2"></i>Care Plan<span class="fw-light">Management</span>
|
||||
</h1>
|
||||
<p class="text-muted">Manage all healthcare plans</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title mb-0">
|
||||
<i class="fas fa-clipboard-list me-2"></i>Care Plan Management
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="panel panel-inverse" data-sortable-id="index-1">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fas fa-clipboard-list me-2"></i>All Care Plans</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
<a href="javascript:" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<!-- Filters -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-2">
|
||||
@ -128,20 +141,20 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button class="btn btn-outline-primary" title="View Details">
|
||||
<a href="{% url 'emr:care_plan_detail' plan.id%}" class="btn btn-outline-primary" title="View Details">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</a>
|
||||
{% if plan.status == 'ACTIVE' %}
|
||||
<button class="btn btn-outline-info" title="Update Progress">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-success"
|
||||
title="Mark Complete"
|
||||
hx-post="{% url 'emr:complete_care_plan' plan.id %}"
|
||||
hx-confirm="Mark this care plan as complete?"
|
||||
hx-swap="none">
|
||||
<i class="fas fa-check"></i>
|
||||
</button>
|
||||
{# <button class="btn btn-outline-success" #}
|
||||
{# title="Mark Complete"#}
|
||||
{# hx-post="{% url 'emr:complete_care_plan' plan.id %}"#}
|
||||
{# hx-confirm="Mark this care plan as complete?"#}
|
||||
{# hx-swap="none">#}
|
||||
{# <i class="fas fa-check"></i>#}
|
||||
{# </button>#}
|
||||
{% endif %}
|
||||
<button class="btn btn-outline-secondary" title="Notes">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
@ -164,33 +177,7 @@
|
||||
|
||||
<!-- Pagination -->
|
||||
{% if is_paginated %}
|
||||
<nav aria-label="Care plan pagination">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1">First</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item active">
|
||||
<span class="page-link">
|
||||
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% include 'partial/pagination.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@ -71,14 +71,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- begin breadcrumb -->
|
||||
<ol class="breadcrumb float-xl-end">
|
||||
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'emr:dashboard' %}">EMR</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'emr:problem_list' %}">Problems</a></li>
|
||||
<li class="breadcrumb-item active">{{ problem.problem_name }}</li>
|
||||
</ol>
|
||||
<!-- end breadcrumb -->
|
||||
|
||||
<!-- begin page-header -->
|
||||
<h1 class="page-header">Problem Detail <small>Comprehensive problem information</small></h1>
|
||||
@ -360,7 +352,7 @@
|
||||
<a href="{% url 'emr:problem_list' %}" class="btn btn-secondary me-2">
|
||||
<i class="fa fa-arrow-left me-1"></i> Back to Problem List
|
||||
</a>
|
||||
<a href="{% url 'emr:patient_detail' problem.patient.id %}" class="btn btn-info">
|
||||
<a href="{% url 'patients:patient_detail' problem.patient.id %}" class="btn btn-info">
|
||||
<i class="fa fa-user me-1"></i> Patient Profile
|
||||
</a>
|
||||
</div>
|
||||
@ -392,7 +384,7 @@
|
||||
<h5 class="modal-title" id="resolveModalLabel">Resolve Problem</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{% url 'emr:problem_resolve' problem.id %}" method="post">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
@ -19,8 +19,17 @@ urlpatterns = [
|
||||
path('vital-signs/', views.VitalSignsListView.as_view(), name='vital_signs_list'),
|
||||
path('add-vital-signs/<int:pk>/', views.VitalSignsCreateView.as_view(), name='add_vital_signs'),
|
||||
path('vital-signs/<int:pk>/', views.VitalSignsDetailView.as_view(), name='vital_signs_detail'),
|
||||
|
||||
path('problems/', views.ProblemListView.as_view(), name='problem_list'),
|
||||
path('problems/<int:pk>/', views.ProblemListDetailView.as_view(), name='problem_detail'),
|
||||
path('problems/<int:pk>/update/', views.ProblemListUpdateView.as_view(), name='problem_update'),
|
||||
path('problems/<int:pk>/delete/', views.ProblemListDeleteView.as_view(), name='problem_delete'),
|
||||
|
||||
path('care-plans/', views.CarePlanListView.as_view(), name='care_plan_list'),
|
||||
path('care-plans/<int:pk>/', views.CarePlanDetailView.as_view(), name='care_plan_detail'),
|
||||
path('care-plans/<int:pk>/update/', views.CarePlanUpdateView.as_view(), name='care_plan_update'),
|
||||
path('care-plans/<int:pk>/delete/', views.CarePlanDeleteView.as_view(), name='care_plan_delete'),
|
||||
|
||||
path('notes/', views.ClinicalNoteListView.as_view(), name='clinical_note_list'),
|
||||
path('notes/<int:pk>/', views.ClinicalNoteDetailView.as_view(), name='clinical_note_detail'),
|
||||
path('notes/<int:pk>/update/', views.ClinicalNoteUpdateView.as_view(), name='clinical_note_update'),
|
||||
|
||||
992
emr/views.py
992
emr/views.py
File diff suppressed because it is too large
Load Diff
Binary file not shown.
68
hr/migrations/0003_alter_employee_role.py
Normal file
68
hr/migrations/0003_alter_employee_role.py
Normal file
@ -0,0 +1,68 @@
|
||||
# Generated by Django 5.2.6 on 2025-09-16 15:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("hr", "0002_alter_employee_id_number"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="employee",
|
||||
name="role",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("SUPER_ADMIN", "Super Administrator"),
|
||||
("ADMIN", "Administrator"),
|
||||
("PHYSICIAN", "Physician"),
|
||||
("SURGEON", "Surgeon"),
|
||||
("NURSE", "Nurse"),
|
||||
("NURSE_PRACTITIONER", "Nurse Practitioner"),
|
||||
("PHYSICIAN_ASSISTANT", "Physician Assistant"),
|
||||
("SURGICAL_TECHNICIAN", "Surgical Technician"),
|
||||
("ANESTHESIOLOGIST", "Anesthesiologist"),
|
||||
("ANESTHESIOLOGIST_ASSOCIATE", "Anesthesiologist Associate"),
|
||||
("CLINICAL_NURSE_ASSOCIATE", "Clinical Nurse Associate"),
|
||||
("CLINICAL_NURSE_SPECIALIST", "Clinical Nurse Specialist"),
|
||||
("CLINICAL_NURSE_MANAGER", "Clinical Nurse Manager"),
|
||||
("CLINICAL_NURSE_TECHNICIAN", "Clinical Nurse Technician"),
|
||||
("CLINICAL_NURSE_COORDINATOR", "Clinical Nurse Coordinator"),
|
||||
("FELLOW", "Fellow"),
|
||||
("INTERN", "Intern"),
|
||||
("INTERNSHIP", "Internship"),
|
||||
("RESIDENT", "Resident"),
|
||||
("WORK_FROM_HOME", "Work from Home"),
|
||||
("WORK_FROM_HOME_PART_TIME", "Work from Home Part-time"),
|
||||
("PHARMACIST", "Pharmacist"),
|
||||
("PHARMACY_TECH", "Pharmacy Technician"),
|
||||
("LAB_TECH", "Laboratory Technician"),
|
||||
("RADIOLOGIST", "Radiologist"),
|
||||
("RAD_TECH", "Radiology Technician"),
|
||||
("THERAPIST", "Therapist"),
|
||||
("SOCIAL_WORKER", "Social Worker"),
|
||||
("CASE_MANAGER", "Case Manager"),
|
||||
("BILLING_SPECIALIST", "Billing Specialist"),
|
||||
("REGISTRATION", "Registration Staff"),
|
||||
("SCHEDULER", "Scheduler"),
|
||||
("MEDICAL_ASSISTANT", "Medical Assistant"),
|
||||
("CLERICAL", "Clerical Staff"),
|
||||
("IT_SUPPORT", "IT Support"),
|
||||
("QUALITY_ASSURANCE", "Quality Assurance"),
|
||||
("COMPLIANCE", "Compliance Officer"),
|
||||
("SECURITY", "Security"),
|
||||
("MAINTENANCE", "Maintenance"),
|
||||
("VOLUNTEER", "Volunteer"),
|
||||
("STUDENT", "Student"),
|
||||
("RESEARCHER", "Researcher"),
|
||||
("CONSULTANT", "Consultant"),
|
||||
("VENDOR", "Vendor"),
|
||||
("GUEST", "Guest"),
|
||||
],
|
||||
default="GUEST",
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
15
hr/models.py
15
hr/models.py
@ -56,9 +56,24 @@ class Employee(models.Model):
|
||||
SUPER_ADMIN = 'SUPER_ADMIN', 'Super Administrator'
|
||||
ADMIN = 'ADMIN', 'Administrator'
|
||||
PHYSICIAN = 'PHYSICIAN', 'Physician'
|
||||
SURGEON = 'SURGEON', 'Surgeon'
|
||||
NURSE = 'NURSE', 'Nurse'
|
||||
NURSE_PRACTITIONER = 'NURSE_PRACTITIONER', 'Nurse Practitioner'
|
||||
PHYSICIAN_ASSISTANT = 'PHYSICIAN_ASSISTANT', 'Physician Assistant'
|
||||
SURGICAL_TECHNICIAN = 'SURGICAL_TECHNICIAN', 'Surgical Technician'
|
||||
ANESTHESIOLOGIST = 'ANESTHESIOLOGIST', 'Anesthesiologist'
|
||||
ANESTHESIOLOGIST_ASSOCIATE = 'ANESTHESIOLOGIST_ASSOCIATE', 'Anesthesiologist Associate'
|
||||
CLINICAL_NURSE_ASSOCIATE = 'CLINICAL_NURSE_ASSOCIATE', 'Clinical Nurse Associate'
|
||||
CLINICAL_NURSE_SPECIALIST = 'CLINICAL_NURSE_SPECIALIST', 'Clinical Nurse Specialist'
|
||||
CLINICAL_NURSE_MANAGER = 'CLINICAL_NURSE_MANAGER', 'Clinical Nurse Manager'
|
||||
CLINICAL_NURSE_TECHNICIAN = 'CLINICAL_NURSE_TECHNICIAN', 'Clinical Nurse Technician'
|
||||
CLINICAL_NURSE_COORDINATOR = 'CLINICAL_NURSE_COORDINATOR', 'Clinical Nurse Coordinator'
|
||||
FELLOW = 'FELLOW', 'Fellow'
|
||||
INTERN = 'INTERN', 'Intern'
|
||||
INTERNSHIP = 'INTERNSHIP', 'Internship'
|
||||
RESIDENT = 'RESIDENT', 'Resident'
|
||||
WORK_FROM_HOME = 'WORK_FROM_HOME', 'Work from Home'
|
||||
WORK_FROM_HOME_PART_TIME = 'WORK_FROM_HOME_PART_TIME', 'Work from Home Part-time'
|
||||
PHARMACIST = 'PHARMACIST', 'Pharmacist'
|
||||
PHARMACY_TECH = 'PHARMACY_TECH', 'Pharmacy Technician'
|
||||
LAB_TECH = 'LAB_TECH', 'Laboratory Technician'
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -153,7 +153,6 @@ class AdmissionForm(forms.ModelForm):
|
||||
is_accepting_admissions=True
|
||||
).order_by('name')
|
||||
|
||||
# Initialize empty bed queryset - will be populated via AJAX
|
||||
self.fields['current_bed'].queryset = Bed.objects.filter(
|
||||
ward__tenant=user.tenant,
|
||||
status='AVAILABLE'
|
||||
@ -162,13 +161,13 @@ class AdmissionForm(forms.ModelForm):
|
||||
self.fields['admitting_physician'].queryset = User.objects.filter(
|
||||
tenant=user.tenant,
|
||||
is_active=True,
|
||||
role__in=['DOCTOR', 'SPECIALIST']
|
||||
employee_profile__role__in=['PHYSICIAN', 'PHYSICIAN_ASSISTANT']
|
||||
).order_by('last_name', 'first_name')
|
||||
|
||||
self.fields['attending_physician'].queryset = User.objects.filter(
|
||||
tenant=user.tenant,
|
||||
is_active=True,
|
||||
role__in=['DOCTOR', 'SPECIALIST']
|
||||
employee_profile__role__in=['PHYSICIAN', 'PHYSICIAN_ASSISTANT']
|
||||
).order_by('last_name', 'first_name')
|
||||
|
||||
def clean_admission_datetime(self):
|
||||
@ -402,13 +401,13 @@ class SurgeryScheduleForm(forms.ModelForm):
|
||||
self.fields['primary_surgeon'].queryset = User.objects.filter(
|
||||
tenant=user.tenant,
|
||||
is_active=True,
|
||||
role__in=['DOCTOR', 'SURGEON', 'SPECIALIST']
|
||||
employee_profile__role__in=['PHYSICIAN', 'SURGEON', 'SPECIALIST']
|
||||
).order_by('last_name', 'first_name')
|
||||
|
||||
self.fields['anesthesiologist'].queryset = User.objects.filter(
|
||||
tenant=user.tenant,
|
||||
is_active=True,
|
||||
role__in=['DOCTOR', 'ANESTHESIOLOGIST']
|
||||
employee_profile__role__in=['PHYSICIAN', 'ANESTHESIOLOGIST']
|
||||
).order_by('last_name', 'first_name')
|
||||
|
||||
def clean_scheduled_date(self):
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
# Generated by Django 5.2.6 on 2025-09-16 15:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("inpatients", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="dischargesummary",
|
||||
name="discharge_disposition",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("HOME", "Home"),
|
||||
("HOME_HEALTH", "Home with Health Services"),
|
||||
("NURSING_HOME", "Nursing Home"),
|
||||
("REHAB_FACILITY", "Rehabilitation Facility"),
|
||||
("HOSPICE", "Hospice"),
|
||||
("TRANSFER", "Transfer to Another Hospital"),
|
||||
("MORGUE", "Morgue"),
|
||||
("OTHER", "Other"),
|
||||
],
|
||||
help_text="Discharge disposition",
|
||||
max_length=30,
|
||||
),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
@ -849,8 +849,6 @@ class Admission(models.Model):
|
||||
return self.status in ['PENDING', 'ADMITTED', 'TRANSFERRED']
|
||||
|
||||
|
||||
|
||||
|
||||
class Transfer(models.Model):
|
||||
"""
|
||||
Patient transfer model for tracking ward/bed changes.
|
||||
@ -1124,6 +1122,7 @@ class DischargeSummary(models.Model):
|
||||
('REHAB_FACILITY', 'Rehabilitation Facility'),
|
||||
('HOSPICE', 'Hospice'),
|
||||
('TRANSFER', 'Transfer to Another Hospital'),
|
||||
('MORGUE', 'Morgue'),
|
||||
('OTHER', 'Other'),
|
||||
]
|
||||
TRANSPORTATION_METHOD_CHOICES = [
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
<i class="fas fa-cog me-2"></i>Quick Actions
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{% url 'inpatients:admission_list' %}?action=new">
|
||||
<li><a class="dropdown-item" href="{% url 'inpatients:admission_create' %}">
|
||||
<i class="fas fa-user-plus me-2"></i>New Admission
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="{% url 'inpatients:bed_management' %}">
|
||||
@ -154,10 +154,10 @@
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#">
|
||||
<li><a class="dropdown-item" href="{% url 'inpatients:transfer_patient' admission.id %}">
|
||||
<i class="fas fa-exchange-alt me-2"></i>Transfer
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="#">
|
||||
<li><a class="dropdown-item" href="{% url 'inpatients:discharge_patient' admission.patient.id %}">
|
||||
<i class="fas fa-sign-out-alt me-2"></i>Discharge
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="#">
|
||||
@ -297,7 +297,7 @@
|
||||
<small class="text-muted">{{ ward.get_ward_type_display }}</small>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<span class="badge bg-primary">{{ ward.o }}/{{ ward.total_beds }}</span>
|
||||
<span class="badge bg-primary">{{ ward.occupied_beds }}/{{ ward.total_beds }}</span>
|
||||
<br><small class="text-muted">{{ ward.occupancy_rate|floatformat:0 }}%</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Surgery Calendar Partial -->
|
||||
<div id="surgery-calendar-container">
|
||||
<!-- Calendar Controls -->
|
||||
@ -164,7 +165,7 @@ $(document).ready(function() {
|
||||
// Event sources
|
||||
events: function(start, end, timezone, callback) {
|
||||
$.ajax({
|
||||
url: '{% url "inpatients:surgery_calendar_data" %}',
|
||||
url: '',
|
||||
data: {
|
||||
start: start.format(),
|
||||
end: end.format()
|
||||
@ -242,7 +243,7 @@ $(document).ready(function() {
|
||||
// Load surgery quick view
|
||||
function loadSurgeryQuickView(surgeryId) {
|
||||
$.ajax({
|
||||
url: '{% url "inpatients:surgery_quick_view" 0 %}'.replace('0', surgeryId),
|
||||
url: ''.replace('0', surgeryId),
|
||||
success: function(data) {
|
||||
$('#surgery-quick-view-content').html(data.html);
|
||||
$('#view-full-surgery').attr('href', data.detail_url);
|
||||
@ -269,7 +270,7 @@ $(document).ready(function() {
|
||||
function loadSelectOptions() {
|
||||
// Load patients
|
||||
$.ajax({
|
||||
url: '{% url "patients:patient_list_api" %}',
|
||||
url: '',
|
||||
success: function(data) {
|
||||
var patientSelect = $('select[name="patient"]');
|
||||
patientSelect.empty().append('<option value="">Select Patient</option>');
|
||||
@ -282,7 +283,7 @@ $(document).ready(function() {
|
||||
|
||||
// Load surgeons
|
||||
$.ajax({
|
||||
url: '{% url "users:surgeon_list_api" %}',
|
||||
url: '',
|
||||
success: function(data) {
|
||||
var surgeonSelect = $('select[name="surgeon"]');
|
||||
surgeonSelect.empty().append('<option value="">Select Surgeon</option>');
|
||||
@ -295,7 +296,7 @@ $(document).ready(function() {
|
||||
|
||||
// Load operating rooms
|
||||
$.ajax({
|
||||
url: '{% url "inpatients:operating_room_list_api" %}',
|
||||
url: '',
|
||||
success: function(data) {
|
||||
var roomSelect = $('select[name="operating_room"]');
|
||||
roomSelect.empty().append('<option value="">Select OR</option>');
|
||||
@ -311,7 +312,7 @@ $(document).ready(function() {
|
||||
var formData = $('#quick-surgery-form').serialize();
|
||||
|
||||
$.ajax({
|
||||
url: '{% url "inpatients:surgery_create_quick" %}',
|
||||
url: '',
|
||||
method: 'POST',
|
||||
data: formData,
|
||||
success: function(response) {
|
||||
@ -419,3 +420,4 @@ $(document).ready(function() {
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -4,19 +4,13 @@
|
||||
{% block title %}Surgery Details - {{ object.procedure_name }}{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
{% 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 'inpatients:dashboard' %}">Inpatients</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'inpatients:surgery_list' %}">Surgeries</a></li>
|
||||
<li class="breadcrumb-item active">{{ object.procedure_name }}</li>
|
||||
</ol>
|
||||
<!-- END breadcrumb -->
|
||||
|
||||
|
||||
<!-- BEGIN page-header -->
|
||||
<h1 class="page-header">
|
||||
@ -32,7 +26,7 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Surgery Information</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="{% url 'inpatients:surgery_update' object.pk %}" class="btn btn-xs btn-primary me-2">
|
||||
<a href="{% url 'inpatients:surgery_update' object.pk %}" class="btn btn-xs btn-outline-theme me-2">
|
||||
<i class="fa fa-edit"></i> Edit
|
||||
</a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
@ -63,8 +57,8 @@
|
||||
<tr>
|
||||
<td class="fw-bold">Primary Surgeon:</td>
|
||||
<td>
|
||||
<a href="{% url 'users:user_detail' object.surgeon.pk %}" class="text-decoration-none">
|
||||
Dr. {{ object.surgeon.get_full_name }}
|
||||
<a href="{% url 'hr:employee_detail' object.primary_surgeon.pk %}" class="text-decoration-none">
|
||||
Dr. {{ object.primary_surgeon.get_full_name }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -148,8 +142,8 @@
|
||||
<h6 class="mb-3">Medical Team</h6>
|
||||
<div class="mb-3">
|
||||
<strong>Primary Surgeon:</strong><br>
|
||||
<a href="{% url 'users:user_detail' object.surgeon.pk %}" class="text-decoration-none">
|
||||
Dr. {{ object.surgeon.get_full_name }}
|
||||
<a href="{% url 'hr:employee_detail' object.primary_surgeon.pk %}" class="text-decoration-none">
|
||||
Dr. {{ object.primary_surgeon.get_full_name }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@ -157,7 +151,7 @@
|
||||
<div class="mb-3">
|
||||
<strong>Assistant Surgeons:</strong><br>
|
||||
{% for surgeon in object.assistant_surgeons.all %}
|
||||
<a href="{% url 'users:user_detail' surgeon.pk %}" class="text-decoration-none">
|
||||
<a href="{% url 'hr:employee_detail' surgeon.pk %}" class="text-decoration-none">
|
||||
Dr. {{ surgeon.get_full_name }}
|
||||
</a>{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
@ -167,7 +161,7 @@
|
||||
{% if object.anesthesiologist %}
|
||||
<div class="mb-3">
|
||||
<strong>Anesthesiologist:</strong><br>
|
||||
<a href="{% url 'users:user_detail' object.anesthesiologist.pk %}" class="text-decoration-none">
|
||||
<a href="{% url 'hr:employee_detail' object.anesthesiologist.pk %}" class="text-decoration-none">
|
||||
Dr. {{ object.anesthesiologist.get_full_name }}
|
||||
</a>
|
||||
</div>
|
||||
@ -179,7 +173,7 @@
|
||||
<div class="mb-3">
|
||||
<strong>Scrub Nurses:</strong><br>
|
||||
{% for nurse in object.scrub_nurses.all %}
|
||||
<a href="{% url 'users:user_detail' nurse.pk %}" class="text-decoration-none">
|
||||
<a href="{% url 'hr:employee_detail' nurse.pk %}" class="text-decoration-none">
|
||||
{{ nurse.get_full_name }}
|
||||
</a>{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
@ -190,7 +184,7 @@
|
||||
<div class="mb-3">
|
||||
<strong>Circulating Nurses:</strong><br>
|
||||
{% for nurse in object.circulating_nurses.all %}
|
||||
<a href="{% url 'users:user_detail' nurse.pk %}" class="text-decoration-none">
|
||||
<a href="{% url 'hr:employee_detail' nurse.pk %}" class="text-decoration-none">
|
||||
{{ nurse.get_full_name }}
|
||||
</a>{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
@ -275,18 +269,18 @@
|
||||
<i class="fa fa-edit me-2"></i>Edit Surgery
|
||||
</a>
|
||||
|
||||
{% if object.status == 'scheduled' %}
|
||||
<button class="btn btn-success" onclick="updateStatus('in_progress')">
|
||||
{% if object.status == 'SCHEDULED' %}
|
||||
<button class="btn btn-success" onclick="updateStatus('IN_PROGRESS')">
|
||||
<i class="fa fa-play me-2"></i>Start Surgery
|
||||
</button>
|
||||
{% elif object.status == 'in_progress' %}
|
||||
<button class="btn btn-warning" onclick="updateStatus('completed')">
|
||||
{% elif object.status == 'IN_PROGRESS' %}
|
||||
<button class="btn btn-warning" onclick="updateStatus('COMPLETED')">
|
||||
<i class="fa fa-check me-2"></i>Complete Surgery
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if object.status in 'scheduled,in_progress' %}
|
||||
<button class="btn btn-danger" onclick="updateStatus('cancelled')">
|
||||
{% if object.status in 'SCHEDULED,IN_PROGRESS' %}
|
||||
<button class="btn btn-danger" onclick="updateStatus('CANCELLED')">
|
||||
<i class="fa fa-times me-2"></i>Cancel Surgery
|
||||
</button>
|
||||
{% endif %}
|
||||
@ -373,6 +367,9 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Patient Information</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="{% url 'patients:patient_detail' object.patient.pk %}" class="btn btn-xs btn-outline-theme me-2">
|
||||
View Profile
|
||||
</a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
</div>
|
||||
@ -381,11 +378,9 @@
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="flex-fill">
|
||||
<div class="fw-bold">{{ object.patient.get_full_name }}</div>
|
||||
<div class="text-muted small">{{ object.patient.medical_record_number }}</div>
|
||||
<div class="text-muted small">{{ object.patient.mrn }}</div>
|
||||
</div>
|
||||
<a href="{% url 'patients:patient_detail' object.patient.pk %}" class="btn btn-sm btn-outline-primary">
|
||||
View Profile
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<table class="table table-sm table-borderless">
|
||||
@ -426,47 +421,47 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
<script>
|
||||
function updateStatus(newStatus) {
|
||||
if (confirm('Are you sure you want to update the surgery status?')) {
|
||||
$.ajax({
|
||||
url: '{% url "inpatients:surgery_update_status" object.pk %}',
|
||||
method: 'POST',
|
||||
data: {
|
||||
'status': newStatus,
|
||||
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
toastr.success('Surgery status updated successfully');
|
||||
location.reload();
|
||||
} else {
|
||||
toastr.error('Failed to update surgery status');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
toastr.error('An error occurred while updating the status');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
{#function updateStatus(newStatus) {#}
|
||||
{# if (confirm('Are you sure you want to update the surgery status?')) {#}
|
||||
{# $.ajax({#}
|
||||
{# url: '{% url "inpatients:surgery_update_status" object.pk %}',#}
|
||||
{# method: 'POST',#}
|
||||
{# data: {#}
|
||||
{# 'status': newStatus,#}
|
||||
{# 'csrfmiddlewaretoken': '{{ csrf_token }}'#}
|
||||
{# },#}
|
||||
{# success: function(response) {#}
|
||||
{# if (response.success) {#}
|
||||
{# toastr.success('Surgery status updated successfully');#}
|
||||
{# location.reload();#}
|
||||
{# } else {#}
|
||||
{# toastr.error('Failed to update surgery status');#}
|
||||
{# }#}
|
||||
{# },#}
|
||||
{# error: function() {#}
|
||||
{# toastr.error('An error occurred while updating the status');#}
|
||||
{# }#}
|
||||
{# });#}
|
||||
{# }#}
|
||||
{# }#}
|
||||
|
||||
function printSurgery() {
|
||||
window.print();
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Auto-refresh timeline every 30 seconds for active surgeries
|
||||
{% if object.status == 'in_progress' %}
|
||||
setInterval(function() {
|
||||
location.reload();
|
||||
}, 30000);
|
||||
{% endif %}
|
||||
});
|
||||
{#function printSurgery() {#}
|
||||
{# window.print();#}
|
||||
{# }#}
|
||||
{##}
|
||||
{#$(document).ready(function() {#}
|
||||
{# // Auto-refresh timeline every 30 seconds for active surgeries#}
|
||||
{# {% if object.status == 'in_progress' %}#}
|
||||
{# setInterval(function() {#}
|
||||
{# location.reload();#}
|
||||
{# }, 30000);#}
|
||||
{# {% endif %}#}
|
||||
{# });#}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -4,21 +4,13 @@
|
||||
{% block title %}{{ object|yesno:"Edit,Create" }} Surgery - Inpatients{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/bootstrap-timepicker/css/bootstrap-timepicker.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/summernote/dist/summernote-lite.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/bootstrap-timepicker/css/bootstrap-timepicker.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/summernote/dist/summernote-lite.css' %}" rel="stylesheet" />
|
||||
{% 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 'inpatients:dashboard' %}">Inpatients</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'inpatients:surgery_list' %}">Surgeries</a></li>
|
||||
<li class="breadcrumb-item active">{{ object|yesno:"Edit,Create" }} Surgery</li>
|
||||
</ol>
|
||||
<!-- END breadcrumb -->
|
||||
|
||||
<!-- BEGIN page-header -->
|
||||
<h1 class="page-header">{{ object|yesno:"Edit,Create" }} Surgery</h1>
|
||||
@ -48,10 +40,10 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.surgeon.id_for_label }}">Primary Surgeon <span class="text-danger">*</span></label>
|
||||
{{ form.surgeon }}
|
||||
{% if form.surgeon.errors %}
|
||||
<div class="invalid-feedback d-block">{{ form.surgeon.errors.0 }}</div>
|
||||
<label class="form-label" for="{{ form.primary_surgeon.id_for_label }}">Primary Surgeon <span class="text-danger">*</span></label>
|
||||
{{ form.primary_surgeon }}
|
||||
{% if form.primary_surgeon.errors %}
|
||||
<div class="invalid-feedback d-block">{{ form.primary_surgeon.errors.0 }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@ -218,9 +210,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="alert alert-info">
|
||||
<h6><i class="fa fa-info-circle me-2"></i>Scheduling Guidelines</h6>
|
||||
<ul class="mb-0">
|
||||
<div>
|
||||
<div class="note alert-info p-3 note-with-end-icon">
|
||||
<div class="note-icon"><i class="fa fa-info-circle"></i></div>
|
||||
<h6>Scheduling Guidelines</h6>
|
||||
<ul class="">
|
||||
<li>Schedule surgeries at least 24 hours in advance for elective procedures</li>
|
||||
<li>Emergency surgeries can be scheduled immediately</li>
|
||||
<li>Verify patient consent and pre-operative requirements</li>
|
||||
@ -228,18 +222,20 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<h6><i class="fa fa-exclamation-triangle me-2"></i>Urgency Levels</h6>
|
||||
<ul class="mb-0">
|
||||
<div class="note alert-warning p-3 note-with-end-icon">
|
||||
<div class="note-icon"><i class="fa fa-exclamation-triangle"></i></div>
|
||||
<h6>Urgency Levels</h6>
|
||||
<ul class="">
|
||||
<li><strong>Emergency:</strong> Life-threatening, immediate surgery required</li>
|
||||
<li><strong>Urgent:</strong> Surgery needed within 24 hours</li>
|
||||
<li><strong>Elective:</strong> Planned surgery, can be scheduled in advance</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success">
|
||||
<h6><i class="fa fa-check-circle me-2"></i>Pre-operative Checklist</h6>
|
||||
<ul class="mb-0">
|
||||
<div class="note alert-success p-3 note-with-end-icon">
|
||||
<div class="note-icon"><i class="fa fa-check-circle"></i></div>
|
||||
<h6>Pre-operative Checklist</h6>
|
||||
<ul class="">
|
||||
<li>Patient consent obtained and documented</li>
|
||||
<li>Pre-operative assessment completed</li>
|
||||
<li>Laboratory results reviewed</li>
|
||||
@ -248,19 +244,43 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
{% if object %}
|
||||
<div class="alert alert-secondary">
|
||||
<h6><i class="fa fa-clock me-2"></i>Surgery Timeline</h6>
|
||||
<ul class="mb-0">
|
||||
<div class="note alert-secondary p-3 note-with-end-icon">
|
||||
<div class="note-icon"><i class="fa fa-clock"></i></div>
|
||||
<h6>Surgery Timeline</h6>
|
||||
<ul class="">
|
||||
<li><strong>Created:</strong> {{ object.created_at|date:"M d, Y H:i" }}</li>
|
||||
{% if object.updated_at != object.created_at %}
|
||||
<li><strong>Last Updated:</strong> {{ object.updated_at|date:"M d, Y H:i" }}</li>
|
||||
{% endif %}
|
||||
<li><strong>Status:</strong> <span class="badge bg-{{ object.get_status_color }}">{{ object.get_status_display }}</span></li>
|
||||
<li>
|
||||
<strong>Status:</strong>
|
||||
{% if object.status == 'SCHEDULED' %}
|
||||
<span class="badge bg-warning">S
|
||||
{% elif object.status == 'CONFIRMED' %}
|
||||
<span class="badge bg-info">
|
||||
{% elif object.status == 'PREP' %}
|
||||
<span class="badge bg-primary">
|
||||
{% elif object.status == 'IN_PROGRESS' %}
|
||||
<span class="badge bg-success">
|
||||
{% elif object.status == 'COMPLETED' %}
|
||||
<span class="badge bg-success">
|
||||
{% elif object.status == 'CANCELLED' %}
|
||||
<span class="badge bg-danger">
|
||||
{% elif object.status == 'POSTPONED' %}
|
||||
<span class="badge bg-secondary">
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">
|
||||
{% endif %}
|
||||
{{ object.get_status_display }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END panel -->
|
||||
</div>
|
||||
@ -268,10 +288,10 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/bootstrap-timepicker/js/bootstrap-timepicker.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/summernote/dist/summernote-lite.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/bootstrap-timepicker/js/bootstrap-timepicker.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/summernote/dist/summernote-lite.min.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize Select2
|
||||
@ -281,71 +301,71 @@ $(document).ready(function() {
|
||||
});
|
||||
|
||||
// Initialize date picker
|
||||
$('input[type="date"]').datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true,
|
||||
startDate: new Date()
|
||||
});
|
||||
{#$('input[type="date"]').datepicker({#}
|
||||
{# format: 'yyyy-mm-dd',#}
|
||||
{# autoclose: true,#}
|
||||
{# todayHighlight: true,#}
|
||||
{# startDate: new Date()#}
|
||||
{# });#}
|
||||
|
||||
// Initialize time picker
|
||||
$('input[type="time"]').timepicker({
|
||||
showMeridian: false,
|
||||
defaultTime: false
|
||||
});
|
||||
{#$('input[type="time"]').timepicker({#}
|
||||
{# showMeridian: false,#}
|
||||
{# defaultTime: false#}
|
||||
{# });#}
|
||||
|
||||
// Initialize Summernote
|
||||
$('.summernote').summernote({
|
||||
height: 150,
|
||||
toolbar: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'italic', 'underline', 'clear']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['insert', ['link']],
|
||||
['view', ['fullscreen', 'codeview']]
|
||||
]
|
||||
});
|
||||
{#$('.summernote').summernote({#}
|
||||
{# height: 150,#}
|
||||
{# toolbar: [#}
|
||||
{# ['style', ['style']],#}
|
||||
{# ['font', ['bold', 'italic', 'underline', 'clear']],#}
|
||||
{# ['para', ['ul', 'ol', 'paragraph']],#}
|
||||
{# ['insert', ['link']],#}
|
||||
{# ['view', ['fullscreen', 'codeview']]#}
|
||||
{# ]#}
|
||||
{# });#}
|
||||
|
||||
// Form validation
|
||||
$('#surgery-form').on('submit', function(e) {
|
||||
var isValid = true;
|
||||
var requiredFields = ['patient', 'surgeon', 'procedure_name', 'scheduled_date', 'scheduled_start_time'];
|
||||
|
||||
requiredFields.forEach(function(field) {
|
||||
var input = $('[name="' + field + '"]');
|
||||
if (!input.val()) {
|
||||
input.addClass('is-invalid');
|
||||
isValid = false;
|
||||
} else {
|
||||
input.removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
if (!isValid) {
|
||||
e.preventDefault();
|
||||
toastr.error('Please fill in all required fields.');
|
||||
}
|
||||
});
|
||||
{#$('#surgery-form').on('submit', function(e) {#}
|
||||
{# var isValid = true;#}
|
||||
{# var requiredFields = ['patient', 'surgeon', 'procedure_name', 'scheduled_date', 'scheduled_start_time'];#}
|
||||
{# #}
|
||||
{# requiredFields.forEach(function(field) {#}
|
||||
{# var input = $('[name="' + field + '"]');#}
|
||||
{# if (!input.val()) {#}
|
||||
{# input.addClass('is-invalid');#}
|
||||
{# isValid = false;#}
|
||||
{# } else {#}
|
||||
{# input.removeClass('is-invalid');#}
|
||||
{# }#}
|
||||
{# });#}
|
||||
{##}
|
||||
{# if (!isValid) {#}
|
||||
{# e.preventDefault();#}
|
||||
{# toastr.error('Please fill in all required fields.');#}
|
||||
{# }#}
|
||||
{# });#}
|
||||
|
||||
// Real-time validation
|
||||
$('input, select, textarea').on('change blur', function() {
|
||||
if ($(this).val()) {
|
||||
$(this).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
{#$('input, select, textarea').on('change blur', function() {#}
|
||||
{# if ($(this).val()) {#}
|
||||
{# $(this).removeClass('is-invalid');#}
|
||||
{# }#}
|
||||
{# });#}
|
||||
|
||||
// Check for scheduling conflicts
|
||||
$('#id_scheduled_date, #id_scheduled_start_time, #id_operating_room').on('change', function() {
|
||||
var date = $('#id_scheduled_date').val();
|
||||
var time = $('#id_scheduled_start_time').val();
|
||||
var room = $('#id_operating_room').val();
|
||||
|
||||
if (date && time && room) {
|
||||
// Check for conflicts (this would be an AJAX call in a real implementation)
|
||||
// For now, just show a placeholder message
|
||||
console.log('Checking for scheduling conflicts...');
|
||||
}
|
||||
});
|
||||
{#$('#id_scheduled_date, #id_scheduled_start_time, #id_operating_room').on('change', function() {#}
|
||||
{# var date = $('#id_scheduled_date').val();#}
|
||||
{# var time = $('#id_scheduled_start_time').val();#}
|
||||
{# var room = $('#id_operating_room').val();#}
|
||||
{# #}
|
||||
{# if (date && time && room) {#}
|
||||
{# // Check for conflicts (this would be an AJAX call in a real implementation)#}
|
||||
{# // For now, just show a placeholder message#}
|
||||
{# console.log('Checking for scheduling conflicts...');#}
|
||||
{# }#}
|
||||
{# });#}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@ -120,7 +120,8 @@
|
||||
title="Confirm Surgery"
|
||||
hx-post="{% url 'inpatients:confirm_surgery' surgery.id %}"
|
||||
hx-confirm="Confirm this surgery?"
|
||||
hx-swap="none">
|
||||
hx-swap="none"
|
||||
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'>
|
||||
<i class="fas fa-check"></i>
|
||||
</button>
|
||||
{% elif surgery.status == 'CONFIRMED' %}
|
||||
@ -128,7 +129,8 @@
|
||||
title="Start Prep"
|
||||
hx-post="{% url 'inpatients:start_surgery_prep' surgery.id %}"
|
||||
hx-confirm="Start surgery prep?"
|
||||
hx-swap="none">
|
||||
hx-swap="none"
|
||||
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'>
|
||||
<i class="fas fa-play"></i>
|
||||
</button>
|
||||
{% elif surgery.status == 'PREP' %}
|
||||
@ -136,7 +138,8 @@
|
||||
title="Start Surgery"
|
||||
hx-post="{% url 'inpatients:start_surgery' surgery.id %}"
|
||||
hx-confirm="Start surgery?"
|
||||
hx-swap="none">
|
||||
hx-swap="none"
|
||||
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'>
|
||||
<i class="fas fa-procedures"></i>
|
||||
</button>
|
||||
{% elif surgery.status == 'IN_PROGRESS' %}
|
||||
@ -144,7 +147,8 @@
|
||||
title="Complete Surgery"
|
||||
hx-post="{% url 'inpatients:complete_surgery' surgery.id %}"
|
||||
hx-confirm="Complete surgery?"
|
||||
hx-swap="none">
|
||||
hx-swap="none"
|
||||
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'>
|
||||
<i class="fas fa-check-circle"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
@ -154,18 +158,19 @@
|
||||
</button>
|
||||
|
||||
{% if surgery.status not in 'COMPLETED,CANCELLED' %}
|
||||
<button class="btn btn-outline-warning"
|
||||
title="Postpone"
|
||||
hx-post="{% url 'inpatients:postpone_surgery' surgery.id %}"
|
||||
hx-confirm="Postpone this surgery?"
|
||||
hx-swap="none">
|
||||
<i class="fas fa-clock"></i>
|
||||
</button>
|
||||
{# <button class="btn btn-outline-warning" #}
|
||||
{# title="Postpone"#}
|
||||
{# hx-post="{% url 'inpatients:s' surgery.id %}"#}
|
||||
{# hx-confirm="Postpone this surgery?"#}
|
||||
{# hx-swap="none">#}
|
||||
{# <i class="fas fa-clock"></i>#}
|
||||
{# </button>#}
|
||||
<button class="btn btn-outline-danger"
|
||||
title="Cancel"
|
||||
hx-post="{% url 'inpatients:cancel_surgery' surgery.id %}"
|
||||
hx-confirm="Cancel this surgery?"
|
||||
hx-swap="none">
|
||||
hx-swap="none"
|
||||
hx-headers='{"X-CSRFToken":"{{ csrf_token }}"}'>
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@ -8,19 +8,31 @@ from . import views
|
||||
app_name = 'inpatients'
|
||||
|
||||
urlpatterns = [
|
||||
# Main views
|
||||
# Main views
|
||||
path('', views.InpatientDashboardView.as_view(), name='dashboard'),
|
||||
# wards
|
||||
path('wards/', views.WardListView.as_view(), name='ward_list'),
|
||||
path('wards/<int:pk>/', views.WardDetailView.as_view(), name='ward_detail'),
|
||||
path('beds/', views.BedManagementView.as_view(), name='bed_management'),
|
||||
path('wards/stats/', views.ward_stats, name='ward_stats'),
|
||||
|
||||
# Admissions
|
||||
path('admissions/', views.AdmissionListView.as_view(), name='admission_list'),
|
||||
path('admissions/<int:pk>/', views.AdmissionDetailView.as_view(), name='admission_detail'),
|
||||
path('admissions/create/', views.AdmissionCreateView.as_view(), name='admission_create'),
|
||||
path('admissions/<int:pk>/edit/', views.AdmissionUpdateView.as_view(), name='admission_update'),
|
||||
path('admission/search/', views.admission_search, name='admission_search'),
|
||||
|
||||
path('discharge/<int:admission_id>/', views.discharge_patient, name='discharge_patient'),
|
||||
|
||||
|
||||
path('transfers/', views.TransferManagementView.as_view(), name='transfer_management'),
|
||||
path('surgery/', views.SurgeryScheduleView.as_view(), name='surgery_schedule'),
|
||||
path('transfer/<int:admission_id>/', views.transfer_patient, name='transfer_patient'),
|
||||
path('transfers/<int:transfer_id>/approve/', views.approve_transfer, name='approve_transfer'),
|
||||
path('transfers/<int:transfer_id>/complete/', views.complete_transfer, name='complete_transfer'),
|
||||
|
||||
|
||||
# Beds
|
||||
path('beds/', views.BedManagementView.as_view(), name='bed_management'),
|
||||
path('beds/', views.BedListView.as_view(), name='bed_list'),
|
||||
path('beds/create/', views.BedCreateView.as_view(), name='bed_create'),
|
||||
path('beds/<int:pk>/', views.BedDetailView.as_view(), name='bed_detail'),
|
||||
@ -30,19 +42,24 @@ urlpatterns = [
|
||||
path('beds/<int:pk>/block/', views.block_bed, name='block_bed'),
|
||||
path('beds/<int:pk>/unblock/', views.unblock_bed, name='unblock_bed'),
|
||||
path('beds/<int:pk>/maintenance/', views.maintenance_bed, name='maintenance_bed'),
|
||||
path('beds/grid/', views.bed_grid, name='bed_grid'),
|
||||
path('beds/<int:bed_id>/status/', views.update_bed_status, name='update_bed_status'),
|
||||
|
||||
# HTMX endpoints
|
||||
path('stats/', views.ward_stats, name='ward_stats'),
|
||||
path('bed-grid/', views.bed_grid, name='bed_grid'),
|
||||
path('admission-search/', views.admission_search, name='admission_search'),
|
||||
path('surgery-calendar/', views.surgery_calendar, name='surgery_calendar'),
|
||||
|
||||
|
||||
path('surgery/', views.SurgeryScheduleView.as_view(), name='surgery_schedule'),
|
||||
path('surgery/list/', views.SurgeryScheduleListView.as_view(), name='surgery_list'),
|
||||
path('surgery/<int:pk>/', views.SurgeryScheduleDetailView.as_view(), name='surgery_detail'),
|
||||
path('surgery/<int:pk>/edit/', views.SurgeryScheduleUpdateView.as_view(), name='surgery_update'),
|
||||
path('surgery/create/', views.SurgeryScheduleCreateView.as_view(), name='surgery_create'),
|
||||
path('surgery/calendar/', views.surgery_calendar, name='surgery_calendar'),
|
||||
path('surgery/<int:pk>/cancel/', views.cancel_surgery, name='cancel_surgery'),
|
||||
|
||||
# Actions
|
||||
path('transfer/<int:admission_id>/', views.transfer_patient, name='transfer_patient'),
|
||||
path('discharge/<int:pk>/', views.discharge_patient, name='discharge_patient'),
|
||||
path('transfer/<int:transfer_id>/approve/', views.approve_transfer, name='approve_transfer'),
|
||||
path('transfer/<int:transfer_id>/complete/', views.complete_transfer, name='complete_transfer'),
|
||||
path('bed/<int:bed_id>/status/', views.update_bed_status, name='update_bed_status'),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# API endpoints
|
||||
# path('api/', include('inpatients.api.urls')),
|
||||
|
||||
1562
inpatients/views.py
1562
inpatients/views.py
File diff suppressed because it is too large
Load Diff
@ -252,7 +252,7 @@ def create_saudi_admissions(tenants, beds, admissions_per_tenant=100):
|
||||
for tenant in tenants:
|
||||
# Get patients and staff for this tenant
|
||||
patients = list(PatientProfile.objects.filter(tenant=tenant))
|
||||
physicians = list(User.objects.filter(tenant=tenant, employee_profile__role='PHYSICIAN'))
|
||||
physicians = list(User.objects.filter(tenant=tenant, employee_profile__role__in=['PHYSICIAN', 'PHYSICIAN_ASSISTANT']))
|
||||
nurses = list(User.objects.filter(tenant=tenant, employee_profile__role__in=['NURSE', 'NURSE_PRACTITIONER']))
|
||||
tenant_beds = [bed for bed in beds if bed.ward.tenant == tenant]
|
||||
|
||||
@ -587,7 +587,7 @@ def create_saudi_surgery_schedules(tenants, surgeries_per_tenant=30):
|
||||
surgeons = list(User.objects.filter(tenant=tenant, employee_profile__role='PHYSICIAN'))
|
||||
anesthesiologists = list(User.objects.filter(tenant=tenant, employee_profile__role='PHYSICIAN'))
|
||||
nurses = list(User.objects.filter(tenant=tenant, employee_profile__role__in=['NURSE', 'NURSE_PRACTITIONER']))
|
||||
admissions = list(Admission.objects.filter(tenant=tenant, status='active'))
|
||||
admissions = list(Admission.objects.filter(tenant=tenant, status='ADMITTED'))
|
||||
|
||||
if not patients or not surgeons or not nurses or not admissions:
|
||||
print(f"Insufficient data for tenant {tenant.name}: patients={len(patients)}, surgeons={len(surgeons)}, nurses={len(nurses)}, admissions={len(admissions)}")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user