go go alpine ranger
This commit is contained in:
parent
5f6139b85d
commit
656aef8f7c
@ -62,7 +62,13 @@ $routes->post('api/specimen/collect/(:any)', 'Specimen::collect/$1');
|
||||
$routes->delete('api/specimen/receive/(:any)', 'Specimen::unreceive/$1');
|
||||
|
||||
/*- lets go alpine -*/
|
||||
|
||||
$routes->group('v2', function($routes) {
|
||||
$routes->get('', 'v2::index');
|
||||
$routes->get('', 'V2::index');
|
||||
$routes->get('login', 'V2::loginPage');
|
||||
$routes->post('login', 'V2::login');
|
||||
$routes->group('Admin/', ['filter' => 'role:1'], function($routes) {
|
||||
$routes->get('', 'V2\Admin::index');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -51,8 +51,8 @@ class Request extends BaseController {
|
||||
$userid = $input['userid'];
|
||||
$comment = $input['comment'];
|
||||
$db = db_connect();
|
||||
$sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=0, VAL1USER=null, VAL1DATE=null, ISVAL2=0, VAL2USER=null, VAL2DATE=null,
|
||||
PENDINGTEXT='$comment', PENDINGUSER='$userid', PENDINGDATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
|
||||
$sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=null, VAL1USER=null, VAL1DATE=null, ISVAL2=null, VAL2USER=null, VAL2DATE=null,
|
||||
ISPENDING=1, PENDINGTEXT='$comment', PENDINGUSER='$userid', PENDINGDATE=GETDATE() where ACCESSNUMBER='$accessnumber'";
|
||||
$db->query($sql);
|
||||
$data = ['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber" ];
|
||||
|
||||
|
||||
@ -4,11 +4,75 @@ namespace App\Controllers;
|
||||
use App\Controllers\BaseController;
|
||||
|
||||
class V2 extends BaseController {
|
||||
/*
|
||||
public function index() {
|
||||
return view("v2/index");
|
||||
}
|
||||
*/
|
||||
public function index() {
|
||||
$session = session();
|
||||
|
||||
public function modal_specimen() {
|
||||
if (! $session->get('isLoggedIn')) {
|
||||
return redirect()->to('v2/login');
|
||||
}
|
||||
|
||||
// Jika sudah login, arahkan sesuai level
|
||||
switch ($session->get('level')) {
|
||||
case 1: return redirect()->to('v2/admin');
|
||||
case 2: return redirect()->to('v2/dokter');
|
||||
case 3: return redirect()->to('v2/analis');
|
||||
case 4: return redirect()->to('v2/cs');
|
||||
default: return redirect()->to('v2/login');
|
||||
}
|
||||
}
|
||||
|
||||
public function loginPage() {
|
||||
return view("v2/login");
|
||||
}
|
||||
|
||||
public function login() {
|
||||
helper(['form', 'url']);
|
||||
$session = session();
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
$userid = strtoupper(trim($this->request->getPost('userid')));
|
||||
$password = $this->request->getPost('password');
|
||||
|
||||
// Gunakan raw SQL sesuai kolom di tabel kamu
|
||||
$query = $db->query("SELECT * FROM gdc_cmod.dbo.USERS WHERE USERID = ?", [$userid]);
|
||||
$user = $query->getRowArray();
|
||||
|
||||
if ($user && !empty($user['PASSWORD']) && password_verify($password, $user['PASSWORD'])) {
|
||||
|
||||
// Role untuk url
|
||||
switch ((int)$user['USERLEVEL']) {
|
||||
case 1: $role = 'admin'; break;
|
||||
case 2: $role = 'doctor'; break;
|
||||
case 3: $role = 'analyst'; break;
|
||||
case 4: $role = 'cs'; break;
|
||||
default: $role = ''; break;
|
||||
}
|
||||
|
||||
// Simpan session
|
||||
$session->set([
|
||||
'isLoggedIn' => true,
|
||||
'userid' => (string) $user['USERID'],
|
||||
'userlevel' => (int) $user['USERLEVEL'],
|
||||
'userrole' => (string) $role,
|
||||
]);
|
||||
|
||||
// Redirect sesuai level dari data didatabase
|
||||
switch ((int)$user['USERLEVEL']) {
|
||||
case 1: return redirect()->to('v2/admin');
|
||||
case 2: return redirect()->to('v2/doctor');
|
||||
case 3: return redirect()->to('v2/analyst');
|
||||
case 4: return redirect()->to('v2/cs');
|
||||
default: return redirect()->to('v2/login');
|
||||
}
|
||||
} else {
|
||||
$session->setFlashdata('error', 'USERID atau PASSWORD salah.');
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
10
app/Views/v2/dialog_unval.php
Normal file
10
app/Views/v2/dialog_unval.php
Normal file
@ -0,0 +1,10 @@
|
||||
<dialog class="modal" :open="isDialogUnvalOpen">
|
||||
<div class="modal-box">
|
||||
<textarea class="textarea textarea-bordered w-full" rows="5" x-model="unvalReason" placeholder="Enter reason for unvalidation..."></textarea>
|
||||
<p class='text-right mt-2'>
|
||||
<button class="btn btn-sm btn-neutral" @click="closeUnvalDialog()">Cancel</button>
|
||||
<button id="unvalidate-btn" x-ref="unvalidateBtn" class="btn btn-sm btn-warning"
|
||||
@click="unvalidate(unvalAccessnumber, '<?=session('userid');?>')" :disabled="!unvalReason.trim()">Unvalidate</button>
|
||||
</p>
|
||||
</div>
|
||||
</dialog>
|
||||
@ -6,10 +6,8 @@
|
||||
<button id="validate-btn" x-ref="validateBtn" class="btn btn-sm btn-success"
|
||||
@click="validate(valAccessnumber, '<?=session('userid');?>')" :disabled="!isValidateEnabled">Validate</button>
|
||||
</p>
|
||||
|
||||
<!-- <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>
|
||||
|
||||
<!-- <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>
|
||||
</div>
|
||||
</template>
|
||||
</dialog>
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
<a class=''>CMOD</a>
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<a>Hi, lisfse</a>
|
||||
<a>Hi, <?=session('userid'); ?></a>
|
||||
</div>
|
||||
<div class="dropdown dropdown-end p-0">
|
||||
<div tabindex="0" role="button" class="btn btn-sm btn-secondary">Menu</div>
|
||||
@ -97,14 +97,22 @@
|
||||
<td x-text="req.TESTS"></td>
|
||||
<td x-text="req.ODR_CRESULT_TO"></td>
|
||||
<td>
|
||||
<div>1: <span x-text="req.val1user"></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 class='flex gap-1 items-center'>
|
||||
<div class='w-15'>
|
||||
<p>1: <span x-text="req.VAL1USER"></span></p>
|
||||
<p>2: <span x-text="req.VAL2USER"></span></p>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="req.ISVAL == 1 && req.ISPENDING != 1">
|
||||
<div class='text-center'>
|
||||
<template x-if="req.VAL1USER == '<?=session('userid');?>' || req.VAL2USER == '<?=session('userid');?>'">
|
||||
<button class="btn btn-xs btn-outline btn-secondary" @click="openUnvalDialog(req.SP_ACCESSNUMBER)"><i class="fa-solid fa-rotate-right"></i></button>
|
||||
</template>
|
||||
<template x-if="req.VAL1USER != '<?=session('userid');?>' && req.VAL2USER != '<?=session('userid');?>'">
|
||||
<button class="btn btn-xs btn-outline btn-success" @click="openValDialog(req.SP_ACCESSNUMBER)"><i class="fa-solid fa-check"></i></button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</td>
|
||||
<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>
|
||||
@ -118,6 +126,7 @@
|
||||
|
||||
<?php echo $this->include('v2/dialog_sample'); ?>
|
||||
<?php echo $this->include('v2/dialog_val'); ?>
|
||||
<?php echo $this->include('v2/dialog_unval'); ?>
|
||||
|
||||
</main>
|
||||
|
||||
@ -200,28 +209,31 @@
|
||||
this.fetchList();
|
||||
},
|
||||
|
||||
isValidated (item) {
|
||||
return item.ISVAL == 1 && item.ISPENDING != 1;
|
||||
},
|
||||
get filtered() {
|
||||
let data = this.list;
|
||||
let filteredList = this.list;
|
||||
if (this.filterKey === 'Validated') {
|
||||
data = data.filter(i => i.ISVAL == 1);
|
||||
filteredList = filteredList.filter(item => this.isValidated(item));
|
||||
} else {
|
||||
const valid = this.statusMap[this.filterKey]
|
||||
if (valid.length > 0) {
|
||||
data = data.filter(i => valid.includes(i.STATS));
|
||||
const validStatuses = this.statusMap[this.filterKey];
|
||||
if (validStatuses.length > 0) {
|
||||
filteredList = filteredList.filter(item => validStatuses.includes(item.STATS));
|
||||
}
|
||||
}
|
||||
if (this.filterTable) {
|
||||
const s = this.filterTable.toLowerCase();
|
||||
data = data.filter(i =>
|
||||
Object.values(i).some(v =>
|
||||
String(v).toLowerCase().includes(s)
|
||||
const searchTerm = this.filterTable.toLowerCase();
|
||||
filteredList = filteredList.filter(item =>
|
||||
Object.values(item).some(value =>
|
||||
String(value).toLowerCase().includes(searchTerm)
|
||||
)
|
||||
);
|
||||
}
|
||||
return data;
|
||||
return filteredList;
|
||||
},
|
||||
get validatedCount() {
|
||||
return this.list.filter(r => r.ISVAL == 1).length;
|
||||
return this.list.filter(r => this.isValidated(r)).length;
|
||||
},
|
||||
|
||||
/*
|
||||
@ -291,21 +303,47 @@
|
||||
closeValDialog () {
|
||||
this.isDialogValOpen = false;
|
||||
},
|
||||
unval(accessnumber) {
|
||||
console.log("Unvalidate access number:", accessnumber);
|
||||
},
|
||||
validate(accessnumber, userid) {
|
||||
fetch(`${BASE_URL}/api/request/validate/${accessnumber}`, {
|
||||
fetch(`${BASEURL}/api/request/validate/${accessnumber}`, {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({ userid:`${userid}` })
|
||||
}).then(response => {
|
||||
this.closeValDialog()
|
||||
console.log('Validate clicked for', this.valAccessnumber);
|
||||
this.closeValDialog();
|
||||
this.fetchList();
|
||||
console.log('Validate clicked for', this.valAccessnumber, 'by user', userid);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
unvalidate dialog
|
||||
*/
|
||||
isDialogUnvalOpen : false,
|
||||
unvalReason : '',
|
||||
unvalAccessnumber : null,
|
||||
openUnvalDialog (accessnumber) {
|
||||
this.unvalReason = '';
|
||||
this.isDialogUnvalOpen = true;
|
||||
this.unvalAccessnumber = accessnumber;
|
||||
},
|
||||
unvalidate(accessnumber, userid) {
|
||||
if(!confirm(`Unvalidate request ${accessnumber}?`)) { return ;}
|
||||
fetch(`${BASEURL}/api/request/validate/${accessnumber}`, {
|
||||
method: "DELETE",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({ userid:`${userid}`, comment: this.unvalReason.trim() })
|
||||
}).then(response => {
|
||||
this.closeUnvalDialog();
|
||||
this.fetchList();
|
||||
console.log(`Unvalidate clicked for ${accessnumber}, by user ${userid}`);
|
||||
});
|
||||
},
|
||||
closeUnvalDialog () {
|
||||
this.isDialogUnvalOpen = false;
|
||||
},
|
||||
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
Alpine.start();
|
||||
</script>
|
||||
|
||||
49
app/Views/v2/login.php
Normal file
49
app/Views/v2/login.php
Normal file
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="cupcake">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login - CMOD</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/js/all.min.js"></script>
|
||||
</head>
|
||||
<body class="min-h-screen flex items-center justify-center bg-gradient-to-br from-green-200 via-blue-100 to-yellow-100">
|
||||
<div class="w-full max-w-sm mx-auto">
|
||||
<div class="card bg-base-100 shadow-xl border-2 border-primary">
|
||||
<div class="card-body items-center text-center">
|
||||
<div class="avatar mb-2">
|
||||
<div class="w-20 rounded-full ring ring-primary ring-offset-base-100 ring-offset-2">
|
||||
<img src="https://api.dicebear.com/7.x/bottts/svg?seed=fun" alt="Fun Avatar" />
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="card-title text-2xl font-bold text-primary mb-2">Welcome to CMOD!</h2>
|
||||
<p class="mb-4 text-base text-gray-500">Sign in to continue your adventure 🚀</p>
|
||||
<form method="post" action="<?=base_url('v2/login')?>" class="w-full flex flex-col gap-3">
|
||||
<div class="form-control">
|
||||
<label class="input input-bordered flex items-center gap-2 w-full">
|
||||
<i class="fa fa-user text-primary"></i>
|
||||
<input type="text" name="userid" placeholder="UserID" class="grow" required />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="input input-bordered flex items-center gap-2 w-full">
|
||||
<i class="fa fa-lock text-primary"></i>
|
||||
<input type="password" name="password" placeholder="Password" class="grow" required />
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block mt-2 w-full">
|
||||
<i class="fa fa-sign-in-alt mr-2"></i> Login
|
||||
</button>
|
||||
</form>
|
||||
<div class="mt-4">
|
||||
<span class="text-xs text-gray-400">Forgot password?</span>
|
||||
<a href="#" class="link link-primary ml-1">Contact admin</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mt-4 text-sm text-gray-400">© 2025 - 5Panda</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user