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

948 lines
51 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Notification Preferences - {{ block.super }}{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Page Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h1 class="h3 mb-1">Notification Preferences</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{% url 'communications:dashboard' %}">Communications</a></li>
<li class="breadcrumb-item"><a href="{% url 'communications:notification_list' %}">Notifications</a></li>
<li class="breadcrumb-item active">Preferences</li>
</ol>
</nav>
</div>
<div class="btn-group">
<a href="{% url 'communications:notification_settings' %}" class="btn btn-outline-secondary">
<i class="fas fa-cog me-2"></i>General Settings
</a>
<a href="{% url 'communications:notification_list' %}" class="btn btn-outline-primary">
<i class="fas fa-arrow-left me-2"></i>Back to Notifications
</a>
</div>
</div>
<div class="row">
<!-- Main Content -->
<div class="col-lg-8">
<!-- Notification Categories -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-layer-group me-2"></i>Notification Categories
</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Category</th>
<th class="text-center">Email</th>
<th class="text-center">SMS</th>
<th class="text-center">Push</th>
<th class="text-center">In-App</th>
<th class="text-center">Priority</th>
<th class="text-center">Actions</th>
</tr>
</thead>
<tbody>
<!-- Appointments -->
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fas fa-calendar-check text-primary me-3"></i>
<div>
<div class="fw-bold">Appointments</div>
<div class="small text-muted">Reminders, confirmations, cancellations</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="appointments_email" checked onchange="updatePreference('appointments', 'email', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="appointments_sms" checked onchange="updatePreference('appointments', 'sms', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="appointments_push" checked onchange="updatePreference('appointments', 'push', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="appointments_in_app" checked onchange="updatePreference('appointments', 'in_app', this.checked)">
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" onchange="updatePreference('appointments', 'priority', this.value)">
<option value="HIGH" selected>High</option>
<option value="NORMAL">Normal</option>
<option value="LOW">Low</option>
</select>
</td>
<td class="text-center">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="customizeCategory('appointments')">
<i class="fas fa-cog"></i>
</button>
</td>
</tr>
<!-- Lab Results -->
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fas fa-flask text-success me-3"></i>
<div>
<div class="fw-bold">Lab Results</div>
<div class="small text-muted">Test results, reports available</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="lab_results_email" checked onchange="updatePreference('lab_results', 'email', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="lab_results_sms" onchange="updatePreference('lab_results', 'sms', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="lab_results_push" checked onchange="updatePreference('lab_results', 'push', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="lab_results_in_app" checked onchange="updatePreference('lab_results', 'in_app', this.checked)">
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" onchange="updatePreference('lab_results', 'priority', this.value)">
<option value="HIGH" selected>High</option>
<option value="NORMAL">Normal</option>
<option value="LOW">Low</option>
</select>
</td>
<td class="text-center">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="customizeCategory('lab_results')">
<i class="fas fa-cog"></i>
</button>
</td>
</tr>
<!-- Medications -->
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fas fa-pills text-warning me-3"></i>
<div>
<div class="fw-bold">Medications</div>
<div class="small text-muted">Reminders, refill alerts, interactions</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="medications_email" onchange="updatePreference('medications', 'email', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="medications_sms" checked onchange="updatePreference('medications', 'sms', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="medications_push" checked onchange="updatePreference('medications', 'push', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="medications_in_app" checked onchange="updatePreference('medications', 'in_app', this.checked)">
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" onchange="updatePreference('medications', 'priority', this.value)">
<option value="HIGH" selected>High</option>
<option value="NORMAL">Normal</option>
<option value="LOW">Low</option>
</select>
</td>
<td class="text-center">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="customizeCategory('medications')">
<i class="fas fa-cog"></i>
</button>
</td>
</tr>
<!-- Billing -->
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fas fa-file-invoice text-info me-3"></i>
<div>
<div class="fw-bold">Billing & Payments</div>
<div class="small text-muted">Bills, payment due, receipts</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="billing_email" checked onchange="updatePreference('billing', 'email', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="billing_sms" onchange="updatePreference('billing', 'sms', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="billing_push" onchange="updatePreference('billing', 'push', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="billing_in_app" checked onchange="updatePreference('billing', 'in_app', this.checked)">
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" onchange="updatePreference('billing', 'priority', this.value)">
<option value="HIGH">High</option>
<option value="NORMAL" selected>Normal</option>
<option value="LOW">Low</option>
</select>
</td>
<td class="text-center">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="customizeCategory('billing')">
<i class="fas fa-cog"></i>
</button>
</td>
</tr>
<!-- Emergency -->
<tr class="table-danger">
<td>
<div class="d-flex align-items-center">
<i class="fas fa-exclamation-triangle text-danger me-3"></i>
<div>
<div class="fw-bold">Emergency Alerts</div>
<div class="small text-muted">Critical alerts, emergency notifications</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="emergency_email" checked disabled>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="emergency_sms" checked disabled>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="emergency_push" checked disabled>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="emergency_in_app" checked disabled>
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" disabled>
<option value="CRITICAL" selected>Critical</option>
</select>
</td>
<td class="text-center">
<span class="badge bg-danger">Required</span>
</td>
</tr>
<!-- System -->
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fas fa-cogs text-secondary me-3"></i>
<div>
<div class="fw-bold">System Updates</div>
<div class="small text-muted">Maintenance, updates, announcements</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="system_email" onchange="updatePreference('system', 'email', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="system_sms" onchange="updatePreference('system', 'sms', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="system_push" onchange="updatePreference('system', 'push', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="system_in_app" checked onchange="updatePreference('system', 'in_app', this.checked)">
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" onchange="updatePreference('system', 'priority', this.value)">
<option value="HIGH">High</option>
<option value="NORMAL">Normal</option>
<option value="LOW" selected>Low</option>
</select>
</td>
<td class="text-center">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="customizeCategory('system')">
<i class="fas fa-cog"></i>
</button>
</td>
</tr>
<!-- Clinical -->
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fas fa-stethoscope text-primary me-3"></i>
<div>
<div class="fw-bold">Clinical Updates</div>
<div class="small text-muted">Care plans, treatment updates, consultations</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="clinical_email" checked onchange="updatePreference('clinical', 'email', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="clinical_sms" onchange="updatePreference('clinical', 'sms', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="clinical_push" checked onchange="updatePreference('clinical', 'push', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="clinical_in_app" checked onchange="updatePreference('clinical', 'in_app', this.checked)">
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" onchange="updatePreference('clinical', 'priority', this.value)">
<option value="HIGH" selected>High</option>
<option value="NORMAL">Normal</option>
<option value="LOW">Low</option>
</select>
</td>
<td class="text-center">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="customizeCategory('clinical')">
<i class="fas fa-cog"></i>
</button>
</td>
</tr>
<!-- Administrative -->
<tr>
<td>
<div class="d-flex align-items-center">
<i class="fas fa-clipboard-list text-muted me-3"></i>
<div>
<div class="fw-bold">Administrative</div>
<div class="small text-muted">Forms, documents, policy updates</div>
</div>
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="administrative_email" onchange="updatePreference('administrative', 'email', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="administrative_sms" onchange="updatePreference('administrative', 'sms', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="administrative_push" onchange="updatePreference('administrative', 'push', this.checked)">
</div>
</td>
<td class="text-center">
<div class="form-check form-switch d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="administrative_in_app" checked onchange="updatePreference('administrative', 'in_app', this.checked)">
</div>
</td>
<td class="text-center">
<select class="form-select form-select-sm" onchange="updatePreference('administrative', 'priority', this.value)">
<option value="HIGH">High</option>
<option value="NORMAL">Normal</option>
<option value="LOW" selected>Low</option>
</select>
</td>
<td class="text-center">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="customizeCategory('administrative')">
<i class="fas fa-cog"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card-footer">
<div class="d-flex justify-content-between align-items-center">
<div class="text-muted small">
<i class="fas fa-info-circle me-1"></i>
Emergency notifications cannot be disabled for safety reasons.
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-success btn-sm" onclick="enableAllCategories()">
<i class="fas fa-check-double me-1"></i>Enable All
</button>
<button type="button" class="btn btn-outline-warning btn-sm" onclick="resetToDefaults()">
<i class="fas fa-undo me-1"></i>Reset Defaults
</button>
<button type="button" class="btn btn-success btn-sm" onclick="savePreferences()">
<i class="fas fa-save me-1"></i>Save Changes
</button>
</div>
</div>
</div>
</div>
<!-- Custom Timing Rules -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-clock me-2"></i>Custom Timing Rules
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h6 class="mb-3">Appointment Reminders</h6>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="reminder_24h" checked>
<label class="form-check-label" for="reminder_24h">
24 hours before
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="reminder_2h" checked>
<label class="form-check-label" for="reminder_2h">
2 hours before
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="reminder_30m">
<label class="form-check-label" for="reminder_30m">
30 minutes before
</label>
</div>
</div>
<div class="col-md-6">
<h6 class="mb-3">Medication Reminders</h6>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="med_reminder_time" checked>
<label class="form-check-label" for="med_reminder_time">
At scheduled time
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="med_reminder_15m">
<label class="form-check-label" for="med_reminder_15m">
15 minutes after missed dose
</label>
</div>
<div class="form-check mb-2">
<input class="form-check-input" type="checkbox" id="med_reminder_refill" checked>
<label class="form-check-label" for="med_reminder_refill">
3 days before refill needed
</label>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Preference Summary -->
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-chart-pie me-2"></i>Preference Summary
</h5>
</div>
<div class="card-body">
<div class="mb-3">
<div class="d-flex justify-content-between mb-2">
<span>Email Notifications:</span>
<span class="badge bg-primary" id="email-count">4/8</span>
</div>
<div class="progress mb-3" style="height: 6px;">
<div class="progress-bar bg-primary" style="width: 50%" id="email-progress"></div>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between mb-2">
<span>SMS Notifications:</span>
<span class="badge bg-success" id="sms-count">3/8</span>
</div>
<div class="progress mb-3" style="height: 6px;">
<div class="progress-bar bg-success" style="width: 37.5%" id="sms-progress"></div>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between mb-2">
<span>Push Notifications:</span>
<span class="badge bg-info" id="push-count">5/8</span>
</div>
<div class="progress mb-3" style="height: 6px;">
<div class="progress-bar bg-info" style="width: 62.5%" id="push-progress"></div>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between mb-2">
<span>In-App Notifications:</span>
<span class="badge bg-warning" id="in-app-count">7/8</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar bg-warning" style="width: 87.5%" id="in-app-progress"></div>
</div>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-bolt me-2"></i>Quick Actions
</h5>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button type="button" class="btn btn-outline-primary" onclick="enableAllCategories()">
<i class="fas fa-check-double me-2"></i>Enable All Categories
</button>
<button type="button" class="btn btn-outline-warning" onclick="enableEssentialOnly()">
<i class="fas fa-exclamation-triangle me-2"></i>Essential Only
</button>
<button type="button" class="btn btn-outline-info" onclick="enableWorkHours()">
<i class="fas fa-business-time me-2"></i>Work Hours Only
</button>
<button type="button" class="btn btn-outline-secondary" onclick="disableNonCritical()">
<i class="fas fa-volume-mute me-2"></i>Disable Non-Critical
</button>
</div>
</div>
</div>
<!-- Recent Changes -->
<div class="card mb-3">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-history me-2"></i>Recent Changes
</h5>
</div>
<div class="card-body">
<div id="recent-changes">
<div class="small text-muted text-center">No recent changes</div>
</div>
</div>
</div>
<!-- Help -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-question-circle me-2"></i>Help
</h5>
</div>
<div class="card-body">
<div class="accordion accordion-flush" id="helpAccordion">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#help1">
Channel Types
</button>
</h2>
<div id="help1" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body small">
<strong>Email:</strong> Detailed notifications sent to your email address.<br>
<strong>SMS:</strong> Brief text messages to your phone.<br>
<strong>Push:</strong> Mobile app notifications.<br>
<strong>In-App:</strong> Notifications within the web application.
</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="#help2">
Priority Levels
</button>
</h2>
<div id="help2" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body small">
<strong>Critical:</strong> Emergency alerts that override all settings.<br>
<strong>High:</strong> Important notifications that may override quiet hours.<br>
<strong>Normal:</strong> Standard notifications.<br>
<strong>Low:</strong> Non-urgent notifications that respect quiet hours.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Category Customization Modal -->
<div class="modal fade" id="categoryCustomizationModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Customize Category</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="categoryCustomizationContent">
<!-- Content will be loaded dynamically -->
</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="saveCategoryCustomization()">Save Changes</button>
</div>
</div>
</div>
</div>
<script>
let preferences = {};
let recentChanges = [];
// Initialize preferences page
document.addEventListener('DOMContentLoaded', function() {
loadCurrentPreferences();
updateSummary();
});
function loadCurrentPreferences() {
fetch('{% url "communications:notification_preferences_api" %}')
.then(response => response.json())
.then(data => {
preferences = data.preferences;
updateFormFromPreferences();
})
.catch(error => console.error('Error loading preferences:', error));
}
function updateFormFromPreferences() {
Object.keys(preferences).forEach(category => {
const categoryPrefs = preferences[category];
Object.keys(categoryPrefs).forEach(channel => {
const checkbox = document.getElementById(`${category}_${channel}`);
if (checkbox && checkbox.type === 'checkbox') {
checkbox.checked = categoryPrefs[channel];
} else if (checkbox && checkbox.tagName === 'SELECT') {
checkbox.value = categoryPrefs[channel];
}
});
});
}
function updatePreference(category, channel, value) {
if (!preferences[category]) {
preferences[category] = {};
}
preferences[category][channel] = value;
// Add to recent changes
const change = {
timestamp: new Date(),
category: category,
channel: channel,
value: value,
action: value ? 'enabled' : 'disabled'
};
recentChanges.unshift(change);
if (recentChanges.length > 5) {
recentChanges.pop();
}
updateSummary();
updateRecentChanges();
// Auto-save after a short delay
clearTimeout(window.autoSaveTimeout);
window.autoSaveTimeout = setTimeout(savePreferences, 2000);
}
function updateSummary() {
const channels = ['email', 'sms', 'push', 'in_app'];
const totalCategories = Object.keys(preferences).length || 8;
channels.forEach(channel => {
let enabledCount = 0;
Object.keys(preferences).forEach(category => {
if (preferences[category] && preferences[category][channel]) {
enabledCount++;
}
});
const percentage = (enabledCount / totalCategories) * 100;
const countElement = document.getElementById(`${channel.replace('_', '-')}-count`);
const progressElement = document.getElementById(`${channel.replace('_', '-')}-progress`);
if (countElement) {
countElement.textContent = `${enabledCount}/${totalCategories}`;
}
if (progressElement) {
progressElement.style.width = `${percentage}%`;
}
});
}
function updateRecentChanges() {
const container = document.getElementById('recent-changes');
if (recentChanges.length === 0) {
container.innerHTML = '<div class="small text-muted text-center">No recent changes</div>';
return;
}
const changesHtml = recentChanges.map(change => {
const timeAgo = getTimeAgo(change.timestamp);
const icon = change.value ? 'fa-check text-success' : 'fa-times text-danger';
return `
<div class="d-flex align-items-center mb-2">
<i class="fas ${icon} me-2"></i>
<div class="flex-grow-1">
<div class="small fw-bold">${change.category.replace('_', ' ').toUpperCase()}</div>
<div class="small text-muted">${change.channel.toUpperCase()} ${change.action}</div>
</div>
<div class="small text-muted">${timeAgo}</div>
</div>
`;
}).join('');
container.innerHTML = changesHtml;
}
function getTimeAgo(timestamp) {
const now = new Date();
const diff = now - timestamp;
const minutes = Math.floor(diff / 60000);
if (minutes < 1) return 'Just now';
if (minutes < 60) return `${minutes}m ago`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h ago`;
const days = Math.floor(hours / 24);
return `${days}d ago`;
}
function enableAllCategories() {
const categories = ['appointments', 'lab_results', 'medications', 'billing', 'system', 'clinical', 'administrative'];
const channels = ['email', 'sms', 'push', 'in_app'];
categories.forEach(category => {
channels.forEach(channel => {
const checkbox = document.getElementById(`${category}_${channel}`);
if (checkbox && !checkbox.disabled) {
checkbox.checked = true;
updatePreference(category, channel, true);
}
});
});
showToast('Success', 'All categories enabled', 'success');
}
function enableEssentialOnly() {
const essentialSettings = {
appointments: { email: true, sms: true, push: true, in_app: true },
lab_results: { email: true, push: true, in_app: true },
medications: { sms: true, push: true, in_app: true },
emergency: { email: true, sms: true, push: true, in_app: true }
};
// First disable all
disableAllCategories();
// Then enable essential
Object.keys(essentialSettings).forEach(category => {
Object.keys(essentialSettings[category]).forEach(channel => {
const checkbox = document.getElementById(`${category}_${channel}`);
if (checkbox && !checkbox.disabled) {
checkbox.checked = essentialSettings[category][channel];
updatePreference(category, channel, essentialSettings[category][channel]);
}
});
});
showToast('Success', 'Essential notifications enabled', 'success');
}
function enableWorkHours() {
// This would typically integrate with quiet hours settings
enableEssentialOnly();
showToast('Info', 'Work hours preset applied. Configure quiet hours in settings for full effect.', 'info');
}
function disableNonCritical() {
const categories = ['system', 'administrative', 'billing'];
const channels = ['email', 'sms', 'push', 'in_app'];
categories.forEach(category => {
channels.forEach(channel => {
const checkbox = document.getElementById(`${category}_${channel}`);
if (checkbox && !checkbox.disabled) {
checkbox.checked = false;
updatePreference(category, channel, false);
}
});
});
showToast('Success', 'Non-critical notifications disabled', 'success');
}
function disableAllCategories() {
const categories = ['appointments', 'lab_results', 'medications', 'billing', 'system', 'clinical', 'administrative'];
const channels = ['email', 'sms', 'push', 'in_app'];
categories.forEach(category => {
channels.forEach(channel => {
const checkbox = document.getElementById(`${category}_${channel}`);
if (checkbox && !checkbox.disabled) {
checkbox.checked = false;
updatePreference(category, channel, false);
}
});
});
}
function resetToDefaults() {
if (confirm('Reset all preferences to default settings?')) {
fetch('{% url "communications:reset_notification_preferences" %}', {
method: 'POST',
headers: {
'X-CSRFToken': getCsrfToken()
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
loadCurrentPreferences();
showToast('Success', 'Preferences reset to defaults', 'success');
} else {
showToast('Error', data.error || 'Failed to reset preferences', 'error');
}
})
.catch(error => {
console.error('Error resetting preferences:', error);
showToast('Error', 'Failed to reset preferences', 'error');
});
}
}
function customizeCategory(category) {
fetch(`{% url 'communications:category_customization' 'CATEGORY' %}`.replace('CATEGORY', category))
.then(response => response.text())
.then(html => {
document.getElementById('categoryCustomizationContent').innerHTML = html;
const modal = new bootstrap.Modal(document.getElementById('categoryCustomizationModal'));
modal.show();
})
.catch(error => {
console.error('Error loading category customization:', error);
showToast('Error', 'Failed to load customization options', 'error');
});
}
function saveCategoryCustomization() {
// Implementation would depend on the specific customization form
bootstrap.Modal.getInstance(document.getElementById('categoryCustomizationModal')).hide();
showToast('Success', 'Category customization saved', 'success');
}
function savePreferences() {
fetch('{% url "communications:save_notification_preferences" %}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCsrfToken()
},
body: JSON.stringify({
preferences: preferences
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('Success', 'Preferences saved successfully', 'success');
} else {
showToast('Error', data.error || 'Failed to save preferences', 'error');
}
})
.catch(error => {
console.error('Error saving preferences:', error);
showToast('Error', 'Failed to save preferences', 'error');
});
}
function getCsrfToken() {
return document.querySelector('[name=csrfmiddlewaretoken]').value;
}
function showToast(title, message, type) {
// Implementation depends on your toast system
console.log(`${type.toUpperCase()}: ${title} - ${message}`);
}
// Auto-update summary when checkboxes change
document.addEventListener('change', function(e) {
if (e.target.type === 'checkbox' && e.target.id.includes('_')) {
updateSummary();
}
});
// Update recent changes display every minute
setInterval(updateRecentChanges, 60000);
</script>
{% endblock %}