update
This commit is contained in:
parent
610e165e17
commit
09932ffe8a
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from accounts.models import User
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
from patients.models import PatientProfile
|
||||
|
||||
@ -8,7 +8,7 @@ urlpatterns = [
|
||||
path('', views.dashboard, name='dashboard'),
|
||||
|
||||
# Donor Management
|
||||
path('donors/', views.donor_list, name='donor_list'),
|
||||
path('donors/', views.DonorListView.as_view(), name='donor_list'),
|
||||
path('donors/<int:donor_id>/', views.donor_detail, name='donor_detail'),
|
||||
path('donors/create/', views.donor_create, name='donor_create'),
|
||||
path('donors/<int:donor_id>/update/', views.donor_update, name='donor_update'),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.contrib import messages
|
||||
@ -10,6 +11,8 @@ from django.contrib.auth.models import User
|
||||
from datetime import timedelta
|
||||
import json
|
||||
|
||||
from django.views.generic import ListView
|
||||
|
||||
from .models import (
|
||||
BloodGroup, Donor, BloodComponent, BloodUnit, BloodTest, CrossMatch,
|
||||
BloodRequest, BloodIssue, Transfusion, AdverseReaction, InventoryLocation,
|
||||
@ -61,45 +64,50 @@ def dashboard(request):
|
||||
|
||||
|
||||
# Donor Management Views
|
||||
@login_required
|
||||
def donor_list(request):
|
||||
"""List all donors with filtering and search"""
|
||||
donors = Donor.objects.select_related('blood_group').order_by('-registration_date')
|
||||
class DonorListView(LoginRequiredMixin, ListView):
|
||||
model = Donor
|
||||
template_name = 'blood_bank/donors/donor_list.html'
|
||||
context_object_name = 'page_obj'
|
||||
paginate_by = 25
|
||||
|
||||
# Search functionality
|
||||
search_query = request.GET.get('search')
|
||||
if search_query:
|
||||
donors = donors.filter(
|
||||
Q(donor_id__icontains=search_query) |
|
||||
Q(first_name__icontains=search_query) |
|
||||
Q(last_name__icontains=search_query) |
|
||||
Q(phone__icontains=search_query)
|
||||
)
|
||||
def get_queryset(self):
|
||||
queryset = Donor.objects.select_related('blood_group').order_by('-registration_date')
|
||||
|
||||
# Filter by status
|
||||
status_filter = request.GET.get('status')
|
||||
if status_filter:
|
||||
donors = donors.filter(status=status_filter)
|
||||
# Search functionality
|
||||
search_query = self.request.GET.get('search')
|
||||
if search_query:
|
||||
queryset = queryset.filter(
|
||||
Q(donor_id__icontains=search_query) |
|
||||
Q(first_name__icontains=search_query) |
|
||||
Q(last_name__icontains=search_query) |
|
||||
Q(phone__icontains=search_query)
|
||||
)
|
||||
|
||||
# Filter by blood group
|
||||
blood_group_filter = request.GET.get('blood_group')
|
||||
if blood_group_filter:
|
||||
donors = donors.filter(blood_group_id=blood_group_filter)
|
||||
# Filter by status
|
||||
status_filter = self.request.GET.get('status')
|
||||
if status_filter:
|
||||
queryset = queryset.filter(status=status_filter)
|
||||
|
||||
paginator = Paginator(donors, 25)
|
||||
page_number = request.GET.get('page')
|
||||
page_obj = paginator.get_page(page_number)
|
||||
# Filter by blood group
|
||||
blood_group_filter = self.request.GET.get('blood_group')
|
||||
if blood_group_filter:
|
||||
queryset = queryset.filter(blood_group_id=blood_group_filter)
|
||||
|
||||
context = {
|
||||
'page_obj': page_obj,
|
||||
'blood_groups': BloodGroup.objects.all(),
|
||||
'status_choices': Donor.STATUS_CHOICES,
|
||||
'search_query': search_query,
|
||||
'status_filter': status_filter,
|
||||
'blood_group_filter': blood_group_filter,
|
||||
}
|
||||
return queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context.update({
|
||||
'blood_groups': BloodGroup.objects.all(),
|
||||
'status_choices': Donor.STATUS_CHOICES,
|
||||
'search_query': self.request.GET.get('search'),
|
||||
'status_filter': self.request.GET.get('status'),
|
||||
'blood_group_filter': self.request.GET.get('blood_group'),
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
return render(request, 'blood_bank/donors/donor_list.html', context)
|
||||
|
||||
|
||||
@login_required
|
||||
@ -553,7 +561,7 @@ def inventory_overview(request):
|
||||
'locations': locations,
|
||||
}
|
||||
|
||||
return render(request, 'blood_bank/inventory/inventory_overview.html', context)
|
||||
return render(request, 'blood_bank/inventory/inventory_dashboard.html', context)
|
||||
|
||||
|
||||
# Quality Control Views
|
||||
|
||||
Binary file not shown.
@ -28,10 +28,6 @@ from .forms import (
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# DASHBOARD AND OVERVIEW VIEWS
|
||||
# ============================================================================
|
||||
|
||||
class InventoryDashboardView(LoginRequiredMixin, TemplateView):
|
||||
"""
|
||||
Main inventory dashboard with comprehensive statistics and recent activity.
|
||||
@ -52,11 +48,11 @@ class InventoryDashboardView(LoginRequiredMixin, TemplateView):
|
||||
).count()
|
||||
|
||||
# Stock statistics
|
||||
# low_stock_items = InventoryStock.objects.filter(
|
||||
# tenant=user.tenant,
|
||||
# quantity_available__lte=F('min_stock_level')
|
||||
# ).count()
|
||||
# context['low_stock_items'] = low_stock_items
|
||||
low_stock_items = InventoryStock.objects.filter(
|
||||
inventory_item__tenant=user.tenant,
|
||||
quantity_available__lte=F('inventory_item__min_stock_level')
|
||||
).count()
|
||||
context['low_stock_items'] = low_stock_items
|
||||
|
||||
expired_items = InventoryStock.objects.filter(
|
||||
inventory_item__tenant=user.tenant,
|
||||
@ -84,22 +80,18 @@ class InventoryDashboardView(LoginRequiredMixin, TemplateView):
|
||||
tenant=user.tenant
|
||||
).order_by('-created_at')[:10]
|
||||
|
||||
# context['low_stock_alerts'] = InventoryStock.objects.filter(
|
||||
# inventory_item__tenant=user.tenant,
|
||||
# quantity__lte=F('minimum_stock_level')
|
||||
# ).select_related('item', 'location').order_by('quantity')[:10]
|
||||
context['low_stock_alerts'] = InventoryStock.objects.filter(
|
||||
inventory_item__tenant=user.tenant,
|
||||
quantity_available__lte=F('inventory_item__min_stock_level')
|
||||
).select_related('inventory_item', 'location').order_by('quantity_available')[:10]
|
||||
|
||||
# context['recent_stock_movements'] = InventoryStock.objects.filter(
|
||||
# tenant=user.tenant
|
||||
# ).order_by('-updated_at')[:10]
|
||||
context['recent_stock_movements'] = InventoryStock.objects.filter(
|
||||
inventory_item__tenant=user.tenant
|
||||
).order_by('-updated_at')[:10]
|
||||
|
||||
return context
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# SUPPLIER VIEWS (FULL CRUD - Master Data)
|
||||
# ============================================================================
|
||||
|
||||
class SupplierListView(LoginRequiredMixin, ListView):
|
||||
"""
|
||||
List all suppliers with search and filtering capabilities.
|
||||
@ -286,10 +278,6 @@ class SupplierDeleteView(LoginRequiredMixin, DeleteView):
|
||||
return redirect(self.success_url)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# INVENTORY LOCATION VIEWS (FULL CRUD - Master Data)
|
||||
# ============================================================================
|
||||
|
||||
class InventoryLocationListView(LoginRequiredMixin, ListView):
|
||||
"""
|
||||
List all inventory locations.
|
||||
@ -442,10 +430,6 @@ class InventoryLocationDeleteView(LoginRequiredMixin, DeleteView):
|
||||
return response
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# INVENTORY ITEM VIEWS (FULL CRUD - Master Data)
|
||||
# ============================================================================
|
||||
|
||||
class InventoryItemListView(LoginRequiredMixin, ListView):
|
||||
"""
|
||||
List all inventory items with search and filtering.
|
||||
@ -609,10 +593,6 @@ class InventoryItemDeleteView(LoginRequiredMixin, DeleteView):
|
||||
return redirect(self.success_url)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# INVENTORY STOCK VIEWS (LIMITED CRUD - Operational Data)
|
||||
# ============================================================================
|
||||
|
||||
class InventoryStockListView(LoginRequiredMixin, ListView):
|
||||
"""
|
||||
List all inventory stock with filtering and search.
|
||||
@ -736,10 +716,6 @@ class InventoryStockUpdateView(LoginRequiredMixin, UpdateView):
|
||||
return response
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# PURCHASE ORDER VIEWS (RESTRICTED CRUD - Operational Data)
|
||||
# ============================================================================
|
||||
|
||||
class PurchaseOrderListView(LoginRequiredMixin, ListView):
|
||||
"""
|
||||
List all purchase orders with filtering.
|
||||
@ -872,10 +848,6 @@ class PurchaseOrderUpdateView(LoginRequiredMixin, UpdateView):
|
||||
return response
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# HTMX AND AJAX VIEWS
|
||||
# ============================================================================
|
||||
|
||||
@login_required
|
||||
def inventory_stats(request):
|
||||
"""
|
||||
@ -898,6 +870,10 @@ def inventory_stats(request):
|
||||
tenant=user.tenant,
|
||||
status__in=['PENDING', 'APPROVED', 'ORDERED']
|
||||
).count(),
|
||||
'recent_stock_movements': InventoryStock.objects.filter(
|
||||
inventory_item__tenant=user.tenant,
|
||||
movement_date__gte=timezone.now().date() - timedelta(days=30)
|
||||
)
|
||||
}
|
||||
|
||||
return render(request, 'inventory/partials/inventory_stats.html', stats)
|
||||
@ -919,10 +895,6 @@ def stock_search(request):
|
||||
})
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# ACTION VIEWS FOR WORKFLOW OPERATIONS
|
||||
# ============================================================================
|
||||
|
||||
@login_required
|
||||
def adjust_stock(request, stock_id):
|
||||
"""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
templates/.DS_Store
vendored
BIN
templates/.DS_Store
vendored
Binary file not shown.
@ -108,39 +108,7 @@
|
||||
|
||||
<!-- Pagination -->
|
||||
{% if is_paginated %}
|
||||
<nav aria-label="Appointment pagination">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% 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 %}">First</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 %}">Previous</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for num in page_obj.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 %}">{{ 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 %}">Next</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}">Last</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% include 'partial/pagination.html' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -94,14 +94,12 @@
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<!-- Check In Button -->
|
||||
{% if appointment.status == 'SCHEDULED' or appointment.status == 'CONFIRMED' %}
|
||||
<button type="button"
|
||||
<a type="button"
|
||||
class="btn btn-outline-success"
|
||||
title="Check In Patient"
|
||||
hx-post="{% url 'appointments:check_in_patient' appointment.id %}"
|
||||
hx-target="#appointment-list"
|
||||
hx-swap="outerHTML">
|
||||
href="{% url 'appointments:check_in_patient' appointment.id %}">
|
||||
<i class="fas fa-check"></i>
|
||||
</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<!-- Telemedicine Join Button -->
|
||||
|
||||
@ -27,11 +27,12 @@
|
||||
</head>
|
||||
<body>
|
||||
<!-- Your page content -->
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js"></script>
|
||||
</body>
|
||||
<script src="{% static 'plugins/apexcharts/dist/apexcharts.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/chart.js/dist/chart.js' %}"></script>
|
||||
{# <script src="{% static 'plugins/apexcharts/dist/apexcharts.min.js' %}"></script>#}
|
||||
<!-- HTMX -->
|
||||
<script src="{% static 'js/htmx.min.js' %}"></script>
|
||||
<!-- ================== END core-css ================== -->
|
||||
|
||||
BIN
templates/blood_bank/.DS_Store
vendored
BIN
templates/blood_bank/.DS_Store
vendored
Binary file not shown.
@ -3,9 +3,9 @@
|
||||
|
||||
{% block title %}Blood Bank Dashboard{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
{% block css %}
|
||||
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -346,11 +346,11 @@
|
||||
<!-- END row -->
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
{% block js %}
|
||||
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
|
||||
{% block title %}Donor Management{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
{% block css %}
|
||||
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -182,68 +182,24 @@
|
||||
<!-- END table -->
|
||||
|
||||
<!-- BEGIN pagination -->
|
||||
{% if page_obj.has_other_pages %}
|
||||
<nav aria-label="Donor pagination">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
|
||||
<i class="fa fa-angle-double-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for num in page_obj.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 search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% 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 search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if search_query %}&search={{ search_query }}{% endif %}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if blood_group_filter %}&blood_group={{ blood_group_filter }}{% endif %}">
|
||||
<i class="fa fa-angle-double-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% if is_paginated %}
|
||||
{% include 'partial/pagination.html' %}
|
||||
{% endif %}
|
||||
<!-- END pagination -->
|
||||
|
||||
<!-- BEGIN summary -->
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-6">
|
||||
<p class="text-muted">
|
||||
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} donors
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-end">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="window.print()">
|
||||
<i class="fa fa-print"></i> Print
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportToCSV()">
|
||||
<i class="fa fa-download"></i> Export
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# <div class="col-md-6 text-end">#}
|
||||
{# <div class="btn-group" role="group">#}
|
||||
{# <button type="button" class="btn btn-outline-secondary btn-sm" onclick="window.print()">#}
|
||||
{# <i class="fa fa-print"></i> Print#}
|
||||
{# </button>#}
|
||||
{# <button type="button" class="btn btn-outline-secondary btn-sm" onclick="exportToCSV()">#}
|
||||
{# <i class="fa fa-download"></i> Export#}
|
||||
{# </button>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
</div>
|
||||
<!-- END summary -->
|
||||
</div>
|
||||
@ -251,18 +207,18 @@
|
||||
<!-- END panel -->
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
{% block js %}
|
||||
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize DataTable for enhanced functionality
|
||||
$('#donorTable').DataTable({
|
||||
responsive: true,
|
||||
pageLength: 25,
|
||||
{#pageLength: 25,#}
|
||||
order: [[0, 'desc']],
|
||||
columnDefs: [
|
||||
{ orderable: false, targets: [9] } // Actions column
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
|
||||
{% block title %}Blood Bank Inventory Dashboard{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link href="{% static 'assets/plugins/chart.js/dist/Chart.min.css' %}" rel="stylesheet" />
|
||||
{% block css %}
|
||||
<link href="{% static 'plugins/chart.js/dist/Chart.min.css' %}" rel="stylesheet" />
|
||||
<style>
|
||||
.inventory-card {
|
||||
border-radius: 10px;
|
||||
@ -368,7 +368,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="{% static 'assets/plugins/chart.js/dist/Chart.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/chart.js/dist/chart.js' %}"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
{% block title %}Blood Unit Management{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -250,62 +250,20 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END table -->
|
||||
|
||||
<!-- BEGIN pagination -->
|
||||
{% if page_obj.has_other_pages %}
|
||||
<nav aria-label="Blood unit pagination">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1">
|
||||
<i class="fa fa-angle-double-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for num in page_obj.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 }}">{{ 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 }}">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">
|
||||
<i class="fa fa-angle-double-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% if is_paginated %}
|
||||
{% include 'partial/pagination.html' %}
|
||||
{% endif %}
|
||||
<!-- END pagination -->
|
||||
|
||||
<!-- BEGIN summary -->
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-6">
|
||||
<p class="text-muted">
|
||||
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} blood units
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 text-end">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="window.print()">
|
||||
|
||||
@ -335,7 +335,7 @@
|
||||
|
||||
{% block js %}
|
||||
<!-- DataTables JS -->
|
||||
<script src="{% static 'plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
|
||||
@ -45,141 +45,58 @@
|
||||
</div>
|
||||
|
||||
<!-- Key Performance Indicators -->
|
||||
<div class="row mb-4" hx-get="{% url 'inventory:inventory_stats' %}" hx-trigger="load, every 30s">
|
||||
<div class="row mb-4" hx-get="{% url 'inventory:inventory_stats' %}">
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card stat-card bg-success text-white">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Total Items</h6>
|
||||
<h3 class="mb-0 text-primary">{{ total_items }}</h3>
|
||||
<small class="text-muted">{{ active_items }} active</small>
|
||||
</div>
|
||||
<div class="bg-primary bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-boxes fa-lg text-white"></i>
|
||||
<h4 class="card-title">{{ total_items }}</h4>
|
||||
<p class="card-text">Total Items</p>
|
||||
</div>
|
||||
<i class="fas fa-boxes fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card stat-card bg-warning">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Locations</h6>
|
||||
<h3 class="mb-0 text-success">{{ total_locations }}</h3>
|
||||
<small class="text-muted">Storage areas</small>
|
||||
</div>
|
||||
<div class="bg-success bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-map-marker-alt fa-lg text-white"></i>
|
||||
<h4 class="card-title">{{ total_locations }}</h4>
|
||||
<p class="card-text">Locations</p>
|
||||
</div>
|
||||
<i class="fas fa-map-marker-alt fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card stat-card bg-primary text-white">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Suppliers</h6>
|
||||
<h3 class="mb-0 text-info">{{ total_suppliers }}</h3>
|
||||
<small class="text-muted">Active partners</small>
|
||||
</div>
|
||||
<div class="bg-info bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-truck fa-lg text-white"></i>
|
||||
<h4 class="card-title">{{ total_suppliers }}</h4>
|
||||
<p class="card-text">Suppliers</p>
|
||||
</div>
|
||||
<i class="fas fa-truck fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card stat-card bg-danger text-white">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Total Value</h6>
|
||||
<h3 class="mb-0 text-warning">${{ total_inventory_value|floatformat:0 }}</h3>
|
||||
<small class="text-muted">Inventory worth</small>
|
||||
</div>
|
||||
<div class="bg-warning bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-dollar-sign fa-lg text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alert Cards -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100 {% if low_stock_items > 0 %}border-warning{% endif %}">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Low Stock</h6>
|
||||
<h3 class="mb-0 {% if low_stock_items > 0 %}text-warning{% else %}text-success{% endif %}">{{ low_stock_items }}</h3>
|
||||
<small class="text-muted">Items below minimum</small>
|
||||
</div>
|
||||
<div class="bg-{% if low_stock_items > 0 %}warning{% else %}success{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-exclamation-triangle fa-lg text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100 {% if expired_items > 0 %}border-danger{% endif %}">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Expired</h6>
|
||||
<h3 class="mb-0 {% if expired_items > 0 %}text-danger{% else %}text-success{% endif %}">{{ expired_items }}</h3>
|
||||
<small class="text-muted">Past expiry date</small>
|
||||
</div>
|
||||
<div class="bg-{% if expired_items > 0 %}danger{% else %}success{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-calendar-times fa-lg text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100 {% if expiring_soon_items > 0 %}border-warning{% endif %}">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Expiring Soon</h6>
|
||||
<h3 class="mb-0 {% if expiring_soon_items > 0 %}text-warning{% else %}text-success{% endif %}">{{ expiring_soon_items }}</h3>
|
||||
<small class="text-muted">Within 30 days</small>
|
||||
</div>
|
||||
<div class="bg-{% if expiring_soon_items > 0 %}warning{% else %}success{% endif %} bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-clock fa-lg text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6 mb-3">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="card-title text-muted mb-1">Active Orders</h6>
|
||||
<h3 class="mb-0 text-primary">{{ active_orders }}</h3>
|
||||
<small class="text-muted">In progress</small>
|
||||
</div>
|
||||
<div class="bg-primary bg-gradient rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-shopping-cart fa-lg text-white"></i>
|
||||
<h4 class="card-title"><span class="symbol">ê</span>{{ total_inventory_value|floatformat:'2g' }}</h4>
|
||||
<p class="card-text">Total Value</p>
|
||||
</div>
|
||||
<i class="fas fa-dollar-sign fa-2x opacity-75"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -195,9 +112,9 @@
|
||||
<div class="panel-heading-btn">
|
||||
<a href="{% url 'inventory:purchase_order_list' %}" class="btn btn-outline-primary btn-xs"><i class="fas fa-list me-1"></i>View All</a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@ -216,20 +133,20 @@
|
||||
<tbody>
|
||||
{% for order in recent_orders %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'inventory:purchase_order_detail' order.pk %}"
|
||||
<td class="fs-12px">
|
||||
<a href="{% url 'inventory:purchase_order_detail' order.pk %}"
|
||||
class="text-decoration-none fw-semibold">
|
||||
{{ order.order_number }}
|
||||
{{ order.po_number }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ order.supplier.name|truncatechars:20 }}</td>
|
||||
<td>
|
||||
<td class="fs-12px">{{ order.supplier.name }}</td>
|
||||
<td class="fs-12px">
|
||||
<span class="badge bg-{% if order.status == 'RECEIVED' %}success{% elif order.status == 'APPROVED' %}info{% elif order.status == 'ORDERED' %}warning{% else %}secondary{% endif %}">
|
||||
{{ order.get_status_display }}
|
||||
</span>
|
||||
</td>
|
||||
<td><span class="symbol">ê</span>{{ order.total_amount|floatformat:'2g' }}</td>
|
||||
<td>{{ order.order_date|date:" Y M d" }}</td>
|
||||
<td class="fs-12px"><span class="symbol">ê</span>{{ order.total_amount|floatformat:'2g' }}</td>
|
||||
<td class="fs-12px">{{ order.order_date|date:" Y M d" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@ -257,9 +174,9 @@
|
||||
<div class="panel-heading-btn">
|
||||
<a href="{% url 'inventory:stock_list' %}?stock_status=low" class="btn btn-outline-warning btn-xs"><i class="fas fa-list me-1"></i>View All</a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@ -308,7 +225,7 @@
|
||||
<div class="panel-body">
|
||||
{% if recent_stock_movements %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<table class="table table-sm table-hover mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Item</th>
|
||||
@ -320,19 +237,19 @@
|
||||
<tbody>
|
||||
{% for stock in recent_stock_movements %}
|
||||
<tr>
|
||||
<td>
|
||||
<td class="fs-12px">
|
||||
<a href="{% url 'inventory:stock_detail' stock.pk %}"
|
||||
class="text-decoration-none">
|
||||
{{ stock.item.item_name|truncatechars:25 }}
|
||||
{{ stock.inventory_item.item_name }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ stock.location.location_name|truncatechars:15 }}</td>
|
||||
<td>
|
||||
<span class="{% if stock.quantity <= stock.minimum_stock_level %}text-warning{% else %}text-success{% endif %} fw-semibold">
|
||||
{{ stock.quantity }}
|
||||
<td class="fs-12px">{{ stock.location.name }}</td>
|
||||
<td class="fs-12px">
|
||||
<span class="{% if stock.quantity_available <= stock.inventory_item.min_stock_level %}text-warning{% else %}text-success{% endif %} fw-semibold">
|
||||
{{ stock.quantity_available }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ stock.updated_at|date:"M d, H:i" }}</td>
|
||||
<td class="fs-12px">{{ stock.updated_at|date:"M d, H:i" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@ -415,9 +332,9 @@
|
||||
</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@ -434,9 +351,9 @@
|
||||
</h4>
|
||||
<div class="panel-heading-btn">
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
|
||||
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>#}
|
||||
{# <a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>#}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@ -446,6 +363,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{% static 'plugins/chart.js/dist/chart.umd.js' %}"></script>
|
||||
<script>
|
||||
// Dashboard functionality
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
@ -453,7 +371,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
initializeCharts();
|
||||
|
||||
// Auto-refresh dashboard every 5 minutes
|
||||
setInterval(refreshDashboard, 300000);
|
||||
{#setInterval(refreshDashboard, 300000);#}
|
||||
});
|
||||
|
||||
function refreshDashboard() {
|
||||
@ -472,7 +390,7 @@ function refreshDashboard() {
|
||||
setTimeout(() => {
|
||||
refreshBtn.innerHTML = originalText;
|
||||
refreshBtn.disabled = false;
|
||||
}, 2000);
|
||||
}, 300000);
|
||||
}
|
||||
|
||||
function initializeCharts() {
|
||||
@ -486,7 +404,7 @@ function initializeCharts() {
|
||||
datasets: [{
|
||||
data: [16, 12, 14, 10, 18, 20, 4],
|
||||
backgroundColor: [
|
||||
'#0d6efd', '#198754', '#ffc107', '#dc3545',
|
||||
'#0d6efd', '#198754', '#ffc107', '#dc3545',
|
||||
'#6f42c1', '#fd7e14', '#20c997', '#6c757d'
|
||||
]
|
||||
}]
|
||||
@ -502,7 +420,7 @@ function initializeCharts() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Stock Status Chart
|
||||
const stockCtx = document.getElementById('stockStatusChart');
|
||||
if (stockCtx) {
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
|
||||
{% block title %}Insurance Claims Management{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
{% block css %}
|
||||
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
<style>
|
||||
.stats-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
@ -432,12 +432,12 @@
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script>
|
||||
{% block js %}
|
||||
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
{% block title %}Emergency Contacts - Patient Management{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -292,11 +292,11 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var table;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user