Fix IPD patient admit search error, add admission type filters to IPD patient list, remove redundant sidebar links, and add OPD Day Care template support
This commit is contained in:
parent
ccb05389e1
commit
3f1e89d4be
|
|
@ -705,6 +705,12 @@ $routes->get('opd_print/invoice_print_pdf/(:num)', 'Opd::invoice_print_pdf/$1');
|
|||
$routes->get('opd_print/opd_PDF_print/(:num)', 'Opd::opd_pdf_print/$1');
|
||||
$routes->get('opd_print/opd_Cont_print/(:num)', 'Opd::opd_cont_print/$1');
|
||||
$routes->get('opd_print/opd_blank_print/(:num)', 'Opd::opd_blank_print/$1');
|
||||
$routes->get('opd_print/opd_day_care/(:num)/(:num)', 'Opd::opd_day_care/$1/$2');
|
||||
$routes->get('opd_print/opd_day_care/(:num)', 'Opd::opd_day_care/$1');
|
||||
$routes->get('Opd_print/opd_day_care/(:num)/(:num)', 'Opd::opd_day_care/$1/$2');
|
||||
$routes->get('Opd_print/opd_day_care/(:num)', 'Opd::opd_day_care/$1');
|
||||
$routes->get('Opd/opd_day_care/(:num)/(:num)', 'Opd::opd_day_care/$1/$2');
|
||||
$routes->get('Opd/opd_day_care/(:num)', 'Opd::opd_day_care/$1');
|
||||
|
||||
$routes->get('Opd_prescription/Prescription/(:num)', 'Opd_prescription::Prescription/$1');
|
||||
$routes->match(['GET', 'POST'], 'Opd_prescription/create_opd_queue/(:num)', 'Opd_prescription::create_opd_queue/$1');
|
||||
|
|
|
|||
|
|
@ -229,9 +229,10 @@ class Ipd extends BaseController
|
|||
}
|
||||
|
||||
$builder = $this->db->table('patient_master p');
|
||||
$builder->select('p.id, p.p_code, p.p_fname as patient_name, p.gender, p.age, p.dob, p.mphone1, p.mphone2');
|
||||
$builder->select('p.id, p.p_code, p.p_fname, p.p_rname, p.gender, p.age, p.dob, p.mphone1, p.mphone2');
|
||||
$builder->groupStart()
|
||||
->like('p.p_fname', $termClean)
|
||||
->orLike('p.p_rname', $termClean)
|
||||
->orLike('p.p_code', $termClean)
|
||||
->orLike('p.mphone1', $termClean)
|
||||
->orLike('p.mphone2', $termClean)
|
||||
|
|
@ -243,12 +244,15 @@ class Ipd extends BaseController
|
|||
$activeIpds = [];
|
||||
if (! empty($patientIds)) {
|
||||
$rows = $this->db->table('ipd_master')
|
||||
->select('id, p_id, coalesce(ipd_code, pid) as ipd_code, admission_type, ipd_status')
|
||||
->select('id, p_id, ipd_code, admission_type, ipd_status')
|
||||
->whereIn('p_id', $patientIds)
|
||||
->where('ipd_status', 0)
|
||||
->get()
|
||||
->getResultArray();
|
||||
foreach ($rows as $r) {
|
||||
if (empty($r['ipd_code'])) {
|
||||
$r['ipd_code'] = '#' . $r['id'];
|
||||
}
|
||||
$activeIpds[(int) $r['p_id']] = $r;
|
||||
}
|
||||
}
|
||||
|
|
@ -256,6 +260,8 @@ class Ipd extends BaseController
|
|||
foreach ($results as &$pt) {
|
||||
$genderVal = (int) ($pt['gender'] ?? 0);
|
||||
$pt['gender_text'] = ($genderVal === 1) ? 'Male' : (($genderVal === 2) ? 'Female' : 'Other');
|
||||
$fullName = trim(($pt['p_fname'] ?? '') . ' ' . ($pt['p_rname'] ?? ''));
|
||||
$pt['patient_name'] = $fullName !== '' ? $fullName : 'Unnamed';
|
||||
$pt['active_ipd'] = $activeIpds[(int) $pt['id']] ?? null;
|
||||
}
|
||||
unset($pt);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,22 @@ class IpdPatient extends BaseController
|
|||
'cleaning' => 0,
|
||||
'total_admitted' => count($records),
|
||||
'nursing_stations' => 0,
|
||||
'count_ipd' => 0,
|
||||
'count_daycare' => 0,
|
||||
'count_emergency' => 0,
|
||||
];
|
||||
|
||||
foreach ($records as $rec) {
|
||||
$admType = strtolower(trim((string) ($rec->admission_type ?? 'ipd')));
|
||||
if ($admType === 'emergency') {
|
||||
$stats['count_emergency']++;
|
||||
} elseif ($admType === 'daycare') {
|
||||
$stats['count_daycare']++;
|
||||
} else {
|
||||
$stats['count_ipd']++;
|
||||
}
|
||||
}
|
||||
|
||||
$floors = [];
|
||||
$wards = [];
|
||||
|
||||
|
|
@ -83,7 +98,7 @@ class IpdPatient extends BaseController
|
|||
|
||||
if ($this->db->tableExists('ipd_master')) {
|
||||
$builder
|
||||
->select('i.id as ipd_id, i.ipd_code, i.register_date, i.r_doc_name')
|
||||
->select('i.id as ipd_id, i.ipd_code, i.register_date, i.r_doc_name, i.admission_type')
|
||||
->join('ipd_master i', 'i.id = b.current_ipd_id AND i.ipd_status = 0', 'left', false);
|
||||
|
||||
if ($this->db->tableExists('patient_master')) {
|
||||
|
|
@ -145,6 +160,7 @@ class IpdPatient extends BaseController
|
|||
'doctor_name' => trim((string) ($row->r_doc_name ?? '')),
|
||||
'ipd_code' => (string) ($row->ipd_code ?? ''),
|
||||
'ipd_id' => (int) ($row->ipd_id ?? 0),
|
||||
'admission_type' => strtolower(trim((string) ($row->admission_type ?? 'ipd'))),
|
||||
'admit_date' => (string) ($row->register_date ?? ''),
|
||||
'days_admitted' => $daysAdmitted,
|
||||
'has_oxygen' => (bool) ($row->has_oxygen ?? false),
|
||||
|
|
|
|||
|
|
@ -2535,6 +2535,18 @@ class Opd extends BaseController
|
|||
return redirect()->to($url);
|
||||
}
|
||||
|
||||
public function opd_day_care(int $opdId, int $mode = 0)
|
||||
{
|
||||
$printConfig = $this->resolveDoctorPrintConfigByField($opdId, 'opd_day_care_template', 'day_care_format');
|
||||
$url = base_url('Opd/opd_lettre_pdf/' . (int) $opdId);
|
||||
if ($printConfig['template'] !== '') {
|
||||
$url .= '?template=' . urlencode($printConfig['template']);
|
||||
} else {
|
||||
$url .= '?template=day_care_format';
|
||||
}
|
||||
return redirect()->to($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{layout:string,template:string}
|
||||
*/
|
||||
|
|
@ -2547,6 +2559,10 @@ class Opd extends BaseController
|
|||
$fallbackLayout = 'full';
|
||||
}
|
||||
|
||||
if (! $this->db->tableExists('doctor_master') || ! $this->db->fieldExists($fieldName, 'doctor_master')) {
|
||||
return ['layout' => $fallbackLayout, 'template' => ''];
|
||||
}
|
||||
|
||||
$query = $this->db->query(
|
||||
'SELECT d.' . $fieldName . ' AS layout_field
|
||||
FROM opd_master o
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ class Doctor extends BaseController
|
|||
'opd_print_format' => 'tmpl_opd_print_format',
|
||||
'opd_blank_print' => 'tmpl_opd_blank_print',
|
||||
'opd_cont_paper_print' => 'tmpl_opd_cont_paper_print',
|
||||
'opd_day_care_template' => 'tmpl_opd_day_care_template',
|
||||
'rx_pre_print_letter_head_format' => 'tmpl_rx_pre_print_letter_head_format',
|
||||
'rx_blank_letter_head' => 'tmpl_rx_blank_letter_head',
|
||||
'rx_plain_paper' => 'tmpl_rx_plain_paper',
|
||||
|
|
@ -229,6 +230,7 @@ class Doctor extends BaseController
|
|||
'opd_print_format' => 'tmpl_opd_print_format',
|
||||
'opd_blank_print' => 'tmpl_opd_blank_print',
|
||||
'opd_cont_paper_print' => 'tmpl_opd_cont_paper_print',
|
||||
'opd_day_care_template' => 'tmpl_opd_day_care_template',
|
||||
'rx_pre_print_letter_head_format' => 'tmpl_rx_pre_print_letter_head_format',
|
||||
'rx_blank_letter_head' => 'tmpl_rx_blank_letter_head',
|
||||
'rx_plain_paper' => 'tmpl_rx_plain_paper',
|
||||
|
|
@ -671,6 +673,7 @@ class Doctor extends BaseController
|
|||
'opd_print_format',
|
||||
'opd_blank_print',
|
||||
'opd_cont_paper_print',
|
||||
'opd_day_care_template',
|
||||
'rx_pre_print_letter_head_format',
|
||||
'rx_blank_letter_head',
|
||||
'rx_plain_paper',
|
||||
|
|
@ -681,6 +684,23 @@ class Doctor extends BaseController
|
|||
}
|
||||
|
||||
$doctorFields = $this->db->getFieldNames('doctor_master') ?? [];
|
||||
if (! in_array('opd_day_care_template', $doctorFields, true)) {
|
||||
try {
|
||||
$forge = \Config\Database::forge();
|
||||
$forge->addColumn('doctor_master', [
|
||||
'opd_day_care_template' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 100,
|
||||
'null' => true,
|
||||
'default' => null,
|
||||
'after' => 'opd_cont_paper_print',
|
||||
],
|
||||
]);
|
||||
$doctorFields[] = 'opd_day_care_template';
|
||||
} catch (\Throwable $e) {
|
||||
// Ignore if unable to add dynamically
|
||||
}
|
||||
}
|
||||
$availableFields = array_values(array_intersect($allTemplateFields, $doctorFields));
|
||||
|
||||
$options = $this->collectStoredTemplateOptions();
|
||||
|
|
@ -737,6 +757,19 @@ class Doctor extends BaseController
|
|||
}
|
||||
}
|
||||
|
||||
$fsDir = APPPATH . 'Views/billing/opd_templates/';
|
||||
if (is_dir($fsDir)) {
|
||||
$files = glob($fsDir . '*.html');
|
||||
if ($files) {
|
||||
foreach ($files as $file) {
|
||||
$templateId = $this->normalizeTemplateId(basename($file, '.html'));
|
||||
if ($templateId !== '') {
|
||||
$options[] = $templateId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddOpdDayCareTemplateToDoctorMaster extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
if ($this->db->tableExists('doctor_master')) {
|
||||
$fields = [];
|
||||
if (! $this->db->fieldExists('opd_day_care_template', 'doctor_master')) {
|
||||
$fields['opd_day_care_template'] = [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 100,
|
||||
'null' => true,
|
||||
'default' => null,
|
||||
'after' => 'opd_cont_paper_print',
|
||||
];
|
||||
}
|
||||
|
||||
if (! empty($fields)) {
|
||||
$this->forge->addColumn('doctor_master', $fields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
if ($this->db->tableExists('doctor_master') && $this->db->fieldExists('opd_day_care_template', 'doctor_master')) {
|
||||
$this->forge->dropColumn('doctor_master', 'opd_day_care_template');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4919,6 +4919,17 @@
|
|||
"Privileges": "select,insert,update,references",
|
||||
"Comment": ""
|
||||
},
|
||||
"opd_day_care_template": {
|
||||
"Field": "opd_day_care_template",
|
||||
"Type": "varchar(100)",
|
||||
"Collation": "utf8mb3_unicode_ci",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": null,
|
||||
"Extra": "",
|
||||
"Privileges": "select,insert,update,references",
|
||||
"Comment": ""
|
||||
},
|
||||
"opd_valid_no_days": {
|
||||
"Field": "opd_valid_no_days",
|
||||
"Type": "int",
|
||||
|
|
|
|||
|
|
@ -134,6 +134,18 @@
|
|||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($templateFieldSet['opd_day_care_template'])) : ?>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Daycare Template</label>
|
||||
<select class="form-select" name="tmpl_opd_day_care_template">
|
||||
<option value="">-- Select Template --</option>
|
||||
<?php foreach ($templateOptions as $tmpl) : ?>
|
||||
<option value="<?= esc($tmpl) ?>" <?= combo_checked($tmpl, strtolower(trim((string) ($formData['tmpl_opd_day_care_template'] ?? '')))) ?>><?= esc($tmpl) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($templateFieldSet['rx_pre_print_letter_head_format'])) : ?>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Rx Pre-Print Letterhead</label>
|
||||
|
|
@ -147,7 +159,7 @@
|
|||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($templateFieldSet['rx_blank_letter_head'])) : ?>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Rx Blank Letterhead</label>
|
||||
<select class="form-select" name="tmpl_rx_blank_letter_head">
|
||||
<option value="">-- Select Template --</option>
|
||||
|
|
|
|||
|
|
@ -175,6 +175,18 @@ if (!empty($data) && !empty($data[0]) && !empty($data[0]->dob)) {
|
|||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($templateFieldSet['opd_day_care_template'])) : ?>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Daycare Template</label>
|
||||
<select class="form-select" name="tmpl_opd_day_care_template">
|
||||
<option value="">-- Select Template --</option>
|
||||
<?php foreach ($templateOptions as $tmpl) : ?>
|
||||
<option value="<?= esc($tmpl) ?>" <?= combo_checked($tmpl, strtolower(trim((string) ($data[0]->opd_day_care_template ?? '')))) ?>><?= esc($tmpl) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($templateFieldSet['rx_pre_print_letter_head_format'])) : ?>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Rx Pre-Print Letterhead</label>
|
||||
|
|
@ -188,7 +200,7 @@ if (!empty($data) && !empty($data[0]) && !empty($data[0]->dob)) {
|
|||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($templateFieldSet['rx_blank_letter_head'])) : ?>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Rx Blank Letterhead</label>
|
||||
<select class="form-select" name="tmpl_rx_blank_letter_head">
|
||||
<option value="">-- Select Template --</option>
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ foreach ($placeholderGroups as $groupName => $groupValues) {
|
|||
|
||||
<div class="alert alert-info">
|
||||
<strong>Old-style (recommended):</strong> save a name (example: <strong>opd_print_parcha_chamunda_hospital_ksp</strong>), then set that name in doctor master fields:<br>
|
||||
<code>opd_print_format</code>, <code>opd_blank_print</code>, <code>rx_pre_print_letter_head_format</code>, <code>rx_blank_letter_head</code>, <code>rx_plain_paper</code>.<br><br>
|
||||
<code>opd_print_format</code>, <code>opd_blank_print</code>, <code>opd_cont_paper_print</code>, <code>opd_day_care_template</code>, <code>rx_pre_print_letter_head_format</code>, <code>rx_blank_letter_head</code>, <code>rx_plain_paper</code>.<br><br>
|
||||
<strong>Optional composed mode:</strong> use <code>compose_default</code> with type-specific parts.
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
127
app/Views/billing/opd_templates/day_care_format.html
Normal file
127
app/Views/billing/opd_templates/day_care_format.html
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
<style>
|
||||
@page {
|
||||
margin-top: 3.5cm;
|
||||
margin-bottom: 1.5cm;
|
||||
margin-left: 0.7cm;
|
||||
margin-right: 0.7cm;
|
||||
margin-header: 0.5cm;
|
||||
margin-footer: 0.5cm;
|
||||
header: html_myHeader;
|
||||
footer: html_myFooter;
|
||||
}
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 11px;
|
||||
color: #111;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
h1.doc-title {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
letter-spacing: 0.05em;
|
||||
margin: 4px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.section-title {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #111;
|
||||
border-bottom: 1px solid #333;
|
||||
padding-bottom: 3px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 8px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.meta-table td {
|
||||
padding: 2px 4px;
|
||||
vertical-align: top;
|
||||
font-size: 11px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<htmlpageheader name="myHeader">
|
||||
<table width="100%" style="font-size: 10px; border-bottom: 2px solid #333; padding-bottom: 4px;">
|
||||
<tr>
|
||||
<td style="width: 15%; vertical-align: middle;">
|
||||
<img style="max-height: 55px; max-width: 90px;" src="{{H_logo_abs}}" />
|
||||
</td>
|
||||
<td style="width: 55%; vertical-align: top; text-align: center;">
|
||||
<div style="font-size: 16px; font-weight: bold;">{{H_Name}}</div>
|
||||
<div style="font-size: 10px; color: #444;">{{H_address_1}} {{H_address_2}}</div>
|
||||
<div style="font-size: 10px; color: #444;">Phone: {{H_phone_No}}</div>
|
||||
<div class="doc-title">DAY CARE DISCHARGE SUMMARY</div>
|
||||
</td>
|
||||
<td style="width: 30%; vertical-align: top; text-align: right;">
|
||||
<div style="font-size: 13px; font-weight: bold;">Dr. {{doctor_name}}</div>
|
||||
<div style="font-size: 10px; color: #333;">{{doctor_short_description}}</div>
|
||||
<div style="font-size: 9px; color: #666;">{{SpecName}}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</htmlpageheader>
|
||||
|
||||
<htmlpagefooter name="myFooter">
|
||||
<table width="100%" style="font-size: 9px; border-top: 1px solid #999; padding-top: 4px;">
|
||||
<tr>
|
||||
<td width="50%">
|
||||
Printed on: {{print_time}} | OPD No: {{opd_no}}
|
||||
</td>
|
||||
<td width="50%" align="right">
|
||||
Authorized Signature: _______________________
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</htmlpagefooter>
|
||||
|
||||
<table class="meta-table" width="100%" style="border-bottom: 1px solid #bbb; padding-bottom: 6px; margin-bottom: 8px;">
|
||||
<tr>
|
||||
<td width="50%">
|
||||
<strong>UHID:</strong> {{uhid_no}}<br/>
|
||||
<strong>Patient Name:</strong> <strong>{{pName}}</strong><br/>
|
||||
<strong>Relation:</strong> {{pRelative}}<br/>
|
||||
<strong>Sex / Age:</strong> {{age_sex}}<br/>
|
||||
<strong>Mobile:</strong> {{phoneno}}<br/>
|
||||
<strong>Address:</strong> {{p_address}}
|
||||
</td>
|
||||
<td width="50%">
|
||||
<strong>Date:</strong> {{opd_date}}<br/>
|
||||
<strong>OPD No:</strong> {{opd_no}}<br/>
|
||||
<strong>Consultant:</strong> Dr. {{doctor_name}}<br/>
|
||||
<strong>Admit Time:</strong> <span style="letter-spacing: 2px;">____________________</span><br/>
|
||||
<strong>Discharge Time:</strong> <span style="letter-spacing: 2px;">____________________</span><br/>
|
||||
<strong>Diagnosis:</strong> {{diagnosis}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="section-title">Course / Treatment in the Hospital</div>
|
||||
<div style="min-height: 140px; font-size: 11px; line-height: 1.6; padding: 4px 0;">
|
||||
{{complaint}}
|
||||
<br/><br/><br/><br/><br/><br/><br/>
|
||||
</div>
|
||||
|
||||
<div class="section-title">Treatment Advice on Discharge</div>
|
||||
<div style="min-height: 180px; font-size: 11px; line-height: 1.6; padding: 4px 0;">
|
||||
{{medical}}
|
||||
{{advice}}
|
||||
<br/><br/><br/><br/><br/>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<table width="100%" style="font-size: 11px;">
|
||||
<tr>
|
||||
<td width="50%" style="vertical-align: bottom;">
|
||||
<strong>Next Follow-up / Visit:</strong> {{next_visit}}<br/>
|
||||
<em>In case of any emergency, please visit the emergency department immediately.</em>
|
||||
</td>
|
||||
<td width="50%" align="right" style="vertical-align: bottom;">
|
||||
<br/><br/>
|
||||
<strong>Dr. {{doctor_name}}</strong><br/>
|
||||
<span>Doctor's Signature</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -49,7 +49,12 @@
|
|||
<div class="col-6 col-sm-4 col-md-2">
|
||||
<div class="card border-0 shadow-sm text-center py-2 bg-info-subtle text-info-emphasis rounded-3 border border-info-subtle">
|
||||
<div class="fs-4 fw-bold mb-0"><?= (int)($stats['total_admitted'] ?? 0) ?></div>
|
||||
<div class="small">Admitted Patients</div>
|
||||
<div class="small fw-semibold">Admitted Patients</div>
|
||||
<div class="d-flex justify-content-center gap-1 mt-1 flex-wrap" style="font-size:10px;">
|
||||
<span class="badge bg-primary px-1" title="Regular Inpatient (IPD)">IPD: <?= (int)($stats['count_ipd'] ?? 0) ?></span>
|
||||
<span class="badge bg-warning text-dark px-1 border border-warning-subtle" title="Day Care Unit (< 24h)">Day Care: <?= (int)($stats['count_daycare'] ?? 0) ?></span>
|
||||
<span class="badge bg-danger px-1" title="Emergency / Casualty">Cas: <?= (int)($stats['count_emergency'] ?? 0) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -58,14 +63,22 @@
|
|||
<div class="card shadow-sm border-0 mb-3">
|
||||
<div class="card-body py-2 px-3">
|
||||
<div class="row g-2 align-items-center">
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-12 col-lg-3">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text bg-light border-end-0"><i class="bi bi-search text-muted"></i></span>
|
||||
<input type="text" class="form-control border-start-0" id="nursing_search_input" placeholder="Search patient name, IPD code, bed..." onkeyup="filterNursingBeds()">
|
||||
<input type="text" class="form-control border-start-0" id="nursing_search_input" placeholder="Search patient, IPD code, bed..." onkeyup="filterNursingBeds()">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="$('#nursing_search_input').val(''); filterNursingBeds();">×</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-sm-6 col-md-3 col-lg-2">
|
||||
<select class="form-select form-select-sm" id="filter_admission_type" onchange="onAdmissionTypeDropdownChange()">
|
||||
<option value="">All Admission Types</option>
|
||||
<option value="ipd">Regular IPD (<?= (int)($stats['count_ipd'] ?? 0) ?>)</option>
|
||||
<option value="daycare">Day Care Unit (<?= (int)($stats['count_daycare'] ?? 0) ?>)</option>
|
||||
<option value="emergency">Emergency / Casualty (<?= (int)($stats['count_emergency'] ?? 0) ?>)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-3 col-lg-2">
|
||||
<select class="form-select form-select-sm" id="filter_nursing_station" onchange="filterNursingBeds()">
|
||||
<option value="">All Nursing Stations</option>
|
||||
<?php foreach (($nursingStations ?? []) as $st): ?>
|
||||
|
|
@ -73,7 +86,7 @@
|
|||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-sm-6 col-md-3 col-lg-2">
|
||||
<select class="form-select form-select-sm" id="filter_nursing_ward" onchange="filterNursingBeds()">
|
||||
<option value="">All Wards</option>
|
||||
<?php foreach (($wards ?? []) as $wId => $wName): ?>
|
||||
|
|
@ -81,7 +94,7 @@
|
|||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 text-end">
|
||||
<div class="col-sm-6 col-md-3 col-lg-3 text-end">
|
||||
<div class="btn-group btn-group-sm" role="group" aria-label="Status Filters">
|
||||
<button type="button" class="btn btn-outline-secondary active btn-status-filter" data-status="all" onclick="setStatusFilter('all', this)">All</button>
|
||||
<button type="button" class="btn btn-outline-success btn-status-filter" data-status="available" onclick="setStatusFilter('available', this)">Free</button>
|
||||
|
|
@ -89,6 +102,25 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Filter by Admission Type Row -->
|
||||
<div class="d-flex align-items-center gap-2 flex-wrap pt-2 border-top mt-2">
|
||||
<span class="small fw-bold text-muted text-uppercase" style="font-size:11px; letter-spacing:0.5px;">Quick Filter by Type:</span>
|
||||
<div class="btn-group btn-group-sm" role="group" aria-label="Admission Type Quick Filters">
|
||||
<button type="button" class="btn btn-secondary btn-sm active btn-type-filter" data-type="all" onclick="setTypeFilter('all', this)">
|
||||
All (<?= (int)($stats['total_admitted'] ?? 0) ?>)
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm btn-type-filter" data-type="ipd" onclick="setTypeFilter('ipd', this)">
|
||||
<i class="bi bi-hospital me-1"></i>Regular IPD (<?= (int)($stats['count_ipd'] ?? 0) ?>)
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-warning text-dark btn-sm btn-type-filter" data-type="daycare" onclick="setTypeFilter('daycare', this)">
|
||||
<i class="bi bi-clock-history me-1"></i>Day Care (< 24h) (<?= (int)($stats['count_daycare'] ?? 0) ?>)
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm btn-type-filter" data-type="emergency" onclick="setTypeFilter('emergency', this)">
|
||||
<i class="bi bi-ambulance me-1"></i>Emergency / Casualty (<?= (int)($stats['count_emergency'] ?? 0) ?>)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -173,10 +205,13 @@
|
|||
$statusLabel = ucfirst($bed['bed_status']);
|
||||
}
|
||||
|
||||
$searchText = strtolower($bed['bed_number'] . ' ' . $bed['bed_code'] . ' ' . $bed['patient_name'] . ' ' . $bed['doctor_name'] . ' ' . $bed['ipd_code'] . ' ' . $wardInfo['ward_name'] . ' ' . $bed['station_name']);
|
||||
$admType = strtolower(trim((string)($bed['admission_type'] ?? 'ipd')));
|
||||
$admTypeLabel = ($admType === 'emergency') ? 'emergency casualty' : (($admType === 'daycare') ? 'daycare day care' : 'ipd inpatient regular');
|
||||
$searchText = strtolower($bed['bed_number'] . ' ' . $bed['bed_code'] . ' ' . $bed['patient_name'] . ' ' . $bed['doctor_name'] . ' ' . $bed['ipd_code'] . ' ' . $wardInfo['ward_name'] . ' ' . $bed['station_name'] . ' ' . $admTypeLabel);
|
||||
?>
|
||||
<div class="col-6 col-sm-4 col-md-3 col-lg-2 bed-card-col"
|
||||
data-status="<?= esc($bed['bed_status']) ?>"
|
||||
data-admission-type="<?= esc($admType) ?>"
|
||||
data-ward="<?= esc($wardInfo['ward_name']) ?>"
|
||||
data-station="<?= esc($bed['station_name']) ?>"
|
||||
data-search="<?= esc($searchText) ?>">
|
||||
|
|
@ -196,11 +231,26 @@
|
|||
<?= esc($bed['doctor_name']) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($bed['days_admitted'] !== null): ?>
|
||||
<span class="badge bg-light text-dark border border-secondary-subtle mt-1" style="font-size: 10px;">
|
||||
<i class="bi bi-clock-history me-1"></i><?= $bed['days_admitted'] ?> days
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<div class="d-flex justify-content-center align-items-center gap-1 flex-wrap mt-1">
|
||||
<?php if ($bed['days_admitted'] !== null): ?>
|
||||
<span class="badge bg-light text-dark border border-secondary-subtle" style="font-size: 10px;">
|
||||
<i class="bi bi-clock-history me-1"></i><?= $bed['days_admitted'] ?>d
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if ($admType === 'emergency'): ?>
|
||||
<span class="badge bg-danger" style="font-size: 10px;" title="Emergency / Casualty">
|
||||
<i class="bi bi-ambulance me-1"></i>Casualty
|
||||
</span>
|
||||
<?php elseif ($admType === 'daycare'): ?>
|
||||
<span class="badge bg-warning text-dark border border-warning-subtle" style="font-size: 10px;" title="Day Care Unit (< 24h)">
|
||||
<i class="bi bi-clock-history me-1"></i>Day Care
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span class="badge bg-primary-subtle text-primary border border-primary-subtle" style="font-size: 10px;" title="Regular Inpatient (IPD)">
|
||||
<i class="bi bi-hospital me-1"></i>IPD
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="my-2 text-success small fw-semibold">
|
||||
|
|
@ -252,6 +302,7 @@
|
|||
<th>IPD Code</th>
|
||||
<th>UHID</th>
|
||||
<th>Patient Name</th>
|
||||
<th>Type</th>
|
||||
<th>Bed & Ward Location</th>
|
||||
<th>Doctor</th>
|
||||
<th>Admit Date</th>
|
||||
|
|
@ -262,17 +313,27 @@
|
|||
<tbody>
|
||||
<?php if (empty($records)): ?>
|
||||
<tr>
|
||||
<td colspan="9" class="text-center py-4 text-muted">
|
||||
<td colspan="10" class="text-center py-4 text-muted">
|
||||
<i class="bi bi-person-x fs-3 d-block mb-1"></i> No current IPD admissions found.
|
||||
</td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($records as $idx => $row) : ?>
|
||||
<tr>
|
||||
<?php $rowType = strtolower(trim((string) ($row->admission_type ?? 'ipd'))); ?>
|
||||
<tr class="table-row-admission" data-admission-type="<?= esc($rowType) ?>">
|
||||
<td class="fw-bold text-secondary ps-3"><?= $idx + 1 ?></td>
|
||||
<td><span class="badge bg-light text-dark border"><?= esc($row->ipd_code ?? '') ?></span></td>
|
||||
<td><code><?= esc($row->p_code ?? '') ?></code></td>
|
||||
<td class="fw-semibold text-primary"><?= esc(trim((string) (($row->p_fname ?? '') . ' ' . ($row->p_rname ?? '')))) ?></td>
|
||||
<td>
|
||||
<?php if ($rowType === 'emergency'): ?>
|
||||
<span class="badge bg-danger"><i class="bi bi-ambulance me-1"></i>Casualty</span>
|
||||
<?php elseif ($rowType === 'daycare'): ?>
|
||||
<span class="badge bg-warning text-dark border border-warning-subtle"><i class="bi bi-clock-history me-1"></i>Day Care</span>
|
||||
<?php else: ?>
|
||||
<span class="badge bg-primary"><i class="bi bi-hospital me-1"></i>Regular IPD</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-info-subtle text-info-emphasis border border-info-subtle">
|
||||
<i class="bi bi-hospital me-1"></i><?= esc($row->Bed_Desc ?? '') ?>
|
||||
|
|
@ -298,6 +359,7 @@
|
|||
|
||||
<script>
|
||||
var currentStatusFilter = 'all';
|
||||
var currentTypeFilter = 'all';
|
||||
|
||||
function switchNursingView(mode) {
|
||||
if (mode === 'grid') {
|
||||
|
|
@ -319,7 +381,45 @@ function switchNursingView(mode) {
|
|||
function setStatusFilter(status, btn) {
|
||||
currentStatusFilter = status;
|
||||
$('.btn-status-filter').removeClass('active btn-secondary btn-success btn-danger').addClass('btn-outline-secondary');
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active');
|
||||
if (status === 'available') {
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active btn-success');
|
||||
} else if (status === 'occupied') {
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active btn-danger');
|
||||
} else {
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active btn-secondary');
|
||||
}
|
||||
filterNursingBeds();
|
||||
}
|
||||
|
||||
function setTypeFilter(type, btn) {
|
||||
currentTypeFilter = type;
|
||||
$('#filter_admission_type').val(type === 'all' ? '' : type);
|
||||
$('.btn-type-filter').removeClass('active btn-secondary btn-primary btn-warning text-dark btn-danger').addClass('btn-outline-secondary');
|
||||
if (type === 'ipd') {
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active btn-primary');
|
||||
} else if (type === 'daycare') {
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active btn-warning text-dark');
|
||||
} else if (type === 'emergency') {
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active btn-danger');
|
||||
} else {
|
||||
$(btn).removeClass('btn-outline-secondary').addClass('active btn-secondary');
|
||||
}
|
||||
filterNursingBeds();
|
||||
}
|
||||
|
||||
function onAdmissionTypeDropdownChange() {
|
||||
var val = $('#filter_admission_type').val() || 'all';
|
||||
currentTypeFilter = val;
|
||||
$('.btn-type-filter').removeClass('active btn-secondary btn-primary btn-warning text-dark btn-danger').addClass('btn-outline-secondary');
|
||||
if (val === 'ipd') {
|
||||
$('.btn-type-filter[data-type="ipd"]').removeClass('btn-outline-secondary').addClass('active btn-primary');
|
||||
} else if (val === 'daycare') {
|
||||
$('.btn-type-filter[data-type="daycare"]').removeClass('btn-outline-secondary').addClass('active btn-warning text-dark');
|
||||
} else if (val === 'emergency') {
|
||||
$('.btn-type-filter[data-type="emergency"]').removeClass('btn-outline-secondary').addClass('active btn-danger');
|
||||
} else {
|
||||
$('.btn-type-filter[data-type="all"]').removeClass('btn-outline-secondary').addClass('active btn-secondary');
|
||||
}
|
||||
filterNursingBeds();
|
||||
}
|
||||
|
||||
|
|
@ -327,10 +427,13 @@ function filterNursingBeds() {
|
|||
var search = ($('#nursing_search_input').val() || '').toLowerCase().trim();
|
||||
var station = ($('#filter_nursing_station').val() || '').toLowerCase().trim();
|
||||
var ward = ($('#filter_nursing_ward').val() || '').toLowerCase().trim();
|
||||
var admType = currentTypeFilter;
|
||||
|
||||
// Filter Visual Bed Grid
|
||||
$('.bed-card-col').each(function() {
|
||||
var $col = $(this);
|
||||
var bStatus = ($col.data('status') || '').toLowerCase();
|
||||
var bAdmType = ($col.data('admission-type') || '').toLowerCase();
|
||||
var bWard = ($col.data('ward') || '').toLowerCase();
|
||||
var bStation = ($col.data('station') || '').toLowerCase();
|
||||
var bSearch = ($col.data('search') || '').toLowerCase();
|
||||
|
|
@ -340,13 +443,19 @@ function filterNursingBeds() {
|
|||
var matchWard = (ward === '' || bWard.indexOf(ward) !== -1);
|
||||
var matchStatus = (currentStatusFilter === 'all' || bStatus === currentStatusFilter);
|
||||
|
||||
if (matchSearch && matchStation && matchWard && matchStatus) {
|
||||
var matchAdmType = true;
|
||||
if (admType !== 'all' && admType !== '') {
|
||||
matchAdmType = (bStatus === 'occupied' && bAdmType === admType);
|
||||
}
|
||||
|
||||
if (matchSearch && matchStation && matchWard && matchStatus && matchAdmType) {
|
||||
$col.removeClass('d-none');
|
||||
} else {
|
||||
$col.addClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
// Hide empty ward blocks
|
||||
$('.ward-block-card').each(function() {
|
||||
var $card = $(this);
|
||||
var visibleBeds = $card.find('.bed-card-col:not(.d-none)').length;
|
||||
|
|
@ -356,5 +465,21 @@ function filterNursingBeds() {
|
|||
$card.removeClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
// Filter Table View rows
|
||||
$('#ipdNursingListTable tbody tr.table-row-admission').each(function() {
|
||||
var $tr = $(this);
|
||||
var rowType = ($tr.data('admission-type') || '').toLowerCase();
|
||||
var rowSearch = $tr.text().toLowerCase();
|
||||
|
||||
var matchSearch = (search === '' || rowSearch.indexOf(search) !== -1);
|
||||
var matchType = (admType === 'all' || admType === '' || rowType === admType);
|
||||
|
||||
if (matchSearch && matchType) {
|
||||
$tr.removeClass('d-none');
|
||||
} else {
|
||||
$tr.addClass('d-none');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -238,18 +238,7 @@ if (! $canChargesSettings && $user && method_exists($user, 'inGroup')) {
|
|||
<span>IPD Billing</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('/billing/ipd/admit?type=emergency') ?>','Emergency / Casualty Admission')">
|
||||
<i class="bi bi-ambulance text-danger"></i>
|
||||
<span>Emergency / Casualty</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('/billing/ipd/admit?type=daycare') ?>','Day Care Admission')">
|
||||
<i class="bi bi-clock-history text-warning"></i>
|
||||
<span>Day Care Unit</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('Orgcase/search_all') ?>','Org. OPD\'s Invoice')">
|
||||
<i class="bi bi-receipt-cutoff"></i>
|
||||
|
|
@ -348,12 +337,7 @@ if (! $canChargesSettings && $user && method_exists($user, 'inGroup')) {
|
|||
<?php if ($canIpdNursing || $canIpdDischarge || $canIpdOt) { ?>
|
||||
<li class="nav-heading">In-Patient & Nursing Care</li>
|
||||
<?php if ($canIpdNursing) { ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('billing/ipd/admit') ?>','Admit Patient Desk')">
|
||||
<i class="bi bi-person-plus text-success"></i>
|
||||
<span>Admit Patient Desk</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('/ipd/patient') ?>','IPD Patient List')">
|
||||
<i class="bi bi-person-vcard"></i>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user