diff --git a/AGENTS.md b/AGENTS.md index 88b9211..9a372a7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,14 +4,14 @@ This file provides guidance to agents when working with code in this repository. ## Project Overview -This is a CodeIgniter 4 PHP application for a laboratory management system (CMOD). It uses SQL Server database with role-based access control for different user types (admin, doctor/analyst, customer service). +CodeIgniter 4 PHP application for laboratory management (GDC CMOD). Handles specimen tracking, request validation, and result management with role-based access control. SQL Server database with Firebird legacy patient data. ## Commands ```bash # Run all tests -./vendor/bin/phpunit composer test +./vendor/bin/phpunit # Run single test file ./vendor/bin/phpunit tests/unit/HealthTest.php @@ -19,249 +19,145 @@ composer test # Run single test method ./vendor/bin/phpunit tests/unit/HealthTest.php --filter testIsDefinedAppPath -# Development server (Linux/Mac) +# Development server php spark serve # List all routes php spark list -# Create controller +# Create controller/model php spark make:controller Admin - -# Create model php spark make:model User ``` -## Code Style Guidelines +## PHP Standards -### PHP Standards -- Use PHP 8.1+ features (typed properties, match expressions where appropriate) +- PHP 8.1+ features (typed properties, match expressions) - Always declare return types for public methods -- Use `strict_types=1` not required (CodeIgniter doesn't use it) -- No comments unless explaining complex logic (per project convention) +- No comments unless explaining complex logic +- Use `esc()` when outputting user data in views -### Naming Conventions -- **Classes**: PascalCase (e.g., `Admin`, `UserController`) -- **Methods**: camelCase (e.g., `index()`, `getUsers()`) -- **Variables**: camelCase (e.g., `$userId`, `$dataList`) -- **Constants**: UPPER_SNAKE_CASE (e.g., `DB_HOST`) -- **Database tables**: UPPER_SNAKE_CASE (e.g., `GDC_CMOD.dbo.USERS`) -- **Views**: lowercase with underscores (e.g., `admin/index.php`) +## Naming Conventions -### Controller Patterns +| Type | Convention | Example | +|------|------------|---------| +| Classes | PascalCase | `Admin`, `UserController` | +| Methods/Variables | camelCase | `getUsers()`, `$userId` | +| Constants | UPPER_SNAKE_CASE | `DB_HOST` | +| Database tables | UPPER_SNAKE_CASE | `GDC_CMOD.dbo.USERS` | +| Views | lowercase_underscores | `admin/index.php` | -#### Base Controllers -- All controllers extend `App\Controllers\BaseController` -- BaseController extends CodeIgniter\Controller +## Role-Based Access Control + +| Role ID | Name | Route Prefix | +|---------|------|--------------| +| 0 | Superuser | `/superuser` | +| 1 | Admin | `/admin` | +| 2 | Lab | `/lab` | +| 3 | Phlebo | `/phlebo` | +| 4 | CS | `/cs` | + +```php +// Single role +['filter' => 'role:1'] +// Multiple roles +['filter' => 'role:1,2'] +``` + +## Controller Patterns ```php namespace App\Controllers; class Admin extends BaseController { - public function index() { - // Method body - } + public function index() { } } -``` - -#### API Controllers -- Controllers use `ResponseTrait` for API responses -- Use `$this->respond()` or `$this->response->setJSON()` for responses - -```php -namespace App\Controllers; +// API Controllers use ResponseTrait use App\Controllers\BaseController; use CodeIgniter\API\ResponseTrait; class Users extends BaseController { use ResponseTrait; - protected $db; public function __construct() { $this->db = \Config\Database::connect(); helper(['url', 'form', 'text']); } - - public function index() { - $query = $this->db->query("SELECT * FROM table"); - return $this->respond(['data' => $query->getResultArray()]); - } } ``` -### Database Operations +## Database Operations -#### Connection Pattern ```php $this->db = \Config\Database::connect(); -``` -#### Query Methods -- `getRowArray()` - returns single row as associative array -- `getResultArray()` - returns multiple rows as array of arrays -- Use parameterized queries to prevent SQL injection - -```php +// Parameterized queries only $query = $this->db->query("SELECT * FROM table WHERE id = ?", [$id]); $row = $query->getRowArray(); $results = $query->getResultArray(); -``` -#### Transactions -```php +// Transactions $this->db->transBegin(); try { $this->db->query("INSERT INTO ...", [$data]); $this->db->transCommit(); } catch (\Throwable $e) { $this->db->transRollback(); - return $this->response->setJSON(['message' => 'Error']); } ``` -### Session Management +## Request/Response Patterns -#### Session Structure ```php -$session->set([ - 'isLoggedIn' => true, - 'userid' => (string) $user['USERID'], - 'userlevel' => (int) $user['USERLEVEL'], - 'userrole' => (string) $role, // 'admin', 'doctor', 'analyst', 'cs' -]); -``` - -#### Session Values -- `isLoggedIn`: bool -- `userid`: string -- `userlevel`: int -- `userrole`: string - -### Role-Based Access Control - -#### Role Values -- `1` = admin -- `2` = doctor (or lab/analyst) -- `3` = analyst -- `4` = cs (customer service) - -#### Route Filter Syntax -```php -// Single role -['filter' => 'role:1'] - -// Multiple roles -['filter' => 'role:1,2'] -``` - -### Request/Response Patterns - -#### Getting Input -```php -// POST data -$input = $this->request->getJSON(true); -$userid = $input['userid']; - -// Query parameters +// GET input $date1 = $this->request->getVar('date1') ?? date('Y-m-d'); -``` -#### JSON Response (V2 API) -```php +// POST JSON +$input = $this->request->getJSON(true); + +// JSON response return $this->respond(['data' => $results]); return $this->response->setJSON(['message' => 'Success']); -``` -#### View Response (Traditional) -```php +// View response return view('admin/index', $data); -``` -#### Redirect with Errors -```php +// Redirect with errors return redirect()->back()->with('errors', ['key' => 'message']); ``` -### API Endpoint Patterns +## Session Structure + +```php +session()->set([ + 'isLoggedIn' => true, + 'userid' => (string) $user['USERID'], + 'userroleid' => (int) $user['USERROLEID'], + 'userrole' => (string) $role, +]); +``` + +## Validation Endpoints -#### Validation Endpoints - `POST /api/{resource}/validate/{id}` - validate a record - `DELETE /api/{resource}/validate/{id}` - unvalidate a record -#### Route Examples -```php -// Admin routes -$routes->group('admin', ['filter' => 'role:1'], function($routes) { - $routes->get('/', 'Admin::index'); - $routes->get('users', 'Admin::users'); - $routes->get('api/users', 'Users::index'); - $routes->post('api/users', 'Users::create'); -}); +## Security -// Lab routes -$routes->group('lab', ['filter' => 'role:2'], function($routes) { - $routes->get('/', 'Lab::index'); - $routes->get('api/requests', 'Requests::index'); -}); -``` - -### Error Handling - -#### Database Operations -```php -try { - // DB operations -} catch (\Throwable $e) { - // Handle error - return $this->response->setJSON(['message' => 'Server error']); -} -``` - -#### Validation Errors -```php -if ($condition) { - return $this->response->setJSON(['message' => 'Error message']); -} -``` - -### Views - -#### View Pattern -- Views are plain PHP files in `app/Views/` -- Use `` syntax -- Pass data as associative array - -```php -// Controller -$data['dataList'] = $results; -return view('admin/index', $data); - -// View - - - -``` - -### Security - -- Always use parameterized queries (never interpolate directly) -- Use `esc()` when outputting user data in views -- Hash passwords with `password_hash()` and verify with `password_verify()` +- Use parameterized queries (never interpolate directly) +- Hash passwords with `password_hash()` / `password_verify()` - Validate and sanitize all input before use -### Helper Functions +## Database Schema -Available helpers loaded via `helper(['name', 'name2'])`: -- `url` - URL helpers -- `form` - Form helpers -- `text` - Text formatting +- Primary: SQL Server (`GDC_CMOD.dbo`) +- Legacy: Firebird (`GLENEAGLES` via ODBC) +- No CI4 Models - raw SQL queries via `Database::connect()` -### Database Schema +## Dual-Level Validation -- Database: SQL Server -- Schema: `dbo` -- Main database: `GDC_CMOD` -- Reference database: `glendb` -- Table naming: `GDC_CMOD.dbo.TABLENAME` +Validation requires 2 different users: +1. First: `ISVAL1=1`, `VAL1USER`, `VAL1DATE` +2. Second (different user): `ISVAL2=1`, `VAL2USER`, `VAL2DATE` diff --git a/CHECKLIST.md b/CHECKLIST.md index c36a7d8..8d4b2d4 100644 --- a/CHECKLIST.md +++ b/CHECKLIST.md @@ -3,16 +3,16 @@ **Last Updated:** January 22, 2026 Pending: - -- Restrict 'UnValidate' to Admin - Restrict Print/Save-to-PDF to CS Role only (Lab can only preview, CS can print/save) +- Add Dedicated Print Button (Trigger browser/system print dialog) - Create 'Detail Unvalidated' History Log/View (Log unvalidation actions with timestamp, user ID, and reason) - Enhanced Patient Detail Logging (Track: Sample Collection Time, Sample Received Time, Print History) -- Add Dedicated Print Button (Trigger browser/system print dialog) - Add Error Handling for Preview Button (Handle empty data gracefully) - Ensure 'Uncollect' Feature Functional (Maintain Uncollect feature functionality) - Backend Performance & Connectivity (Investigate intermittent connection issues with Server 253) - Update PDF Report Metadata (Replace 'Printed By' with validating user's name) +- Reprint Label (Add functionality to reprint labels) +- **Print Result Audit** (Track when result reports are printed/exported, log user and timestamp) Completed: - 01 : Update User Role levels (Standardize roles: Superuser, Admin, Lab, Phlebo, CS) @@ -29,6 +29,9 @@ Completed: - 12 : Remove 'status' field on dashboard - 13 : Restrict 'Validate' to Lab, Admin, Superuser - 14 : Hide/Disable 'Validation' button after 2nd validation (Prevent redundant validation actions) +- 15 : Restrict 'UnValidate' to Admin, Superuser +- 16 : Remove 'UnCollect' + Addition on dev : - adding init-isDev on index.php to set default date on dev dashboard \ No newline at end of file diff --git a/README.md b/README.md index 5da909d..1e4dc0b 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ This application uses role-based access control with four user roles. - **Dashboard** - View all requests with status filters (Pend, Coll, Recv, Inc, Fin, Val) - **User Management** - Create, edit, delete users; assign roles - **Request Management** - View, validate, unvalidate all requests -- **Sample Management** - Collect, uncollect, receive, unreceive samples +- **Sample Management** - Collect, receive, unreceive samples - **Result Management** - Preview and print results #### Lab diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 53fb98b..cc8cbfb 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -35,6 +35,7 @@ $routes->group('api', function ($routes) { // Requests - All Roles (0,1,2,3,4) $routes->group('requests', ['filter' => 'role:0,1,2,3,4'], function ($routes) { $routes->get('', 'RequestsController::index'); + $routes->get('(:any)/audit', 'ApiRequestsAuditController::show/$1'); $routes->post('validate/(:any)', 'RequestsController::val/$1'); $routes->delete('validate/(:any)', 'RequestsController::unval/$1'); }); @@ -52,9 +53,8 @@ $routes->group('api', function ($routes) { $routes->get('(:any)', 'SamplesController::show/$1'); }); - // Uncollect & Unreceive - Only Superuser (0) and Admin (1) + // Unreceive - Only Superuser (0) and Admin (1) $routes->group('', ['filter' => 'role:0,1'], function ($routes) { - $routes->delete('collect/(:any)', 'SamplesController::uncollect/$1'); $routes->delete('receive/(:any)', 'SamplesController::unreceive/$1'); }); }); diff --git a/app/Controllers/ApiRequestsAuditController.php b/app/Controllers/ApiRequestsAuditController.php new file mode 100644 index 0000000..c620999 --- /dev/null +++ b/app/Controllers/ApiRequestsAuditController.php @@ -0,0 +1,52 @@ + $accessnumber, + 'validation' => [], + 'sample_collection' => [] + ]; + + $sqlAudit = "SELECT EVENT_TYPE, USERID, EVENT_AT, REASON + FROM GDC_CMOD.dbo.AUDIT_EVENTS + WHERE ACCESSNUMBER = ? + ORDER BY EVENT_AT ASC"; + $auditRows = $db->query($sqlAudit, [$accessnumber])->getResultArray(); + + foreach ($auditRows as $row) { + $isUnval = $row['EVENT_TYPE'] === 'UNVAL'; + $result['validation'][] = [ + 'type' => $row['EVENT_TYPE'], + 'user' => trim($row['USERID']), + 'datetime' => $row['EVENT_AT'] ? date('Y-m-d H:i:s', strtotime($row['EVENT_AT'])) : null, + 'reason' => $isUnval ? trim($row['REASON']) : null + ]; + } + + $sqlTube = "SELECT TUBENUMBER, USERID, STATUS, LOGDATE + FROM GDC_CMOD.dbo.AUDIT_TUBES + WHERE ACCESSNUMBER = ? + ORDER BY LOGDATE ASC"; + $tubeRows = $db->query($sqlTube, [$accessnumber])->getResultArray(); + + foreach ($tubeRows as $row) { + $action = $row['STATUS'] == 1 ? 'COLLECTED' : 'UNRECEIVED'; + $result['sample_collection'][] = [ + 'tubenumber' => trim($row['TUBENUMBER']), + 'user' => trim($row['USERID']), + 'datetime' => $row['LOGDATE'] ? date('Y-m-d H:i:s', strtotime($row['LOGDATE'])) : null, + 'action' => $action + ]; + } + + return $this->respond(['status' => 'success', 'data' => $result]); + } +} diff --git a/app/Controllers/LabelController.php b/app/Controllers/LabelController.php index 8cc230a..9124fb1 100644 --- a/app/Controllers/LabelController.php +++ b/app/Controllers/LabelController.php @@ -6,7 +6,8 @@ class LabelController extends BaseController public function coll($reqnum) { $db = \Config\Database::connect(); - //$reqnum = str_pad($reqnum, 10, 0, STR_PAD_LEFT); + $userid = session()->get('userid') ?? 'system'; + $sql = "select p.PATNUMBER, [Name] = case when p.TITLEID is not null then ISNULL(p.FIRSTNAME,'') + ' ' + ISNULL(p.NAME,'') + ', ' + tx.SHORTTEXT @@ -70,6 +71,8 @@ P1\n]"; public function dispatch($reqnum, $samid) { $db = \Config\Database::connect(); + $userid = session()->get('userid') ?? 'system'; + $sql = "select p.PATNUMBER, [Name] = case when p.TITLEID is not null then ISNULL(p.FIRSTNAME,'') + ' ' + ISNULL(p.NAME,'') + ', ' + tx.SHORTTEXT @@ -147,6 +150,8 @@ P1 public function print_all($accessnumber) { $db = \Config\Database::connect(); + $userid = session()->get('userid') ?? 'system'; + $this->coll($accessnumber); $sql = "select SAMPCODE from GDC_CMOD.dbo.v_sp_reqtube where SP_ACCESSNUMBER='$accessnumber'"; $rows = $db->query($sql)->getResultArray(); diff --git a/app/Controllers/Pages/AdminController.php b/app/Controllers/Pages/AdminController.php index 1cfc957..c4a4f70 100644 --- a/app/Controllers/Pages/AdminController.php +++ b/app/Controllers/Pages/AdminController.php @@ -4,24 +4,29 @@ namespace App\Controllers\Pages; use App\Controllers\BaseController; -class AdminController extends BaseController { +class AdminController extends BaseController +{ - public function __construct() { + public function __construct() + { helper(['url', 'form', 'text']); } - public function index() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + public function index() + { + $config = require APPPATH . 'Views/shared/config.php'; return view('admin/index', ['roleConfig' => $config['admin']]); } - public function users() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + public function users() + { + $config = require APPPATH . 'Views/shared/config.php'; return view('admin/users', ['roleConfig' => $config['admin']]); } - public function validationPage() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + public function validationPage() + { + $config = require APPPATH . 'Views/shared/config.php'; return view('admin/validate', ['roleConfig' => $config['admin']]); } diff --git a/app/Controllers/Pages/CsController.php b/app/Controllers/Pages/CsController.php index cc65f84..c6e0c98 100644 --- a/app/Controllers/Pages/CsController.php +++ b/app/Controllers/Pages/CsController.php @@ -4,14 +4,17 @@ namespace App\Controllers\Pages; use App\Controllers\BaseController; -class CsController extends BaseController { +class CsController extends BaseController +{ - public function __construct() { + public function __construct() + { helper(['url', 'form', 'text']); } - public function index() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + public function index() + { + $config = require APPPATH . 'Views/shared/config.php'; return view('cs/index', ['roleConfig' => $config['cs']]); } diff --git a/app/Controllers/Pages/LabController.php b/app/Controllers/Pages/LabController.php index 7bc551e..bd6e41f 100644 --- a/app/Controllers/Pages/LabController.php +++ b/app/Controllers/Pages/LabController.php @@ -4,19 +4,23 @@ namespace App\Controllers\Pages; use App\Controllers\BaseController; -class LabController extends BaseController { +class LabController extends BaseController +{ - public function __construct() { + public function __construct() + { helper(['url', 'form', 'text']); } - public function index() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + public function index() + { + $config = require APPPATH . 'Views/shared/config.php'; return view('lab/index', ['roleConfig' => $config['lab']]); } - public function validationPage() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + public function validationPage() + { + $config = require APPPATH . 'Views/shared/config.php'; return view('lab/validate', ['roleConfig' => $config['lab']]); } diff --git a/app/Controllers/Pages/PhlebotomistController.php b/app/Controllers/Pages/PhlebotomistController.php index 4f33b8d..441ac82 100644 --- a/app/Controllers/Pages/PhlebotomistController.php +++ b/app/Controllers/Pages/PhlebotomistController.php @@ -4,14 +4,17 @@ namespace App\Controllers\Pages; use App\Controllers\BaseController; -class PhlebotomistController extends BaseController { +class PhlebotomistController extends BaseController +{ - public function __construct() { + public function __construct() + { helper(['url', 'form', 'text']); } - public function index() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + public function index() + { + $config = require APPPATH . 'Views/shared/config.php'; return view('phlebo/index', ['roleConfig' => $config['phlebo']]); } diff --git a/app/Controllers/Pages/SuperuserController.php b/app/Controllers/Pages/SuperuserController.php index 16185cb..329c8c7 100644 --- a/app/Controllers/Pages/SuperuserController.php +++ b/app/Controllers/Pages/SuperuserController.php @@ -14,19 +14,19 @@ class SuperuserController extends BaseController public function index() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + $config = require APPPATH . 'Views/shared/config.php'; return view('superuser/index', ['roleConfig' => $config['superuser']]); } public function users() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + $config = require APPPATH . 'Views/shared/config.php'; return view('superuser/users', ['roleConfig' => $config['superuser']]); } public function validatePage() { - $config = require APPPATH . 'Views/shared/dashboard_config.php'; + $config = require APPPATH . 'Views/shared/config.php'; return view('superuser/validate', ['roleConfig' => $config['superuser']]); } diff --git a/app/Controllers/RequestsController.php b/app/Controllers/RequestsController.php index b2a09cf..02482d0 100644 --- a/app/Controllers/RequestsController.php +++ b/app/Controllers/RequestsController.php @@ -63,13 +63,17 @@ class RequestsController extends BaseController public function unval($accessnumber) { $input = $this->request->getJSON(true); - // Securely get userid from session $userid = session('userid'); $comment = $input['comment']; $db = \Config\Database::connect(); $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); + + $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT, REASON) + VALUES (?, 'UNVAL', ?, GETDATE(), ?)"; + $db->query($logAudit, [$accessnumber, $userid, $comment]); + $data = ['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber"]; return $this->response->setJSON($data); @@ -86,6 +90,10 @@ class RequestsController extends BaseController if (!isset($result[0])) { $sql = "insert into GDC_CMOD.dbo.CM_REQUESTS(ACCESSNUMBER, ISVAL1, VAL1USER, VAL1DATE) VALUES ('$accessnumber', 1, '$userid', GETDATE())"; $db->query($sql); + + $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL1', ?, GETDATE())"; + $db->query($logAudit, [$accessnumber, $userid]); + $data['val'] = 1; $data['userid'] = $userid; } else { @@ -99,6 +107,10 @@ class RequestsController extends BaseController } else { if ($val1user != $userid) { $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL2=1, VAL2USER='$userid', VAL2DATE=GETDATE() where ACCESSNUMBER='$accessnumber'"; + + $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL2', ?, GETDATE())"; + $db->query($logAudit, [$accessnumber, $userid]); + $data['val'] = 2; $data['userid'] = $userid; } else { @@ -108,6 +120,10 @@ class RequestsController extends BaseController } } else { $sql = "update GDC_CMOD.dbo.CM_REQUESTS set ISVAL1=1, VAL1USER='$userid', VAL1DATE=GETDATE() where ACCESSNUMBER='$accessnumber'"; + + $logAudit = "INSERT INTO GDC_CMOD.dbo.AUDIT_EVENTS (ACCESSNUMBER, EVENT_TYPE, USERID, EVENT_AT) VALUES (?, 'VAL1', ?, GETDATE())"; + $db->query($logAudit, [$accessnumber, $userid]); + $data['val'] = 1; $data['userid'] = $userid; } diff --git a/app/Controllers/SamplesController.php b/app/Controllers/SamplesController.php index f6cecfa..205dbdd 100644 --- a/app/Controllers/SamplesController.php +++ b/app/Controllers/SamplesController.php @@ -76,20 +76,6 @@ class SamplesController extends BaseController return $this->respondCreated(['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber-$samplenumber"], 201); } - public function uncollect($accessnumber) - { - $db = \Config\Database::connect(); - $input = $this->request->getJSON(true); - $samplenumber = $input['samplenumber']; - $userid = session('userid'); - $sql = "update GDC_CMOD.dbo.TUBES set USERID='$userid',STATUS='0', COLLECTIONDATE=getdate() where ACCESSNUMBER='$accessnumber' and TUBENUMBER='$samplenumber'"; - $db->query($sql); - $sql = "INSERT INTO GDC_CMOD.dbo.AUDIT_TUBES(ACCESSNUMBER, TUBENUMBER, USERID, STATUS, LOGDATE) - VALUES ('$accessnumber', '$samplenumber', '$userid', '0', getdate())"; - $db->query($sql); - return $this->respondCreated(['status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber-$samplenumber"], 201); - } - public function unreceive($accessnumber) { $db = \Config\Database::connect(); diff --git a/app/Controllers/backup/Sample.php b/app/Controllers/backup/Sample.php index 01f0d75..ef3bdce 100644 --- a/app/Controllers/backup/Sample.php +++ b/app/Controllers/backup/Sample.php @@ -72,19 +72,6 @@ class Sample extends BaseController { return $this->respondCreated([ 'status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber-$samplenumber" ], 201); } - public function uncollect($accessnumber) { - $db = \Config\Database::connect(); - $input = $this->request->getJSON(true); - $samplenumber = $input['samplenumber']; - $userid = $input['userid']; - $sql = "update GDC_CMOD.dbo.TUBES set USERID='$userid',STATUS='0', COLLECTIONDATE=getdate() where ACCESSNUMBER='$accessnumber' and TUBENUMBER='$samplenumber'"; - $db->query($sql); - $sql = "INSERT INTO GDC_CMOD.dbo.AUDIT_TUBES(ACCESSNUMBER, TUBENUMBER, USERID, STATUS, LOGDATE) - VALUES ('$accessnumber', '$samplenumber', '$userid', '0', getdate())"; - $db->query($sql); - return $this->respondCreated([ 'status' => 'success', 'message' => 'Data updated successfully', 'data' => "$accessnumber-$samplenumber" ], 201); - } - public function unreceive($accessnumber) { $db = \Config\Database::connect(); $input = $this->request->getJSON(true); diff --git a/app/Views/admin/index.php b/app/Views/admin/index.php index 6a0bd70..30d690d 100644 --- a/app/Views/admin/index.php +++ b/app/Views/admin/index.php @@ -1,22 +1,23 @@ -extend('shared/layout_dashboard', ['roleConfig' => $roleConfig]); ?> +extend('shared/layout', ['roleConfig' => $roleConfig]); ?> section('content'); ?>
- include('shared/dashboard_table', ['config' => $roleConfig]); ?> + include('shared/content_requests', ['config' => $roleConfig]); ?> include('shared/dialog_sample', ['config' => $roleConfig]); ?> include('shared/dialog_unval'); ?> include('shared/dialog_preview'); ?> + include('shared/dialog_audit'); ?>
endSection(); ?> section('script'); ?> -endSection(); ?> +endSection(); ?> \ No newline at end of file diff --git a/app/Views/admin/validate.php b/app/Views/admin/validate.php index 37c18db..dd01237 100644 --- a/app/Views/admin/validate.php +++ b/app/Views/admin/validate.php @@ -1,19 +1,19 @@ -extend('shared/layout_dashboard', ['roleConfig' => $roleConfig]); ?> +extend('shared/layout', ['roleConfig' => $roleConfig]); ?> section('content'); ?>
- include('shared/dashboard_validate', ['config' => $roleConfig]); ?> + include('shared/content_validation', ['config' => $roleConfig]); ?>
endSection(); ?> section('script'); ?> -endSection(); ?> +endSection(); ?> \ No newline at end of file diff --git a/app/Views/cs/index.php b/app/Views/cs/index.php index 4872ef0..0163abb 100644 --- a/app/Views/cs/index.php +++ b/app/Views/cs/index.php @@ -1,22 +1,23 @@ -extend('shared/layout_dashboard', ['roleConfig' => $roleConfig]); ?> +extend('shared/layout', ['roleConfig' => $roleConfig]); ?> section('content'); ?>
- include('shared/dashboard_table', ['config' => $roleConfig]); ?> + include('shared/content_requests', ['config' => $roleConfig]); ?> include('shared/dialog_sample', ['config' => $roleConfig]); ?> include('shared/dialog_unval'); ?> include('shared/dialog_preview'); ?> + include('shared/dialog_audit'); ?>
endSection(); ?> section('script'); ?> -endSection(); ?> +endSection(); ?> \ No newline at end of file diff --git a/app/Views/dummy_page.php b/app/Views/dummy_page.php index 8edb1cc..1db2b63 100644 --- a/app/Views/dummy_page.php +++ b/app/Views/dummy_page.php @@ -1,5 +1,6 @@ + @@ -10,6 +11,7 @@ padding: 0; box-sizing: border-box; } + body { min-height: 100vh; display: flex; @@ -22,51 +24,71 @@ text-align: center; padding: 20px; } + .container { max-width: 600px; } + h1 { font-size: 3rem; margin-bottom: 1rem; animation: bounce 2s infinite; } + @keyframes bounce { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-20px); } + + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-20px); + } } + .message { font-size: 1.5rem; margin-bottom: 2rem; opacity: 0.9; } + .loader { width: 80px; height: 80px; - border: 8px solid rgba(255,255,255,0.3); + border: 8px solid rgba(255, 255, 255, 0.3); border-top-color: white; border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto 2rem; } + @keyframes spin { - to { transform: rotate(360deg); } + to { + transform: rotate(360deg); + } } + .cat { font-size: 5rem; margin-bottom: 1rem; } + .fact { - background: rgba(255,255,255,0.2); + background: rgba(255, 255, 255, 0.2); padding: 1.5rem; border-radius: 15px; margin-top: 2rem; } + .fact h3 { margin-bottom: 0.5rem; } + .buttons { margin-top: 2rem; } + .btn { display: inline-block; padding: 12px 30px; @@ -78,16 +100,19 @@ font-weight: bold; transition: transform 0.2s, box-shadow 0.2s; } + .btn:hover { transform: scale(1.05); - box-shadow: 0 5px 20px rgba(0,0,0,0.3); + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3); } + .shrug { font-size: 2rem; margin: 1rem 0; } +
👀
@@ -101,11 +126,6 @@
🙹 🧀 🦽
- -
- Go Back - Home -
- + + \ No newline at end of file diff --git a/app/Views/lab/index.php b/app/Views/lab/index.php index 8495d48..575d21c 100644 --- a/app/Views/lab/index.php +++ b/app/Views/lab/index.php @@ -1,22 +1,23 @@ -extend('shared/layout_dashboard', ['roleConfig' => $roleConfig]); ?> +extend('shared/layout', ['roleConfig' => $roleConfig]); ?> section('content'); ?>
- include('shared/dashboard_table', ['config' => $roleConfig]); ?> + include('shared/content_requests', ['config' => $roleConfig]); ?> include('shared/dialog_sample', ['config' => $roleConfig]); ?> include('shared/dialog_unval'); ?> include('shared/dialog_preview'); ?> + include('shared/dialog_audit'); ?>
endSection(); ?> section('script'); ?> -endSection(); ?> +endSection(); ?> \ No newline at end of file diff --git a/app/Views/lab/validate.php b/app/Views/lab/validate.php index db16a5d..bf1a5ff 100644 --- a/app/Views/lab/validate.php +++ b/app/Views/lab/validate.php @@ -1,19 +1,19 @@ -extend('shared/layout_dashboard', ['roleConfig' => $roleConfig]); ?> +extend('shared/layout', ['roleConfig' => $roleConfig]); ?> section('content'); ?>
- include('shared/dashboard_validate', ['config' => $roleConfig]); ?> + include('shared/content_validation', ['config' => $roleConfig]); ?>
endSection(); ?> section('script'); ?> -endSection(); ?> +endSection(); ?> \ No newline at end of file diff --git a/app/Views/phlebo/index.php b/app/Views/phlebo/index.php index 93a97b9..cf1999e 100644 --- a/app/Views/phlebo/index.php +++ b/app/Views/phlebo/index.php @@ -1,22 +1,23 @@ -extend('shared/layout_dashboard', ['roleConfig' => $roleConfig]); ?> +extend('shared/layout', ['roleConfig' => $roleConfig]); ?> section('content'); ?>
- include('shared/dashboard_table', ['config' => $roleConfig]); ?> + include('shared/content_requests', ['config' => $roleConfig]); ?> include('shared/dialog_sample', ['config' => $roleConfig]); ?> include('shared/dialog_unval'); ?> include('shared/dialog_preview'); ?> + include('shared/dialog_audit'); ?>
endSection(); ?> section('script'); ?> -endSection(); ?> +endSection(); ?> \ No newline at end of file diff --git a/app/Views/shared/dashboard_config.php b/app/Views/shared/config.php similarity index 100% rename from app/Views/shared/dashboard_config.php rename to app/Views/shared/config.php diff --git a/app/Views/shared/dashboard_table.php b/app/Views/shared/content_requests.php similarity index 95% rename from app/Views/shared/dashboard_table.php rename to app/Views/shared/content_requests.php index 84b556f..32a0e9d 100644 --- a/app/Views/shared/dashboard_table.php +++ b/app/Views/shared/content_requests.php @@ -189,6 +189,7 @@ ResTo Val Result + @@ -212,12 +213,15 @@ @@ -228,6 +232,13 @@ @click="openPreviewDialog(req.SP_ACCESSNUMBER, 'preview', req)">Preview + + + diff --git a/app/Views/shared/dashboard_validate.php b/app/Views/shared/content_validation.php similarity index 85% rename from app/Views/shared/dashboard_validate.php rename to app/Views/shared/content_validation.php index f345ef3..d4419cb 100644 --- a/app/Views/shared/dashboard_validate.php +++ b/app/Views/shared/content_validation.php @@ -2,15 +2,18 @@
-
-
-
-

- Pending Validation -

-
-
- requests +
+
+

+ + + + Pending Validation +

+
+ + + requests
@@ -51,36 +54,30 @@ - - - - - - - diff --git a/app/Views/shared/content_validation_new.php b/app/Views/shared/content_validation_new.php new file mode 100644 index 0000000..79c979b --- /dev/null +++ b/app/Views/shared/content_validation_new.php @@ -0,0 +1,276 @@ +
+
+ + +
+
+
+

+ Pending Validation +

+
+
+
+ + Not Started + +
+
+ + 1st Val + +
+
+ + Done + +
+
+
+ + +
+
+ Overall Progress + +
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+ + - + +
+
+ +
+ + +
+ + + +
+ +
+
+
+ + +
+ +
+ Legend: +
+ + Pending +
+
+ + 1st Val +
+
+ + Done +
+
+ + + + + + +
+ + +
+
+ Showing to + of + entries +
+
+ + + +
+
+ +
+
+ + +include('shared/dialog_val'); ?> diff --git a/app/Views/shared/dialog_audit.php b/app/Views/shared/dialog_audit.php new file mode 100644 index 0000000..7f7c8a6 --- /dev/null +++ b/app/Views/shared/dialog_audit.php @@ -0,0 +1,89 @@ + + + diff --git a/app/Views/shared/dialog_sample.php b/app/Views/shared/dialog_sample.php index 06a3c5d..dd3806f 100644 --- a/app/Views/shared/dialog_sample.php +++ b/app/Views/shared/dialog_sample.php @@ -1,6 +1,15 @@
+
+
+
+
-
-
+
-
-