nhance/app/Views/layout/footer.php

1902 lines
80 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

</div> <!-- container -->
</div> <!-- content -->
<?php include(__DIR__ . '/../ticket_type_modal.php'); ?>
</div>
<!-- ============================================================== -->
<!-- End Page content -->
<!-- ============================================================== -->
<!-- Footer Start -->
<div style="background-color: white !important;" >
<footer class="footer" style="background-color: white !important;">
<div class="">
<div class="row">
<div class="">
<script>
document.write(new Date().getFullYear())
</script> &copy; NHANCE
</div>
<!-- <div class="col-md-6">
<div class="text-md-right footer-links d-none d-sm-block">
<a href="javascript:void(0);">About Us</a>
<a href="javascript:void(0);">Help</a>
<a href="javascript:void(0);">Contact Us</a>
</div>
</div> -->
</div>
</div>
</footer>
</div>
<!-- end Footer -->
</div>
<!-- END wrapper -->
<!-- Right Sidebar -->
<div class="right-bar">
<div class="h-100">
<!-- Notifications Header -->
<h6 class="font-weight-medium px-3 m-0 py-2 font-13 text-uppercase bg-light fixed-header">
<i class="mdi mdi-message-text-outline font-22"></i>
<span class="header-title">Notification</span>
</h6>
<div class="scrollable-content">
<ul class="list-unstyled" id="messages-list">
<!-- Notifications list items go here -->
</ul>
</div>
<!-- Pending Action Header -->
<h6 class="font-weight-medium px-3 m-0 py-2 font-13 bg-light fixed-header">
<i class="mdi mdi-format-list-checks font-22"></i>
<span class="header-title">TO DOs</span>
</h6>
<div class="scrollable-content">
<ul class="list-unstyled" id="messages-list-2">
<!-- Pending action list items go here -->
</ul>
</div>
</div> <!-- end simplebar -->
</div>
<!-- /Right-bar -->
<!-- Right bar overlay-->
<div class="rightbar-overlay"></div>
<!-- Vendor js -->
<script src="<?= base_url() . "public"; ?>/assets/js/vendor.min.js"></script>
<!-- KNOB JS -->
<script src="<?= base_url() . "public"; ?>/assets/libs/jquery-knob/jquery.knob.min.js"></script>
<!-- Apex js-->
<script src="<?= base_url() . "public"; ?>/assets/libs/apexcharts/apexcharts.min.js"></script>
<!-- third party js -->
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-bs4/js/dataTables.bootstrap4.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-responsive/js/dataTables.responsive.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-buttons/js/dataTables.buttons.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-buttons-bs4/js/buttons.bootstrap4.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-buttons/js/buttons.html5.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-buttons/js/buttons.flash.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-buttons/js/buttons.print.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-keytable/js/dataTables.keyTable.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/datatables.net-select/js/dataTables.select.min.js"></script>
<!-- <script src="<?= base_url() . "public"; ?>/assets/libs/pdfmake/build/pdfmake.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/pdfmake/build/vfs_fonts.js"></script> -->
<!-- third party js ends -->
<script>
(function () {
if (typeof jQuery === 'undefined' || !jQuery.fn || !jQuery.fn.dataTable) {
return;
}
var $ = jQuery;
// Global defaults for all list pages unless overridden in a specific view.
// scrollY + scrollCollapse split thead/tbody and misalign columns vs headers (see batch_list).
// Wide tables: rely on .table-responsive; set scrollX: true on a page only if required.
$.extend(true, $.fn.dataTable.defaults, {
scrollX: false,
scrollY: false,
scrollCollapse: false,
bScrollCollapse: false,
/* Hungarian names — copied into oScroll before the wrapper is built (preInit.dt is too late). */
sScrollX: "",
sScrollY: "",
sScrollXInner: "",
autoWidth: false,
pageLength: 10,
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
responsive: false,
language: {
search: '<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">_INPUT_<i class="mdi mdi-magnify datatable-search-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666;"></i><i class="mdi mdi-close-circle datatable-clear-icon" style="position:absolute; right:11px; top:50%; transform:translateY(-53%); color:#666; display:none;"></i></div>',
searchPlaceholder: "Search",
emptyTable: '<div class="text-center text-muted">No Data found</div>'
}
});
// responsive: false for all tables (row-collapse mode off).
// Note: preInit.dt runs *after* pb() in DT 1.10.x, so it cannot disable scroll split; use sScrollX/sScrollY
// in defaults + nhanceMergeListDataTableOptions instead.
$(document).on('preInit.dt', function (e, settings) {
if (settings && settings.oInit) {
settings.oInit.responsive = false;
}
});
function normalizeAddButtonLabel(buttonApi) {
if (!buttonApi || !buttonApi.length) {
return;
}
buttonApi.each(function () {
var node = this.node ? this.node() : null;
if (!node) {
return;
}
var $btn = $(node);
var rawText = ($btn.text() || '').trim().toLowerCase();
if (rawText !== 'add') {
return;
}
if ($btn.find('.mdi-plus').length) {
return;
}
$btn.html('<i class="mdi mdi-plus"></i><span class="btn-custom"> Add </span>');
});
}
function normalizeExportButtonLabel(buttonApi) {
if (!buttonApi || !buttonApi.length) {
return;
}
buttonApi.each(function () {
var node = this.node ? this.node() : null;
if (!node) {
return;
}
var $btn = $(node);
var rawText = ($btn.text() || '').trim().toLowerCase();
if (rawText !== 'export') {
return;
}
if ($btn.find('.mdi-menu-down').length) {
return;
}
$btn.html('<span class="btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>');
});
}
// Keep Add CTA visual consistent across all DataTables pages.
$(document).on('init.dt', function (e, settings) {
if (!settings || !settings.nTable) {
return;
}
try {
var dt = $(settings.nTable).DataTable();
normalizeAddButtonLabel(dt.buttons());
normalizeExportButtonLabel(dt.buttons());
} catch (err) {
// Do not block table render if a specific page has non-standard buttons.
}
});
})();
</script>
<!-- Shared list DataTable helpers (batch_list-style: scroll/align/columns.adjust) -->
<script src="<?= base_url() . "public"; ?>/assets/js/pages/nhance-list-datatable.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/moment/min/moment.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/bootstrap-daterangepicker/daterangepicker.js"></script>
<!-- Datatables init -->
<!-- <script src="<?= base_url() . "public"; ?>/assets/js/pages/datatables.init.js"></script> -->
<script src="<?= base_url() . "public"; ?>/assets/js/pages/tickets.init.js"></script>
<!-- Plugins js-->
<script src="<?= base_url() . "public"; ?>/assets/libs/admin-resources/jquery.vectormap/jquery-jvectormap-1.2.2.min.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/admin-resources/jquery.vectormap/maps/jquery-jvectormap-us-merc-en.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/libs/parsleyjs/parsley.min.js"></script>
<!-- Dashboard init-->
<script src="<?= base_url() . "public"; ?>/assets/js/pages/dashboard-analytics.init.js"></script>
<!-- Validation init js-->
<script src="<?= base_url() . "public"; ?>/assets/js/pages/form-validation.init.js"></script>
<!-- App js -->
<script src="<?= base_url() . "public"; ?>/assets/js/app.min.js"></script>
<!-- Sweet Alert CDN -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap-multiselect@1.1.0/dist/js/bootstrap-multiselect.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.13/css/bootstrap-multiselect.css" />
<script src="https://cdn.jsdelivr.net/npm/toastr@2.1.4/toastr.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/toastr@2.1.4/build/toastr.min.css" rel="stylesheet">
<!-- flatpicker datepicker -->
<link href="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.js"></script>
<!-- bootstrap datepicker -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.10.0/js/bootstrap-datepicker.min.js"></script> -->
<script>
/**
* Bootstrap popover compatibility shim for x-editable/bootstrap-editable.
* Some builds expect `$.fn.popover.defaults` (BS3 style) which is missing
* in newer Bootstrap plugin wrappers. Mirror Constructor defaults to keep
* old plugins working and avoid:
* "a.fn.popover.defaults is undefined".
*/
(function (window) {
if (!window.jQuery || !window.jQuery.fn || !window.jQuery.fn.popover) {
return;
}
var $ = window.jQuery;
var ctor = $.fn.popover.Constructor;
if (!$.fn.popover.defaults) {
$.fn.popover.defaults = (ctor && (ctor.Default || ctor.DEFAULT)) ? (ctor.Default || ctor.DEFAULT) : {};
}
})(window);
</script>
<script src="<?= base_url() . "public"; ?>/assets/js/pages/jquery.xeditable.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/js/form-xeditable.init.js"></script>
<script src="<?= base_url() . "public"; ?>/assets/js/bootstrap-editable.min.js"></script>
<!-- Jodit Js -->
<script src="<?= base_url() . "public"; ?>/assets/js/jodit.min.js"></script>
<!-- select2 -->
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script src="https://cdn.datatables.net/plug-ins/2.0.8/sorting/scientific.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.8.0/jszip.min.js"></script>
<script>
toastr.options = {
"timeOut": 5000,
"closeButton": true,
};
</script>
<script>
(function (window, document) {
var MAX_GLOBAL_UPLOAD_BYTES = 25 * 1024 * 1024; // 25 MB
var textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;
function formatBytesToMb(bytes) {
return (bytes / (1024 * 1024)).toFixed(2);
}
function getFilesSizeFromInput(input) {
if (!input || !input.files || !input.files.length) {
return 0;
}
var total = 0;
for (var i = 0; i < input.files.length; i++) {
total += input.files[i].size || 0;
}
return total;
}
function getAllFileInputsScope(source) {
if (!source) {
return [];
}
if (source.matches && source.matches('form')) {
return source.querySelectorAll('input[type="file"]');
}
if (source.form) {
return source.form.querySelectorAll('input[type="file"]');
}
return document.querySelectorAll('input[type="file"]');
}
function getTotalPayloadBytes(source) {
var inputs = getAllFileInputsScope(source);
var total = 0;
for (var i = 0; i < inputs.length; i++) {
total += getFilesSizeFromInput(inputs[i]);
}
return total;
}
function showGlobalFileWarning(message) {
if (window.toastr && typeof window.toastr.warning === 'function') {
window.toastr.warning(message, 'Validation');
} else {
window.alert(message);
}
}
function validateGlobalUploadPayload(source) {
var totalPayloadBytes = getTotalPayloadBytes(source);
if (totalPayloadBytes > MAX_GLOBAL_UPLOAD_BYTES) {
showGlobalFileWarning(
'Total selected file size is ' +
formatBytesToMb(totalPayloadBytes) +
' MB. Allowed maximum is 25 MB.'
);
return false;
}
return true;
}
function formatPayloadSize(bytes) {
return {
bytes: bytes,
kb: (bytes / 1024).toFixed(2),
mb: (bytes / (1024 * 1024)).toFixed(2)
};
}
function getTextBytes(value) {
var textValue = String(value == null ? '' : value);
if (textEncoder) {
return textEncoder.encode(textValue).length;
}
return unescape(encodeURIComponent(textValue)).length;
}
function calculateFormPayloadBytes(form) {
if (!form || typeof FormData === 'undefined') {
return 0;
}
var total = 0;
var formData = new FormData(form);
formData.forEach(function (value) {
if (value instanceof File) {
total += value.size || 0;
} else {
total += getTextBytes(value);
}
});
return total;
}
function getFormIdentity(form) {
if (!form) {
return 'unknown-form';
}
if (form.id) {
return '#' + form.id;
}
if (form.name) {
return 'name="' + form.name + '"';
}
return form.getAttribute('action') || 'anonymous-form';
}
window.validateGlobalUploadPayload = validateGlobalUploadPayload;
document.addEventListener('change', function (event) {
var target = event.target;
if (!target || !target.matches || !target.matches('input[type="file"]')) {
return;
}
if (!validateGlobalUploadPayload(target)) {
target.value = '';
}
});
document.addEventListener(
'submit',
function (event) {
var form = event.target;
if (!form || !form.matches || !form.matches('form')) {
return;
}
var payloadBytes = calculateFormPayloadBytes(form);
var payloadMeta = formatPayloadSize(payloadBytes);
console.log(
'[Form Payload] ' + getFormIdentity(form) +
' => ' + payloadMeta.bytes + ' bytes (' +
payloadMeta.kb + ' KB, ' + payloadMeta.mb + ' MB)'
);
if (form.querySelector('input[type="file"]') && !validateGlobalUploadPayload(form)) {
event.preventDefault();
event.stopPropagation();
}
},
true
);
})(window, document);
</script>
<script>
window.__navPageName = "<?= esc($page_name ?? '') ?>";
window.__navUserName = "<?= esc(get_session_userdata()->first_name ?? 'NOT SET') ?>";
window.applyTopNavbarTitle = function() {
var pageName = window.__navPageName || "";
var userName = window.__navUserName || "";
var extraTitle = (typeof pageTitle !== 'undefined') ? pageTitle : false;
var backButton = (typeof pageBackButton !== 'undefined') ? pageBackButton : false;
var titleHtml = "";
var $titleEl = $(".top-navbar-title");
var $navDiv = $(".top-navbar-div");
if (pageName && pageName == "Dashboard") {
titleHtml = `<h6 style="margin-right:5px !important;">Welcome ${userName}</h6>
<h3>Dashboard</h3>`;
$titleEl.css({ display: "block", bottom: "12px" });
$navDiv.css({ marginTop: "20px" });
} else if (pageName && extraTitle && typeof pageHideMainNavTitle !== 'undefined' && pageHideMainNavTitle && !backButton) {
titleHtml = `<h3 style="margin-right:5px !important;">${extraTitle}</h3>`;
$titleEl.css({ display: "block", bottom: "12px" });
$navDiv.css({ marginTop: "20px" });
} else if (pageName && backButton && extraTitle && typeof pageHideMainNavTitle !== 'undefined' && pageHideMainNavTitle) {
titleHtml = `<h3 class="d-flex align-items-center" style="margin-right:5px !important; gap:12px;">${backButton}<span>${extraTitle}</span></h3>`;
$titleEl.css({ display: "block", bottom: "12px" });
$navDiv.css({ marginTop: "20px" });
} else if (pageName && backButton && extraTitle) {
titleHtml = `<h3 style="margin-right:5px !important;">${pageName}</h3>`;
titleHtml += `<h6>${backButton}&nbsp;${extraTitle}</h6>`;
$titleEl.css({ display: "block", bottom: "12px" });
$navDiv.css({ marginTop: "0px" });
} else if (pageName && extraTitle) {
titleHtml = `<h3 style="margin-right:5px !important;">${pageName}</h3>`;
titleHtml += `<h6>${extraTitle}</h6>`;
$titleEl.css({ display: "block", bottom: "12px" });
$navDiv.css({ marginTop: "0px" });
} else {
titleHtml = `<h3 style="margin-right:5px !important;">${pageName}</h3>`;
$titleEl.css({ display: "flex", bottom: "0px" });
$navDiv.css({ marginTop: "20px" });
}
$titleEl.html(titleHtml);
};
$(document).ready(function() {
applyTopNavbarTitle();
// var pageName = "<?= esc($page_name ?? '') ?>";
// var titleHtml = (pageName && pageName !== "Dashboard") ?
// `<h3 style="margin-right:5px !important;">${pageName}</h3>` :
// " ";
// if (pageName && pageName == "Dashboard") {
// titleHtml = `<h6 style="margin-right:5px !important;">Welcome <?= esc(get_session_userdata()->first_name ?? 'NOT SET') ?></h6>
// <h3>Dashboard</h3>`;
// }
// $(".top-navbar-title").html(titleHtml);
$('#collapseOne').on('show.bs.collapse', function() {
// When open
$('#icon').removeClass('mdi-chevron-down').addClass('mdi-chevron-up');
// $('#filterAccordion').removeAttr("style"); // remove bg/border when open
});
$('#collapseOne').on('hide.bs.collapse', function() {
// When closed
$('#icon').removeClass('mdi-chevron-up').addClass('mdi-chevron-down');
// $('#filterAccordion').css({
// "background-color": "#F5FFFF",
// "border": "2px solid #F5FFFF",
// "border-radius": "10px",
// "box-shadow": "0px 4px 4px 0px #00000040"
// });
});
const observer = new MutationObserver(() => {
document.querySelectorAll('.select2-search__field').forEach(el => {
el.style.setProperty('box-shadow', 'none', 'important');
});
});
observer.observe(document.body, { childList: true, subtree: true });
});
</script>
<script>
var pullNotificationCount = 0;
var pendingActionCount = 0;
$(document).ready(function() {
function fetchMessages() {
$.ajax({
url: '<?= base_url('dashboard/get-notification') ?>',
method: 'GET',
success: function(response) {
// console.log('responce', response)
if (response.status == false) {
$('#notification_count').html('0')
console.log('The session is not set correctly. ')
return;
}
let messagesList = $('#messages-list');
messagesList.empty();
var html = "";
pullNotificationCount = response.message.length
localStorage.setItem('pullNotificationCount', pullNotificationCount)
response.message.forEach(message => {
// if (!message.is_read) {
// unreadCount++;
// }
var jasonDecodeData = JSON.parse(message.message_text)
var toast_body_css = 'background : #bfd7eb !important;';
var toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
var toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto';
var toast_status_word = 'Success';
if (jasonDecodeData.msg_status == 'failure') {
toast_body_css = 'background : #fdcfcf !important;';
toast_head_css = 'background-color : rgb(235 105 105 / 85%) !important; color :#000; border-bottom: 0;';
toast_icon = 'mdi mdi-information mr-auto'
toast_status_word = 'Failure';
} else if (jasonDecodeData.msg_status == 'success') {
toast_body_css = 'background : #bfd7eb !important;';
toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto'
toast_status_word = 'Success';
}
var html = ` <li data-id="${message.id}" data-url="${jasonDecodeData.action_url != undefined && jasonDecodeData.action_url != "" ? jasonDecodeData.action_url : 'dashboard/view'}">
<div class="p-3">
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-toggle="toast">
<div class="toast-header " style="${toast_head_css}" >
<strong class="${toast_icon}"> ${toast_status_word}</strong>
<button type="button" class="ml-2 mb-1 close rm_msg" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body" style="${toast_body_css}">
<strong>${jasonDecodeData.msg_title ? jasonDecodeData.msg_title : ''}</strong> <br><br>
<small style="position: relative;bottom: 8px;">${jasonDecodeData.message_text}</small>
<div class="toast-footer">
<a href="#" class="redirect_page" data-toggle="tooltip" data-placement="bottom" title="Click Go to the Page"><small style="margin-right: 25px;position: relative;top: 2px;">${jasonDecodeData.action_url != undefined && jasonDecodeData.action_url != "" ? 'see more' : ''}</small></a>
<small style="position: relative;top: 2px;left: 5px;font-size: 10px;">${formatDate(message.created_at)}</small>
</div>
</div>
</div>
</div>
</li>`
messagesList.append(html);
$(function() {
$('[data-toggle="tooltip"]').tooltip();
});
});
},
error: function(xhr, status, error) {
console.error(xhr.responseText); // Log the error response
}
});
let PNCount = parseInt(localStorage.getItem('pullNotificationCount'));
let PACount = parseInt(localStorage.getItem('pendingActionCount'));
totalcount = PNCount + PACount
$('#notification_count').html(totalcount);
}
function acknowledgeMessage(messageId) {
$.ajax({
url: '<?= base_url('dashboard/acknowledge-notification/') ?>' + messageId,
method: 'GET',
success: function(response) {
fetchMessages();
},
error: function(xhr, status, error) {
console.error(xhr.responseText); // Log the error response
}
});
}
$('#messages-list').on('click', 'li', function(event) {
//console.log('messages-list click li')
if ($(event.target).closest('.rm_msg').length > 0) {
//console.log('.rm_msg')
let messageId = $(this).data('id');
let url = $(this).data('url');
acknowledgeMessage(messageId);
$(this).delay(300).fadeOut('slow', function() {
$(this).remove();
});
} else if ($(event.target).closest('.redirect_page').length > 0) {
//console.log('redirect_page')
let messageId = $(this).data('id');
let url = $(this).data('url');
//console.log('url : ', url)
acknowledgeMessage(messageId);
window.location.href = '<?= base_url() ?>' + url;
}
});
// fetchMessages();
// setInterval(fetchMessages, 60000); // Fetch messages every sixty seconds
});
$(document).ready(function() {
function fetchPendingAction() {
$.ajax({
url: '<?= base_url('dashboard/get-pending-action') ?>',
method: 'GET',
success: function(response) {
console.log(response);
if (response.length == 0) {
pendingActionCount = 0;
localStorage.setItem('pendingActionCount', pendingActionCount);
}
for (let key in response) {
// console.log(response[key].length)
// console.log('type', typeof response[key].length)
// console.log('key', response[key])
if (response[key].length != 'undefined' && response[key].length != undefined) {
pendingActionCount = pendingActionCount + response[key].length;
}
}
console.log(pendingActionCount);
let messagesList = $('#messages-list-2');
messagesList.empty();
if (response.inception) {
$.each(response.inception, function(index, item) {
var queryParams = {
client_id: item.client_id,
client_policy_id: item.client_policy_id,
client_branch_id: item.branch_id,
actions: 'inception'
};
const queryString = objectToQueryString(queryParams);
var url = 'employee/upload?' + queryString
////console.log(url)
var toast_body_css = 'background : #bfd7eb !important;';
var toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
var toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto';
var toast_status_word = 'Info';
if (!item.branch_name.toLowerCase().includes('branch')) {
//console.log(item.branch_name)
item.branch_name += ' branch';
}
////console.log(item.branch_name);
var toast_body_data = item.client_name + '( ' + item.branch_name + ' ) ' + ' - ' + item.policy_name;
////console.log(toast_body_data);
var html = ` <li data-id="" data-url="${url}">
<div class="p-3">
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-toggle="toast">
<div class="toast-header " style="${toast_head_css}" >
<strong class="${toast_icon}"> ${toast_status_word}</strong>
<button type="button" class="ml-2 mb-1 close rm_msg" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body" style="${toast_body_css}">
<strong>Inception Pending</strong><br><br>
<small style="position: relative;bottom: 8px;">${toast_body_data}</small>
<div class="toast-footer">
<a href="#" class="redirect_page" data-toggle="tooltip" data-placement="bottom" title="Click Go to the Page"><small style="margin-right: 142px;position: relative;top: 2px;">see more</small></a>
<small style="position: relative;top: 2px;left: 5px;font-size: 10px;"></small>
</div>
</div>
</div>
</div>
</li>`
messagesList.append(html);
});
} else {
console.log('response.inception is undefined or null');
}
if (response.correction) {
$.each(response.correction, function(index, item) {
if (item.batch_export_count == 0 || item.batch_import_count == 0) {
var queryParams = {
client_id: item.client_id,
client_branch_id: item.branch_id,
event: 'correction',
actions: 'export',
insurer_or_tpa: 'tpa',
};
const queryString = objectToQueryString(queryParams);
var url = 'employee/upload?' + queryString + '#KYC-DOC-tab'
////console.log(url)
var toast_body_css = 'background : #bfd7eb !important;';
var toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
var toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto';
var toast_status_word = 'Info';
var title = 'Correction Pending';
if (!item.branch_name.toLowerCase().includes('branch')) {
//console.log(item.branch_name)
item.branch_name += ' branch';
}
////console.log(item.branch_name);
// if (item.batch_export_count > 0) {
// title = 'Correction Import Pending';
// }
var toast_body_data = item.client_name + ' - ' + item.branch_name;
////console.log(toast_body_data);
var html = ` <li data-id="" data-url="${url}">
<div class="p-3">
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-toggle="toast">
<div class="toast-header " style="${toast_head_css}" >
<strong class="${toast_icon}"> ${toast_status_word}</strong>
<button type="button" class="ml-2 mb-1 close rm_msg" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body" style="${toast_body_css}">
<strong>${title}</strong><br><br>
<small style="position: relative;bottom: 8px;">${toast_body_data}</small>
<div class="toast-footer">
<a href="#" class="redirect_page" data-toggle="tooltip" data-placement="bottom" title="Click Go to the Page"><small style="margin-right: 142px;position: relative;top: 2px;">see more</small></a>
<small style="position: relative;top: 2px;left: 5px;font-size: 10px;"></small>
</div>
</div>
</div>
</div>
</li>`
messagesList.append(html);
}
});
} else {
console.log('response.correction is undefined or null');
}
if (response.deletion) {
$.each(response.deletion, function(index, item) {
if (item.batch_export_count == 0 || item.batch_import_count == 0) {
var queryParams = {
client_id: item.client_id,
client_policy_id: item.client_policy_id,
client_branch_id: item.branch_id,
event: 'deletion',
actions: 'export',
insurer_or_tpa: 'tpa',
};
const queryString = objectToQueryString(queryParams);
var url = 'employee/upload?' + queryString + '#KYC-DOC-tab'
////console.log(url)
var toast_body_css = 'background : #bfd7eb !important;';
var toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
var toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto';
var toast_status_word = 'Info';
var title = 'Deletion Pending';
if (!item.branch_name.toLowerCase().includes('branch')) {
//console.log(item.branch_name)
item.branch_name += ' branch';
}
////console.log(item.branch_name);
// if (item.batch_export_count > 0) {
// title = 'Deletion Import Pending';
// }
var toast_body_data = item.client_name + '( ' + item.branch_name + ' ) ' + ' - ' + item.policy_name;
////console.log(toast_body_data);
var html = ` <li data-id="" data-url="${url}">
<div class="p-3">
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-toggle="toast">
<div class="toast-header " style="${toast_head_css}" >
<strong class="${toast_icon}"> ${toast_status_word}</strong>
<button type="button" class="ml-2 mb-1 close rm_msg" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body" style="${toast_body_css}">
<strong>${title}</strong><br><br>
<small style="position: relative;bottom: 8px;">${toast_body_data}</small>
<div class="toast-footer">
<a href="#" class="redirect_page" data-toggle="tooltip" data-placement="bottom" title="Click Go to the Page"><small style="margin-right: 142px;position: relative;top: 2px;">see more</small></a>
<small style="position: relative;top: 2px;left: 5px;font-size: 10px;"></small>
</div>
</div>
</div>
</div>
</li>`
messagesList.append(html);
}
});
} else {
console.log('response.deletion is undefined or null');
}
if (response.si_enhancement) {
$.each(response.si_enhancement, function(index, item) {
if (item.batch_export_count == 0 || item.batch_import_count == 0) {
var queryParams = {
client_id: item.client_id,
client_policy_id: item.client_policy_id,
client_branch_id: item.branch_id,
event: 'si_enhancement',
actions: 'export',
insurer_or_tpa: 'tpa',
};
const queryString = objectToQueryString(queryParams);
var url = 'employee/upload?' + queryString + '#KYC-DOC-tab'
////console.log(url)
var toast_body_css = 'background : #bfd7eb !important;';
var toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
var toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto';
var toast_status_word = 'Info';
var title = 'SI Enhancement Pending';
if (!item.branch_name.toLowerCase().includes('branch')) {
//console.log(item.branch_name)
item.branch_name += ' branch';
}
////console.log(item.branch_name);
// if (item.batch_export_count > 0) {
// title = 'SI Enhancement Import Pending';
// }
var toast_body_data = item.client_name + '( ' + item.branch_name + ' ) ' + ' - ' + item.policy_name;
////console.log(toast_body_data);
var html = ` <li data-id="" data-url="${url}">
<div class="p-3">
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-toggle="toast">
<div class="toast-header " style="${toast_head_css}" >
<strong class="${toast_icon}"> ${toast_status_word}</strong>
<button type="button" class="ml-2 mb-1 close rm_msg" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body" style="${toast_body_css}">
<strong>${title}</strong><br><br>
<small style="position: relative;bottom: 8px;">${toast_body_data}</small>
<div class="toast-footer">
<a href="#" class="redirect_page" data-toggle="tooltip" data-placement="bottom" title="Click Go to the Page"><small style="margin-right: 142px;position: relative;top: 2px;">see more</small></a>
<small style="position: relative;top: 2px;left: 5px;font-size: 10px;"></small>
</div>
</div>
</div>
</div>
</li>`
messagesList.append(html);
}
});
} else {
console.log('response.si_enhancement is undefined or null');
}
if (response.tpa) {
$.each(response.tpa, function(index, item) {
if (item.batch_export_count == 0 || item.batch_import_count == 0) {
var queryParams = {
client_id: item.client_id,
client_policy_id: item.client_policy_id,
client_branch_id: item.branch_id,
event: 'inception',
insurer_or_tpa: 'tpa',
actions: 'export',
};
const queryString = objectToQueryString(queryParams);
var url = 'employee/upload?' + queryString + '#KYC-DOC-tab'
////console.log(url)
var toast_body_css = 'background : #bfd7eb !important;';
var toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
var toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto';
var toast_status_word = 'Info';
var title = 'TPA Pending';
if (!item.branch_name.toLowerCase().includes('branch')) {
//console.log(item.branch_name)
item.branch_name += ' branch';
}
////console.log(item.branch_name);
// if (item.batch_export_count > 0) {
// title = 'TPA Import Pending';
// }
var toast_body_data = item.client_name + '( ' + item.branch_name + ' ) ' + ' - ' + item.policy_name;
////console.log(toast_body_data);
var html = ` <li data-id="" data-url="${url}">
<div class="p-3">
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-toggle="toast">
<div class="toast-header " style="${toast_head_css}" >
<strong class="${toast_icon}"> ${toast_status_word}</strong>
<button type="button" class="ml-2 mb-1 close rm_msg" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body" style="${toast_body_css}">
<strong>${title}</strong><br><br>
<small style="position: relative;bottom: 8px;">${toast_body_data}</small>
<div class="toast-footer">
<a href="#" class="redirect_page" data-toggle="tooltip" data-placement="bottom" title="Click Go to the Page"><small style="margin-right: 142px;position: relative;top: 2px;">see more</small></a>
<small style="position: relative;top: 2px;left: 5px;font-size: 10px;"></small>
</div>
</div>
</div>
</div>
</li>`
messagesList.append(html);
}
});
} else {
console.log('response.tpa is undefined or null');
}
if (response.uhid) {
$.each(response.uhid, function(index, item) {
if (item.batch_export_count == 0 || item.batch_import_count == 0) {
var queryParams = {
client_id: item.client_id,
client_policy_id: item.client_policy_id,
client_branch_id: item.branch_id,
event: 'inception',
insurer_or_tpa: 'insurer',
actions: 'export',
};
const queryString = objectToQueryString(queryParams);
var url = 'employee/upload?' + queryString + '#KYC-DOC-tab'
//console.log(url)
var toast_body_css = 'background : #bfd7eb !important;';
var toast_head_css = 'background-color : rgb(2, 168, 181) !important; color :#000; border-bottom: 0;';
var toast_icon = 'mdi mdi-checkbox-marked-circle mr-auto';
var toast_status_word = 'Info';
var title = 'Insurer Pending';
if (!item.branch_name.toLowerCase().includes('branch')) {
//console.log(item.branch_name)
item.branch_name += ' branch';
}
////console.log(item.branch_name);
// if (item.batch_export_count > 0) {
// title = 'Insurer Import Pending';
// }
var toast_body_data = item.client_name + '( ' + item.branch_name + ' ) ' + ' - ' + item.policy_name;
////console.log(toast_body_data);
var html = ` <li data-id="" data-url="${url}">
<div class="p-3">
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-toggle="toast">
<div class="toast-header " style="${toast_head_css}" >
<strong class="${toast_icon}"> ${toast_status_word}</strong>
<button type="button" class="ml-2 mb-1 close rm_msg" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body" style="${toast_body_css}">
<strong>${title}</strong><br><br>
<small style="position: relative;bottom: 8px;">${toast_body_data}</small>
<div class="toast-footer">
<a href="#" class="redirect_page" data-toggle="tooltip" data-placement="bottom" title="Click Go to the Page"><small style="margin-right: 142px;position: relative;top: 2px;">see more</small></a>
<small style="position: relative;top: 2px;left: 5px;font-size: 10px;"></small>
</div>
</div>
</div>
</div>
</li>`
messagesList.append(html);
}
});
} else {
console.log('response.uhid is undefined or null');
}
localStorage.setItem('pendingActionCount', pendingActionCount)
},
error: function(xhr, status, error) {
console.error(xhr.responseText); // Log the error response
}
});
}
// fetchPendingAction()
$('#messages-list-2').on('click', 'li', function(event) {
//console.log('messages-list-2 click li')
if ($(event.target).closest('.rm_msg').length > 0) {
//console.log('.rm_msg')
$(this).delay(300).fadeOut('slow', function() {
$(this).remove();
});
} else if ($(event.target).closest('.redirect_page').length > 0) {
//console.log('redirect_page')
let url = $(this).data('url');
//console.log('url : ', url);
window.location.href = '<?= base_url() ?>' + url;
}
});
})
function objectToQueryString(obj) {
return Object.keys(obj).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&');
}
</script>
<script>
function formatDate(dateString) {
// Parse the input date string
let date = new Date(dateString);
// Define months array
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
// Extract day, month, year, hours, and minutes
let day = date.getDate();
let month = months[date.getMonth()];
let year = date.getFullYear();
let hours = date.getHours();
let minutes = date.getMinutes();
// Convert hours to 12-hour format
let period = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // Handle midnight (0 hours)
// Format the time string
let timeString = ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2) + ' ' + period;
// Format the date string
let formattedDate = day + '-' + month + '-' + year + ' ' + timeString;
return formattedDate;
}
function printCurrentTime() {
var now = new Date();
var hours = now.getHours().toString().padStart(2, '0');
var minutes = now.getMinutes().toString().padStart(2, '0');
var seconds = now.getSeconds().toString().padStart(2, '0');
var currentTime = hours + ':' + minutes + ':' + seconds;
// console.log("Current Time:", currentTime);
return currentTime;
}
</script>
<script>
function checkDuplicateTableFieldValue(tableName, fieldName, value, callback) {
$.ajax({
url: '<?= base_url('util/checkDuplicateTableFieldValue') ?>', // Adjust this to your endpoint in CodeIgniter
type: 'POST',
data: {
table: tableName,
field: fieldName,
value: value
},
dataType: 'json',
success: function(response) {
if (typeof callback === 'function') {
callback(response.isDuplicate); // Pass the result to the callback
}
},
error: function(xhr, status, error) {
console.error('AJAX Error:', error);
}
});
}
function sendAjaxRequestForGlobal(url, method, data = {}, successCallback = null, errorCallback = null) {
$.ajax({
url: url,
method: method,
data: data,
dataType: 'json', // Expected response type
success: function(response) {
// If a success callback is provided, call it with the response
if (successCallback) {
successCallback(response);
}
},
error: function(xhr, status, error) {
// Handle errors if provided error callback
if (errorCallback) {
errorCallback(xhr, status, error);
} else {
console.error('AJAX Error:', error);
}
}
});
}
function confirmActionSweertAlert(message = "Are you sure?", confirmText = "Yes, Proceed!", cancelText = "Cancel", icon = "warning") {
return Swal.fire({
title: message,
icon: icon,
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: confirmText,
cancelButtonText: cancelText
}).then((result) => {
return result.isConfirmed; // Returns true if confirmed, false otherwise
});
}
</script>
<script>
function restoreDashboardHistoryIfNeeded() {
const dashboardHistoryString = localStorage.getItem('dashboardHistory');
if (!dashboardHistoryString) {
console.log("dashboardHistory not found");
return;
}
const dashboardHistory = JSON.parse(dashboardHistoryString);
if (window.location.href === dashboardHistory.dashboard_url) {
const tabSelector = dashboardHistory.tab;
if (tabSelector) {
const tabElement = document.querySelector(`a[href="${tabSelector}"]`);
if (tabElement) {
tabElement.click();
}
}
const functionName = dashboardHistory.function_name;
const params = dashboardHistory.tile_params;
if (functionName && typeof window[functionName] === 'function') {
if (params.majorType == 0 && params.minorType == 0) {
window[functionName]();
} else {
window[functionName](params.majorType, params.minorType);
}
}
console.log("inside location match");
}
}
// Run on popstate (back/forward buttons)
window.addEventListener('popstate', restoreDashboardHistoryIfNeeded);
// Run on page load (refresh)
window.addEventListener('DOMContentLoaded', () => {
// slight delay ensures DOM/tab loads completely
setTimeout(restoreDashboardHistoryIfNeeded, 100);
});
</script>
<script>
$(document).ready(function() {
const activeItem = localStorage.getItem("activeLi");
if (activeItem) {
// Use .children('a') to only target the main icon links
$('.li-seperate').children('a').removeClass('img-active').addClass('img-inactive');
// Set the active class only on the top-level anchor of the saved ID
$('#' + activeItem).children('a').first().removeClass('img-inactive').addClass('img-active');
}
$('.li-seperate').on('click', function() {
// 1. Reset ONLY the top-level anchors of all menu items
$('.li-seperate').children('a').removeClass('img-active').addClass('img-inactive');
// 2. Add active class ONLY to the immediate <a> of the clicked <li>
$(this).children('a').first().removeClass('img-inactive').addClass('img-active');
// 3. Store the ID
const id = $(this).attr("id");
if(id) {
localStorage.setItem("activeLi", id);
}
});
});
</script>
<script>
$(document).ready(function() {
$('.nav-link').click(function() {
// change bg color of tab
$('.nav-link').removeClass('active-tab');
$(this).addClass('active-tab');
});
});
$(document).ready(function() {
// find all nav anchors
let $nav = $("ul.nav.nav-pills.navtab-bg");
// check if no anchor has active classes
if ($nav.find("a.active.active-tab").length === 0) {
// add classes to the first anchor
$nav.find("li:first-child a").addClass("active active-tab");
// also need to find the tab name and show only active image
// let tab_name = $nav.find("li:first-child a").attr('href').split('-')[0];
let href = $nav.find("li:first-child a").attr('href');
let tab_name = href ? href.split('-')[0] : '';
tab_name = tab_name.replace('#', '');
switch (tab_name) {
case "leads":
$('.active_leads').show();
$('.inactive_leads').hide();
break;
case "bds":
$('.active_bds').show();
$('.inactive_bds').hide();
break;
case "claims":
$('.active_claims').show();
$('.inactive_claims').hide();
break;
case "pending":
$('.active_pending').show();
$('.inactive_pending').hide();
break;
default:
break;
}
}
});
$(function(){
let $nav = $("#myTab");
$(".left-btn").on("click", function(){
$nav.stop().animate({ scrollLeft: $nav.scrollLeft() - 150 }, 200);
});
$(".right-btn").on("click", function(){
$nav.stop().animate({ scrollLeft: $nav.scrollLeft() + 150 }, 200);
});
});
// function openModal(modalId) {
// console.log('openModal called with ID:', modalId);
// var modalEl = document.getElementById(modalId);
// if (typeof bootstrap !== "undefined" && bootstrap.Modal && typeof bootstrap.Modal.getOrCreateInstance === "function") {
// // ✅ Bootstrap 5
// var modal = bootstrap.Modal.getOrCreateInstance(modalEl);
// modal.show();
// } else if (typeof $ !== "undefined" && typeof $.fn.modal === "function") {
// // ✅ Bootstrap 4
// $('#' + modalId).modal('show');
// } else {
// console.error("No compatible Bootstrap modal found.");
// }
// }
</script>
<script>
$(document).ready(function(){
$('.nav-link').click(function(){
// change bg color of tab
$('.nav-link').removeClass('active-tab');
$(this).addClass('active-tab');
});
});
</script>
<script>
function closeModalById(modalId) {
// Get the modal element
var modal = document.getElementById(modalId);
if (!modal) return; // Exit if no modal found
// Hide it by removing "show" or "in" classes and setting display:none
modal.style.display = 'none';
modal.classList.remove('in', 'show'); // 'in' for BS3, 'show' for BS4/5
modal.setAttribute('aria-hidden', 'true');
modal.removeAttribute('aria-modal'); // optional
modal.removeAttribute('role'); // optional
// Remove backdrop if present
var backdrop = document.querySelector('.modal-backdrop');
if (backdrop) backdrop.remove();
// Allow page scrolling again
document.body.classList.remove('modal-open');
}
</script>
<script>
const insurer_category = {
1: "general", 2: "general", 3: "general", 4: "general", 5: "general",
6: "life", 7: "life", 8: "general", 9: "general", 10: "general",
11: "general", 12: "general", 13: "general", 14: "general", 15: "general",
16: "general", 17: "general", 18: "general", 19: "general", 20: "general",
21: "general", 22: "general", 23: "general", 24: "general", 25: "general",
26: "general", 27: "general", 28: "general", 29: "general", 30: "general",
31: "general", 32: "life", 33: "general", 34: "life", 35: "general",
36: "general", 37: "general", 38: "general", 39: "life", 40: "general",
41: "general", 42: "general", 43: "general", 44: "general", 45: "general",
46: "general", 47: "general", 48: "general", 49: "general", 50: "general",
51: "general", 52: "general", 53: "general", 54: "general", 55: "general",
56: "general", 57: "general", 58: "general", 59: "general", 60: "general",
61: "general", 62: "general", 63: "general", 64: "general", 65: "general",
66: "general", 67: "general", 68: "general", 69: "general", 70: "general",
71: "general"
};
function appendInsurerByCategory(data, object, type)
{
return true;
$(object).empty();
$(object).append($('<option>', {
value: '',
text: 'Select Insurer'
}));
$.each(data, function(index, item) {
var displayValue = item.insurer_name + ' - ' + item.branch_code;
var dbValue = item.id+'-'+item.insurer_id
if(item.category == type){
var option = $('<option>', {
value: dbValue,
text: displayValue,
'data-id': item.insurer_id,
'data-bid': item.id,
'data-ic': item.category,
});
$(object).append(option);
}
});
$(object).select2();
}
// SVR asked - Add padding to input so text doesnt merge with icon
$(document).on('init.dt', function () {
$('.dataTables_filter input[type="search"]').css('padding-right', '30px');
});
// SVR asked - Toggle icons
$(document).on('input', '.dataTables_filter input', function() {
const wrapper = $(this).closest('.datatable-search-wrapper');
if ($(this).val()) {
wrapper.find('.datatable-search-icon').hide();
wrapper.find('.datatable-clear-icon').show();
} else {
wrapper.find('.datatable-search-icon').show();
wrapper.find('.datatable-clear-icon').hide();
}
});
// SVR asked - Clear search
$(document).on('click', '.datatable-clear-icon', function() {
const input = $(this).closest('.datatable-search-wrapper').find('input');
input.val('').trigger('input');
table.search('').draw();
});
/**
* NHance — DataTables row action menus (tbody .dropdown)
*
* Moving the menu to body broke Bootstrap: clicks on Edit/Delete are no longer inside
* the .btn-group parent, so the menu closes before the link receives the click.
*
* Keep the menu in the DOM under the ⋯: data-display="static" (no Popper transforms),
* data-boundary="scrollParent" (no position-static parent). While open, set overflow
* visible on .table-responsive / scroll body so the menu is not clipped. If there is
* more room above the button than below, add Bootstraps .dropup so the menu opens
* upward (last rows / short viewport).
*/
(function () {
if (typeof jQuery === 'undefined') {
return;
}
var $ = jQuery;
var syncNs = '.nhDtRowToolbarDd';
function nhRowDropdownScrollHost($dd) {
var $body = $dd.closest('.dataTables_scrollBody');
if ($body.length) {
return $body;
}
return $dd.closest('.table-responsive');
}
function nhScheduleDropdownPopper($dd) {
var $toggle = $dd.children('[data-toggle="dropdown"]').first();
if (!$toggle.length) {
return;
}
var inst = $toggle.data('bs.dropdown');
if (inst && inst._popper) {
inst._popper.scheduleUpdate();
}
}
function nhRowActionDropdownOpts() {
$('.dataTables_wrapper table.dataTable tbody [data-toggle="dropdown"]').attr({
'data-boundary': 'scrollParent',
'data-display': 'static',
'data-flip': 'false'
});
}
function nhNormalizeActionCells(tableApi) {
if (!tableApi) {
return;
}
var $table = $(tableApi.table().node());
$table.find('tbody tr').each(function () {
var $row = $(this);
var $actionCell = $row.find('td').filter(function () {
return $(this).find('.btn-group.dropdown, .dropdown-menu').length > 0;
}).last();
if ($actionCell.length) {
$actionCell.addClass('table-action-cell');
}
});
}
function nhClearForcedDropup(tableApi) {
if (!tableApi) {
return;
}
var $table = $(tableApi.table().node());
$table.find('tbody tr').removeClass('nh-force-dropup');
$table.find('tbody td.table-action-cell .btn-group.dropdown, tbody td.table-action-cell .dropdown').removeClass('dropup');
}
$(function () {
var D = $.fn.dropdown && $.fn.dropdown.Constructor && $.fn.dropdown.Constructor.Default;
if (D) {
D.boundary = 'window';
}
nhRowActionDropdownOpts();
});
$(document).on('draw.dt', 'table.dataTable', function () {
nhRowActionDropdownOpts();
var dt = $(this).DataTable();
nhNormalizeActionCells(dt);
nhClearForcedDropup(dt);
});
$(document).on('show.bs.dropdown', '.dataTables_wrapper table.dataTable tbody .dropdown', function () {
var $dd = $(this);
var $toggle = $dd.children('[data-toggle="dropdown"]').first();
var $menu = $dd.children('.dropdown-menu').first();
var el = $toggle[0];
var $scroll = $dd.closest('.dataTables_scrollBody');
if ($scroll.length) {
$scroll.data('nh-prev-overflow', $scroll.css('overflow'));
$scroll.css('overflow', 'visible');
}
var $resp = $dd.closest('.table-responsive');
if ($resp.length) {
$resp.data('nh-prev-overflow-tr', $resp.css('overflow'));
$resp.css('overflow', 'visible');
}
var $cardBody = $dd.closest('.card-body');
if ($cardBody.length) {
$cardBody.data('nh-prev-overflow-cb', $cardBody.css('overflow'));
$cardBody.css('overflow', 'visible');
}
if (!el || !el.getClientRects().length) {
return;
}
var rect = el.getBoundingClientRect();
var vh = window.innerHeight;
var below = Math.max(0, vh - rect.bottom - 8);
var above = Math.max(0, rect.top - 8);
var menuHeight = 0;
if ($menu.length) {
// Measure true menu height even while hidden.
var prevStyle = $menu.attr('style');
$menu.css({ display: 'block', visibility: 'hidden', maxHeight: '', overflowY: '' });
menuHeight = $menu.outerHeight() || 0;
if (prevStyle !== undefined) {
$menu.attr('style', prevStyle);
} else {
$menu.removeAttr('style');
}
}
// Pick direction by space; prefer the side that can fit the full menu.
var openUp = false;
if (menuHeight > 0) {
if (below >= menuHeight) {
openUp = false;
} else if (above >= menuHeight) {
openUp = true;
} else {
openUp = above > below;
}
} else {
openUp = below < 150 && above > below;
}
$dd.removeClass('dropup');
$dd.removeData('nh-auto-dropup');
if (openUp) {
$dd.addClass('dropup');
$dd.data('nh-auto-dropup', 1);
}
// Keep action menu fully expanded (no inner scroll).
if ($menu.length && menuHeight > 0) {
$menu.css({
maxHeight: '',
overflowY: '',
overflowX: '',
scrollBehavior: '',
overscrollBehavior: '',
zIndex: '20050'
}).addClass('nh-action-menu-elevated');
}
});
$(document).on('hidden.bs.dropdown', '.dataTables_wrapper table.dataTable tbody .dropdown', function () {
var $dd = $(this);
var $scroll = $dd.closest('.dataTables_scrollBody');
if ($scroll.length) {
var o = $scroll.data('nh-prev-overflow');
if (o !== undefined) {
$scroll.css('overflow', o);
}
$scroll.removeData('nh-prev-overflow');
}
var $resp = $dd.closest('.table-responsive');
if ($resp.length) {
var o2 = $resp.data('nh-prev-overflow-tr');
if (o2 !== undefined) {
$resp.css('overflow', o2);
}
$resp.removeData('nh-prev-overflow-tr');
}
var $cardBody = $dd.closest('.card-body');
if ($cardBody.length) {
var o3 = $cardBody.data('nh-prev-overflow-cb');
if (o3 !== undefined) {
$cardBody.css('overflow', o3);
}
$cardBody.removeData('nh-prev-overflow-cb');
}
if ($dd.data('nh-auto-dropup')) {
$dd.removeClass('dropup');
$dd.removeData('nh-auto-dropup');
}
$dd.children('.dropdown-menu').css({
maxHeight: '',
overflowY: '',
overflowX: '',
scrollBehavior: '',
overscrollBehavior: '',
zIndex: ''
}).removeClass('nh-action-menu-elevated');
});
$(document).on('shown.bs.dropdown', '.dataTables_wrapper .dropdown', function () {
var $dd = $(this);
if ($dd.closest('table.dataTable tbody').length) {
return;
}
var sync = function () {
nhScheduleDropdownPopper($dd);
};
nhScheduleDropdownPopper($dd);
nhRowDropdownScrollHost($dd).off(syncNs).on('scroll' + syncNs, sync);
$(window).off(syncNs).on('scroll' + syncNs, sync);
var $contentPage = $dd.closest('.content-page');
if ($contentPage.length) {
$contentPage.off(syncNs).on('scroll' + syncNs, sync);
}
});
$(document).on('hidden.bs.dropdown', '.dataTables_wrapper .dropdown', function () {
var $dd = $(this);
if ($dd.closest('table.dataTable tbody').length) {
return;
}
nhRowDropdownScrollHost($dd).off(syncNs);
$(window).off(syncNs);
$dd.closest('.content-page').off(syncNs);
});
/**
* NHance — standardize DataTables control layout for pages still using
* default DataTables DOM:
* top: length + search, bottom: info + paginate
*
* Requirement format:
* - top row: search (left), buttons (right if present)
* - bottom row: info (left), show-length + pagination (right)
*
* For wrappers without custom dom, move top `.dataTables_length` to
* bottom row before `.dataTables_paginate`.
*/
function normalizeDataTableLayout(wrapper) {
if (!wrapper || !wrapper.length) {
return;
}
var $rows = wrapper.children('div.row');
if ($rows.length < 2) {
return;
}
var $top = $rows.first();
var $bottom = $rows.last();
var $topLength = $top.find('div.dataTables_length').first();
var $bottomPaginate = $bottom.find('div.dataTables_paginate').first();
if (!$topLength.length || !$bottomPaginate.length) {
applyBottomSlotClasses($bottom);
return;
}
if ($bottom.find('div.dataTables_length').length) {
applyBottomSlotClasses($bottom);
return; // already normalized/customized
}
$bottomPaginate.before($topLength);
applyBottomSlotClasses($bottom);
}
/**
* Mark bottom row containers so CSS can enforce exact requirement layout:
* info left; length + pagination grouped right.
*/
function applyBottomSlotClasses($bottomRow) {
if (!$bottomRow || !$bottomRow.length) {
return;
}
$bottomRow.children('div').removeClass('nh-dt-bottom-info nh-dt-bottom-length nh-dt-bottom-paginate');
var $info = $bottomRow.find('div.dataTables_info').first().closest('div');
var $len = $bottomRow.find('div.dataTables_length').first().closest('div');
var $pag = $bottomRow.find('div.dataTables_paginate').first().closest('div');
if ($info.length) {
$info.addClass('nh-dt-bottom-info');
}
if ($len.length) {
$len.addClass('nh-dt-bottom-length');
}
if ($pag.length) {
$pag.addClass('nh-dt-bottom-paginate');
}
}
$(document).on('init.dt', function (e, settings) {
if (!settings || !settings.nTableWrapper) {
return;
}
var wrapper = $(settings.nTableWrapper);
normalizeDataTableLayout(wrapper);
/* Stops Bootstrap `.table-responsive` from adding a second horizontal scrollbar under pagination */
wrapper.closest('.table-responsive').addClass('nh-dt-no-outer-scroll');
try {
var dt = $(settings.nTable).DataTable();
nhNormalizeActionCells(dt);
nhClearForcedDropup(dt);
} catch (err) {
// keep page running if a table has non-standard setup
}
});
/**
* Prev/next disabled state (first page, last page, single page): DataTables
* normally sets `li.page-item.disabled`; re-sync from page.info() after each
* draw so grey-arrow styles in custom.css / header always match behaviour.
*/
$(document).on('draw.dt', function (e, settings) {
if (!settings || !settings.nTableWrapper || !settings.oFeatures || !settings.oFeatures.bPaginate) {
return;
}
var api;
try {
api = new $.fn.dataTable.Api(settings);
} catch (err) {
return;
}
var info = api.page.info();
var $pag = $(settings.nTableWrapper).find('.dataTables_paginate');
if (!$pag.length) {
return;
}
var pages = info.pages;
var atFirst = info.page <= 0;
var atLast = pages <= 0 || info.page >= pages - 1;
$pag.find('li.paginate_button.page-item.previous, li.page-item.previous').toggleClass('disabled', atFirst);
$pag.find('li.paginate_button.page-item.next, li.page-item.next').toggleClass('disabled', atLast);
$pag.find('a.paginate_button.previous').toggleClass('disabled', atFirst);
$pag.find('a.paginate_button.next').toggleClass('disabled', atLast);
});
})();
</script>
</body>
</html>