This commit implements a comprehensive status color system across the dashboard and validation interfaces, ensuring visual consistency between table rows and filter buttons. Color System Changes: - Updated statusRowBg mapping in script_requests.php with custom hex colors: * Pend: white (#ffffff) with black text * PartColl: pink (#ff99aa) with black text * Coll: red (#d63031) with white text * PartRecv: light blue (#a0c0d9) with black text * Recv: blue (#0984e3) with white text * Inc: yellow (#ffff00) with black text * Fin: green (#008000) with white text - Added custom CSS button classes in layout.php matching row background colors - Applied color backgrounds to table rows (Order through Tests columns) - Removed hardcoded text-white classes, now using dynamic text colors from mapping UI/UX Improvements: - Table rows now have consistent color-coded backgrounds based on request status - Filter button badges match their corresponding row background colors - Yellow status uses black text for better readability - Swapped Coll (yellow) and Inc (orange) colors as requested Validation Dialog Enhancement: - Updated dialog_val.php iframe to use dynamic URL generation - Removed preview type selection (ID, EN, PDF options) - uses default only - Added getPreviewUrl() method in script_validation.php - Now uses same URL pattern as preview dialog: http://glenlis/spooler_db/main_dev.php?acc={accessnumber} Documentation Updates: - Added Serena MCP tool usage guidelines to AGENTS.md - Renamed CHECKLIST.md to TODO.md - Removed CLAUDE.md Technical Details: - Color mappings now include both background and text color classes - Implemented using Tailwind arbitrary values for precise hex color matching - Status buttons use btn-status-{status} and badge-status-{status} classes - All 7 columns from Order through Tests have status-colored backgrounds
196 lines
7.4 KiB
PHP
196 lines
7.4 KiB
PHP
<div class="card bg-base-100 shadow-xl h-full border border-base-200 overflow-hidden">
|
|
<div class="card-body p-0 h-full flex flex-col">
|
|
|
|
<!-- Header & Filters -->
|
|
<div class="p-4 border-b border-base-200 bg-gradient-to-r from-primary/10 to-base-100">
|
|
<div class="flex flex-col md:flex-row justify-between items-center gap-4 mb-2">
|
|
<h2 class="text-2xl font-bold flex items-center gap-3">
|
|
<span class="w-10 h-10 rounded-lg bg-primary text-primary-content flex items-center justify-center shadow-lg">
|
|
<i class="fa fa-clipboard-check"></i>
|
|
</span>
|
|
Pending Validation
|
|
</h2>
|
|
<div class="badge badge-lg badge-primary gap-2 px-4 py-3 shadow-lg">
|
|
<i class="fa fa-layer-group animate-pulse"></i>
|
|
<span class="font-bold text-lg" x-text="unvalidatedCount"></span>
|
|
<span class="font-medium">requests</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Date Filter -->
|
|
<div class="flex flex-col md:flex-row gap-3 items-end bg-base-100 p-3 rounded-lg border border-base-200 shadow-sm">
|
|
<div class="form-control">
|
|
<label class="label text-xs font-bold py-1 text-base-content/60">Date Range</label>
|
|
<div class="join">
|
|
<input type="date" class="input input-sm input-bordered join-item" x-model="filter.date1" />
|
|
<span class="join-item btn btn-sm btn-ghost no-animation bg-base-200 font-normal px-2">-</span>
|
|
<input type="date" class="input input-sm input-bordered join-item" x-model="filter.date2" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex gap-2">
|
|
<button class="btn btn-sm btn-primary" @click="fetchUnvalidated()">
|
|
<i class="fa fa-search"></i> Search
|
|
</button>
|
|
<button class="btn btn-sm btn-neutral" @click="resetUnvalidated()">
|
|
<i class="fa fa-sync-alt"></i> Reset
|
|
</button>
|
|
</div>
|
|
|
|
<span class="flex-1"></span>
|
|
|
|
<div class="form-control w-full md:w-auto">
|
|
<label class="input input-sm input-bordered">
|
|
<i class="fa fa-filter"></i>
|
|
<input type="text" placeholder="Type to filter..." x-model="filterTable" />
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Table Section -->
|
|
<div class="flex-1 overflow-y-auto px-4 pb-4">
|
|
<template x-if="isLoading">
|
|
<table class="table table-xs table-zebra w-full">
|
|
<thead class="bg-base-100 sticky top-0 z-10">
|
|
<tr>
|
|
<th style="width: 18%;">
|
|
<div class="skeleton h-4 w-24"></div>
|
|
</th>
|
|
<th style="width: 25%;">
|
|
<div class="skeleton h-4 w-32"></div>
|
|
</th>
|
|
<th style="width: 12%;">
|
|
<div class="skeleton h-4 w-20"></div>
|
|
</th>
|
|
<th style="width: 12%;">
|
|
<div class="skeleton h-4 w-24"></div>
|
|
</th>
|
|
<th style="width: 13%;">
|
|
<div class="skeleton h-4 w-20"></div>
|
|
</th>
|
|
<th style="width: 20%;">
|
|
<div class="skeleton h-4 w-full"></div>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<template x-for="i in 5" :key="i">
|
|
<tr>
|
|
<td colspan="6">
|
|
<div class="skeleton h-4 w-full"></div>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
</template>
|
|
|
|
<template x-if="!isLoading && !unvalidatedList.length">
|
|
<div class="text-center py-10">
|
|
<i class="fa fa-check-circle text-4xl mb-2 opacity-50"></i>
|
|
<p>All requests have been validated!</p>
|
|
</div>
|
|
</template>
|
|
|
|
<template x-if="!isLoading && unvalidatedList.length">
|
|
<table class="table table-xs table-zebra w-full">
|
|
<thead class="bg-base-100 sticky top-0 z-10">
|
|
<tr>
|
|
<th style="width: 18%;" @click="sort('REQDATE')"
|
|
class="cursor-pointer hover:bg-base-200 transition-colors select-none">
|
|
<div class="flex items-center gap-1">
|
|
Order Datetime
|
|
<i class="fa text-xs"
|
|
:class="sortCol === 'REQDATE' ? (sortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort opacity-20'"></i>
|
|
</div>
|
|
</th>
|
|
<th style="width: 25%;" @click="sort('Name')"
|
|
class="cursor-pointer hover:bg-base-200 transition-colors select-none">
|
|
<div class="flex items-center gap-1">
|
|
Patient Name
|
|
<i class="fa text-xs"
|
|
:class="sortCol === 'Name' ? (sortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort opacity-20'"></i>
|
|
</div>
|
|
</th>
|
|
<th style="width: 12%;" @click="sort('SP_ACCESSNUMBER')"
|
|
class="cursor-pointer hover:bg-base-200 transition-colors select-none">
|
|
<div class="flex items-center gap-1">
|
|
No Lab
|
|
<i class="fa text-xs"
|
|
:class="sortCol === 'SP_ACCESSNUMBER' ? (sortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort opacity-20'"></i>
|
|
</div>
|
|
</th>
|
|
<th style="width: 12%;" @click="sort('HOSTORDERNUMBER')"
|
|
class="cursor-pointer hover:bg-base-200 transition-colors select-none">
|
|
<div class="flex items-center gap-1">
|
|
No Register
|
|
<i class="fa text-xs"
|
|
:class="sortCol === 'HOSTORDERNUMBER' ? (sortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort opacity-20'"></i>
|
|
</div>
|
|
</th>
|
|
<th style="width: 13%;" @click="sort('REFF')"
|
|
class="cursor-pointer hover:bg-base-200 transition-colors select-none">
|
|
<div class="flex items-center gap-1">
|
|
Reff
|
|
<i class="fa text-xs"
|
|
:class="sortCol === 'REFF' ? (sortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort opacity-20'"></i>
|
|
</div>
|
|
</th>
|
|
<th style="width: 20%;" @click="sort('DOC')"
|
|
class="cursor-pointer hover:bg-base-200 transition-colors select-none">
|
|
<div class="flex items-center gap-1">
|
|
Doctor
|
|
<i class="fa text-xs"
|
|
:class="sortCol === 'DOC' ? (sortAsc ? 'fa-sort-up' : 'fa-sort-down') : 'fa-sort opacity-20'"></i>
|
|
</div>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<template x-for="req in unvalidatedPaginated" :key="req.SP_ACCESSNUMBER">
|
|
<tr class="hover:bg-base-300 cursor-pointer"
|
|
@click="openValDialog(req.SP_ACCESSNUMBER)"
|
|
tabindex="0"
|
|
@keydown.enter="openValDialog(req.SP_ACCESSNUMBER)"
|
|
@keydown.escape="closeValDialog()">
|
|
<td x-text="req.REQDATE"></td>
|
|
<td x-text="req.Name"></td>
|
|
<td x-text="req.SP_ACCESSNUMBER" class="font-bold"></td>
|
|
<td x-text="req.HOSTORDERNUMBER" class="font-bold"></td>
|
|
<td x-text="req.REFF"></td>
|
|
<td x-text="req.DOC"></td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
</template>
|
|
</div>
|
|
|
|
<!-- Pagination Control -->
|
|
<div class="p-2 border-t border-base-200 bg-base-50 flex justify-between items-center"
|
|
x-show="!isLoading && unvalidatedList.length > 0">
|
|
<div class="text-xs text-base-content/60">
|
|
Showing <span class="font-bold" x-text="((currentPage - 1) * pageSize) + 1"></span> to
|
|
<span class="font-bold" x-text="Math.min(currentPage * pageSize, unvalidatedFiltered.length)"></span> of
|
|
<span class="font-bold" x-text="unvalidatedFiltered.length"></span> entries
|
|
</div>
|
|
<div class="join">
|
|
<button class="join-item btn btn-sm" @click="prevPage()" :disabled="currentPage === 1">
|
|
<i class="fa fa-chevron-left"></i>
|
|
</button>
|
|
<button class="join-item btn btn-sm no-animation bg-base-100 cursor-default">
|
|
Page <span x-text="currentPage"></span> / <span x-text="unvalidatedTotalPages"></span>
|
|
</button>
|
|
<button class="join-item btn btn-sm" @click="nextPage()" :disabled="currentPage === unvalidatedTotalPages">
|
|
<i class="fa fa-chevron-right"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Validate Dialog -->
|
|
<?= $this->include('shared/dialog_val'); ?>
|