feat: implement View Controls - add department filter and active status indicator
This commit is contained in:
parent
a5a3857eff
commit
44795310e1
@ -24,8 +24,10 @@ class ControlApiController extends BaseController
|
||||
|
||||
public function index()
|
||||
{
|
||||
$keyword = $this->request->getGet('keyword');
|
||||
$deptId = $this->request->getGet('deptId');
|
||||
try {
|
||||
$rows = $this->dictControlModel->getWithDept();
|
||||
$rows = $this->dictControlModel->getWithDept($keyword, $deptId);
|
||||
return $this->respond([
|
||||
'status' => 'success',
|
||||
'message' => 'fetch success',
|
||||
|
||||
@ -19,11 +19,23 @@ class DictControlModel extends BaseModel
|
||||
return $this->where('dept_ref_id', $deptId)->findAll();
|
||||
}
|
||||
|
||||
public function getWithDept()
|
||||
public function getWithDept($keyword = null, $deptId = null)
|
||||
{
|
||||
$builder = $this->db->table('dict_controls c');
|
||||
$builder->select('c.*, d.name as dept_name');
|
||||
$builder->join('dict_depts d', 'd.dept_id = c.dept_ref_id', 'left');
|
||||
|
||||
if ($keyword) {
|
||||
$builder->groupStart();
|
||||
$builder->like('c.name', $keyword);
|
||||
$builder->orLike('c.lot', $keyword);
|
||||
$builder->groupEnd();
|
||||
}
|
||||
|
||||
if ($deptId) {
|
||||
$builder->where('c.dept_ref_id', $deptId);
|
||||
}
|
||||
|
||||
return $builder->get()->getResultArray();
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,12 @@
|
||||
<i class="fa-solid fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-slate-400"></i>
|
||||
<input type="text" x-model="keyword" @keyup.enter="fetchList()" class="w-full pl-10 pr-4 py-2.5 text-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" placeholder="Search controls...">
|
||||
</div>
|
||||
<select x-model="deptId" @change="fetchList()" class="select select-bordered select-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500">
|
||||
<option value="">All Departments</option>
|
||||
<template x-for="dept in depts" :key="dept.dept_id">
|
||||
<option :value="dept.dept_id" x-text="dept.name"></option>
|
||||
</template>
|
||||
</select>
|
||||
<button @click="fetchList()" class="btn btn-primary">
|
||||
<i class="fa-solid fa-magnifying-glass mr-2"></i>Search
|
||||
</button>
|
||||
@ -66,6 +72,7 @@
|
||||
<th class="py-3 px-5 font-semibold">Name</th>
|
||||
<th class="py-3 px-5 font-semibold">Lot</th>
|
||||
<th class="py-3 px-5 font-semibold">Department</th>
|
||||
<th class="py-3 px-5 font-semibold">Status</th>
|
||||
<th class="py-3 px-5 font-semibold">Expiry Date</th>
|
||||
<th class="py-3 px-5 font-semibold text-right">Actions</th>
|
||||
</tr>
|
||||
@ -79,6 +86,9 @@
|
||||
<span class="font-mono text-xs bg-slate-100 text-slate-600 px-2 py-1 rounded" x-text="item.lot || '-'"></span>
|
||||
</td>
|
||||
<td class="py-3 px-5 text-slate-600" x-text="item.dept_name || '-'"></td>
|
||||
<td class="py-3 px-5">
|
||||
<span :class="isExpired(item.expdate) ? 'bg-red-100 text-red-700' : 'bg-emerald-100 text-emerald-700'" class="px-2 py-1 text-xs font-medium rounded-full" x-text="isExpired(item.expdate) ? 'Expired' : 'Active'"></span>
|
||||
</td>
|
||||
<td class="py-3 px-5 text-slate-600" x-text="item.expdate ? new Date(item.expdate).toLocaleDateString() : '-'"></td>
|
||||
<td class="py-3 px-5 text-right">
|
||||
<button @click="showForm(item.control_id)" class="text-blue-600 hover:text-blue-800 mr-3">
|
||||
@ -111,6 +121,7 @@ document.addEventListener('alpine:init', () => {
|
||||
errors: {},
|
||||
error: '',
|
||||
keyword: '',
|
||||
deptId: '',
|
||||
depts: <?= json_encode($depts ?? []) ?>,
|
||||
tests: <?= json_encode($tests ?? []) ?>,
|
||||
|
||||
@ -122,7 +133,10 @@ document.addEventListener('alpine:init', () => {
|
||||
this.loading = true;
|
||||
this.error = '';
|
||||
try {
|
||||
const res = await fetch(`${window.BASEURL}/api/control`);
|
||||
const params = new URLSearchParams();
|
||||
if (this.keyword) params.append('keyword', this.keyword);
|
||||
if (this.deptId) params.append('deptId', this.deptId);
|
||||
const res = await fetch(`${window.BASEURL}/api/control?${params}`);
|
||||
const data = await res.json();
|
||||
if (data.status === 'success') {
|
||||
this.list = data.data || [];
|
||||
@ -137,6 +151,11 @@ document.addEventListener('alpine:init', () => {
|
||||
}
|
||||
},
|
||||
|
||||
isExpired(expdate) {
|
||||
if (!expdate) return false;
|
||||
return new Date(expdate) < new Date();
|
||||
},
|
||||
|
||||
async showForm(id = null) {
|
||||
this.errors = {};
|
||||
if (id) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user