This commit is contained in:
mahdahar 2025-12-04 16:54:22 +07:00
parent fff385d7c6
commit d4a835fe0b
3 changed files with 113 additions and 31 deletions

View File

@ -1,8 +1,8 @@
<dialog id="form" class="modal" :open="isDialogSampleOpen"> <dialog class="modal" :open="isDialogSampleOpen">
<div class="modal-box w-2/3 max-w-5xl"> <div class="modal-box w-2/3 max-w-5xl">
<p class='text-right'><button class="btn btn-xs btn-neutral" @click="closeSampleDialog()">X</button></p> <p class='text-right'><button class="btn btn-xs btn-neutral" @click="closeSampleDialog()">X</button></p>
<table class="table table-xs table-compact w-full"> <table class="table table-xs table-compact w-full mb-4">
<tr> <tr>
<td>MR# </td> <td x-text="': '+item.patnumber"></td> <td>MR# </td> <td x-text="': '+item.patnumber"></td>
<td>Patient Name </td> <td x-text="': '+item.patname"></td> <td>Patient Name </td> <td x-text="': '+item.patname"></td>
@ -12,7 +12,11 @@
<td>Sex / Age </td> <td x-text="': '+item.placeofbirth+' '+item.gender+' / '+item.age"></td> <td>Sex / Age </td> <td x-text="': '+item.placeofbirth+' '+item.gender+' / '+item.age"></td>
</tr> </tr>
<tr> <tr>
<td>Note</td> <td colspan='3' x-text="': '+item.comment"></td> <td>Note</td>
<td colspan='3'>
<textarea x-text="item.comment" class="textarea textarea-bordered w-full"></textarea>
<button class="btn btn-sm btn-primary mt-2" @click="saveComment(item.accessnumber)">Save</button>
</td>
</tr> </tr>
</table> </table>
@ -37,27 +41,31 @@
<td></td> <td>All</td> <td></td> <td></td> <td></td> <td>All</td> <td></td> <td></td>
<td> <td>
<button class="btn btn-sm btn-secondary px-2 py-1"><i class="fa-solid fa-print"></i></i></button> <button class="btn btn-sm btn-secondary px-2 py-1"><i class="fa-solid fa-print"></i></i></button>
<button class="btn btn-success px-2 py-1" onclick=""><h6 class="p-0 m-0">Coll.</h6></button> <button class="btn btn-sm btn-success px-2 py-1" onclick=""><h6 class="p-0 m-0">Coll.</h6></button>
<button class="btn btn-warning px-2 py-1" onclick=""><h6 class="p-0 m-0">Un-Coll.</h6></button> <button class="btn btn-sm btn-warning px-2 py-1" onclick=""><h6 class="p-0 m-0">Un-Coll.</h6></button>
<button class="btn btn-warning px-2 py-1" onclick=""><h6 class="p-0 m-0">Un-Recv.</h6></button> <button class="btn btn-sm btn-warning px-2 py-1" onclick=""><h6 class="p-0 m-0">Un-Recv.</h6></button>
</td> </td>
</tr> </tr>
[{"samptypeid":40,"sampcode":"900","name":"Other","colstatus":"1","tubestatus":0}]
<template x-for="samples as sample" :key="sample.samptypeid">
<template x-for="sample in item.samples">
<tr> <tr>
<td x-text="sample.sampcode"></td> <td x-text="sample.sampcode"></td>
<td x-text="sample.name"></td> <td x-text="sample.name"></td>
<td class='text-center'> <td class='text-center'>
<input type="checkbox" class="checkbox" x-bind:checked="sample.colstatus === 1" disabled> <input type="checkbox" class="checkbox" x-bind:checked="sample.colstatus == 1" disabled>
</td> </td>
<td class='text-center'> <td class='text-center'>
<input type="checkbox" class="checkbox" x-bind:checked="sample.tubestatus != 0" disabled> <input type="checkbox" class="checkbox" x-bind:checked="sample.tubestatus != 0" disabled>
</td> </td>
<td> <td>
<button class="btn btn-sm btn-secondary px-2 py-1"><i class="fa-solid fa-printer"></i></button> <button class="btn btn-sm btn-secondary px-2 py-1"><i class="fa-solid fa-print"></i></button>
<button class="btn btn-sm btn-success px-2 py-1" onclick="collect({{accessnumber}}, {{sampcode}}, 1)"><h6 class="p-0 m-0">Coll.</h6></button> <button class="btn btn-sm btn-success px-2 py-1" @click="collect(sample.sampcode, item.accessnumber)">
<button class="btn btn-sm btn-warning px-2 py-1" onclick="collect({{accessnumber}}, {{sampcode}}, 0)"><h6 class="p-0 m-0">Un-Coll.</h6></button> <h6 class="p-0 m-0">Coll.</h6></button>
<button class="btn btn-sm gbtn-warning px-2 py-1" onclick="unreceive({{accessnumber}}, {{sampcode}})"><h6 class="p-0 m-0">Un-Recv.</h6></button> <button class="btn btn-sm btn-warning px-2 py-1" @click="uncollect(sample.sampcode, item.accessnumber)">
<h6 class="p-0 m-0">Un-Coll.</h6></button>
<button class="btn btn-sm btn-warning px-2 py-1" @click="unreceive(sample.sampcode, item.accessnumber)">
<h6 class="p-0 m-0">Un-Recv.</h6></button>
</td> </td>
<td> <td>
@ -65,14 +73,6 @@
</tr> </tr>
</template> </template>
<tr class="text-center">
<td colspan="6">
<h6 class="p-0 m-0">
<i class="fa-solid fa-pencil" role="button" onclick="commentValue()"></i>
</h6>
</td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@ -0,0 +1,15 @@
<dialog class="modal" :open="isDialogValOpen">
<div class="modal-box w-2/3 max-w-5xl">
<p class='text-right mx-3 mb-2'>
<button class="btn btn-sm btn-neutral" @click="closeValDialog()">Cancel</button>
<button id="validate-btn" x-ref="validateBtn" class="btn btn-sm btn-success"
@click="validate(valAccessnumber)" :disabled="!isValidateEnabled">Validate</button>
</p>
<template x-if="valAccessnumber">
<!-- <iframe id="result-iframe" src="http://glenlis/spooler_db/main_dev.php?acc=" width="750px" height="600px"></iframe> -->
<iframe id="result-iframe" x-ref="resultIframe" src="<?=base_url('dummypage');?>" width="750px" height="600px"></iframe>
</template>
</div>
</dialog>

View File

@ -53,6 +53,7 @@
<button @click="filterKey = 'Inc'" :class="filterKey === 'Inc' ? 'btn-active' : ''" class="btn btn-outline btn-sm btn-warning"><span x-text="counters.Inc"></span> Incomplete</button> <button @click="filterKey = 'Inc'" :class="filterKey === 'Inc' ? 'btn-active' : ''" class="btn btn-outline btn-sm btn-warning"><span x-text="counters.Inc"></span> Incomplete</button>
<button @click="filterKey = 'Fin'" :class="filterKey === 'Fin' ? 'btn-active' : ''" class="btn btn-outline btn-sm btn-success"><span x-text="counters.Fin"></span> Final</button> <button @click="filterKey = 'Fin'" :class="filterKey === 'Fin' ? 'btn-active' : ''" class="btn btn-outline btn-sm btn-success"><span x-text="counters.Fin"></span> Final</button>
<button @click="filterKey = 'Total'" :class="filterKey === 'Total' ? 'btn-active' : ''" class="btn btn-outline btn-sm"><span x-text="counters.Total"></span> Total</button> <button @click="filterKey = 'Total'" :class="filterKey === 'Total' ? 'btn-active' : ''" class="btn btn-outline btn-sm"><span x-text="counters.Total"></span> Total</button>
<button @click="filterKey = 'Validated'" :class="filterKey === 'Validated' ? 'btn-active' : ''" class="btn btn-outline btn-sm btn-info"><span x-text="validatedCount"></span> Val</button>
</div> </div>
</div> </div>
<div class="flex gap-3 mb-2"> <div class="flex gap-3 mb-2">
@ -98,8 +99,14 @@
<td> <td>
<div>1: <span x-text="req.val1user"></span></div> <div>1: <span x-text="req.val1user"></span></div>
<div>2: <span x-text="req.val2user"></span></div> <div>2: <span x-text="req.val2user"></span></div>
<template x-if="req.ISVAL == 1">
<div>
<button class="btn btn-xs btn-outline btn-secondary" @click="unval(req.SP_ACCESSNUMBER)"><i class="fa-solid fa-rotate-right"></i></button>
<button class="btn btn-xs btn-outline btn-success" @click="openValDialog(req.SP_ACCESSNUMBER)"><i class="fa-solid fa-check"></i></button>
</div>
</template>
</td> </td>
<td><button x-text="req.STATS" class="btn btn-xs" <td><button x-text="req.STATS === 'Fin' ? 'Final' : req.STATS" class="btn btn-xs"
:class="statusColor[req.STATS]" @click="openSampleDialog(req.SP_ACCESSNUMBER)"></button></td> :class="statusColor[req.STATS]" @click="openSampleDialog(req.SP_ACCESSNUMBER)"></button></td>
</tr> </tr>
</template> </template>
@ -110,6 +117,8 @@
</div> </div>
<?php echo $this->include('v2/dialog_sample'); ?> <?php echo $this->include('v2/dialog_sample'); ?>
<?php echo $this->include('v2/dialog_val'); ?>
</main> </main>
<footer class='bg-base-100 p-1'>&copy; 2025 - 5Panda</footer> <footer class='bg-base-100 p-1'>&copy; 2025 - 5Panda</footer>
@ -149,11 +158,11 @@
init() { init() {
this.today = new Date().toISOString().slice(0, 10); this.today = new Date().toISOString().slice(0, 10);
this.filter.date1 = "2025-05-05"; this.filter.date1 = "2025-03-03";
this.filter.date2 = "2025-05-05"; this.filter.date2 = "2025-03-03";
//this.fetchList();
//this.filter.date1 = this.today; //this.filter.date1 = this.today;
//this.filter.date2 = this.today; //this.filter.date2 = this.today;
this.fetchList();
}, },
fetchList(){ fetchList(){
@ -193,10 +202,14 @@
get filtered() { get filtered() {
let data = this.list; let data = this.list;
if (this.filterKey === 'Validated') {
data = data.filter(i => i.ISVAL == 1);
} else {
const valid = this.statusMap[this.filterKey] const valid = this.statusMap[this.filterKey]
if (valid.length > 0) { if (valid.length > 0) {
data = data.filter(i => valid.includes(i.STATS)); data = data.filter(i => valid.includes(i.STATS));
} }
}
if (this.filterTable) { if (this.filterTable) {
const s = this.filterTable.toLowerCase(); const s = this.filterTable.toLowerCase();
data = data.filter(i => data = data.filter(i =>
@ -205,9 +218,11 @@
) )
); );
} }
return data; return data;
}, },
get validatedCount() {
return this.list.filter(r => r.ISVAL == 1).length;
},
/* /*
sample dialog sample dialog
@ -228,10 +243,62 @@
this.item = []; this.item = [];
fetch(`${BASEURL}/api/sample/${accessnumber}`, { method: 'GET', headers: {'Content-Type': 'application/json'}}) fetch(`${BASEURL}/api/sample/${accessnumber}`, { method: 'GET', headers: {'Content-Type': 'application/json'}})
.then(res => res.json()).then(data => { .then(res => res.json()).then(data => {
this.item = data.data ?? []; this.item = data.data ?? {};
if (!Array.isArray(this.item.samples)) this.item.samples = [];
}); });
}, },
/*
validate dialog
*/
isDialogValOpen : false,
isValidateEnabled: false,
valAccessnumber : null,
openValDialog (accessnumber) {
this.isDialogValOpen = true;
this.valAccessnumber = accessnumber;
this.$nextTick(() => {
// refs will be available after render
const iframe = this.$root.querySelector('#result-iframe') || (this.$refs && this.$refs.resultIframe);
const validateBtn = this.$root.querySelector('#validate-btn') || (this.$refs && this.$refs.validateBtn);
if (!iframe || !validateBtn) return;
const setup = () => {
try {
const doc = iframe.contentDocument || iframe.contentWindow.document;
const scrollable = doc.documentElement || doc.body;
const checkScroll = () => {
try {
const atBottom = (scrollable.scrollHeight - scrollable.scrollTop - scrollable.clientHeight) < 2;
this.isValidateEnabled = atBottom;
validateBtn.disabled = !atBottom;
} catch (e) { /* cross-origin or not ready */ }
};
iframe.contentWindow.removeEventListener('scroll', checkScroll);
iframe.contentWindow.addEventListener('scroll', checkScroll);
checkScroll();
} catch (e) { /* ignore cross-origin */ }
};
// If iframe already loaded, setup immediately; otherwise wait for load
if (iframe.contentWindow && (iframe.contentDocument && iframe.contentDocument.readyState === 'complete')) {
setup();
} else {
iframe.addEventListener('load', setup);
}
});
},
closeValDialog () {
this.isDialogValOpen = false;
},
unval(accessnumber) {
console.log("Unvalidate access number:", accessnumber);
},
validate() {
// implement validation action
console.log('Validate clicked for', this.valAccessnumber);
},
})); }));
}); });