663 lines
28 KiB
HTML
663 lines
28 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}{% if object %}Edit{% else %}Add{% endif %} Patient Note - Patients{% endblock %}
|
|
|
|
{% block css %}
|
|
<link href="{% static 'assets/plugins/summernote/dist/summernote-lite.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 'patients:patient_list' %}">Patients</a></li>
|
|
{% if object %}
|
|
<li class="breadcrumb-item"><a href="{% url 'patients:patient_detail' object.patient.pk %}">{{ object.patient.get_full_name }}</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'patients:patient_note_detail' object.pk %}">{{ object.title|truncatechars:20 }}</a></li>
|
|
<li class="breadcrumb-item active">Edit</li>
|
|
{% else %}
|
|
<li class="breadcrumb-item"><a href="{% url 'patients:patient_note_list' %}">Notes</a></li>
|
|
<li class="breadcrumb-item active">Add Note</li>
|
|
{% endif %}
|
|
</ol>
|
|
<!-- END breadcrumb -->
|
|
|
|
<!-- BEGIN page-header -->
|
|
<h1 class="page-header">
|
|
{% if object %}Edit Patient Note{% else %}Add Patient Note{% endif %}
|
|
<small>{% if object %}{{ object.title }}{% else %}New Clinical Note{% endif %}</small>
|
|
</h1>
|
|
<!-- END page-header -->
|
|
|
|
<div class="row">
|
|
<div class="col-xl-8">
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Note Information</h4>
|
|
<div class="panel-heading-btn">
|
|
<button type="button" class="btn btn-xs btn-info me-2" onclick="saveDraft()">
|
|
<i class="fa fa-save"></i> Save Draft
|
|
</button>
|
|
<button type="button" class="btn btn-xs btn-secondary me-2" onclick="useTemplate()">
|
|
<i class="fa fa-file-text"></i> Use Template
|
|
</button>
|
|
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
|
</div>
|
|
</div>
|
|
<div class="panel-body">
|
|
<form method="post" id="note-form" enctype="multipart/form-data" novalidate>
|
|
{% csrf_token %}
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
{{ form.patient }}
|
|
<label for="{{ form.patient.id_for_label }}">Patient <span class="text-danger">*</span></label>
|
|
{% if form.patient.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.patient.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
{{ form.category }}
|
|
<label for="{{ form.category.id_for_label }}">Category <span class="text-danger">*</span></label>
|
|
{% if form.category.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.category.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-md-8">
|
|
<div class="form-floating">
|
|
{{ form.title }}
|
|
<label for="{{ form.title.id_for_label }}">Note Title <span class="text-danger">*</span></label>
|
|
{% if form.title.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.title.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-floating">
|
|
{{ form.priority }}
|
|
<label for="{{ form.priority.id_for_label }}">Priority <span class="text-danger">*</span></label>
|
|
{% if form.priority.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.priority.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.content.id_for_label }}" class="form-label">Note Content <span class="text-danger">*</span></label>
|
|
{{ form.content }}
|
|
{% if form.content.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.content.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Use the rich text editor to format your note. You can add lists, links, and formatting.</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-floating">
|
|
{{ form.follow_up_date }}
|
|
<label for="{{ form.follow_up_date.id_for_label }}">Follow-up Date</label>
|
|
{% if form.follow_up_date.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.follow_up_date.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-check mt-3">
|
|
{{ form.is_confidential }}
|
|
<label class="form-check-label" for="{{ form.is_confidential.id_for_label }}">
|
|
<i class="fa fa-lock me-1"></i>Confidential Note
|
|
</label>
|
|
{% if form.is_confidential.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_confidential.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Confidential notes have restricted access</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.follow_up_notes.id_for_label }}" class="form-label">Follow-up Instructions</label>
|
|
{{ form.follow_up_notes }}
|
|
{% if form.follow_up_notes.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.follow_up_notes.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Specific instructions for follow-up actions or appointments.</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="{{ form.tags.id_for_label }}" class="form-label">Tags</label>
|
|
{{ form.tags }}
|
|
{% if form.tags.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.tags.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Add tags to help categorize and search for this note (comma-separated).</div>
|
|
</div>
|
|
|
|
<!-- Attachments -->
|
|
<div class="mb-3">
|
|
<label class="form-label">Attachments</label>
|
|
<div class="border rounded p-3">
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<input type="file" class="form-control" id="attachment-input" multiple accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.txt">
|
|
</div>
|
|
<div class="col-md-4">
|
|
<button type="button" class="btn btn-outline-primary w-100" onclick="addAttachment()">
|
|
<i class="fa fa-plus me-2"></i>Add File
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="attachment-list" class="mt-3">
|
|
{% if object.attachments.exists %}
|
|
{% for attachment in object.attachments.all %}
|
|
<div class="d-flex align-items-center justify-content-between p-2 border rounded mb-2">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fa fa-file me-2"></i>
|
|
<span>{{ attachment.name }}</span>
|
|
<small class="text-muted ms-2">({{ attachment.file_size|filesizeformat }})</small>
|
|
</div>
|
|
<button type="button" class="btn btn-sm btn-outline-danger" onclick="removeAttachment('{{ attachment.pk }}')">
|
|
<i class="fa fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="form-text">Supported formats: PDF, DOC, DOCX, JPG, JPEG, PNG, TXT. Max size: 10MB per file.</div>
|
|
</div>
|
|
|
|
<!-- Form Actions -->
|
|
<div class="d-flex justify-content-between">
|
|
<div>
|
|
<a href="{% if object %}{% url 'patients:patient_note_detail' object.pk %}{% else %}{% url 'patients:patient_note_list' %}{% endif %}" class="btn btn-secondary">
|
|
<i class="fa fa-arrow-left me-2"></i>Cancel
|
|
</a>
|
|
</div>
|
|
<div>
|
|
<button type="button" class="btn btn-info me-2" onclick="saveDraft()">
|
|
<i class="fa fa-save me-2"></i>Save Draft
|
|
</button>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fa fa-check me-2"></i>{% if object %}Update{% else %}Create{% endif %} Note
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
</div>
|
|
|
|
<div class="col-xl-4">
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Help & Guidelines</h4>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div class="alert alert-info">
|
|
<h6 class="alert-heading">Note Writing Tips</h6>
|
|
<ul class="mb-0 small">
|
|
<li>Be clear and concise in your documentation</li>
|
|
<li>Use appropriate medical terminology</li>
|
|
<li>Include relevant dates and times</li>
|
|
<li>Mark urgent items with high priority</li>
|
|
<li>Add follow-up dates for actionable items</li>
|
|
<li>Use confidential flag for sensitive information</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="card border-primary mb-3">
|
|
<div class="card-header bg-primary text-white">
|
|
<h6 class="card-title mb-0">Required Fields</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<ul class="list-unstyled mb-0 small">
|
|
<li><i class="fa fa-check text-success me-2"></i>Patient</li>
|
|
<li><i class="fa fa-check text-success me-2"></i>Note Title</li>
|
|
<li><i class="fa fa-check text-success me-2"></i>Category</li>
|
|
<li><i class="fa fa-check text-success me-2"></i>Priority</li>
|
|
<li><i class="fa fa-check text-success me-2"></i>Note Content</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-warning mb-3">
|
|
<div class="card-header bg-warning text-dark">
|
|
<h6 class="card-title mb-0">Priority Guidelines</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<ul class="list-unstyled mb-0 small">
|
|
<li><span class="badge bg-danger me-2">URGENT</span>Immediate attention required</li>
|
|
<li><span class="badge bg-warning me-2">HIGH</span>Important, address soon</li>
|
|
<li><span class="badge bg-success me-2">NORMAL</span>Standard priority</li>
|
|
<li><span class="badge bg-secondary me-2">LOW</span>For reference only</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-success">
|
|
<div class="card-header bg-success text-white">
|
|
<h6 class="card-title mb-0">Quick Actions</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<button type="button" class="btn btn-outline-primary btn-sm" onclick="useTemplate()">
|
|
<i class="fa fa-file-text me-2"></i>Use Template
|
|
</button>
|
|
<button type="button" class="btn btn-outline-info btn-sm" onclick="insertDateTime()">
|
|
<i class="fa fa-clock me-2"></i>Insert Date/Time
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="insertSignature()">
|
|
<i class="fa fa-signature me-2"></i>Insert Signature
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
|
|
{% if object %}
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Current Patient</h4>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div class="text-center mb-3">
|
|
<div class="w-60px h-60px bg-primary rounded-circle d-flex align-items-center justify-content-center mx-auto mb-2">
|
|
<i class="fa fa-user text-white"></i>
|
|
</div>
|
|
<h6 class="mb-1">{{ object.patient.get_full_name }}</h6>
|
|
<small class="text-muted">{{ object.patient.patient_id }}</small>
|
|
</div>
|
|
|
|
<table class="table table-borderless table-sm">
|
|
<tr>
|
|
<td class="fw-bold" width="60">DOB:</td>
|
|
<td>{{ object.patient.date_of_birth|date:"M d, Y" }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Age:</td>
|
|
<td>{{ object.patient.age }} years</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Gender:</td>
|
|
<td>{{ object.patient.get_gender_display }}</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<div class="d-grid">
|
|
<a href="{% url 'patients:patient_detail' object.patient.pk %}" class="btn btn-outline-primary btn-sm">
|
|
<i class="fa fa-user me-2"></i>View Patient
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
{% endif %}
|
|
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Form Status</h4>
|
|
</div>
|
|
<div class="panel-body">
|
|
<div id="form-status">
|
|
<div class="alert alert-secondary">
|
|
<i class="fa fa-info-circle me-2"></i>
|
|
<span id="status-text">Form not saved</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="small text-muted">
|
|
<div>Last saved: <span id="last-saved">Never</span></div>
|
|
<div>Auto-save: <span class="text-success">Enabled</span></div>
|
|
<div>Word count: <span id="word-count">0</span></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Recent Notes</h4>
|
|
</div>
|
|
<div class="panel-body">
|
|
{% for note in recent_notes %}
|
|
<div class="d-flex align-items-center mb-2 p-2 border rounded">
|
|
<div class="me-2">
|
|
<span class="badge bg-{% if note.priority == 'URGENT' %}danger{% elif note.priority == 'HIGH' %}warning{% else %}secondary{% endif %}">
|
|
{{ note.get_priority_display|slice:":1" }}
|
|
</span>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<div class="fw-bold small">{{ note.title|truncatechars:25 }}</div>
|
|
<small class="text-muted">{{ note.created_at|date:"M d" }}</small>
|
|
</div>
|
|
</div>
|
|
{% empty %}
|
|
<div class="text-center text-muted">
|
|
<i class="fa fa-sticky-note fa-2x mb-2"></i>
|
|
<div>No recent notes</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Template Modal -->
|
|
<div class="modal fade" id="templateModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Select Note Template</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="list-group" id="template-categories">
|
|
<button type="button" class="list-group-item list-group-item-action active" data-category="clinical">
|
|
Clinical Notes
|
|
</button>
|
|
<button type="button" class="list-group-item list-group-item-action" data-category="administrative">
|
|
Administrative
|
|
</button>
|
|
<button type="button" class="list-group-item list-group-item-action" data-category="follow-up">
|
|
Follow-up
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<div id="template-list">
|
|
<!-- Templates will be loaded here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-primary" onclick="applyTemplate()" disabled id="apply-template-btn">
|
|
<i class="fa fa-check me-2"></i>Apply Template
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script src="{% static 'assets/plugins/summernote/dist/summernote-lite.min.js' %}"></script>
|
|
|
|
<script>
|
|
var selectedTemplate = null;
|
|
var autoSaveTimer;
|
|
|
|
$(document).ready(function() {
|
|
// Initialize Summernote
|
|
$('#{{ form.content.id_for_label }}').summernote({
|
|
height: 300,
|
|
toolbar: [
|
|
['style', ['style']],
|
|
['font', ['bold', 'underline', 'clear']],
|
|
['color', ['color']],
|
|
['para', ['ul', 'ol', 'paragraph']],
|
|
['table', ['table']],
|
|
['insert', ['link']],
|
|
['view', ['fullscreen', 'codeview', 'help']]
|
|
],
|
|
callbacks: {
|
|
onChange: function(contents, $editable) {
|
|
updateWordCount(contents);
|
|
clearTimeout(autoSaveTimer);
|
|
autoSaveTimer = setTimeout(function() {
|
|
saveDraft();
|
|
}, 5000);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Form validation
|
|
$('#note-form').on('submit', function(e) {
|
|
if (!validateForm()) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
// Auto-save functionality
|
|
$('#note-form input, #note-form select, #note-form textarea').on('change input', function() {
|
|
clearTimeout(autoSaveTimer);
|
|
autoSaveTimer = setTimeout(function() {
|
|
saveDraft();
|
|
}, 5000);
|
|
});
|
|
|
|
// Priority change handler
|
|
$('#{{ form.priority.id_for_label }}').on('change', function() {
|
|
var priority = $(this).val();
|
|
if (priority === 'URGENT') {
|
|
toastr.warning('Urgent priority selected. This note will require immediate attention.');
|
|
}
|
|
});
|
|
|
|
// Category change handler
|
|
$('#{{ form.category.id_for_label }}').on('change', function() {
|
|
var category = $(this).val();
|
|
if (category === 'CLINICAL') {
|
|
$('#{{ form.is_confidential.id_for_label }}').prop('checked', true);
|
|
}
|
|
});
|
|
|
|
// Initial word count
|
|
updateWordCount($('#{{ form.content.id_for_label }}').summernote('code'));
|
|
});
|
|
|
|
function validateForm() {
|
|
var isValid = true;
|
|
var errors = [];
|
|
|
|
// Required field validation
|
|
var requiredFields = ['{{ form.patient.id_for_label }}', '{{ form.title.id_for_label }}', '{{ form.category.id_for_label }}', '{{ form.priority.id_for_label }}'];
|
|
|
|
requiredFields.forEach(function(fieldId) {
|
|
var field = $('#' + fieldId);
|
|
if (!field.val()) {
|
|
field.addClass('is-invalid');
|
|
errors.push(field.closest('.form-floating').find('label').text().replace(' *', '') + ' is required');
|
|
isValid = false;
|
|
} else {
|
|
field.removeClass('is-invalid');
|
|
}
|
|
});
|
|
|
|
// Content validation
|
|
var content = $('#{{ form.content.id_for_label }}').summernote('code');
|
|
if (!content || content.trim() === '' || content === '<p><br></p>') {
|
|
$('#{{ form.content.id_for_label }}').addClass('is-invalid');
|
|
errors.push('Note content is required');
|
|
isValid = false;
|
|
} else {
|
|
$('#{{ form.content.id_for_label }}').removeClass('is-invalid');
|
|
}
|
|
|
|
if (!isValid) {
|
|
toastr.error('Please fix the following errors:\n' + errors.join('\n'));
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
|
|
function updateWordCount(content) {
|
|
var text = $(content).text();
|
|
var wordCount = text.trim() === '' ? 0 : text.trim().split(/\s+/).length;
|
|
$('#word-count').text(wordCount);
|
|
}
|
|
|
|
function saveDraft() {
|
|
var formData = $('#note-form').serialize();
|
|
var content = $('#{{ form.content.id_for_label }}').summernote('code');
|
|
formData += '&content=' + encodeURIComponent(content);
|
|
|
|
$.ajax({
|
|
url: '{% url "patients:save_note_draft" %}',
|
|
method: 'POST',
|
|
data: formData,
|
|
success: function(response) {
|
|
updateFormStatus('Draft saved', 'success');
|
|
$('#last-saved').text(new Date().toLocaleTimeString());
|
|
},
|
|
error: function() {
|
|
updateFormStatus('Failed to save draft', 'danger');
|
|
}
|
|
});
|
|
}
|
|
|
|
function updateFormStatus(message, type) {
|
|
var alertClass = 'alert-' + type;
|
|
$('#form-status').html('<div class="alert ' + alertClass + '"><i class="fa fa-info-circle me-2"></i>' + message + '</div>');
|
|
}
|
|
|
|
function useTemplate() {
|
|
$('#templateModal').modal('show');
|
|
loadTemplates('clinical');
|
|
}
|
|
|
|
function loadTemplates(category) {
|
|
$.ajax({
|
|
url: '{% url "patients:get_note_templates" %}',
|
|
method: 'GET',
|
|
data: { category: category },
|
|
success: function(response) {
|
|
$('#template-list').html(response.html);
|
|
}
|
|
});
|
|
}
|
|
|
|
function selectTemplate(templateId) {
|
|
selectedTemplate = templateId;
|
|
$('.template-item').removeClass('selected');
|
|
$('[data-template="' + templateId + '"]').addClass('selected');
|
|
$('#apply-template-btn').prop('disabled', false);
|
|
}
|
|
|
|
function applyTemplate() {
|
|
if (!selectedTemplate) return;
|
|
|
|
$.ajax({
|
|
url: '{% url "patients:get_note_template" %}',
|
|
method: 'GET',
|
|
data: { template_id: selectedTemplate },
|
|
success: function(response) {
|
|
$('#{{ form.title.id_for_label }}').val(response.title);
|
|
$('#{{ form.category.id_for_label }}').val(response.category);
|
|
$('#{{ form.priority.id_for_label }}').val(response.priority);
|
|
$('#{{ form.content.id_for_label }}').summernote('code', response.content);
|
|
$('#templateModal').modal('hide');
|
|
toastr.success('Template applied successfully');
|
|
}
|
|
});
|
|
}
|
|
|
|
function insertDateTime() {
|
|
var now = new Date();
|
|
var dateTime = now.toLocaleString();
|
|
var currentContent = $('#{{ form.content.id_for_label }}').summernote('code');
|
|
$('#{{ form.content.id_for_label }}').summernote('code', currentContent + '<p><strong>Date/Time:</strong> ' + dateTime + '</p>');
|
|
}
|
|
|
|
function insertSignature() {
|
|
var signature = '<p><strong>{{ user.get_full_name }}</strong><br>{{ user.profile.title|default:"Healthcare Provider" }}</p>';
|
|
var currentContent = $('#{{ form.content.id_for_label }}').summernote('code');
|
|
$('#{{ form.content.id_for_label }}').summernote('code', currentContent + signature);
|
|
}
|
|
|
|
function addAttachment() {
|
|
var input = $('#attachment-input')[0];
|
|
if (input.files.length === 0) {
|
|
toastr.warning('Please select files to attach');
|
|
return;
|
|
}
|
|
|
|
// Add files to attachment list (this would normally upload via AJAX)
|
|
for (var i = 0; i < input.files.length; i++) {
|
|
var file = input.files[i];
|
|
var attachmentHtml = '<div class="d-flex align-items-center justify-content-between p-2 border rounded mb-2">' +
|
|
'<div class="d-flex align-items-center">' +
|
|
'<i class="fa fa-file me-2"></i>' +
|
|
'<span>' + file.name + '</span>' +
|
|
'<small class="text-muted ms-2">(' + formatFileSize(file.size) + ')</small>' +
|
|
'</div>' +
|
|
'<button type="button" class="btn btn-sm btn-outline-danger" onclick="$(this).closest(\'.d-flex\').remove()">' +
|
|
'<i class="fa fa-trash"></i>' +
|
|
'</button>' +
|
|
'</div>';
|
|
$('#attachment-list').append(attachmentHtml);
|
|
}
|
|
|
|
input.value = '';
|
|
toastr.success('Files added to attachment list');
|
|
}
|
|
|
|
function removeAttachment(attachmentId) {
|
|
if (confirm('Remove this attachment?')) {
|
|
// This would normally make an AJAX call to remove the attachment
|
|
$('[onclick*="' + attachmentId + '"]').closest('.d-flex').remove();
|
|
toastr.success('Attachment removed');
|
|
}
|
|
}
|
|
|
|
function formatFileSize(bytes) {
|
|
if (bytes === 0) return '0 Bytes';
|
|
var k = 1024;
|
|
var sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
}
|
|
|
|
// Template category selection
|
|
$(document).on('click', '[data-category]', function() {
|
|
var category = $(this).data('category');
|
|
$('.list-group-item').removeClass('active');
|
|
$(this).addClass('active');
|
|
loadTemplates(category);
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
.template-item {
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.template-item:hover {
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.template-item.selected {
|
|
background-color: #e3f2fd;
|
|
border-color: #2196f3;
|
|
}
|
|
|
|
.note-content {
|
|
min-height: 200px;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|