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

503 lines
30 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Broadcast Message{% endblock %}
{% block css %}
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/summernote/dist/summernote-lite.min.css' %}" rel="stylesheet" />
{% endblock %}
{% block content %}
<div id="content" class="app-content">
<div class="container">
<div class="row justify-content-center">
<div class="col-xl-10">
<ul class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'communications:message_list' %}">Messages</a></li>
<li class="breadcrumb-item active">Broadcast</li>
</ul>
<div class="row align-items-center mb-3">
<div class="col">
<h1 class="page-header">Broadcast Message</h1>
<p class="text-muted">Send important announcements and alerts to multiple recipients</p>
</div>
<div class="col-auto">
<div class="btn-group">
<button type="button" class="btn btn-outline-primary" onclick="loadTemplate('emergency')">
<i class="fa fa-exclamation-triangle me-2"></i>Emergency
</button>
<button type="button" class="btn btn-outline-info" onclick="loadTemplate('announcement')">
<i class="fa fa-bullhorn me-2"></i>Announcement
</button>
<button type="button" class="btn btn-outline-success" onclick="loadTemplate('update')">
<i class="fa fa-info-circle me-2"></i>System Update
</button>
</div>
</div>
</div>
<!-- Broadcast Statistics -->
<div class="row mb-4">
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<div class="fs-20px fw-600 text-primary">{{ total_users }}</div>
<div class="text-muted small">Total Users</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<div class="fs-20px fw-600 text-success">{{ online_users }}</div>
<div class="text-muted small">Online Now</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<div class="fs-20px fw-600 text-info">{{ departments_count }}</div>
<div class="text-muted small">Departments</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<div class="fs-20px fw-600 text-warning">{{ recent_broadcasts }}</div>
<div class="text-muted small">Recent Broadcasts</div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
<form method="post" class="form-horizontal" enctype="multipart/form-data" id="broadcastForm">
{% csrf_token %}
<div class="row mb-4">
<label class="col-form-label col-md-2">Broadcast Type <span class="text-danger">*</span></label>
<div class="col-md-10">
<div class="btn-group w-100" role="group">
<input type="radio" class="btn-check" name="broadcast_type" id="type_announcement" value="announcement" checked>
<label class="btn btn-outline-primary" for="type_announcement">
<i class="fa fa-bullhorn me-2"></i>Announcement
</label>
<input type="radio" class="btn-check" name="broadcast_type" id="type_alert" value="alert">
<label class="btn btn-outline-warning" for="type_alert">
<i class="fa fa-exclamation-triangle me-2"></i>Alert
</label>
<input type="radio" class="btn-check" name="broadcast_type" id="type_emergency" value="emergency">
<label class="btn btn-outline-danger" for="type_emergency">
<i class="fa fa-exclamation-circle me-2"></i>Emergency
</label>
<input type="radio" class="btn-check" name="broadcast_type" id="type_maintenance" value="maintenance">
<label class="btn btn-outline-info" for="type_maintenance">
<i class="fa fa-wrench me-2"></i>Maintenance
</label>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Priority Level <span class="text-danger">*</span></label>
<div class="col-md-10">
<select name="priority" class="form-select" required>
<option value="normal">Normal - Standard notification</option>
<option value="high">High - Important message</option>
<option value="urgent">Urgent - Immediate attention required</option>
<option value="critical">Critical - Emergency response needed</option>
</select>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Target Audience <span class="text-danger">*</span></label>
<div class="col-md-10">
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h6 class="card-title mb-0">Departments</h6>
</div>
<div class="card-body">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="select_all_departments">
<label class="form-check-label fw-bold" for="select_all_departments">
Select All Departments
</label>
</div>
<hr>
{% for department in departments %}
<div class="form-check">
<input class="form-check-input department-check" type="checkbox"
name="departments" value="{{ department.id }}" id="dept_{{ department.id }}">
<label class="form-check-label" for="dept_{{ department.id }}">
{{ department.name }}
<small class="text-muted">({{ department.user_count }} users)</small>
</label>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h6 class="card-title mb-0">User Roles</h6>
</div>
<div class="card-body">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="select_all_roles">
<label class="form-check-label fw-bold" for="select_all_roles">
Select All Roles
</label>
</div>
<hr>
{% for role in user_roles %}
<div class="form-check">
<input class="form-check-input role-check" type="checkbox"
name="roles" value="{{ role.id }}" id="role_{{ role.id }}">
<label class="form-check-label" for="role_{{ role.id }}">
{{ role.name }}
<small class="text-muted">({{ role.user_count }} users)</small>
</label>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="mt-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="include_all_staff" id="include_all_staff">
<label class="form-check-label" for="include_all_staff">
<strong>Broadcast to ALL Staff</strong>
<small class="text-muted d-block">Override selections and send to everyone</small>
</label>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Subject <span class="text-danger">*</span></label>
<div class="col-md-10">
<input type="text" name="subject" class="form-control" required
placeholder="Enter broadcast subject" maxlength="200">
<div class="form-text">Keep it concise and descriptive (max 200 characters)</div>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Message Content <span class="text-danger">*</span></label>
<div class="col-md-10">
<textarea name="content" id="broadcastContent" class="form-control" required></textarea>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Delivery Channels</label>
<div class="col-md-10">
<div class="row">
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="channels" value="in_app" id="channel_app" checked>
<label class="form-check-label" for="channel_app">
<i class="fa fa-bell text-primary me-2"></i>In-App Notification
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="channels" value="email" id="channel_email">
<label class="form-check-label" for="channel_email">
<i class="fa fa-envelope text-info me-2"></i>Email Notification
</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="channels" value="sms" id="channel_sms">
<label class="form-check-label" for="channel_sms">
<i class="fa fa-mobile text-success me-2"></i>SMS Alert
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="channels" value="push" id="channel_push">
<label class="form-check-label" for="channel_push">
<i class="fa fa-mobile-alt text-warning me-2"></i>Push Notification
</label>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Broadcast Schedule</label>
<div class="col-md-10">
<div class="form-check mb-2">
<input class="form-check-input" type="radio" name="schedule_type" id="send_immediately" value="immediate" checked>
<label class="form-check-label" for="send_immediately">
Send Immediately
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="radio" name="schedule_type" id="schedule_broadcast" value="scheduled">
<label class="form-check-label" for="schedule_broadcast">
Schedule for Later
</label>
</div>
<div id="schedule_options" style="display: none;">
<div class="row mt-2">
<div class="col-md-6">
<input type="datetime-local" name="scheduled_at" class="form-control">
<small class="form-text text-muted">Select broadcast date and time</small>
</div>
<div class="col-md-6">
<select name="timezone" class="form-select">
<option value="local">Local Time</option>
<option value="utc">UTC</option>
<option value="est">Eastern Time</option>
<option value="pst">Pacific Time</option>
</select>
<small class="form-text text-muted">Time zone</small>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Broadcast Options</label>
<div class="col-md-10">
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" name="require_acknowledgment" id="require_ack">
<label class="form-check-label" for="require_ack">
Require acknowledgment from recipients
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" name="track_delivery" id="track_delivery" checked>
<label class="form-check-label" for="track_delivery">
Track delivery and read status
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" name="persistent_notification" id="persistent_notif">
<label class="form-check-label" for="persistent_notif">
Keep notification visible until acknowledged
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="auto_expire" id="auto_expire">
<label class="form-check-label" for="auto_expire">
Auto-expire after 7 days
</label>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-form-label col-md-2">Attachments</label>
<div class="col-md-10">
<input type="file" name="attachments" class="form-control" multiple
accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif">
<small class="form-text text-muted">
Attach relevant documents or images. Max 25MB total.
</small>
</div>
</div>
<!-- Recipient Summary -->
<div class="row mb-4">
<div class="col-md-10 offset-md-2">
<div class="card bg-light">
<div class="card-body">
<h6 class="card-title">Broadcast Summary</h6>
<div id="recipientSummary">
<div class="text-muted">Select departments or roles to see recipient count</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-10 offset-md-2">
<button type="submit" name="action" value="broadcast" class="btn btn-primary btn-lg">
<i class="fa fa-broadcast-tower me-2"></i>Send Broadcast
</button>
<button type="submit" name="action" value="preview" class="btn btn-info ms-2">
<i class="fa fa-eye me-2"></i>Preview
</button>
<button type="submit" name="action" value="draft" class="btn btn-secondary ms-2">
<i class="fa fa-save me-2"></i>Save Draft
</button>
<a href="{% url 'communications:message_list' %}" class="btn btn-outline-secondary ms-2">
<i class="fa fa-times me-2"></i>Cancel
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script>
<script src="{% static 'assets/plugins/summernote/dist/summernote-lite.min.js' %}"></script>
<script>
$(document).ready(function() {
// Initialize Summernote
$('#broadcastContent').summernote({
height: 250,
toolbar: [
['style', ['style']],
['font', ['bold', 'italic', 'underline', 'clear']],
['fontname', ['fontname']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link']],
['view', ['fullscreen', 'codeview', 'help']]
]
});
// Handle schedule type changes
$('input[name="schedule_type"]').change(function() {
if ($(this).val() === 'scheduled') {
$('#schedule_options').show();
} else {
$('#schedule_options').hide();
}
});
// Handle select all checkboxes
$('#select_all_departments').change(function() {
$('.department-check').prop('checked', $(this).is(':checked'));
updateRecipientSummary();
});
$('#select_all_roles').change(function() {
$('.role-check').prop('checked', $(this).is(':checked'));
updateRecipientSummary();
});
// Handle individual checkbox changes
$('.department-check, .role-check').change(function() {
updateRecipientSummary();
});
// Handle include all staff
$('#include_all_staff').change(function() {
if ($(this).is(':checked')) {
$('.department-check, .role-check').prop('disabled', true);
$('#select_all_departments, #select_all_roles').prop('disabled', true);
} else {
$('.department-check, .role-check').prop('disabled', false);
$('#select_all_departments, #select_all_roles').prop('disabled', false);
}
updateRecipientSummary();
});
// Set default scheduled time
var now = new Date();
now.setHours(now.getHours() + 1);
var dateTimeString = now.toISOString().slice(0, 16);
$('input[name="scheduled_at"]').val(dateTimeString);
// Initial summary update
updateRecipientSummary();
});
function updateRecipientSummary() {
var summary = '';
var totalRecipients = 0;
if ($('#include_all_staff').is(':checked')) {
summary = '<div class="alert alert-info mb-0"><i class="fa fa-users me-2"></i><strong>Broadcasting to ALL STAFF</strong> ({{ total_users }} users)</div>';
totalRecipients = {{ total_users }};
} else {
var selectedDepts = $('.department-check:checked').length;
var selectedRoles = $('.role-check:checked').length;
if (selectedDepts === 0 && selectedRoles === 0) {
summary = '<div class="text-muted">No recipients selected</div>';
} else {
var parts = [];
if (selectedDepts > 0) {
parts.push(selectedDepts + ' department' + (selectedDepts > 1 ? 's' : ''));
}
if (selectedRoles > 0) {
parts.push(selectedRoles + ' role' + (selectedRoles > 1 ? 's' : ''));
}
// Calculate approximate recipient count (simplified)
totalRecipients = (selectedDepts * 15) + (selectedRoles * 8); // Rough estimate
summary = '<div class="text-success"><i class="fa fa-check me-2"></i>Broadcasting to ' + parts.join(' and ') + ' (~' + totalRecipients + ' users)</div>';
}
}
$('#recipientSummary').html(summary);
}
function loadTemplate(type) {
var templates = {
emergency: {
subject: 'EMERGENCY ALERT - Immediate Action Required',
content: '<div style="background-color: #f8d7da; border: 1px solid #f5c6cb; padding: 15px; border-radius: 5px;"><h4 style="color: #721c24;">🚨 EMERGENCY ALERT</h4><p>This is an emergency notification requiring immediate attention from all staff.</p><p><strong>Action Required:</strong> [Describe required action]</p><p><strong>Timeline:</strong> [Specify timeline]</p><p><strong>Contact:</strong> [Emergency contact information]</p></div>',
priority: 'critical',
type: 'emergency'
},
announcement: {
subject: 'Important Announcement - [Subject]',
content: '<h4>📢 Announcement</h4><p>We would like to inform all staff about the following:</p><p>[Your announcement content here]</p><p>If you have any questions, please contact [contact information].</p><p>Thank you for your attention.</p>',
priority: 'normal',
type: 'announcement'
},
update: {
subject: 'System Update Notification',
content: '<h4>🔄 System Update</h4><p>A system update has been scheduled with the following details:</p><ul><li><strong>Update Date:</strong> [Date and time]</li><li><strong>Expected Duration:</strong> [Duration]</li><li><strong>Affected Systems:</strong> [List systems]</li><li><strong>Impact:</strong> [Describe impact]</li></ul><p>Please plan accordingly and contact IT support if you have any concerns.</p>',
priority: 'high',
type: 'maintenance'
}
};
var template = templates[type];
if (template) {
$('input[name="subject"]').val(template.subject);
$('#broadcastContent').summernote('code', template.content);
$('select[name="priority"]').val(template.priority);
$('input[name="broadcast_type"][value="' + template.type + '"]').prop('checked', true);
}
}
</script>
{% endblock %}