gdc_cmod/app/Views/v2/index.php
2025-11-28 16:52:44 +07:00

183 lines
6.3 KiB
PHP

<!DOCTYPE html>
<html lang="en" data-theme="corporate">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>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>
<style>
body {
margin: 0;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-size: 0.75rem;
}
.navbar {
padding: 0.2rem 1rem;
min-height: 0rem;
}
</style>
</head>
<body class="bg-base-200 min-h-screen flex flex-col">
<nav class="navbar bg-secondary shadow-sm text-white">
<div class='flex-1 '>
<a class=''>CMOD</a>
</div>
<div class="mr-2">
<a>Hi, lisfse</a>
</div>
<div class="dropdown dropdown-end p-0">
<div tabindex="0" role="button" class="btn btn-sm btn-secondary">Menu</div>
<ul tabindex="-1" class="dropdown-content menu bg-base-100 rounded-box z-1 w-46 p-2 shadow-sm text-black">
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
</ul>
</div>
</nav>
<main class="p-4 flex-1" x-data="dashboard">
<h3 class="text-lg font-bold mb-1">Dashboard</h3>
<div class="card bg-base-200">
<div class="card-body p-1">
<div class="flex gap-3 mb-2">
<div class="flex-1 flex gap-1 items-center">
<div>Date</div>
<input type="date" class="input input-sm w-39" x-model="filter.date1"/>-
<input type="date" class="input input-sm w-39" x-model="filter.date2"/>
<button class="btn btn-sm btn-primary" @click='fetchList()'><i class='fa fa-search'></i>Search</button>
<button class="btn btn-sm btn-secondary" @click='reset()'><i class='fa fa-refresh'></i>Reset</button>
</div>
<div class="flex gap-1 text-right">
<button class="btn btn-outline btn-sm"><span x-text="counters.Pend"></span> Pending</button>
<button class="btn btn-outline btn-sm"><span x-text="counters.PartColl"></span> P. Collected</button>
<button class="btn btn-outline btn-sm"><span x-text="counters.Coll"></span> Collected</button>
<button class="btn btn-outline btn-sm"><span x-text="counters.PartRecv"></span> P. Received</button>
<button class="btn btn-outline btn-sm"><span x-text="counters.Recv"></span> Received</button>
<button class="btn btn-outline btn-sm"><span x-text="counters.Inc"></span> Incomplete</button>
<button class="btn btn-outline btn-sm"><span x-text="counters.Fin"></span> Final</button>
<button class="btn btn-outline btn-sm"><span x-text="counters.All"></span> Total</button>
</div>
</div>
</div>
</div>
<template x-if="list.length">
<div class="card bg-base-100 w-full">
<div class="card-body p-1">
<table class="table table-sm table-zebra w-full">
<thead>
<tr>
<th style='width:7%;'>Order Datetime</th>
<th style='width:15%;'>Patient Name</th>
<th style='width:7%;'>No Lab</th>
<th style='width:7%;'>No Register</th>
<th style='width:8%;'>Reff</th>
<th style='width:8%;'>Doctor</th>
<th style='width:15%;'>Tests</th>
<th style='width:5%;'>Result To</th>
<th style='width:5%;'>Validation</th>
<th style='width:4%;'>Status</th>
</tr>
</thead>
<tbody>
<template x-for="req in list" :key="req.SP_ACCESSNUMBER">
<tr class="hover:bg-base-300">
<td x-text="req.REQDATE"></td>
<td x-text="req.Name"></td>
<td x-text="req.SP_ACCESSNUMBER"></td>
<td x-text="req.HOSTORDERNUMBER"></td>
<td x-text="req.REFF"></td>
<td x-text="req.DOC"></td>
<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>
</td>
<td x-text="req.STATS" :class="statusColor[req.STATS]"></td>
</tr>
</template>
</tbody>
</table>
</div>
</div>
</template>
</main>
<footer class='bg-base-100 p-1'>&copy; 2025 - 5Panda</footer>
<script>
window.BASEURL = "<?=base_url();?>";
</script>
<script type="module">
import Alpine from '<?=base_url("js/app.js");?>';
document.addEventListener('alpine:init', () => {
Alpine.data("dashboard", ()=> ({
today: "",
filter: { date1: "", date2: "" },
list: [],
counters: {
Pend: 0,
PartColl: 0,
Coll: 0,
PartRecv: 0,
Recv: 0,
Inc: 0,
Fin: 0,
},
statusColor: {
Pend: 'bg-white text-black font-bold',
PartColl: 'bg-orange-300 text-black font-bold',
Coll: 'bg-orange-500 text-white font-bold',
PartRecv: 'bg-blue-200 text-black font-bold',
Recv: 'bg-blue-500 text-white font-bold',
Inc: 'bg-yellow-500 text-white font-bold',
Fin: 'bg-green-500 text-white font-bold',
},
init() {
this.today = new Date().toISOString().slice(0, 10);
this.filter.date1 = this.today;
this.filter.date2 = this.today;
},
fetchList(){
this.list = [];
let statusOrder = { Pend: 1, PartColl: 2, Coll: 3, PartRecv: 4, Recv: 5, Inc: 6, Fin: 7 };
let param = new URLSearchParams(this.filter).toString();
// reset counters before processing
for (let k in this.counters) { this.counters[k] = 0; }
fetch(`${BASEURL}/api/request?${param}`, {
method: 'GET',
headers: {'Content-Type': 'application/json'},
}).then(res => res.json()).then(data => {
this.list = data.data ?? [];
// count + sort in a single loop
this.list.forEach(item => {
if (this.counters[item.STATS] !== undefined) { this.counters[item.STATS]++; }
});
this.list.sort((a, b) => {
let codeA = statusOrder[a.STATS] ?? 0;
let codeB = statusOrder[b.STATS] ?? 0;
return codeA - codeB;
});
});
},
reset() {
this.filter.date1 = this.today;
this.filter.date2 = this.today;
this.fetchList();
}
}));
});
Alpine.start();
</script>
</body>
</html>