This commit is contained in:
mahdahar 2025-11-25 14:14:14 +07:00
parent 05846f4344
commit 40d7754876
11 changed files with 338 additions and 322 deletions

View File

@ -19,8 +19,6 @@ $routes->get('/logout', 'Auth::logout');
$routes->get('label/coll/(:any)', 'Label::coll/$1'); $routes->get('label/coll/(:any)', 'Label::coll/$1');
$routes->get('label/dispatch/(:any)/(:any)', 'Label::dispatch/$1/$2'); $routes->get('label/dispatch/(:any)/(:any)', 'Label::dispatch/$1/$2');
$routes->get('label/all/(:any)', 'Label::print_all/$1'); $routes->get('label/all/(:any)', 'Label::print_all/$1');
$routes->get('result/(:any)', 'Result::show/$1');
$routes->post('result/validate', 'Result::res_validate');
// ------------------------------------------------------Page Based on Role------------------------------------------------------ // // ------------------------------------------------------Page Based on Role------------------------------------------------------ //
$routes->group('admin', ['filter' => 'role:1'], function($routes) { $routes->group('admin', ['filter' => 'role:1'], function($routes) {
@ -30,7 +28,6 @@ $routes->group('admin', ['filter' => 'role:1'], function($routes) {
$routes->post('user/create', 'User::create'); $routes->post('user/create', 'User::create');
$routes->post('user/update', 'User::update'); $routes->post('user/update', 'User::update');
$routes->post('user/delete', 'User::delete'); $routes->post('user/delete', 'User::delete');
$routes->get('result/invalidate/(:any)', 'Result::invalidate/$1');
}); });
$routes->group('doctor', ['filter' => 'role:2'], function($routes) { $routes->group('doctor', ['filter' => 'role:2'], function($routes) {
@ -45,10 +42,15 @@ $routes->group('cs', ['filter' => 'role:4'], function($routes) {
$routes->get('/', 'CustomerService::index'); $routes->get('/', 'CustomerService::index');
}); });
// dummy long page
$routes->get('/dummypage', 'Home::dummyPage');
// ------------------------------------------------------For API------------------------------------------------------ // // ------------------------------------------------------For API------------------------------------------------------ //
// $routes->get('/api/dashboard', 'ApiDashboard::index'); // $routes->get('/api/dashboard', 'ApiDashboard::index');
$routes->get('api/result/(:any)', 'Result::show/$1'); $routes->get('api/request/validate/(:any)', 'Request::show/$1');
$routes->post('api/request/validate/(:any)', 'Request::val/$1');
$routes->delete('api/request/validate/(:any)', 'Request::unval/$1');
$routes->get('api/specimen/(:any)', 'Specimen::show/$1'); $routes->get('api/specimen/(:any)', 'Specimen::show/$1');
$routes->post('api/specimen/collect/(:any)', 'Specimen::collect/$1'); $routes->post('api/specimen/collect/(:any)', 'Specimen::collect/$1');
$routes->post('api/specimen/unreceive/(:any)', 'Specimen::unreceive/$1'); $routes->delete('api/specimen/receive/(:any)', 'Specimen::unreceive/$1');

View File

@ -113,7 +113,4 @@ class Admin extends BaseController
return view('admin/modal_specimen'); return view('admin/modal_specimen');
} }
public function result_show() {
return view('result/result_show');
}
} }

View File

@ -2,12 +2,10 @@
namespace App\Controllers; namespace App\Controllers;
class Home extends BaseController class Home extends BaseController {
{
// Khusus Untuk Menangani URL http://glenlis // Khusus Untuk Menangani URL http://glenlis
public function index() public function index() {
{
$session = session(); $session = session();
// Jika belum login, arahkan ke /login // Jika belum login, arahkan ke /login
@ -24,4 +22,8 @@ class Home extends BaseController
default: return redirect()->to('/login'); default: return redirect()->to('/login');
} }
} }
public function dummyPage() {
return view('dummy_page');
}
} }

View File

@ -0,0 +1,76 @@
<?php
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
class Request extends BaseController {
use ResponseTrait;
public function show($accessnumber) {
$db = db_connect();
$data['accessnumber'] = $accessnumber;
$sql = "SELECT d.STATS, r.* FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d
left join GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER=d.SP_ACCESSNUMBER
WHERE d.SP_ACCESSNUMBER='$accessnumber'";
$result = $db
->query($sql)
->getResultArray();
$data['val1'] = $result[0]['ISVAL1'];
$data['val1user'] = $result[0]['VAL1USER'];
$data['val2'] = $result[0]['ISVAL2'];
$data['val2user'] = $result[0]['VAL2USER'];
return view('admin/modal_request',$data);
}
public function unval($accessnumber) {
$input = $this->request->getJSON(true);
$userid = $input['userid'];
$db = db_connect();
$sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=0, VAL1USER=null, VAL1DATE=null,
ISVAL2=0, VAL2USER=null, VAL2DATE=null where ACCESSNUMBER='$accessnumber'";
$result = $db->query($sql);
$data = ['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber" ];
return $this->response->setJSON($data);
}
public function val($accessnumber) {
$input = $this->request->getJSON(true);
$userid = $input['userid'];
$db = db_connect();
//cek val
$sql = "select * from GDC_CMOD.dbo.CM_REQUESTS where ACCESSNUMBER='$accessnumber'";
$result = $db->query($sql)->getResultArray();
$data['sql1'] = $sql;
//$data['data'] = $result;
if(!isset($result[0])) {
$sql = "insert into GDC_CMOD.dbo.CM_REQUESTS(ACCESSNUMBER, ISVAL1, VAL1USER, VAL1DATE) VALUES ('$accessnumber', 1, '$userid', GETDATE())";
$db->query($sql);
} else {
$row = $result[0];
$isval1 = $row['ISVAL1'];
$isval2 = $row['ISVAL2'];
$val1user = $row['VAL1USER'];
if( $isval1 == 1 ) {
// val done
if ( $isval2 == 1 ) { return $this->response->setJSON(['message'=> 'validation done, not updating anything']); }
else {
// val2 if user val1 != userid
if($val1user != $userid) {
$sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL2=1, VAL2USER='$userid', VAL2DATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
} else {
$this->response->setStatusCode(500);
return $this->response->setJSON([ 'message'=> 'user already validate this request' ]);
}
}
} else {
// val1
$sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=1, VAL1USER='$userid', VAL1DATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
}
$db->query($sql);
$data['message'] = "Validation updated";
}
return $this->response->setJSON($data);
}
}

View File

@ -1,44 +0,0 @@
<?php
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
class Result extends BaseController {
use ResponseTrait;
public function show($accessnumber) {
$db = db_connect();
$data['accessnumber'] = $accessnumber;
$sql = "SELECT d.STATS, r.ISVAL2 FROM GDC_CMOD.dbo.V_DASHBOARD_DEV d
left join GDC_CMOD.dbo.CM_REQUESTS r ON r.ACCESSNUMBER=d.SP_ACCESSNUMBER
WHERE d.SP_ACCESSNUMBER='$accessnumber'";
$result = $db
->query($sql)
->getResultArray();
$data['status'] = $result[0]['STATS'];
$data['verif'] = $result[0]['ISVAL2'];
//return view('result/result_show',$data);
return view('admin/modal_result',$data);
}
public function invalidate($accessnumber) {
$db = db_connect();
$sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL=null, VALUSER=null, VALDATE=null,
ISVAL2=null, VAL2USER=null, VAL2DATE=null where ACCESSNUMBER='$accessnumber'";
$result = $db->query($sql);
$data = ['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber" ];
return $this->response->setJSON($data);
}
public function res_validate() {
$input = $this->request->getJSON(true);
$accessnumber = $input['accessnumber'];
$userid = $input['userid'];
$db = db_connect();
$sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL2=1, VAL2USER='$userid', VAL2DATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
$result = $db->query($sql);
$data = ['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber" ];
return $this->response->setJSON($data);
}
}

View File

@ -126,8 +126,8 @@
<?php if($row['val'] != 2) { ?> <?php if($row['val'] != 2) { ?>
<tr> <tr>
<td> <td>
<button class='btn btn-xs btn-outline-secondary px-1 py-0 mb-1' onclick="unverify(<?=$row['sp_accessnumber'];?>)"><i class="bi bi-arrow-counterclockwise"></i></button> <button class='btn btn-xs btn-outline-secondary px-1 py-0 mb-1' onclick="unvalidate(<?=$row['sp_accessnumber'];?>,'<?=session('userid');?>?>')"><i class="bi bi-arrow-counterclockwise"></i></button>
<button class='btn btn-xs btn-outline-success px-1 py-0 mb-1' onclick="verifyShow(<?=$row['sp_accessnumber'];?>)" data-bs-toggle="modal" data-bs-target="#verifyModal"><i class="bi bi-check-lg"></i></button> <button class='btn btn-xs btn-outline-success px-1 py-0 mb-1' onclick="validateShow(<?=$row['sp_accessnumber'];?>)" data-bs-toggle="modal" data-bs-target="#verifyModal"><i class="bi bi-check-lg"></i></button>
</td> </td>
</tr> </tr>
<?php } ?> <?php } ?>
@ -138,12 +138,9 @@
<a href="http://glenlis/spooler_db/main_dev.php?acc=<?=$row['sp_accessnumber'];?>&eng=1" target="_blank" class="btn btn-xs btn-primary py-0 px-1">Eng</a> | <a href="http://glenlis/spooler_db/main_dev.php?acc=<?=$row['sp_accessnumber'];?>&eng=1" target="_blank" class="btn btn-xs btn-primary py-0 px-1">Eng</a> |
<a href="#" class="btn btn-xs btn-secondary py-0 px-1">Pdf</a> <br /> <a href="#" class="btn btn-xs btn-secondary py-0 px-1">Pdf</a> <br />
<?php } ?> <?php } ?>
<?php if ($row['val'] != 0) {?>
<a href="#" class="btn btn-xs btn-secondary py-0 px-2 invalidate-btn" onclick="invalidate('<?=$row['sp_accessnumber'];?>'); return false;">Invalidate</a><br>
<?php }?>
--> -->
</td> </td>
<td class="pointercol <?= esc($class) ?>" data-access="<?= $row['sp_accessnumber'] ?>" data-bs-toggle="modal" data-bs-target="#detailModal"> <?= esc($row['stats']) ?> </td> <td class="pointercol <?= esc($class) ?>" data-access="<?= $row['sp_accessnumber'] ?>" onclick="detailShow(<?=$row['sp_accessnumber'];?>)" data-bs-toggle="modal" data-bs-target="#detailModal"> <?= esc($row['stats']) ?> </td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
@ -167,10 +164,6 @@
<div class="modal fade" id="verifyModal" aria-hidden="true" aria-labelledby="verifyModal" tabindex="-1"> <div class="modal fade" id="verifyModal" aria-hidden="true" aria-labelledby="verifyModal" tabindex="-1">
<div class="modal-dialog modal-xl modal-dialog-centered"> <div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fw-bold fs-4" id="detailModal">Verification</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="verifyModalContent"> </div> <div class="modal-body" id="verifyModalContent"> </div>
</div> </div>
</div> </div>
@ -224,137 +217,8 @@
}); });
function invalidate(accessnumber) { const BASE_URL = "<?= base_url(); ?>";
if(confirm("Are you sure?")) {
$.get(`<?=base_url('admin/result/invalidate/');?>/${accessnumber}`);
const cell = document.querySelector(`[data-acc="${accessnumber}"]`);
if(cell){
cell.querySelector(".badge").textContent = "0";
const btn = cell.querySelector(".invalidate-btn");
if (btn) btn.remove();
}
}
}
function collect(accessnumber, samplenumber, status) {
// toggle checkbox
const row = document.getElementById(`row-${accessnumber}-${samplenumber}`);
const checkbox = row.querySelector('.coll-checkbox');
checkbox.checked = status;
$.ajax({
url: `<?=base_url('api/specimen/collect');?>/${accessnumber}`,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ samplenumber:samplenumber, status:status, userid:"<?=session('userid');?>" }),
success: function(response) {
console.log("Success:", response);
},
error: function(xhr, status, error) {
console.error("Error:", status, error);
}
});
}
function verifyShow(accessNumber) {
const modalBody = $('#verifyModal .modal-body');
modalBody.html('<div class="text-center py-5"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div><p class="mt-2">Fetching verification details for #' + accessNumber + '...</p></div>');
$.ajax({
url: '<?= base_url('api/result/'); ?>'+accessNumber,
method: 'GET',
dataType: 'html',
success: function(response) {
modalBody.html(response);
},
error: function(xhr, status, error) {
console.error("AJAX Error:", status, error);
modalBody.html(`
<div class="alert alert-danger" role="alert">
<strong>Error loading content:</strong> Could not retrieve verification details.
<p class="mt-1 mb-0"><small>Details: ${error}</small></p>
</div>
`);
}
});
};
function verify(accessnumber) {
// toggle checkbox
const row = document.getElementById(`row-${accessnumber}`);
$.ajax({
url: `<?=base_url('api/request/verify');?>/${accessnumber}`,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ userid:"<?=session('userid');?>" }),
success: function(response) {
console.log("Success:", response);
},
error: function(xhr, status, error) {
console.error("Error:", status, error);
}
});
}
function unreceive(accessnumber, samplenumber) {
// toggle checkbox
const row = document.getElementById(`row-${accessnumber}-${samplenumber}`);
const checkbox = row.querySelector('.recv-checkbox');
checkbox.checked = status;
$.ajax({
url: `<?=base_url('api/specimen/unreceive');?>/${accessnumber}`,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ samplenumber:samplenumber }),
success: function(response) {
console.log("Success:", response);
},
error: function(xhr, status, error) {
console.error("Error:", status, error);
}
});
}
// Untuk Koment Value
function commentValue() {
const input = prompt("Masukkan Komentar :");
}
// Untuk Detail
document.addEventListener('DOMContentLoaded', function () {
const modal = document.getElementById('detailModal');
const modalContent = document.getElementById('specimenModalContent');
document.querySelectorAll('.pointercol').forEach(td => {
td.addEventListener('click', async function () {
const access = this.dataset.access;
modalContent.innerHTML =
"<p class='text-center text-muted'>Loading data...</p>";
try {
$.getJSON(`<?=base_url();?>api/specimen/${access}`, function(data) {
$.get(`<?=base_url('admin/modal_specimen');?>`, function(tpl) {
data.samples = data.samples.map(s => ({
...s,
is_coll: s.colstatus == 1,
is_recv: s.tubestatus == 4
}));
console.log(data);
const html = Mustache.render(tpl, data);
modalContent.innerHTML=html;
});
});
} catch (err) {
modalContent.innerHTML = "<p class='text-danger text-center'>Gagal memuat data.</p>";
console.error(err);
}
});
});
});
</script> </script>
<script src="<?=base_url('js/admin/specimen.js');?>"></script>
<script src="<?=base_url('js/admin/request.js');?>"></script>
<?= $this->endSection() ?> <?= $this->endSection() ?>

View File

@ -1,17 +1,13 @@
<div class='row mt-1'> <div class='row mb-2 mx-2'>
<div class="col"></div> <div class="col">val : <?=$val1user;?> - <?=$val2user;?></div>
<div class='col text-end'> <div class='col text-end'>
<button id='result-button' class='btn btn-xs btn-success' onclick='verify(<?=$accessnumber;?>)' disabled>Verify</button> <button id='result-button' class='btn btn-xs btn-success' onclick='validate(<?=$accessnumber;?>, "<?=session('userid');?>" )' disabled>Verify</button>
</div> </div>
</div> </div>
<div class="row mx-auto"> <div class="row mx-auto">
<iframe <!-- <iframe id="result-iframe" src="http://glenlis/spooler_db/main_dev.php?acc=<?=$accessnumber;?>" width="750px" height="600px"> -->
id="result-iframe" <iframe id="result-iframe" src="<?=base_url('dummypage');?>" width="750px" height="600px">
class="embed-responsive-item"
src="http://glenlis/spooler_db/main_dev.php?acc=<?=$accessnumber;?>"
width="750px" height="600px"
>
<p>Your browser does not support iframes. Please contact the technical support.</p> <p>Your browser does not support iframes. Please contact the technical support.</p>
</iframe> </iframe>

96
app/Views/dummy_page.php Normal file
View File

@ -0,0 +1,96 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title> Test display of HTML elements </title>
<!-- based off of https://www.cs.tut.fi/~jkorpela/www/testel.html, with additions of newer features -->
</head>
<body>
<header>
<h1>Testing display of HTML elements</h1>
<p>This is the document <code>header</code></p>
</header>
<main>
<article aria-label="headings">
<h1>This is 1st level heading</h1>
<p>This is a test paragraph.</p>
<h2>This is 2nd level heading</h2>
<p>This is a test paragraph.</p>
<h3>This is 3rd level heading</h3>
<p>This is a test paragraph.</p>
<h4>This is 4th level heading</h4>
<p>This is a test paragraph.</p>
<h5>This is 5th level heading</h5>
<p>This is a test paragraph.</p>
<h6>This is 6th level heading</h6>
<p>This is a test paragraph.</p>
</article>
<article>
<h2>Basic block level elements</h2>
<p>
This is a normal paragraph (<code>p</code> element). To add some length to it, let us mention that this page was primarily written for testing the effect of <strong>user style sheets</strong>. You can use it for various other purposes as well, like just checking how your browser displays various HTML elements by default. It can also be useful when testing conversions from HTML format to other formats, since some elements can go wrong then.
</p>
<p>
This is another paragraph. I think it needs to be added that the set of elements tested is not exhaustive in any sense. I have selected those elements for which it can make sense to write user style sheet rules, in my opionion.
</p>
<div>This is a <code>div</code> element. Authors may use such elements instead of paragraph markup for various reasons. (End of <code>div</code>.)</div>
<blockquote>
<p>
This is a block quotation containing a single paragraph. Well, not quite, since this is not <em>really</em> quoted text, but I hope you understand the point. After all, this page does not use HTML markup very normally anyway.
</p>
</blockquote>
<p>The following contains address information about the author, in an <code>address</code> element.</p>
<address>
<a href="../somelink.html" lang="fr" hreflang="en">Mon nom en francais</a>,
<a href="mailto:example@example.com">example@example.com</a><br>
3 Rue Jules Ferry, Neuilly Sur Seine, France 94000
</address>
</article>
<article>
<h2>Lists</h2>
<p>
This is a paragraph before an <strong>unnumbered</strong> list (<code>ul</code>). Note that the spacing between a paragraph and a list before or after that is hard to tune in a user style sheet. You can't guess which paragraphs are logically related to a list, e.g. as a "list header".
</p>
<ul>
<li> One.</li>
<li> Two.</li>
<li> Three. Well, probably this list item should be longer. Note that for short items lists look better if they are compactly presented, whereas for long items, it would be better to have more vertical spacing between items.</li>
<li> Four. This is the last item in this list. Let us terminate the list now without making any more fuss about it.</li>
</ul>
<p>The following is a <code>menu</code> list:</p>
<menu>
<li> One.</li>
<li> Two.</li>
<li> Three. Well, probably this list item should be longer so that it will probably wrap to the next line in rendering.</li>
</menu>
<p>The following is a <code>dir</code> list:</p>
<dir>
<li> One.</li>
<li> Two.</li>
<li> Three. Well, probably this list item should be longer so that it will probably wrap to the next line in rendering.</li>
</dir>
<p>
This is a paragraph before a <strong>numbered</strong> list (<code>ol</code>). Note that the spacing between a paragraph and a list before or after that is hard to tune in a user style sheet. You can't guess which paragraphs are logically related to a list, e.g. as a "list header".
</p>
<ol>
<li> One.</li>
<li> Two.</li>
<li> Three. Well, probably this list item should be longer. Note that if items are short, lists look better if they are compactly presented, whereas for long items, it would be better to have more vertical spacing between items.</li>
<li> Four. This is the last item in this list. Let us terminate the list now without making any more fuss about it.</li>
</ol>
<p>
This is a paragraph before a <strong>definition</strong> list (<code>dl</code>). In principle, such a list should consist of <em>terms</em> and associated definitions. But many authors use <code>dl</code> elements for fancy "layout" things. Usually the effect is not <em>too</em> bad, if you design user style sheet rules for <code>dl</code> which are suitable for real definition lists.
</p>
<dl>
<dt> recursion</dt>
<dd> see recursion</dd>
<dt> recursion, indirect</dt>
<dd> see indirect recursion</dd>
<dt> indirect recursion</dt>
<dd> see recursion, indirect</dd>
<dt> term</dt>
<dd> a word or other expression taken into specific use in a well-defined meaning, which is often defined rather rigorously, even formally, and may differ quite a lot from an everyday meaning</dd>
</dl>
</article>
</body>
</html>

View File

@ -1,113 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Result <?=$accessnumber?></title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
}
}
}
</script>
</head>
<?php
$userid = session('userid');
?>
<body class="bg-gray-50 flex items-start justify-center">
<div class="w-full max-w-4xl min-h-screen flex flex-col ">
<div class="flex-1 flex flex-col h-full bg-white rounded-2xl shadow-2xl space-y-6 p-3 m-2">
<header>
<p class="text-end">user : <?=$userid;?></p>
<p>Result lab# <?=$accessnumber;?><br />Status : <?=$status;?></p>
</header>
<div class='flex-1 flex flex-col relative shadow-inner bg-gray-100 border border-gray-300'>
<iframe
id="result-iframe"
title="PHP Embedded Content Demo"
class="flex-1"
src="http://glenlis/spooler_db/main_dev.php?acc=<?=$accessnumber;?>">
<p>Your browser does not support iframes. Please contact the technical support.</p>
</iframe>
<?php if($verif == 0) { ?>
<div class="absolute inset-0 flex items-center justify-center pointer-events-none z-20">
<span class="text-7xl font-black text-gray-600 opacity-20 transform rotate-[-30deg] select-none">
Unverified
</span>
</div>
<?php } ?>
</div>
<footer>
<?php if($verif == 0) { ?>
<p class='text-end'>
<button id='result-button'
class='bg-blue-500 text-white py-2 px-3 text-sm rounded-md
disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-gray-400 disabled:text-gray-200'
disabled onclick="validate()">Validate</button>
</p>
<?php } ?>
<p class="mt-2 text-gray-500 text-xs text-center">&copy; 2025 - 5panda</p>
</footer>
</div>
</div>
<script>
<?php if($verif == 0) { ?>
const iframe = document.getElementById('result-iframe');
const button = document.getElementById('result-button');
iframe.addEventListener('load', () => {
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
const scrollElement = iframeDoc.scrollingElement || iframeDoc.documentElement;
iframeDoc.addEventListener('scroll', () => {
const scrollTop = scrollElement.scrollTop;
const scrollHeight = scrollElement.scrollHeight;
const clientHeight = scrollElement.clientHeight;
// Check if scrolled to bottom
if (scrollTop + clientHeight >= scrollHeight - 2) {
button.disabled = false;
}
});
});
function validate() {
const ok = confirm('Are you sure?');
if (!ok) return;
const postData = {
accessnumber: '<?=$accessnumber;?>',
userid: '<?=$userid?>'
};
fetch('<?=base_url("result/validate");?>', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(postData)
})
.then(function (response) {
if (!response.ok) throw new Error('Failed to send data');
//return response.json();
})
.then(function (data) {
//location.reload();
})
.catch(function (error) {
alert('Error: ' + error.message);
});
}
<?php }?>
</script>
</body>
</html>

View File

@ -0,0 +1,62 @@
function validateShow(accessnumber) {
const modalBody = $('#verifyModal .modal-body');
modalBody.html('<div class="text-center py-5"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div><p class="mt-2">Fetching verification details for #' + accessnumber + '...</p></div>');
$.ajax({
url: `${BASE_URL}/api/request/validate/${accessnumber}`,
method: 'GET',
dataType: 'html',
success: function(response) {
modalBody.html(response);
},
error: function(xhr, status, error) {
console.error("AJAX Error:", status, error);
modalBody.html(`
<div class="alert alert-danger" role="alert">
<strong>Error loading content:</strong> Could not retrieve verification details.
<p class="mt-1 mb-0"><small>Details: ${error}</small></p>
</div>
`);
}
});
}
function invalidate(accessnumber,userid) {
if(confirm("Are you sure?")) {
$.ajax({
url: `${BASE_URL}/api/request/validate/${accessNumber}`,
type: "DELETE",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ userid:`${userid}` }),
success: function(response) {
console.log("Success:", response);
},
error: function(xhr, status, error) {
console.error("Error:", status, error);
}
});
const cell = document.querySelector(`[data-acc="${accessnumber}"]`);
if(cell){
cell.querySelector(".badge").textContent = "0";
const btn = cell.querySelector(".invalidate-btn");
if (btn) btn.remove();
}
}
}
function validate(accessnumber,userid) {
// toggle checkbox
const row = document.getElementById(`row-${accessnumber}`);
fetch(`${BASE_URL}/api/request/validate/${accessnumber}`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({ userid:`${userid}` })
}).then(response => {
console.log("Success:", response);
}).catch(error => {
});
}

View File

@ -0,0 +1,78 @@
function collect(accessnumber, samplenumber, status) {
// toggle checkbox
const row = document.getElementById(`row-${accessnumber}-${samplenumber}`);
const checkbox = row.querySelector('.coll-checkbox');
checkbox.checked = status;
$.ajax({
url: `${BASE_URL}/api/specimen/collect/${accessnumber}`,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ samplenumber:samplenumber, status:status, userid:"<?=session('userid');?>" }),
success: function(response) {
console.log("Success:", response);
},
error: function(xhr, status, error) {
console.error("Error:", status, error);
}
});
}
function unreceive(accessnumber, samplenumber) {
// toggle checkbox
const row = document.getElementById(`row-${accessnumber}-${samplenumber}`);
const checkbox = row.querySelector('.recv-checkbox');
checkbox.checked = status;
$.ajax({
url: `${BASE_URL}/api/specimen/unreceive/${accessnumber}`,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ samplenumber:samplenumber }),
success: function(response) {
console.log("Success:", response);
},
error: function(xhr, status, error) {
console.error("Error:", status, error);
}
});
}
// Untuk Koment Value
function commentValue() {
const input = prompt("Masukkan Komentar :");
}
function detailShow() {
{
const modal = document.getElementById('detailModal');
const modalContent = document.getElementById('specimenModalContent');
document.querySelectorAll('.pointercol').forEach(td => {
td.addEventListener('click', async function () {
const access = this.dataset.access;
modalContent.innerHTML =
"<p class='text-center text-muted'>Loading data...</p>";
try {
$.getJSON(`${BASE_URL}/api/specimen/${access}`, function(data) {
$.get(`${BASE_URL}/admin/modal_specimen`, function(tpl) {
data.samples = data.samples.map(s => ({
...s,
is_coll: s.colstatus == 1,
is_recv: s.tubestatus == 4
}));
const html = Mustache.render(tpl, data);
modalContent.innerHTML=html;
});
});
} catch (err) {
modalContent.innerHTML = "<p class='text-danger text-center'>Gagal memuat data.</p>";
console.error(err);
}
});
});
}
}