feat: add referral search to patient and IPD flows

Load referral master data into patient registration/edit screens, persist patient referby, expose searchable referral inputs in patient and IPD forms, and make referral title editable as free text in referral master CRUD.
This commit is contained in:
DevSoftTech Server 2026-08-07 11:18:50 +05:30
parent bedb1c922a
commit 780ebaa263
8 changed files with 136 additions and 20 deletions

View File

@ -36,6 +36,8 @@ class Patient extends BaseController
->getResultArray();
}
$data['refer_master'] = $this->getActiveReferMasters();
return view('billing/Patient_V', $data);
}
@ -130,6 +132,7 @@ class Patient extends BaseController
'udai' => strtoupper((string) $this->request->getPost('input_udai')),
'estimate_dob' => $estimate_dob,
];
$this->applyPatientReferbyField($data, (string) $this->request->getPost('refer_by_name'));
$this->applyPatientAbhaFieldValues($data, $abhaId, $abhaAddress);
if ($chk_age === 'on') {
@ -715,6 +718,8 @@ class Patient extends BaseController
$query = $this->db->query($sql);
$data['blood_group'] = $query->getResult();
$data['refer_master'] = $this->getActiveReferMasters();
$sql = "select * from tag_master Order by tag_name";
$query = $this->db->query($sql);
$data['tag_master'] = $query->getResult();
@ -823,6 +828,7 @@ class Patient extends BaseController
'estimate_dob' => $estimate_dob,
'blood_group' => $this->request->getPost('input_blood_group'),
];
$this->applyPatientReferbyField($data, (string) $this->request->getPost('refer_by_name'));
if ($isAbhaVerifiedLocked) {
$data['p_fname'] = (string) ($existingPatient['p_fname'] ?? $data['p_fname']);
@ -863,6 +869,28 @@ class Patient extends BaseController
]);
}
private function getActiveReferMasters(): array
{
if (! $this->db->tableExists('refer_master')) {
return [];
}
return $this->db->table('refer_master')
->where('active', 1)
->orderBy('f_name', 'ASC')
->get()
->getResult();
}
private function applyPatientReferbyField(array &$data, string $referByName): void
{
if (! $this->db->fieldExists('referby', 'patient_master')) {
return;
}
$data['referby'] = trim(strtoupper($referByName));
}
public function update_aadhar()
{
if (!$this->request->isAJAX()) {

View File

@ -15,12 +15,7 @@
<div class="row g-3">
<div class="col-md-2">
<label class="form-label">Title</label>
<select class="form-select" name="cbo_title" id="cbo_title">
<option value="Mr.">Mr.</option>
<option value="Mrs.">Mrs.</option>
<option value="Ms.">Ms.</option>
<option value="Dr.">Dr.</option>
</select>
<input class="form-control" name="cbo_title" id="cbo_title" type="text" placeholder="Title / Clinic / Hospital" autocomplete="off">
</div>
<div class="col-md-3">
<label class="form-label">Name</label>

View File

@ -16,12 +16,7 @@
<div class="row g-3">
<div class="col-md-2">
<label class="form-label">Title</label>
<select class="form-select" name="cbo_title" id="cbo_title">
<option value="Mr." <?= combo_checked('Mr.', $data[0]->title ?? '') ?>>Mr.</option>
<option value="Mrs." <?= combo_checked('Mrs.', $data[0]->title ?? '') ?>>Mrs.</option>
<option value="Ms." <?= combo_checked('Ms.', $data[0]->title ?? '') ?>>Ms.</option>
<option value="Dr." <?= combo_checked('Dr.', $data[0]->title ?? '') ?>>Dr.</option>
</select>
<input class="form-control" name="cbo_title" id="cbo_title" type="text" placeholder="Title / Clinic / Hospital" value="<?= esc($data[0]->title ?? '') ?>" autocomplete="off">
</div>
<div class="col-md-3">
<label class="form-label">Name</label>

View File

@ -236,6 +236,20 @@
</select>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label class="form-label">Refer By</label>
<input class="form-control" name="refer_by_name" id="refer_by_name"
list="refer_by_name_list" placeholder="Type to search referral"
autocomplete="off">
<datalist id="refer_by_name_list">
<?php foreach (($refer_master ?? []) as $row) : ?>
<?php $referLabel = trim((string) (($row->title ?? '') . ' ' . ($row->f_name ?? ''))); ?>
<option value="<?= esc($referLabel) ?>"></option>
<?php endforeach; ?>
</datalist>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="form-label">Address</label>

View File

@ -238,6 +238,20 @@
</select>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>Refer By</label>
<input class="form-control input-sm" name="refer_by_name" id="refer_by_name"
list="refer_by_name_list" placeholder="Type to search referral"
value="<?= esc($data[0]->referby ?? '') ?>" autocomplete="off">
<datalist id="refer_by_name_list">
<?php foreach (($refer_master ?? []) as $row) : ?>
<?php $referLabel = trim((string) (($row->title ?? '') . ' ' . ($row->f_name ?? ''))); ?>
<option value="<?= esc($referLabel) ?>"></option>
<?php endforeach; ?>
</datalist>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">

View File

@ -128,6 +128,16 @@
<?php endif; ?>
</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label">Refer By</div>
<div class="col-lg-9 col-md-8">
<?php if (trim((string) ($data[0]->referby ?? '')) !== '') : ?>
<?= esc(ucwords(strtolower((string) ($data[0]->referby ?? '')))) ?>
<?php else : ?>
<span class="text-muted small">Not filled</span>
<?php endif; ?>
</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label">Aadhar No.</div>
<div class="col-lg-9 col-md-8"><?=$data[0]->udai?></div>

View File

@ -256,12 +256,13 @@
<div class="col-md-6">
<div class="form-group">
<label>Refer By</label>
<select class="form-control" name="refer_by_list" id="refer_by_list">
<option value="0">Select Refer By</option>
<input type="hidden" name="refer_by_list" id="refer_by_list" value="0">
<input class="form-control" id="refer_by_list_search" list="refer_by_list_options" placeholder="Type to search referral" autocomplete="off">
<datalist id="refer_by_list_options">
<?php foreach ($refer_master as $row): ?>
<option value="<?= esc($row->id ?? 0) ?>"><?= esc(trim(($row->title ?? '') . ' ' . ($row->f_name ?? ''))) ?></option>
<option value="<?= esc(trim(($row->title ?? '') . ' ' . ($row->f_name ?? ''))) ?>" data-id="<?= esc($row->id ?? 0) ?>"></option>
<?php endforeach; ?>
</select>
</datalist>
</div>
</div>
</div>
@ -308,6 +309,37 @@
<script>
$(function() {
function bindReferByDatalist(hiddenSelector, inputSelector, listSelector) {
var $hidden = $(hiddenSelector);
var $input = $(inputSelector);
var list = document.querySelector(listSelector);
if (!$hidden.length || !$input.length || !list) {
return;
}
function syncReferByValue() {
var typedValue = ($input.val() || '').trim();
var matchedId = '0';
var options = list.querySelectorAll('option');
options.forEach(function(option) {
if (matchedId !== '0') {
return;
}
if ((option.value || '').trim().toUpperCase() === typedValue.toUpperCase()) {
matchedId = option.getAttribute('data-id') || '0';
}
});
$hidden.val(matchedId);
}
$input.on('input change blur', syncReferByValue);
}
bindReferByDatalist('#refer_by_list', '#refer_by_list_search', '#refer_by_list_options');
function formatLegacyDate(dateValue) {
if (!dateValue) {
return '';

View File

@ -150,12 +150,14 @@ $alertId = 'ipd-admission-alert-' . (int) ($ipd->id ?? 0);
</div>
<div class="col-lg-6 col-md-12">
<label class="form-label">Refer By</label>
<select name="refer_by" class="form-select">
<option value="0">Select Refer By</option>
<input type="hidden" name="refer_by" id="refer_by" value="<?= (int) ($ipd->refer_by ?? 0) ?>">
<input class="form-control" id="refer_by_search" list="refer_by_options" placeholder="Type to search referral" autocomplete="off"
value="<?= esc($referByName !== 'Not set' ? $referByName : '') ?>">
<datalist id="refer_by_options">
<?php foreach ($referMaster as $refer) : ?>
<option value="<?= (int) ($refer->id ?? 0) ?>" <?= (int) ($refer->id ?? 0) === (int) ($ipd->refer_by ?? 0) ? 'selected' : '' ?>><?= esc(trim((string) (($refer->title ?? '') . ' ' . ($refer->f_name ?? '')))) ?></option>
<option value="<?= esc(trim((string) (($refer->title ?? '') . ' ' . ($refer->f_name ?? '')))) ?>" data-id="<?= (int) ($refer->id ?? 0) ?>"></option>
<?php endforeach; ?>
</select>
</datalist>
</div>
<div class="col-12">
<label class="form-label">Assigned Doctors</label>
@ -239,8 +241,34 @@ $alertId = 'ipd-admission-alert-' . (int) ($ipd->id ?? 0);
submitButton.textContent = isSaving ? 'Saving...' : 'Save Admission Changes';
}
function syncReferByValue() {
var hiddenInput = document.getElementById('refer_by');
var searchInput = document.getElementById('refer_by_search');
var optionsList = document.getElementById('refer_by_options');
if (!hiddenInput || !searchInput || !optionsList) {
return;
}
var typedValue = (searchInput.value || '').trim().toUpperCase();
var matchedId = '0';
optionsList.querySelectorAll('option').forEach(function(option) {
if (matchedId !== '0') {
return;
}
if (((option.value || '').trim().toUpperCase()) === typedValue) {
matchedId = option.getAttribute('data-id') || '0';
}
});
hiddenInput.value = matchedId;
}
$('#refer_by_search').on('input change blur', syncReferByValue);
form.addEventListener('submit', function(event) {
event.preventDefault();
syncReferByValue();
setSavingState(true);
if (alertBox) {
alertBox.innerHTML = '';