2025-08-12 13:33:25 +03:00

499 lines
24 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}{% if object %}Edit Message{% else %}Compose Message{% endif %} - Communications{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Breadcrumb -->
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0">{% if object %}Edit Message{% else %}Compose Message{% endif %}</h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'communications:dashboard' %}">Communications</a></li>
<li class="breadcrumb-item"><a href="{% url 'communications:message_list' %}">Messages</a></li>
<li class="breadcrumb-item active">{% if object %}Edit{% else %}Compose{% endif %}</li>
</ol>
</div>
</div>
</div>
</div>
<form method="post" id="messageForm">
{% csrf_token %}
<div class="row">
<!-- Main Form -->
<div class="col-lg-8">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-envelope me-2"></i>
Message Details
</h5>
</div>
<div class="card-body">
<!-- Subject -->
<div class="mb-3">
<label for="{{ form.subject.id_for_label }}" class="form-label">Subject *</label>
{{ form.subject }}
{% if form.subject.errors %}
<div class="invalid-feedback d-block">
{{ form.subject.errors.0 }}
</div>
{% endif %}
<div class="form-text">Enter a clear, descriptive subject line</div>
</div>
<!-- Message Type and Priority -->
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.message_type.id_for_label }}" class="form-label">Message Type *</label>
{{ form.message_type }}
{% if form.message_type.errors %}
<div class="invalid-feedback d-block">
{{ form.message_type.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.priority.id_for_label }}" class="form-label">Priority *</label>
{{ form.priority }}
{% if form.priority.errors %}
<div class="invalid-feedback d-block">
{{ form.priority.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
<!-- Template Selection -->
<div class="mb-3">
<label for="{{ form.template.id_for_label }}" class="form-label">Template</label>
<div class="input-group">
{{ form.template }}
<button class="btn btn-outline-secondary" type="button" onclick="loadTemplate()">
<i class="fas fa-download me-1"></i>Load
</button>
<button class="btn btn-outline-info" type="button" onclick="previewTemplate()">
<i class="fas fa-eye me-1"></i>Preview
</button>
</div>
{% if form.template.errors %}
<div class="invalid-feedback d-block">
{{ form.template.errors.0 }}
</div>
{% endif %}
<div class="form-text">Optional: Select a template to pre-fill the message content</div>
</div>
<!-- Message Body -->
<div class="mb-3">
<label for="{{ form.body.id_for_label }}" class="form-label">Message Content *</label>
{{ form.body }}
{% if form.body.errors %}
<div class="invalid-feedback d-block">
{{ form.body.errors.0 }}
</div>
{% endif %}
<div class="form-text">
<div class="d-flex justify-content-between">
<span>Enter your message content. You can use variables like {patient_name}, {appointment_date}</span>
<span id="charCount" class="text-muted">0 characters</span>
</div>
</div>
</div>
<!-- Scheduled Time -->
<div class="mb-3">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="scheduleMessage">
<label class="form-check-label" for="scheduleMessage">
Schedule for later
</label>
</div>
<div id="scheduledTimeGroup" style="display: none;">
<label for="{{ form.scheduled_time.id_for_label }}" class="form-label">Scheduled Time</label>
{{ form.scheduled_time }}
{% if form.scheduled_time.errors %}
<div class="invalid-feedback d-block">
{{ form.scheduled_time.errors.0 }}
</div>
{% endif %}
<div class="form-text">Leave empty to send immediately</div>
</div>
</div>
</div>
</div>
<!-- Recipients -->
<div class="card">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">
<i class="fas fa-users me-2"></i>
Recipients
</h5>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-outline-secondary" onclick="selectAllRecipients()">
Select All
</button>
<button type="button" class="btn btn-outline-secondary" onclick="clearAllRecipients()">
Clear All
</button>
</div>
</div>
</div>
<div class="card-body">
<!-- Recipient Search -->
<div class="mb-3">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search recipients..." id="recipientSearch">
<button class="btn btn-outline-secondary" type="button">
<i class="fas fa-search"></i>
</button>
</div>
</div>
<!-- Quick Recipient Groups -->
<div class="mb-3">
<label class="form-label">Quick Select:</label>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-outline-primary" onclick="selectGroup('doctors')">
Doctors
</button>
<button type="button" class="btn btn-outline-success" onclick="selectGroup('nurses')">
Nurses
</button>
<button type="button" class="btn btn-outline-info" onclick="selectGroup('admin')">
Admin Staff
</button>
<button type="button" class="btn btn-outline-warning" onclick="selectGroup('patients')">
Patients
</button>
</div>
</div>
<!-- Recipients List -->
<div class="recipients-container" style="max-height: 300px; overflow-y: auto;">
{{ form.recipients }}
</div>
{% if form.recipients.errors %}
<div class="invalid-feedback d-block">
{{ form.recipients.errors.0 }}
</div>
{% endif %}
<div class="form-text">Select one or more recipients for this message</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Form Actions -->
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-cog me-2"></i>
Actions
</h5>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button type="submit" name="action" value="save_draft" class="btn btn-secondary">
<i class="fas fa-save me-1"></i>
Save as Draft
</button>
<button type="submit" name="action" value="send_now" class="btn btn-success">
<i class="fas fa-paper-plane me-1"></i>
Send Now
</button>
<button type="submit" name="action" value="schedule" class="btn btn-primary">
<i class="fas fa-clock me-1"></i>
Schedule Message
</button>
<hr>
<button type="button" class="btn btn-outline-info" onclick="previewMessage()">
<i class="fas fa-eye me-1"></i>
Preview Message
</button>
<button type="button" class="btn btn-outline-secondary" onclick="testMessage()">
<i class="fas fa-flask me-1"></i>
Send Test
</button>
<hr>
<a href="{% url 'communications:message_list' %}" class="btn btn-outline-danger">
<i class="fas fa-times me-1"></i>
Cancel
</a>
</div>
</div>
</div>
<!-- Message Help -->
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-question-circle me-2"></i>
Help & Tips
</h5>
</div>
<div class="card-body">
<div class="accordion" id="helpAccordion">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#variables">
Message Variables
</button>
</h2>
<div id="variables" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body">
<small>
<strong>Patient Variables:</strong><br>
{patient_name}, {patient_id}, {patient_phone}<br><br>
<strong>Appointment Variables:</strong><br>
{appointment_date}, {appointment_time}, {provider_name}<br><br>
<strong>System Variables:</strong><br>
{hospital_name}, {current_date}, {current_time}
</small>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#messageTypes">
Message Types
</button>
</h2>
<div id="messageTypes" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body">
<small>
<strong>Internal:</strong> Staff-to-staff communication<br>
<strong>Email:</strong> External email messages<br>
<strong>SMS:</strong> Text messages to mobile phones<br>
<strong>Push:</strong> Mobile app notifications<br>
<strong>System:</strong> Automated system messages
</small>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#bestPractices">
Best Practices
</button>
</h2>
<div id="bestPractices" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body">
<small>
• Keep subjects clear and concise<br>
• Use appropriate priority levels<br>
• Test messages before sending<br>
• Schedule non-urgent messages appropriately<br>
• Use templates for consistency
</small>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Message Statistics -->
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-chart-bar me-2"></i>
Estimated Reach
</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-borderless table-sm">
<tr>
<td class="fw-bold text-muted">Selected Recipients:</td>
<td><span id="selectedCount">0</span></td>
</tr>
<tr>
<td class="fw-bold text-muted">Estimated Cost:</td>
<td><span id="estimatedCost">$0.00</span></td>
</tr>
<tr>
<td class="fw-bold text-muted">Delivery Time:</td>
<td><span id="deliveryTime">Immediate</span></td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<!-- Preview Modal -->
<div class="modal fade" id="previewModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Message Preview</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div id="previewContent"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="sendFromPreview()">Send Message</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
// Character counter
document.getElementById('{{ form.body.id_for_label }}').addEventListener('input', function() {
document.getElementById('charCount').textContent = this.value.length + ' characters';
});
// Schedule message toggle
document.getElementById('scheduleMessage').addEventListener('change', function() {
const scheduledTimeGroup = document.getElementById('scheduledTimeGroup');
scheduledTimeGroup.style.display = this.checked ? 'block' : 'none';
});
// Recipient selection functions
function selectAllRecipients() {
const checkboxes = document.querySelectorAll('input[name="{{ form.recipients.name }}"]');
checkboxes.forEach(checkbox => {
checkbox.checked = true;
});
updateSelectedCount();
}
function clearAllRecipients() {
const checkboxes = document.querySelectorAll('input[name="{{ form.recipients.name }}"]');
checkboxes.forEach(checkbox => {
checkbox.checked = false;
});
updateSelectedCount();
}
function selectGroup(group) {
// Implementation for selecting specific groups
alert(`Selecting ${group} group - functionality to be implemented`);
}
function updateSelectedCount() {
const selected = document.querySelectorAll('input[name="{{ form.recipients.name }}"]:checked').length;
document.getElementById('selectedCount').textContent = selected;
// Update estimated cost (example calculation)
const messageType = document.getElementById('{{ form.message_type.id_for_label }}').value;
let costPerMessage = 0;
if (messageType === 'SMS') costPerMessage = 0.05;
else if (messageType === 'EMAIL') costPerMessage = 0.01;
const estimatedCost = (selected * costPerMessage).toFixed(2);
document.getElementById('estimatedCost').textContent = '$' + estimatedCost;
}
// Template functions
function loadTemplate() {
const templateSelect = document.getElementById('{{ form.template.id_for_label }}');
const templateId = templateSelect.value;
if (templateId) {
fetch(`/communications/templates/${templateId}/content/`)
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('{{ form.subject.id_for_label }}').value = data.subject;
document.getElementById('{{ form.body.id_for_label }}').value = data.body;
updateSelectedCount();
}
});
}
}
function previewTemplate() {
const templateSelect = document.getElementById('{{ form.template.id_for_label }}');
const templateId = templateSelect.value;
if (templateId) {
window.open(`/communications/templates/${templateId}/preview/`, '_blank');
} else {
alert('Please select a template first');
}
}
// Message functions
function previewMessage() {
const subject = document.getElementById('{{ form.subject.id_for_label }}').value;
const body = document.getElementById('{{ form.body.id_for_label }}').value;
const previewContent = `
<div class="card">
<div class="card-header">
<h6 class="mb-0">${subject}</h6>
</div>
<div class="card-body">
${body.replace(/\n/g, '<br>')}
</div>
</div>
`;
document.getElementById('previewContent').innerHTML = previewContent;
new bootstrap.Modal(document.getElementById('previewModal')).show();
}
function testMessage() {
if (confirm('Send a test message to yourself?')) {
// Implementation for test message
alert('Test message functionality will be implemented');
}
}
function sendFromPreview() {
document.querySelector('button[name="action"][value="send_now"]').click();
}
// Initialize
document.addEventListener('DOMContentLoaded', function() {
updateSelectedCount();
// Add event listeners to recipient checkboxes
const checkboxes = document.querySelectorAll('input[name="{{ form.recipients.name }}"]');
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateSelectedCount);
});
// Recipient search functionality
document.getElementById('recipientSearch').addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
const labels = document.querySelectorAll('.recipients-container label');
labels.forEach(label => {
const text = label.textContent.toLowerCase();
label.style.display = text.includes(searchTerm) ? 'block' : 'none';
});
});
});
</script>
{% endblock %}