773 lines
35 KiB
PHP
773 lines
35 KiB
PHP
<?php helper('common'); ?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
|
|
|
<title>Welcome</title>
|
|
<meta content="" name="description">
|
|
<meta content="" name="keywords">
|
|
|
|
<link href="<?= base_url('assets/img/logo.ico') ?>" rel="icon" type="image/x-icon">
|
|
<link href="<?= base_url('assets/img/favicon.png') ?>" rel="alternate icon" type="image/png">
|
|
<link href="<?= base_url('assets/img/apple-touch-icon.png') ?>" rel="apple-touch-icon">
|
|
|
|
<meta name="csrf-token-name" content="<?= csrf_token() ?>">
|
|
<meta name="csrf-token" content="<?= csrf_hash() ?>">
|
|
<meta name="csrf-header" content="<?= config('Security')->headerName ?>">
|
|
|
|
<!-- Google Fonts removed: offline app uses system fonts -->
|
|
|
|
<link href="<?= base_url('assets/vendor/bootstrap/css/bootstrap.min.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/bootstrap-icons/bootstrap-icons.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/boxicons/css/boxicons.min.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/quill/quill.snow.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/quill/quill.bubble.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/remixicon/remixicon.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/simple-datatables/style.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/datatables/jquery.dataTables.min.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/datatables/dataTables.bootstrap5.min.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/jquery-ui/jquery-ui.min.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/select2/select2.min.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/vendor/select2/select2-bootstrap4.min.css') ?>" rel="stylesheet">
|
|
|
|
<link href="<?= base_url('assets/css/style.css') ?>" rel="stylesheet">
|
|
<link href="<?= base_url('assets/css/custom-theme-dark-borders.css') ?>" rel="stylesheet">
|
|
|
|
<style>
|
|
/* Sticky footer layout: keeps footer pinned to the bottom on all screen sizes */
|
|
html, body {
|
|
height: 100%;
|
|
}
|
|
body {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
#main {
|
|
flex: 1 0 auto;
|
|
min-height: calc(100vh - 130px);
|
|
}
|
|
#footer {
|
|
margin-top: auto;
|
|
flex-shrink: 0;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
(function() {
|
|
var checkingSession = false;
|
|
var terminated = false;
|
|
|
|
function checkActiveSession() {
|
|
if (checkingSession || terminated || document.hidden) {
|
|
return;
|
|
}
|
|
checkingSession = true;
|
|
|
|
fetch('<?= base_url('auth/session-status') ?>', {
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
},
|
|
cache: 'no-store',
|
|
credentials: 'same-origin'
|
|
}).then(function(response) {
|
|
if (response.status !== 409) {
|
|
return null;
|
|
}
|
|
return response.json();
|
|
}).then(function(payload) {
|
|
if (!payload || !payload.session_terminated || terminated) {
|
|
return;
|
|
}
|
|
terminated = true;
|
|
window.alert(payload.message || 'This login session was ended. Please sign in again.');
|
|
window.location.assign(payload.login_url || '<?= base_url('login') ?>');
|
|
}).catch(function() {
|
|
}).finally(function() {
|
|
checkingSession = false;
|
|
});
|
|
}
|
|
|
|
window.setInterval(checkActiveSession, 15000);
|
|
document.addEventListener('visibilitychange', function() {
|
|
if (!document.hidden) {
|
|
checkActiveSession();
|
|
}
|
|
});
|
|
window.setTimeout(checkActiveSession, 3000);
|
|
})();
|
|
</script>
|
|
|
|
<script>
|
|
// Early fallback so javascript:load_form(...) links never fail before full app scripts initialize.
|
|
if (typeof window.load_form !== 'function') {
|
|
window.load_form = function(ourl) {
|
|
if (ourl) {
|
|
window.location.href = ourl;
|
|
}
|
|
};
|
|
}
|
|
if (typeof window.load_form_div !== 'function') {
|
|
window.load_form_div = function(ourl, xdiv) {
|
|
if (!ourl) {
|
|
return;
|
|
}
|
|
if (!xdiv) {
|
|
window.location.href = ourl;
|
|
return;
|
|
}
|
|
var el = document.getElementById(String(xdiv));
|
|
if (el) {
|
|
el.innerHTML = '<div class="text-muted">Loading...</div>';
|
|
}
|
|
window.location.href = ourl;
|
|
};
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<?php $user = auth()->user(); ?>
|
|
<?php $footerVersion = hms_footer_version(); ?>
|
|
|
|
<header id="header" class="header fixed-top d-flex align-items-center">
|
|
<div class="d-flex align-items-center justify-content-between">
|
|
<a href="<?= base_url('/') ?>" class="logo d-flex align-items-center">
|
|
<img src="<?= base_url('assets/img/logo.png') ?>" alt="">
|
|
<span class="d-none d-lg-block">E-Atria</span>
|
|
</a>
|
|
<i class="bi bi-list toggle-sidebar-btn"></i>
|
|
</div>
|
|
<?= $this->include('partials/header') ?>
|
|
</header>
|
|
|
|
<aside id="sidebar" class="sidebar">
|
|
<?= $this->include('partials/sidebar') ?>
|
|
</aside>
|
|
|
|
<main id="main" class="main">
|
|
|
|
</main>
|
|
|
|
<footer id="footer" class="footer">
|
|
<div class="copyright">
|
|
© 2017 - 2026 <strong><span><a href="https://www.e-atria.in" target="_blank" rel="noopener">E-Atria</a></span></strong>. All Rights Reserved |
|
|
<a href="<?= base_url('software-use-license.html') ?>" target="_blank" rel="noopener">Software Use License</a> |
|
|
Version: <?= esc($footerVersion) ?>
|
|
</div>
|
|
</footer>
|
|
<div id="wait"
|
|
style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(255,255,255,0.6);z-index:9999;">
|
|
<div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="toast-container position-fixed top-0 end-0 p-3" id="toast-container"></div>
|
|
<a href="#" class="back-to-top d-flex align-items-center justify-content-center"><i class="bi bi-arrow-up-short"></i></a>
|
|
|
|
<script src="<?= base_url('assets/vendor/jquery/jquery-3.7.1.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/js/csrf-guard.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/inputmask/inputmask.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/inputmask/jquery.inputmask.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/jquery-ui/jquery-ui.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/datatables/jquery.dataTables.min.js') ?>"></script>
|
|
<script>
|
|
// The local DataTables file is a lightweight shim in this project.
|
|
// Load Bootstrap 5 adapter only when full DataTables core API exists.
|
|
(function() {
|
|
if (!(window.jQuery && jQuery.fn && jQuery.fn.dataTable && jQuery.fn.dataTable.defaults)) {
|
|
return;
|
|
}
|
|
|
|
var script = document.createElement('script');
|
|
script.src = "<?= base_url('assets/vendor/datatables/dataTables.bootstrap5.min.js') ?>";
|
|
document.head.appendChild(script);
|
|
})();
|
|
</script>
|
|
<script>
|
|
if (window.jQuery && typeof jQuery.isArray !== 'function') {
|
|
jQuery.isArray = Array.isArray;
|
|
}
|
|
if (window.jQuery && typeof jQuery.trim !== 'function') {
|
|
jQuery.trim = function(value) {
|
|
return String(value ?? '').trim();
|
|
};
|
|
}
|
|
</script>
|
|
<script src="<?= base_url('assets/vendor/select2/select2.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/apexcharts/apexcharts.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/bootstrap/js/bootstrap.bundle.min.js') ?>"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
var tooltipEls = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
|
tooltipEls.forEach(function (el) { new bootstrap.Tooltip(el); });
|
|
});
|
|
</script>
|
|
<script src="<?= base_url('assets/vendor/chart.js/chart.umd.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/echarts/echarts.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/quill/quill.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/ckeditor/ckeditor.js') ?>"></script>
|
|
<script>
|
|
if (window.CKEDITOR) {
|
|
CKEDITOR.config.versionCheck = false;
|
|
}
|
|
</script>
|
|
<script src="<?= base_url('assets/vendor/simple-datatables/simple-datatables.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/tinymce/tinymce.min.js') ?>"></script>
|
|
<script src="<?= base_url('assets/vendor/php-email-form/validate.js') ?>"></script>
|
|
|
|
<?php
|
|
// Get user settings (use hospital defaults as fallback)
|
|
$sidebarAutoHideSeconds = (int) hospital_setting_value('SIDEBAR_AUTO_HIDE_SECONDS', '7');
|
|
|
|
if (function_exists('auth') && auth()->loggedIn()) {
|
|
$authUser = auth()->user();
|
|
if ($authUser && isset($authUser->id)) {
|
|
$userSettingsModel = model('App\Models\UserSettings');
|
|
$userSidebarSetting = $userSettingsModel->getUserSetting(
|
|
(int) $authUser->id,
|
|
'SIDEBAR_AUTO_HIDE_SECONDS',
|
|
''
|
|
);
|
|
if ($userSidebarSetting !== '') {
|
|
$sidebarAutoHideSeconds = (int) $userSidebarSetting;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($sidebarAutoHideSeconds < 0) {
|
|
$sidebarAutoHideSeconds = 0;
|
|
}
|
|
if ($sidebarAutoHideSeconds > 60) {
|
|
$sidebarAutoHideSeconds = 60;
|
|
}
|
|
?>
|
|
<script>
|
|
window.SIDEBAR_AUTO_HIDE_DELAY_MS = <?= (int) ($sidebarAutoHideSeconds * 1000) ?>;
|
|
</script>
|
|
|
|
<script src="<?= base_url('assets/js/main.js') ?>"></script>
|
|
|
|
<script>
|
|
(function() {
|
|
const REQUEST_TIMEOUT_MS = 60000;
|
|
|
|
function requireJquery() {
|
|
if (!window.jQuery) {
|
|
console.error('jQuery is not loaded.');
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function executeInjectedScripts(containerId) {
|
|
var container = document.getElementById(containerId);
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
// Some pages (dashboard charts) can be reloaded into the same canvas IDs.
|
|
// Destroy existing chart instances before executing injected scripts.
|
|
if (window.Chart) {
|
|
var canvases = container.querySelectorAll('canvas');
|
|
canvases.forEach(function(canvasEl) {
|
|
try {
|
|
if (typeof window.Chart.getChart === 'function') {
|
|
var existingChart = window.Chart.getChart(canvasEl);
|
|
if (existingChart) {
|
|
existingChart.destroy();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.warn('Chart cleanup failed', e);
|
|
}
|
|
});
|
|
}
|
|
|
|
var scripts = container.querySelectorAll('script');
|
|
if (!scripts || scripts.length === 0) {
|
|
return;
|
|
}
|
|
|
|
scripts.forEach(function(oldScript) {
|
|
var newScript = document.createElement('script');
|
|
|
|
for (var i = 0; i < oldScript.attributes.length; i++) {
|
|
var attr = oldScript.attributes[i];
|
|
newScript.setAttribute(attr.name, attr.value);
|
|
}
|
|
|
|
if (oldScript.src) {
|
|
var existing = document.querySelector('script[src="' + oldScript.src + '"]');
|
|
if (existing) {
|
|
return;
|
|
}
|
|
} else {
|
|
newScript.text = oldScript.textContent || oldScript.innerText || '';
|
|
}
|
|
|
|
document.head.appendChild(newScript);
|
|
if (!oldScript.src) {
|
|
document.head.removeChild(newScript);
|
|
}
|
|
});
|
|
}
|
|
|
|
function handleAuthError(jqXHR, containerId) {
|
|
if (!jqXHR) {
|
|
return false;
|
|
}
|
|
|
|
// HTTP 401: Unauthorized -> User session is genuinely lost or expired
|
|
if (jqXHR.status === 401) {
|
|
alert('Your session has expired or you have been logged out. Please login again.');
|
|
window.location.href = '<?= base_url('login') ?>';
|
|
return true;
|
|
}
|
|
|
|
// HTTP 403: Forbidden -> User IS logged in, but lacks permission for this action/link
|
|
if (jqXHR.status === 403) {
|
|
var raw = (jqXHR.responseText ? String(jqXHR.responseText) : '');
|
|
var detailMsg = '';
|
|
if (raw && !/<!DOCTYPE/i.test(raw)) {
|
|
detailMsg = raw.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
|
|
}
|
|
|
|
var accessDeniedHtml =
|
|
'<div class="container-fluid py-5">' +
|
|
'<div class="row justify-content-center">' +
|
|
'<div class="col-12 col-md-8 col-lg-6">' +
|
|
'<div class="card shadow-sm border-0 text-center p-4" style="border-radius: 12px; background: #fff;">' +
|
|
'<div class="card-body p-3">' +
|
|
'<div class="mb-3">' +
|
|
'<span class="d-inline-flex align-items-center justify-content-center rounded-circle bg-danger-subtle text-danger" style="width: 76px; height: 76px; font-size: 36px;">' +
|
|
'<i class="bi bi-shield-lock-fill"></i>' +
|
|
'</span>' +
|
|
'</div>' +
|
|
'<h4 class="fw-bold text-dark mb-2">Access Restricted</h4>' +
|
|
'<p class="text-muted mb-3" style="font-size: 14px;">You do not have permission to access this module or view this information with your current user account.</p>' +
|
|
'<div class="alert alert-warning border-0 bg-warning-subtle text-warning-emphasis text-start p-3 mb-4 rounded-3 small">' +
|
|
'<div class="fw-bold mb-1"><i class="bi bi-info-circle-fill me-1"></i> How to get access:</div>' +
|
|
'<div>Please communicate with your <strong>Hospital Administrator</strong> or IT Department to assign the required permissions or roles to your account.</div>' +
|
|
(detailMsg ? '<div class="mt-2 pt-2 border-top border-warning-subtle text-muted" style="font-size: 11px;">Notice: ' + detailMsg.substring(0, 160) + '</div>' : '') +
|
|
'</div>' +
|
|
'<div class="d-flex justify-content-center gap-2 flex-wrap">' +
|
|
'<button type="button" class="btn btn-outline-secondary px-3 btn-sm" onclick="if(window.history.length > 1){ window.history.back(); } else { load_form(\'<?= base_url('dashboard') ?>\', \'Dashboard\'); }">' +
|
|
'<i class="bi bi-arrow-left me-1"></i> Go Back' +
|
|
'</button>' +
|
|
'<button type="button" class="btn btn-primary px-3 btn-sm" onclick="load_form(\'<?= base_url('dashboard') ?>\', \'Dashboard\');">' +
|
|
'<i class="bi bi-grid me-1"></i> Back to Dashboard' +
|
|
'</button>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
|
|
if (containerId) {
|
|
var targetEl = document.getElementById(String(containerId));
|
|
if (targetEl) {
|
|
targetEl.innerHTML = accessDeniedHtml;
|
|
} else if (window.jQuery) {
|
|
$('#' + containerId).html(accessDeniedHtml);
|
|
}
|
|
}
|
|
|
|
if (typeof window.notify === 'function') {
|
|
window.notify('danger', 'Access Restricted: ', 'You do not have permission to access this module. Please communicate with your Hospital Administrator.');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function cleanupBootstrapModalState() {
|
|
try {
|
|
document.querySelectorAll('.modal.show').forEach(function(modalEl) {
|
|
if (window.bootstrap && window.bootstrap.Modal) {
|
|
var instance = window.bootstrap.Modal.getInstance(modalEl);
|
|
if (instance) {
|
|
try { instance.dispose(); } catch (e) {}
|
|
}
|
|
}
|
|
modalEl.classList.remove('show');
|
|
modalEl.style.display = 'none';
|
|
modalEl.setAttribute('aria-hidden', 'true');
|
|
});
|
|
document.querySelectorAll('.modal-backdrop').forEach(function(backdrop) {
|
|
try { backdrop.remove(); } catch (e) {}
|
|
});
|
|
document.body.classList.remove('modal-open');
|
|
document.body.style.removeProperty('overflow');
|
|
document.body.style.removeProperty('padding-right');
|
|
} catch (e) {
|
|
console.warn('cleanupBootstrapModalState failed', e);
|
|
}
|
|
}
|
|
window.cleanupBootstrapModalState = cleanupBootstrapModalState;
|
|
|
|
window.load_form = function(ourl, top_title = '') {
|
|
if (!requireJquery()) return;
|
|
var normalizedUrl = String(ourl || '');
|
|
if (!normalizedUrl || /(^|\/)undefined($|\/|\?|#)/i.test(normalizedUrl) || /(^|\/)null($|\/|\?|#)/i.test(normalizedUrl)) {
|
|
console.error('load_form blocked invalid url', { url: ourl });
|
|
$('#main').html('Invalid request URL. Please reload and try again.');
|
|
return;
|
|
}
|
|
if (typeof window.pageCleanup === 'function') {
|
|
try {
|
|
window.pageCleanup();
|
|
} catch (e) {
|
|
console.warn('pageCleanup failed', e);
|
|
}
|
|
}
|
|
cleanupBootstrapModalState();
|
|
$.ajax({
|
|
url: normalizedUrl,
|
|
dataType: "html",
|
|
async: true,
|
|
timeout: REQUEST_TIMEOUT_MS,
|
|
beforeSend: function() {
|
|
cleanupBootstrapModalState();
|
|
$('#main').html('loading...');
|
|
$("#wait").css("display", "block");
|
|
}
|
|
})
|
|
.done(function(html) {
|
|
if (typeof delete_varible === 'function') {
|
|
delete_varible();
|
|
}
|
|
$("#wait").css("display", "none");
|
|
var mainEl = document.getElementById('main');
|
|
if (mainEl) {
|
|
mainEl.innerHTML = html;
|
|
}
|
|
cleanupBootstrapModalState();
|
|
executeInjectedScripts('main');
|
|
if (typeof window.showPageNotifications === 'function') {
|
|
window.showPageNotifications(mainEl);
|
|
}
|
|
if (typeof initfunc === 'function') {
|
|
initfunc();
|
|
}
|
|
if (top_title !== '') document.title = top_title;
|
|
})
|
|
.fail(function(jqXHR, textStatus, errorThrown) {
|
|
$("#wait").css("display", "none");
|
|
if (handleAuthError(jqXHR, 'main')) return;
|
|
console.error('load_form failed', {
|
|
url: normalizedUrl,
|
|
status: jqXHR.status,
|
|
statusText: jqXHR.statusText,
|
|
textStatus: textStatus,
|
|
error: errorThrown
|
|
});
|
|
if (textStatus === 'timeout') {
|
|
$('#main').html('Request timed out. Please try again.');
|
|
return;
|
|
}
|
|
var details = 'Error loading content.';
|
|
if (jqXHR && jqXHR.status) {
|
|
details += ' [HTTP ' + jqXHR.status + ']';
|
|
}
|
|
var raw = (jqXHR && jqXHR.responseText) ? String(jqXHR.responseText) : '';
|
|
if (raw !== '') {
|
|
raw = raw.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
|
|
if (raw !== '') {
|
|
details += '<br><small>' + raw.substring(0, 220) + '</small>';
|
|
}
|
|
}
|
|
$('#main').html(details);
|
|
});
|
|
};
|
|
|
|
window.load_form_div = function(ourl, xdiv, top_title = '') {
|
|
if (!requireJquery()) return;
|
|
$.ajax({
|
|
url: ourl,
|
|
dataType: "html",
|
|
cache: false,
|
|
async: true,
|
|
timeout: REQUEST_TIMEOUT_MS
|
|
})
|
|
.done(function(html) {
|
|
var targetEl = document.getElementById(String(xdiv));
|
|
if (!targetEl && (xdiv === 'searchresult' || xdiv === 'test_div')) {
|
|
targetEl = document.getElementById('medical-main') || document.getElementById('main');
|
|
}
|
|
if (targetEl) {
|
|
targetEl.innerHTML = html;
|
|
}
|
|
executeInjectedScripts(targetEl ? targetEl.id : xdiv);
|
|
if (typeof window.showPageNotifications === 'function') {
|
|
window.showPageNotifications(targetEl);
|
|
}
|
|
if (typeof initfunc === 'function') {
|
|
initfunc();
|
|
}
|
|
if (top_title !== '') document.title = top_title;
|
|
})
|
|
.fail(function(jqXHR, textStatus, errorThrown) {
|
|
if (handleAuthError(jqXHR, xdiv)) return;
|
|
console.error('load_form_div failed', {
|
|
url: ourl,
|
|
status: jqXHR.status,
|
|
statusText: jqXHR.statusText,
|
|
textStatus: textStatus,
|
|
error: errorThrown
|
|
});
|
|
if (textStatus === 'timeout') {
|
|
$("#" + xdiv).html('Request timed out. Please try again.');
|
|
return;
|
|
}
|
|
var details = 'Error loading content.';
|
|
if (jqXHR && jqXHR.status) {
|
|
details += ' [HTTP ' + jqXHR.status + ']';
|
|
}
|
|
var raw = (jqXHR && jqXHR.responseText) ? String(jqXHR.responseText) : '';
|
|
if (raw !== '') {
|
|
raw = raw.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
|
|
if (raw !== '') {
|
|
details += '<br><small>' + raw.substring(0, 220) + '</small>';
|
|
}
|
|
}
|
|
$("#" + xdiv).html(details);
|
|
});
|
|
};
|
|
})();
|
|
</script>
|
|
|
|
<script>
|
|
(function() {
|
|
const initialRoute = <?= json_encode($initial_route ?? '') ?>;
|
|
const initialTitle = <?= json_encode($initial_title ?? '') ?>;
|
|
if (!initialRoute) {
|
|
return;
|
|
}
|
|
const loadInitial = function() {
|
|
if (typeof window.load_form === 'function') {
|
|
window.load_form(initialRoute, initialTitle);
|
|
}
|
|
};
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', loadInitial);
|
|
} else {
|
|
loadInitial();
|
|
}
|
|
})();
|
|
</script>
|
|
<script>
|
|
if (typeof window.notify !== 'function') {
|
|
window.notify = function(type, title, message) {
|
|
var container = document.getElementById('toast-container');
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
var toast = document.createElement('div');
|
|
var variant = type === 'success' ? 'success' : 'danger';
|
|
toast.className = 'toast align-items-center text-bg-' + variant + ' border-0';
|
|
toast.setAttribute('role', 'alert');
|
|
toast.setAttribute('aria-live', 'assertive');
|
|
toast.setAttribute('aria-atomic', 'true');
|
|
|
|
toast.innerHTML =
|
|
'<div class="d-flex">'
|
|
+ '<div class="toast-body">'
|
|
+ '<strong class="me-2">' + (title || '') + '</strong>' + (message || '')
|
|
+ '</div>'
|
|
+ '<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>'
|
|
+ '</div>';
|
|
|
|
container.appendChild(toast);
|
|
|
|
if (window.bootstrap && bootstrap.Toast) {
|
|
var bsToast = bootstrap.Toast.getOrCreateInstance(toast, { delay: 3000 });
|
|
bsToast.show();
|
|
} else {
|
|
toast.classList.add('show');
|
|
setTimeout(function() {
|
|
toast.classList.remove('show');
|
|
toast.remove();
|
|
}, 3000);
|
|
}
|
|
};
|
|
}
|
|
|
|
window.showPageNotifications = function(root) {
|
|
var scope = root && root.querySelectorAll ? root : document;
|
|
scope.querySelectorAll('[data-page-notification]:not([data-notification-shown])').forEach(function(item) {
|
|
item.setAttribute('data-notification-shown', '1');
|
|
window.notify(
|
|
item.getAttribute('data-notification-type') || 'error',
|
|
item.getAttribute('data-notification-title') || 'Notification',
|
|
item.getAttribute('data-notification-message') || ''
|
|
);
|
|
});
|
|
};
|
|
</script>
|
|
<script>
|
|
(function() {
|
|
if (!window.jQuery) {
|
|
return;
|
|
}
|
|
|
|
var SEARCH_URL = '<?= base_url('Lab_Admin/pathology_masters_search') ?>';
|
|
var debounceTimer = null;
|
|
|
|
function escHtml(str) {
|
|
return String(str || '')
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"');
|
|
}
|
|
|
|
function getModalEls() {
|
|
return {
|
|
input: document.getElementById('add_panel_name'),
|
|
list: document.getElementById('add-panel-suggestions'),
|
|
spinner: document.getElementById('add-panel-search-spinner'),
|
|
meta: document.getElementById('add-panel-master-meta')
|
|
};
|
|
}
|
|
|
|
function hideList() {
|
|
var els = getModalEls();
|
|
if (!els.list) {
|
|
return;
|
|
}
|
|
els.list.style.display = 'none';
|
|
els.list.innerHTML = '';
|
|
}
|
|
|
|
function renderList(items) {
|
|
var els = getModalEls();
|
|
if (!els.list) {
|
|
return;
|
|
}
|
|
|
|
els.list.innerHTML = '';
|
|
if (!items || items.length === 0) {
|
|
hideList();
|
|
return;
|
|
}
|
|
|
|
items.forEach(function(item) {
|
|
var btn = document.createElement('button');
|
|
btn.type = 'button';
|
|
btn.className = 'list-group-item list-group-item-action d-flex justify-content-between align-items-center';
|
|
btn.innerHTML = '<span>' + escHtml(item.name || item.test_name || '') + '</span>'
|
|
+ (item.loinc_code ? '<span class="badge bg-success ms-2">' + escHtml(item.loinc_code) + '</span>' : '<span class="badge bg-light text-muted border ms-2">No LOINC</span>');
|
|
|
|
btn.addEventListener('click', function() {
|
|
if (els.input) {
|
|
els.input.value = String(item.test_name || item.name || '').trim();
|
|
}
|
|
if (els.meta) {
|
|
els.meta.innerHTML = 'Selected from ABDM API: ' + escHtml(item.test_name || item.name || '');
|
|
}
|
|
hideList();
|
|
});
|
|
|
|
els.list.appendChild(btn);
|
|
});
|
|
|
|
els.list.style.display = 'block';
|
|
}
|
|
|
|
$(document)
|
|
.off('input.abdmPanelSearch', '#add_panel_name')
|
|
.on('input.abdmPanelSearch', '#add_panel_name', function() {
|
|
clearTimeout(debounceTimer);
|
|
|
|
var q = String(this.value || '').trim();
|
|
var els = getModalEls();
|
|
|
|
if (q.length < 2) {
|
|
hideList();
|
|
if (els.meta) {
|
|
els.meta.innerHTML = 'Type at least 2 letters to live-search panel templates from ABDM Gateway API.';
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (els.spinner) {
|
|
els.spinner.classList.remove('d-none');
|
|
}
|
|
if (els.meta) {
|
|
els.meta.innerHTML = 'Searching panel templates from ABDM Gateway API...';
|
|
}
|
|
|
|
debounceTimer = setTimeout(function() {
|
|
$.ajax({
|
|
url: SEARCH_URL,
|
|
method: 'GET',
|
|
dataType: 'json',
|
|
data: { q: q, source: 'api', panel_only: 1 },
|
|
cache: false,
|
|
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
|
})
|
|
.done(function(payload) {
|
|
if (els.spinner) {
|
|
els.spinner.classList.add('d-none');
|
|
}
|
|
|
|
if (payload && !Array.isArray(payload) && Number(payload.ok || 0) === 0) {
|
|
hideList();
|
|
if (els.meta) {
|
|
els.meta.innerHTML = 'Search failed: ' + escHtml(payload.error || 'Gateway API search failed');
|
|
}
|
|
return;
|
|
}
|
|
|
|
var items = Array.isArray(payload)
|
|
? payload
|
|
: (payload && Array.isArray(payload.items) ? payload.items : []);
|
|
|
|
renderList(items);
|
|
if (els.meta) {
|
|
els.meta.innerHTML = items.length > 0
|
|
? ('Found ' + items.length + ' API matches')
|
|
: ('No API matches for "' + escHtml(q) + '"');
|
|
}
|
|
})
|
|
.fail(function(jqXHR, textStatus) {
|
|
if (els.spinner) {
|
|
els.spinner.classList.add('d-none');
|
|
}
|
|
hideList();
|
|
if (els.meta) {
|
|
els.meta.innerHTML = 'API search request failed (' + escHtml(textStatus || 'error') + ').';
|
|
}
|
|
});
|
|
}, 280);
|
|
});
|
|
|
|
$(document)
|
|
.off('click.abdmPanelSearchDoc')
|
|
.on('click.abdmPanelSearchDoc', function(e) {
|
|
var input = document.getElementById('add_panel_name');
|
|
var list = document.getElementById('add-panel-suggestions');
|
|
if (!input || !list) {
|
|
return;
|
|
}
|
|
if (!input.contains(e.target) && !list.contains(e.target)) {
|
|
hideList();
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|