hospital-management/templates/core/notification_list.html
2025-08-12 13:33:25 +03:00

578 lines
36 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}System Notifications{% 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">System Notifications</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 active">System Notifications</li>
</ol>
</div>
</div>
</div>
</div>
<!-- Filters and Actions -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="d-flex flex-wrap gap-3">
<!-- Search Form -->
<div class="flex-grow-1">
<form method="get" class="d-flex gap-2">
<div class="input-group">
<span class="input-group-text"><i class="fas fa-search"></i></span>
<input type="text" class="form-control" name="search" placeholder="Search notifications..." value="{{ request.GET.search|default:'' }}">
</div>
<button type="submit" class="btn btn-primary">Search</button>
{% if request.GET.search or request.GET.status or request.GET.priority or request.GET.category %}
<a href="{% url 'core:system_notification_list' %}" class="btn btn-outline-secondary">Clear</a>
{% endif %}
</form>
</div>
<!-- Actions -->
<div class="d-flex gap-2">
<div class="btn-group">
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-filter me-1"></i>
Filter
</button>
<div class="dropdown-menu p-3" style="min-width: 250px;">
<form method="get">
<div class="mb-3">
<label class="form-label">Status</label>
<select name="status" class="form-select">
<option value="">All</option>
<option value="active" {% if request.GET.status == 'active' %}selected{% endif %}>Active</option>
<option value="inactive" {% if request.GET.status == 'inactive' %}selected{% endif %}>Inactive</option>
<option value="scheduled" {% if request.GET.status == 'scheduled' %}selected{% endif %}>Scheduled</option>
<option value="expired" {% if request.GET.status == 'expired' %}selected{% endif %}>Expired</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Priority</label>
<select name="priority" class="form-select">
<option value="">All</option>
<option value="LOW" {% if request.GET.priority == 'LOW' %}selected{% endif %}>Low</option>
<option value="MEDIUM" {% if request.GET.priority == 'MEDIUM' %}selected{% endif %}>Medium</option>
<option value="HIGH" {% if request.GET.priority == 'HIGH' %}selected{% endif %}>High</option>
<option value="CRITICAL" {% if request.GET.priority == 'CRITICAL' %}selected{% endif %}>Critical</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Category</label>
<select name="category" class="form-select">
<option value="">All</option>
{% for category in categories %}
<option value="{{ category }}" {% if request.GET.category == category %}selected{% endif %}>{{ category }}</option>
{% endfor %}
</select>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">Apply Filters</button>
</div>
</form>
</div>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-sort me-1"></i>
Sort
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="?{% if request.GET.search %}search={{ request.GET.search }}&{% endif %}sort=priority">Priority</a></li>
<li><a class="dropdown-item" href="?{% if request.GET.search %}search={{ request.GET.search }}&{% endif %}sort=start_date">Start Date</a></li>
<li><a class="dropdown-item" href="?{% if request.GET.search %}search={{ request.GET.search }}&{% endif %}sort=end_date">End Date</a></li>
<li><a class="dropdown-item" href="?{% if request.GET.search %}search={{ request.GET.search }}&{% endif %}sort=created_at">Created Date</a></li>
</ul>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-cog me-1"></i>
Actions
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="bulkActivate()">Activate Selected</a></li>
<li><a class="dropdown-item" href="#" onclick="bulkDeactivate()">Deactivate Selected</a></li>
<li><a class="dropdown-item" href="#" onclick="bulkDelete()">Delete Selected</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="exportNotifications()">Export Notifications</a></li>
</ul>
</div>
<a href="{% url 'core:system_notification_create' %}" class="btn btn-success">
<i class="fas fa-plus me-1"></i>
New Notification
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- View Toggle -->
<div class="row mb-3">
<div class="col-12">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="viewMode" id="tableView" autocomplete="off" checked>
<label class="btn btn-outline-primary" for="tableView">
<i class="fas fa-table me-1"></i>
Table View
</label>
<input type="radio" class="btn-check" name="viewMode" id="cardView" autocomplete="off">
<label class="btn btn-outline-primary" for="cardView">
<i class="fas fa-th-large me-1"></i>
Card View
</label>
</div>
</div>
</div>
<!-- Table View -->
<div class="row" id="tableViewContent">
<div class="col-12">
<div class="card">
<div class="card-body">
<form id="bulkActionForm" method="post" action="">
{% csrf_token %}
<input type="hidden" name="action" id="bulkAction" value="">
<div class="table-responsive">
<table class="table table-striped table-hover align-middle">
<thead>
<tr>
<th style="width: 30px;">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="selectAll">
</div>
</th>
<th>Title</th>
<th>Priority</th>
<th>Category</th>
<th>Status</th>
<th>Period</th>
<th style="width: 150px;">Actions</th>
</tr>
</thead>
<tbody>
{% for notification in notifications %}
<tr>
<td>
<div class="form-check">
<input class="form-check-input notification-checkbox" type="checkbox" name="selected_ids" value="{{ notification.pk }}">
</div>
</td>
<td>
<div class="d-flex align-items-center">
<div class="flex-shrink-0">
<div class="avatar-xs me-2">
<span class="avatar-title rounded-circle bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %} text-white">
<i class="fas fa-{% if notification.priority == 'LOW' %}info{% elif notification.priority == 'MEDIUM' %}exclamation{% elif notification.priority == 'HIGH' %}exclamation-triangle{% elif notification.priority == 'CRITICAL' %}radiation{% else %}bell{% endif %}"></i>
</span>
</div>
</div>
<div class="flex-grow-1">
<a href="{% url 'core:system_notification_detail' notification.pk %}" class="text-reset fw-medium">{{ notification.title }}</a>
<p class="text-muted mb-0 small">{{ notification.message|truncatechars:50 }}</p>
</div>
</div>
</td>
<td>
<span class="badge bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %}">
{{ notification.get_priority_display }}
</span>
</td>
<td>{{ notification.category }}</td>
<td>
{% if notification.is_active %}
{% if notification.start_date <= now and notification.end_date >= now %}
<span class="badge bg-success">Active</span>
{% elif notification.start_date > now %}
<span class="badge bg-info">Scheduled</span>
{% elif notification.end_date < now %}
<span class="badge bg-secondary">Expired</span>
{% endif %}
{% else %}
<span class="badge bg-danger">Inactive</span>
{% endif %}
</td>
<td>
<small class="d-block">From: {{ notification.start_date|date:"M d, Y" }}</small>
<small class="d-block">To: {{ notification.end_date|date:"M d, Y" }}</small>
</td>
<td>
<div class="dropdown">
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
Actions
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="{% url 'core:system_notification_detail' notification.pk %}">
<i class="fas fa-eye me-2"></i>View
</a></li>
<li><a class="dropdown-item" href="{% url 'core:system_notification_update' notification.pk %}">
<i class="fas fa-edit me-2"></i>Edit
</a></li>
<li><a class="dropdown-item" href="{% url 'core:system_notification_delete' notification.pk %}">
<i class="fas fa-trash me-2"></i>Delete
</a></li>
<li><hr class="dropdown-divider"></li>
{% if notification.is_active %}
<li><a class="dropdown-item" href="{% url 'core:deactivate_notification' notification.pk %}">
<i class="fas fa-power-off me-2"></i>Deactivate
</a></li>
{% else %}
<li><a class="dropdown-item" href="{% url 'core:activate_notification' notification.pk %}">
<i class="fas fa-power-off me-2"></i>Activate
</a></li>
{% endif %}
</ul>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="7" class="text-center py-4">
<div class="d-flex flex-column align-items-center">
<i class="fas fa-bell-slash fa-3x text-muted mb-3"></i>
<h5>No notifications found</h5>
<p class="text-muted">No system notifications match your criteria.</p>
<a href="{% url 'core:system_notification_create' %}" class="btn btn-primary mt-2">
<i class="fas fa-plus me-1"></i>
Create New Notification
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
<!-- Pagination -->
{% if is_paginated %}
<div class="d-flex justify-content-between align-items-center mt-3">
<div>
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ paginator.count }} notifications
</div>
<nav>
<ul class="pagination mb-0">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-double-left"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-left"></i>
</a>
</li>
{% endif %}
{% for num in paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-right"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ paginator.num_pages }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-double-right"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Card View -->
<div class="row" id="cardViewContent" style="display: none;">
{% for notification in notifications %}
<div class="col-md-6 col-lg-4 col-xl-3">
<div class="card">
<div class="card-header bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %} bg-opacity-25">
<div class="d-flex align-items-center">
<div class="flex-shrink-0">
<div class="avatar-sm me-2">
<span class="avatar-title rounded-circle bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %} text-white">
<i class="fas fa-{% if notification.priority == 'LOW' %}info{% elif notification.priority == 'MEDIUM' %}exclamation{% elif notification.priority == 'HIGH' %}exclamation-triangle{% elif notification.priority == 'CRITICAL' %}radiation{% else %}bell{% endif %}"></i>
</span>
</div>
</div>
<div class="flex-grow-1">
<h5 class="card-title mb-0">{{ notification.title|truncatechars:30 }}</h5>
<small class="text-muted">{{ notification.category }}</small>
</div>
</div>
</div>
<div class="card-body">
<p class="card-text">{{ notification.message|truncatechars:100 }}</p>
<div class="d-flex justify-content-between align-items-center mb-3">
<span class="badge bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %}">
{{ notification.get_priority_display }}
</span>
{% if notification.is_active %}
{% if notification.start_date <= now and notification.end_date >= now %}
<span class="badge bg-success">Active</span>
{% elif notification.start_date > now %}
<span class="badge bg-info">Scheduled</span>
{% elif notification.end_date < now %}
<span class="badge bg-secondary">Expired</span>
{% endif %}
{% else %}
<span class="badge bg-danger">Inactive</span>
{% endif %}
</div>
<div class="small text-muted mb-3">
<div><i class="fas fa-calendar-alt me-1"></i> From: {{ notification.start_date|date:"M d, Y" }}</div>
<div><i class="fas fa-calendar-check me-1"></i> To: {{ notification.end_date|date:"M d, Y" }}</div>
</div>
<div class="d-grid gap-2">
<a href="{% url 'core:system_notification_detail' notification.pk %}" class="btn btn-sm btn-outline-primary">
<i class="fas fa-eye me-1"></i>
View Details
</a>
<div class="btn-group" role="group">
<a href="{% url 'core:system_notification_update' notification.pk %}" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-edit"></i>
</a>
{% if notification.is_active %}
<a href="{% url 'core:deactivate_notification' notification.pk %}" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-power-off"></i>
</a>
{% else %}
<a href="{% url 'core:activate_notification' notification.pk %}" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-power-off"></i>
</a>
{% endif %}
<a href="{% url 'core:system_notification_delete' notification.pk %}" class="btn btn-sm btn-outline-danger">
<i class="fas fa-trash"></i>
</a>
</div>
</div>
</div>
<div class="card-footer text-muted">
<small>Created: {{ notification.created_at|date:"M d, Y" }}</small>
</div>
</div>
</div>
{% empty %}
<div class="col-12">
<div class="card">
<div class="card-body text-center py-5">
<i class="fas fa-bell-slash fa-3x text-muted mb-3"></i>
<h5>No notifications found</h5>
<p class="text-muted">No system notifications match your criteria.</p>
<a href="{% url 'core:system_notification_create' %}" class="btn btn-primary mt-2">
<i class="fas fa-plus me-1"></i>
Create New Notification
</a>
</div>
</div>
</div>
{% endfor %}
<!-- Pagination for Card View -->
{% if is_paginated %}
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ paginator.count }} notifications
</div>
<nav>
<ul class="pagination mb-0">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-double-left"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-left"></i>
</a>
</li>
{% endif %}
{% for num in paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-right"></i>
</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ paginator.num_pages }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.priority %}&priority={{ request.GET.priority }}{% endif %}{% if request.GET.category %}&category={{ request.GET.category }}{% endif %}{% if request.GET.sort %}&sort={{ request.GET.sort }}{% endif %}">
<i class="fas fa-angle-double-right"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
</div>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock %}
{% block js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// View toggle
const tableView = document.getElementById('tableView');
const cardView = document.getElementById('cardView');
const tableViewContent = document.getElementById('tableViewContent');
const cardViewContent = document.getElementById('cardViewContent');
tableView.addEventListener('change', function() {
if (this.checked) {
tableViewContent.style.display = 'flex';
cardViewContent.style.display = 'none';
localStorage.setItem('notificationViewMode', 'table');
}
});
cardView.addEventListener('change', function() {
if (this.checked) {
tableViewContent.style.display = 'none';
cardViewContent.style.display = 'flex';
localStorage.setItem('notificationViewMode', 'card');
}
});
// Load saved view preference
const savedViewMode = localStorage.getItem('notificationViewMode');
if (savedViewMode === 'card') {
cardView.checked = true;
tableViewContent.style.display = 'none';
cardViewContent.style.display = 'flex';
} else {
tableView.checked = true;
}
// Select all checkboxes
const selectAll = document.getElementById('selectAll');
const checkboxes = document.querySelectorAll('.notification-checkbox');
selectAll.addEventListener('change', function() {
checkboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
});
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
const allChecked = Array.from(checkboxes).every(c => c.checked);
const anyChecked = Array.from(checkboxes).some(c => c.checked);
selectAll.checked = allChecked;
selectAll.indeterminate = anyChecked && !allChecked;
});
});
});
function bulkActivate() {
if (confirmBulkAction('activate')) {
document.getElementById('bulkAction').value = 'activate';
document.getElementById('bulkActionForm').submit();
}
}
function bulkDeactivate() {
if (confirmBulkAction('deactivate')) {
document.getElementById('bulkAction').value = 'deactivate';
document.getElementById('bulkActionForm').submit();
}
}
function bulkDelete() {
if (confirmBulkAction('delete')) {
document.getElementById('bulkAction').value = 'delete';
document.getElementById('bulkActionForm').submit();
}
}
function confirmBulkAction(action) {
const checkboxes = document.querySelectorAll('.notification-checkbox:checked');
if (checkboxes.length === 0) {
alert('Please select at least one notification.');
return false;
}
let message = '';
switch (action) {
case 'activate':
message = `Are you sure you want to activate ${checkboxes.length} notification(s)?`;
break;
case 'deactivate':
message = `Are you sure you want to deactivate ${checkboxes.length} notification(s)?`;
break;
case 'delete':
message = `Are you sure you want to delete ${checkboxes.length} notification(s)? This action cannot be undone.`;
break;
}
return confirm(message);
}
{#function exportNotifications() {#}
{# window.open('{% url "core:export_notifications" %}', '_blank');#}
{# }#}
</script>
{% endblock %}