Add engineering result dialog and functionality across all roles
This commit is contained in:
parent
4fa33194a5
commit
5f6cf47689
@ -36,9 +36,10 @@ $routes->group('api', function ($routes) {
|
||||
// Requests - All Roles (0,1,2,3,4)
|
||||
$routes->group('requests', ['filter' => 'role:0,1,2,3,4'], function ($routes) {
|
||||
$routes->get('', 'RequestsController::index');
|
||||
$routes->get('(:any)/audit', 'ApiRequestsAuditController::show/$1');
|
||||
$routes->post('validate/(:any)', 'RequestsController::val/$1');
|
||||
$routes->delete('validate/(:any)', 'RequestsController::unval/$1');
|
||||
$routes->get('(:any)/audit', 'ApiRequestsAuditController::show/$1');
|
||||
$routes->post('validate/(:any)', 'RequestsController::val/$1');
|
||||
$routes->delete('validate/(:any)', 'RequestsController::unval/$1');
|
||||
$routes->post('(:any)/eng', 'RequestsController::setEngLanguage/$1');
|
||||
});
|
||||
|
||||
// Validate API - Lab (2), Admin (1), Superuser (0)
|
||||
|
||||
@ -16,14 +16,16 @@ class RequestsController extends BaseController
|
||||
|
||||
// Only allow Lab role (role 2)
|
||||
if ($userroleid == 2) {
|
||||
$sql = "SELECT * from GDC_CMOD.dbo.V_DASHBOARD_DEV where
|
||||
COLLECTIONDATE between '$date1 00:00' and '$date2 23:59'
|
||||
and ODR_DDATE between '$date1 00:00' and '$date2 23:59'
|
||||
and (TESTS IS NOT NULL AND TESTS like '%[A-Za-z]%')";
|
||||
$sql = "SELECT d.*, r.REPORT_LANG from GDC_CMOD.dbo.V_DASHBOARD_DEV d
|
||||
LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER=d.SP_ACCESSNUMBER
|
||||
where d.COLLECTIONDATE between '$date1 00:00' and '$date2 23:59'
|
||||
and d.ODR_DDATE between '$date1 00:00' and '$date2 23:59'
|
||||
and (d.TESTS IS NOT NULL AND d.TESTS like '%[A-Za-z]%')";
|
||||
} else {
|
||||
$sql = "SELECT * from GDC_CMOD.dbo.V_DASHBOARD_DEV where
|
||||
COLLECTIONDATE between '$date1 00:00' and '$date2 23:59'
|
||||
and ODR_DDATE between '$date1 00:00' and '$date2 23:59'";
|
||||
$sql = "SELECT d.*, r.REPORT_LANG from GDC_CMOD.dbo.V_DASHBOARD_DEV d
|
||||
LEFT JOIN GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER=d.SP_ACCESSNUMBER
|
||||
where d.COLLECTIONDATE between '$date1 00:00' and '$date2 23:59'
|
||||
and d.ODR_DDATE between '$date1 00:00' and '$date2 23:59'";
|
||||
}
|
||||
|
||||
$rows = $db->query($sql)->getResultArray();
|
||||
@ -132,4 +134,20 @@ class RequestsController extends BaseController
|
||||
|
||||
return $this->response->setJSON($data);
|
||||
}
|
||||
|
||||
public function setEngLanguage($accessnumber)
|
||||
{
|
||||
$userid = session('userid');
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
// Set REPORT_LANG to 1 (English)
|
||||
$sql = "UPDATE GDC_CMOD.dbo.CM_REQUESTS SET REPORT_LANG=1 WHERE ACCESSNUMBER='$accessnumber'";
|
||||
$db->query($sql);
|
||||
|
||||
// Log the action
|
||||
$logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'SET_ENG', ?, GETDATE())";
|
||||
$db->query($logAudit, [$accessnumber, $userid]);
|
||||
|
||||
return $this->response->setJSON(['status' => 'success', 'message' => 'English result created']);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ $roleConfig = $config['admin'];
|
||||
<?= $this->include('shared/dialog_unval'); ?>
|
||||
<?= $this->include('shared/dialog_audit'); ?>
|
||||
<?= $this->include('shared/dialog_results_generate'); ?>
|
||||
<?= $this->include('shared/dialog_eng_result'); ?>
|
||||
<?= $this->include('shared/dialog_preview'); ?>
|
||||
</main>
|
||||
<?= $this->endSection(); ?>
|
||||
|
||||
@ -11,6 +11,7 @@ $roleConfig = $config['cs'];
|
||||
<?= $this->include('shared/dialog_unval'); ?>
|
||||
<?= $this->include('shared/dialog_audit'); ?>
|
||||
<?= $this->include('shared/dialog_results_generate'); ?>
|
||||
<?= $this->include('shared/dialog_eng_result'); ?>
|
||||
</main>
|
||||
<?= $this->endSection(); ?>
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ $roleConfig = $config['lab'];
|
||||
<?= $this->include('shared/dialog_unval'); ?>
|
||||
<?= $this->include('shared/dialog_audit'); ?>
|
||||
<?= $this->include('shared/dialog_results_generate'); ?>
|
||||
<?= $this->include('shared/dialog_eng_result'); ?>
|
||||
<?= $this->include('shared/dialog_preview'); ?>
|
||||
</main>
|
||||
<?= $this->endSection(); ?>
|
||||
|
||||
@ -11,6 +11,7 @@ $roleConfig = $config['phlebo'];
|
||||
<?= $this->include('shared/dialog_unval'); ?>
|
||||
<?= $this->include('shared/dialog_audit'); ?>
|
||||
<?= $this->include('shared/dialog_results_generate'); ?>
|
||||
<?= $this->include('shared/dialog_eng_result'); ?>
|
||||
</main>
|
||||
<?= $this->endSection(); ?>
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<div class="card bg-base-100 shadow-xl h-full border border-base-200 overflow-hidden">
|
||||
<div class="card-body p-0 h-full flex flex-col">
|
||||
<div class="card bg-base-100 shadow-xl border border-base-200 h-full">
|
||||
<div class="card-body p-0 flex flex-col h-full">
|
||||
|
||||
<!-- Header & Filters -->
|
||||
<div class="p-4 border-b border-base-200 bg-base-50">
|
||||
@ -76,7 +76,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-y-auto px-4 pb-4">
|
||||
<div class="flex-1 px-4 pb-4">
|
||||
<template x-if="isLoading">
|
||||
<table class="table table-xs table-zebra w-full">
|
||||
<thead class="bg-base-100 sticky top-0 z-10">
|
||||
@ -229,16 +229,16 @@ $previewEnabled = $configFile[$configKey]['previewEnabled'] ?? false;
|
||||
</button>
|
||||
</template>
|
||||
<template x-if="req.VAL1USER && req.VAL2USER">
|
||||
<div class="dropdown dropdown-end dropdown-hover">
|
||||
<div class="dropdown dropdown-top dropdown-end dropdown-hover">
|
||||
<div tabindex="0" role="button"
|
||||
class="btn btn-xs w-full btn-success text-white">
|
||||
<i class="fa fa-clipboard-check mr-1"></i>
|
||||
<span class="text-xs">Ready</span>
|
||||
</div>
|
||||
<ul tabindex="0"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-40 p-2 shadow-lg border border-base-300">
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-40 p-2 shadow-lg border border-base-300 text-xs">
|
||||
<?php else: ?>
|
||||
<div class="dropdown dropdown-end dropdown-hover">
|
||||
<div class="dropdown dropdown-top dropdown-end dropdown-hover">
|
||||
<div tabindex="0" role="button"
|
||||
class="btn btn-xs w-full"
|
||||
:class="req.VAL1USER && req.VAL2USER ? 'btn-success text-white' : 'btn-warning'">
|
||||
@ -246,20 +246,30 @@ $previewEnabled = $configFile[$configKey]['previewEnabled'] ?? false;
|
||||
<span class="text-xs" x-text="req.VAL1USER && req.VAL2USER ? 'Ready' : 'Pending'"></span>
|
||||
</div>
|
||||
<ul tabindex="0"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-40 p-2 shadow-lg border border-base-300">
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-40 p-2 shadow-lg border border-base-300 text-xs">
|
||||
<?php endif; ?>
|
||||
<template x-if="req.VAL1USER && req.VAL2USER">
|
||||
<div>
|
||||
<li>
|
||||
<a :href="'<?=base_url('report/');?>' + req.SP_ACCESSNUMBER" target="_blank">
|
||||
<i class="fa fa-print mr-2"></i> Print
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a :href="'http://glenlis/pdf/' + req.REQDATE.split(' ')[0].split('-').join('/') + '/' + req.SP_ACCESSNUMBER + '.pdf'" target="_blank">
|
||||
<i class="fa fa-file-pdf mr-2"></i> PDF
|
||||
</a>
|
||||
</li>
|
||||
<div>
|
||||
<li>
|
||||
<a :href="'<?=base_url('report/');?>' + req.SP_ACCESSNUMBER" target="_blank">
|
||||
<i class="fa fa-print mr-2"></i> Print
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a :href="'http://glenlis/pdf/' + req.REQDATE.split(' ')[0].split('-').join('/') + '/' + req.SP_ACCESSNUMBER + '.pdf'" target="_blank">
|
||||
<i class="fa fa-file-pdf mr-2"></i> PDF
|
||||
</a>
|
||||
</li>
|
||||
<li x-show="req.REPORT_LANG == 1">
|
||||
<a :href="'<?=base_url('report/');?>' + req.SP_ACCESSNUMBER + '/print/eng'" target="_blank">
|
||||
<i class="fa fa-print mr-2"></i> Print Eng
|
||||
</a>
|
||||
</li>
|
||||
<li x-show="req.REPORT_LANG == 1">
|
||||
<a :href="'http://glenlis/pdf/' + req.REQDATE.split(' ')[0].split('-').join('/') + '/' + req.SP_ACCESSNUMBER + '_eng.pdf'" target="_blank">
|
||||
<i class="fa fa-file-pdf mr-2"></i> PDF Eng
|
||||
</a>
|
||||
</li>
|
||||
<?php if (!in_array(session('userroleid'), [3, 4])): ?>
|
||||
<li>
|
||||
<a @click="openGenerateDialog(req.SP_ACCESSNUMBER)">
|
||||
@ -268,7 +278,13 @@ $previewEnabled = $configFile[$configKey]['previewEnabled'] ?? false;
|
||||
</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<li x-show="!req.REPORT_LANG || req.REPORT_LANG != 1">
|
||||
<a @click="openEngResultDialog(req)">
|
||||
<i class="fa fa-language mr-2"></i>
|
||||
<span>Create Eng Result</span>
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
</template>
|
||||
<?php if (!$previewEnabled): ?>
|
||||
<template x-if="!req.VAL1USER || !req.VAL2USER">
|
||||
@ -289,12 +305,12 @@ $previewEnabled = $configFile[$configKey]['previewEnabled'] ?? false;
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<div class="dropdown dropdown-end dropdown-hover">
|
||||
<div class="dropdown dropdown-top dropdown-end dropdown-hover">
|
||||
<div tabindex="0" role="button" class="btn btn-xs btn-primary w-full">
|
||||
<i class="fa fa-cog mr-1"></i> Actions
|
||||
</div>
|
||||
<ul tabindex="0"
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-48 p-2 shadow-lg border border-base-300">
|
||||
class="dropdown-content menu bg-base-100 rounded-box z-[1] w-48 p-2 shadow-lg border border-base-300 text-xs">
|
||||
<li x-show="req.ISVAL == 1 && req.ISPENDING != 1 && (req.VAL1USER == '<?= session('userid'); ?>' || req.VAL2USER == '<?= session('userid'); ?>')">
|
||||
<?php if (session()->get('userlevel') <= 1): ?>
|
||||
<a @click="openUnvalDialog(req.SP_ACCESSNUMBER)" class="text-error hover:bg-error/10">
|
||||
|
||||
72
app/Views/shared/dialog_eng_result.php
Normal file
72
app/Views/shared/dialog_eng_result.php
Normal file
@ -0,0 +1,72 @@
|
||||
<dialog class="modal" :open="isDialogEngResultOpen" @keydown.escape="closeEngResultDialog()">
|
||||
<div class="modal-box w-2/3 max-w-5xl h-[85vh] flex flex-col p-0 overflow-hidden bg-base-100" x-trap.noreturn="isDialogEngResultOpen">
|
||||
<!-- Header -->
|
||||
<div class="bg-base-200 p-3 border-b border-base-300">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<h3 class="font-bold text-lg">Create Eng Result</h3>
|
||||
<div class="text-sm text-base-content/70 mt-1">
|
||||
Access#: <span x-text="engResultItem?.SP_ACCESSNUMBER" class="font-mono font-bold"></span>
|
||||
<span class="mx-2">|</span>
|
||||
Patient: <span x-text="engResultItem?.PATNAME || engResultItem?.Name"></span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-ghost" @click="closeEngResultDialog()" aria-label="Close">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="flex-1 flex flex-col min-h-0 p-4">
|
||||
<p class="text-sm text-base-content/70 mb-3">
|
||||
Review the English version below. If it looks correct, click Confirm to enable Print Eng and PDF Eng options.
|
||||
<span x-show="!engResultItem?.VAL1USER || !engResultItem?.VAL2USER" class="text-error ml-2">
|
||||
<i class="fa fa-exclamation-circle"></i> Request must be validated first
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="flex-1 relative">
|
||||
<!-- Loading spinner -->
|
||||
<template x-if="!isEngResultIframeLoaded">
|
||||
<div class="absolute inset-0 flex items-center justify-center bg-base-100 z-10">
|
||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- English report iframe -->
|
||||
<iframe id="eng-result-iframe"
|
||||
x-ref="engResultIframe"
|
||||
:src="getEngResultUrl()"
|
||||
@load="onEngResultIframeLoad()"
|
||||
class="w-full h-full border border-base-300 rounded"
|
||||
frameborder="0"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="bg-base-200 p-4 border-t border-base-300 flex justify-between items-center">
|
||||
<div class="text-xs text-base-content/60">
|
||||
<span x-show="!isEngResultIframeLoaded">Loading preview...</span>
|
||||
<span x-show="isEngResultIframeLoaded" class="text-success">
|
||||
<i class="fa fa-check-circle"></i> Preview loaded
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button class="btn btn-sm" @click="closeEngResultDialog()">
|
||||
Cancel
|
||||
</button>
|
||||
<button class="btn btn-sm btn-primary"
|
||||
@click="confirmCreateEngResult()"
|
||||
:disabled="!isEngResultIframeLoaded || isCreatingEngResult || !engResultItem?.VAL1USER || !engResultItem?.VAL2USER">
|
||||
<span x-show="!isCreatingEngResult">Confirm</span>
|
||||
<span x-show="isCreatingEngResult" class="flex items-center gap-2">
|
||||
<span class="loading loading-spinner loading-xs"></span>
|
||||
Creating...
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-backdrop bg-black/30" @click="closeEngResultDialog()"></div>
|
||||
</dialog>
|
||||
@ -101,12 +101,14 @@
|
||||
<h6 class="p-0 m-0">Coll.</h6>
|
||||
</button>
|
||||
</template>
|
||||
<template x-if="sample.tubestatus != 0">
|
||||
<button class="btn btn-sm btn-error px-2 py-1"
|
||||
@click="unreceive(sample.sampcode, item.accessnumber)">
|
||||
<h6 class="p-0 m-0">Un-Recv.</h6>
|
||||
</button>
|
||||
</template>
|
||||
<?php if (in_array(session('userroleid'), [0, 1])): ?>
|
||||
<template x-if="sample.tubestatus != 0">
|
||||
<button class="btn btn-sm btn-error px-2 py-1"
|
||||
@click="unreceive(sample.sampcode, item.accessnumber)">
|
||||
<h6 class="p-0 m-0">Un-Recv.</h6>
|
||||
</button>
|
||||
</template>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td></td>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
</head>
|
||||
|
||||
<body class="bg-base-200 h-screen overflow-hidden" x-data="main">
|
||||
<div class="flex flex-col h-full">
|
||||
<div class="flex flex-col h-screen">
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar bg-base-100 shadow-md px-6 z-20">
|
||||
<div class='flex-1'>
|
||||
@ -73,7 +73,9 @@
|
||||
</nav>
|
||||
|
||||
<!-- Page Content -->
|
||||
<?= $this->renderSection('content'); ?>
|
||||
<div class="flex-1 overflow-y-auto">
|
||||
<?= $this->renderSection('content'); ?>
|
||||
</div>
|
||||
<?= $this->include('shared/dialog_setPassword'); ?>
|
||||
|
||||
<footer class='bg-base-100 p-1 mt-auto'>© <?= date('Y'); ?> - 5Panda</footer>
|
||||
|
||||
@ -532,6 +532,65 @@ document.addEventListener('alpine:init', () => {
|
||||
}
|
||||
},
|
||||
|
||||
// English Result Dialog
|
||||
isDialogEngResultOpen: false,
|
||||
engResultAccessnumber: null,
|
||||
engResultItem: null,
|
||||
isCreatingEngResult: false,
|
||||
isEngResultIframeLoaded: false,
|
||||
|
||||
openEngResultDialog(item) {
|
||||
this.engResultItem = item;
|
||||
this.engResultAccessnumber = item.SP_ACCESSNUMBER;
|
||||
this.isEngResultIframeLoaded = false;
|
||||
this.isCreatingEngResult = false;
|
||||
this.isDialogEngResultOpen = true;
|
||||
},
|
||||
|
||||
closeEngResultDialog() {
|
||||
this.isDialogEngResultOpen = false;
|
||||
this.engResultAccessnumber = null;
|
||||
this.engResultItem = null;
|
||||
this.isEngResultIframeLoaded = false;
|
||||
this.isCreatingEngResult = false;
|
||||
},
|
||||
|
||||
getEngResultUrl() {
|
||||
if (this.engResultAccessnumber) {
|
||||
return `${BASEURL}report/${this.engResultAccessnumber}?eng=1`;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
onEngResultIframeLoad() {
|
||||
this.isEngResultIframeLoaded = true;
|
||||
},
|
||||
|
||||
async confirmCreateEngResult() {
|
||||
if (!this.engResultAccessnumber || this.isCreatingEngResult) return;
|
||||
|
||||
this.isCreatingEngResult = true;
|
||||
try {
|
||||
const res = await fetch(`${BASEURL}/api/requests/${this.engResultAccessnumber}/eng`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
const data = await res.json();
|
||||
this.isCreatingEngResult = false;
|
||||
|
||||
if (data.status === 'success') {
|
||||
this.showToast('English result created successfully', 'success');
|
||||
this.closeEngResultDialog();
|
||||
this.fetchList();
|
||||
} else {
|
||||
this.showToast(data.message || 'Failed to create English result', 'error');
|
||||
}
|
||||
} catch (e) {
|
||||
this.isCreatingEngResult = false;
|
||||
this.showToast('Failed to create English result', 'error');
|
||||
}
|
||||
},
|
||||
|
||||
showToast(message, type = 'success') {
|
||||
const toast = document.createElement('div');
|
||||
toast.className = `alert alert-${type} fixed top-4 right-4 z-50`;
|
||||
|
||||
@ -11,6 +11,7 @@ $roleConfig = $config['superuser'];
|
||||
<?= $this->include('shared/dialog_unval'); ?>
|
||||
<?= $this->include('shared/dialog_audit'); ?>
|
||||
<?= $this->include('shared/dialog_results_generate'); ?>
|
||||
<?= $this->include('shared/dialog_eng_result'); ?>
|
||||
<?= $this->include('shared/dialog_preview'); ?>
|
||||
</main>
|
||||
<?= $this->endSection(); ?>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user