Fix IPD discharge complaint live add/remove and section refresh sync

This commit is contained in:
DevSoftTech Server 2026-07-17 17:23:43 +05:30
parent c4533b0294
commit 7c76973ca3
2 changed files with 307 additions and 37 deletions

View File

@ -6109,6 +6109,112 @@ class Ipd_discharge extends BaseController
],
]);
$complaintJson = trim((string) ($this->request->getPost('discharge_complaints_json') ?? ''));
$decodedComplaints = [];
if ($complaintJson !== '') {
$decoded = json_decode($complaintJson, true);
if (is_array($decoded)) {
$decodedComplaints = $decoded;
}
}
if (empty($decodedComplaints)) {
$postedIds = $this->request->getPost('complaint_row_id');
$postedTerms = $this->request->getPost('complaint_term');
$postedDurations = $this->request->getPost('complaint_duration');
$postedFreq = $this->request->getPost('complaint_frequency');
$postedSeverity = $this->request->getPost('complaint_severity');
if (is_array($postedTerms)) {
$count = count($postedTerms);
for ($i = 0; $i < $count; $i++) {
$decodedComplaints[] = [
'id' => (int) (is_array($postedIds) ? ($postedIds[$i] ?? 0) : 0),
'term' => (string) ($postedTerms[$i] ?? ''),
'duration' => (string) (is_array($postedDurations) ? ($postedDurations[$i] ?? '') : ''),
'frequency' => (string) (is_array($postedFreq) ? ($postedFreq[$i] ?? '') : ''),
'severity' => (string) (is_array($postedSeverity) ? ($postedSeverity[$i] ?? '') : ''),
];
}
}
}
if (is_array($decodedComplaints) && $this->tableHasColumns('ipd_discharge_complaint', ['ipd_id', 'comp_report'])) {
{
$existingComplaintRows = $this->db->table('ipd_discharge_complaint')
->select('id')
->where('ipd_id', $ipdId)
->get()
->getResultArray();
$existingIdSet = [];
foreach ($existingComplaintRows as $row) {
$existingId = (int) ($row['id'] ?? 0);
if ($existingId > 0) {
$existingIdSet[$existingId] = true;
}
}
$keepIds = [];
$orderIndex = 1;
foreach ($decodedComplaints as $row) {
if (! is_array($row)) {
continue;
}
$term = trim((string) ($row['term'] ?? ''));
if ($term === '') {
continue;
}
$duration = trim((string) ($row['duration'] ?? ''));
$rowId = (int) ($row['id'] ?? 0);
$commonData = [
'comp_report' => $term,
'comp_remark' => $duration,
'update_by' => $userLabel,
];
if ($this->db->fieldExists('order_id', 'ipd_discharge_complaint')) {
$commonData['order_id'] = $orderIndex;
}
if ($rowId > 0 && isset($existingIdSet[$rowId])) {
$savedAny = (bool) $this->db->table('ipd_discharge_complaint')
->where('id', $rowId)
->where('ipd_id', $ipdId)
->update($commonData) || $savedAny;
$keepIds[$rowId] = $rowId;
} else {
$insertData = $commonData;
$insertData['ipd_id'] = $ipdId;
if ($this->db->fieldExists('comp_code', 'ipd_discharge_complaint')) {
$insertData['comp_code'] = 0;
}
$inserted = (bool) $this->db->table('ipd_discharge_complaint')->insert($insertData);
$savedAny = $inserted || $savedAny;
if ($inserted) {
$newId = (int) ($this->db->insertID() ?? 0);
if ($newId > 0) {
$keepIds[$newId] = $newId;
}
}
}
$orderIndex++;
}
$deleteBuilder = $this->db->table('ipd_discharge_complaint')->where('ipd_id', $ipdId);
if (! empty($keepIds)) {
$deleteBuilder->whereNotIn('id', array_values($keepIds));
}
$savedAny = (bool) $deleteBuilder->delete() || $savedAny;
}
}
if ($complaintRemark !== '' || $this->tableHasColumns('ipd_discharge_complaint_remark', ['ipd_id'])) {
$savedAny = $this->upsertByIpd('ipd_discharge_complaint_remark', $ipdId, [
'comp_report' => $this->buildComplaintMetaPayload(['pain_value' => $painValue]),

View File

@ -748,6 +748,22 @@ $historyFields = [
</table>
<!-- Hidden fields to store data for form submission -->
<?php
$complaintSeedRows = [];
if (isset($complaint_rows) && is_array($complaint_rows)) {
foreach ($complaint_rows as $row) {
$complaintSeedRows[] = [
'id' => (int) ($row['id'] ?? 0),
'term' => (string) ($row['comp_report'] ?? ''),
'frequency' => '',
'severity' => '',
'duration' => (string) ($row['comp_remark'] ?? ''),
'date' => '',
];
}
}
?>
<input type="hidden" id="discharge_complaint_seed_json" value="<?= esc((string) json_encode($complaintSeedRows), 'attr') ?>">
<input type="hidden" name="discharge_complaints_json" id="discharge_complaints_json" value="">
<!-- Fixed dropdowns for table cell inputs -->
@ -1908,27 +1924,30 @@ $historyFields = [
var selectedDischargeComplaints = [];
function initDischargeComplaintsTable() {
// Load existing complaints from PHP (if any)
<?php if (isset($complaint_rows) && is_array($complaint_rows) && !empty($complaint_rows)): ?>
selectedDischargeComplaints = [
<?php
$itemCount = count($complaint_rows);
$currentIndex = 0;
foreach ($complaint_rows as $row):
$currentIndex++;
?> {
id: <?= (int) ($row['id'] ?? 0) ?>,
term: <?= json_encode((string) ($row['comp_report'] ?? '')) ?>,
frequency: '',
severity: '',
duration: <?= json_encode((string) ($row['comp_remark'] ?? '')) ?>,
date: ''
}
<?= $currentIndex < $itemCount ? ',' : '' ?>
// Always reset from server-rendered state to avoid stale rows after section reload.
selectedDischargeComplaints = [];
<?php endforeach; ?>
];
<?php endif; ?>
// Load existing complaints from section-scoped seed JSON.
var seedEl = document.getElementById('discharge_complaint_seed_json');
if (seedEl) {
try {
var seedRows = JSON.parse(String(seedEl.value || '[]'));
if (Array.isArray(seedRows)) {
selectedDischargeComplaints = seedRows.map(function(row) {
return {
id: parseInt((row && row.id) || 0, 10) || 0,
term: String((row && row.term) || ''),
frequency: String((row && row.frequency) || ''),
severity: String((row && row.severity) || ''),
duration: String((row && row.duration) || ''),
date: String((row && row.date) || '')
};
});
}
} catch (err) {
selectedDischargeComplaints = [];
}
}
renderDischargeComplaintTable();
}
@ -1941,6 +1960,7 @@ $historyFields = [
if (selectedDischargeComplaints.length === 0) {
tbody.innerHTML = '<tr><td colspan="6" class="text-muted text-center">No complaints yet. Add using the input below.</td></tr>';
syncDischargeComplaintJsonField();
return;
}
@ -1959,6 +1979,7 @@ $historyFields = [
td2.className = 'p-1';
var nameInput = document.createElement('input');
nameInput.type = 'text';
nameInput.name = 'complaint_term[]';
nameInput.className = 'form-control form-control-sm';
nameInput.value = item.term || '';
nameInput.placeholder = 'Complaint…';
@ -1966,6 +1987,7 @@ $historyFields = [
nameInput.setAttribute('data-idx', idx);
nameInput.addEventListener('input', function() {
selectedDischargeComplaints[idx].term = this.value;
syncDischargeComplaintJsonField();
});
td2.appendChild(nameInput);
tr.appendChild(td2);
@ -1975,12 +1997,14 @@ $historyFields = [
td3.className = 'p-1';
var freqInput = document.createElement('input');
freqInput.type = 'text';
freqInput.name = 'complaint_frequency[]';
freqInput.className = 'form-control form-control-sm';
freqInput.value = item.frequency || '';
freqInput.placeholder = 'daily…';
freqInput.style.fontSize = '.82rem';
freqInput.addEventListener('input', function() {
selectedDischargeComplaints[idx].frequency = this.value;
syncDischargeComplaintJsonField();
});
td3.appendChild(freqInput);
tr.appendChild(td3);
@ -1990,12 +2014,14 @@ $historyFields = [
td4.className = 'p-1';
var sevInput = document.createElement('input');
sevInput.type = 'text';
sevInput.name = 'complaint_severity[]';
sevInput.className = 'form-control form-control-sm';
sevInput.value = item.severity || '';
sevInput.placeholder = 'mild…';
sevInput.style.fontSize = '.82rem';
sevInput.addEventListener('input', function() {
selectedDischargeComplaints[idx].severity = this.value;
syncDischargeComplaintJsonField();
});
td4.appendChild(sevInput);
tr.appendChild(td4);
@ -2005,16 +2031,24 @@ $historyFields = [
td5.className = 'p-1';
var durInput = document.createElement('input');
durInput.type = 'text';
durInput.name = 'complaint_duration[]';
durInput.className = 'form-control form-control-sm';
durInput.value = item.duration || '';
durInput.placeholder = '2 days…';
durInput.style.fontSize = '.82rem';
durInput.addEventListener('input', function() {
selectedDischargeComplaints[idx].duration = this.value;
syncDischargeComplaintJsonField();
});
td5.appendChild(durInput);
tr.appendChild(td5);
var idInput = document.createElement('input');
idInput.type = 'hidden';
idInput.name = 'complaint_row_id[]';
idInput.value = parseInt(item.id || 0, 10) || 0;
tr.appendChild(idInput);
// Remove button
var td6 = document.createElement('td');
td6.className = 'p-1 text-center';
@ -2024,14 +2058,112 @@ $historyFields = [
removeBtn.style.lineHeight = '1';
removeBtn.innerHTML = '×';
removeBtn.addEventListener('click', function() {
var rowId = parseInt((item && item.id) || 0, 10) || 0;
if (rowId > 0) {
var painValue = '';
var painHidden = document.getElementById('pain_value');
if (painHidden) {
painValue = String(painHidden.value || '').trim();
}
saveComplaintRowAjax({
action: 'remove_complaint',
complaint_remove_id: rowId,
complaint_remark: getComplaintEditorText(),
pain_value: painValue
}, 'Complaint removed.');
return;
}
selectedDischargeComplaints.splice(idx, 1);
renderDischargeComplaintTable();
syncDischargeComplaintJsonField();
});
td6.appendChild(removeBtn);
tr.appendChild(td6);
tbody.appendChild(tr);
});
syncDischargeComplaintJsonField();
}
function syncDischargeComplaintJsonField() {
var hidden = document.getElementById('discharge_complaints_json');
if (!hidden) {
return;
}
var rows = [];
selectedDischargeComplaints.forEach(function(item) {
var term = String((item && item.term) || '').trim();
if (term === '') {
return;
}
rows.push({
id: parseInt((item && item.id) || 0, 10) || 0,
term: term,
frequency: String((item && item.frequency) || '').trim(),
severity: String((item && item.severity) || '').trim(),
duration: String((item && item.duration) || '').trim(),
date: String((item && item.date) || '').trim()
});
});
hidden.value = JSON.stringify(rows);
}
function refreshComplaintSectionFromServerHtml(html, form, statusText, statusLevel) {
var holder = document.createElement('div');
holder.innerHTML = String(html || '');
if (!patchSectionFromHtml(holder, 'section-complaints')) {
setComplaintStatus('Unable to refresh complaint section.', 'error');
return;
}
updateCsrfFromHtml(holder, form);
patchNoticeFromHtml(holder);
notifyFromHtml(holder);
initComplaintEditor();
initComplaintTools();
bindDischargeAjaxSubmit();
initNabhHistorySection(document.querySelector('form[action*="Ipd_discharge/ipd_select/"]'));
syncNavOnScroll();
if (statusText) {
window.setTimeout(function() {
setComplaintStatus(statusText, statusLevel || 'success');
}, 0);
}
}
function saveComplaintRowAjax(payload, successText) {
var form = getDischargeForm();
if (!form || !window.jQuery) {
setComplaintStatus('Unable to reach server right now.', 'error');
return;
}
var csrf = getCsrfPair(form);
payload = payload || {};
payload[csrf.name] = csrf.value;
setComplaintStatus('Saving complaint...', 'muted');
window.jQuery.ajax({
url: form.getAttribute('action') || window.location.href,
type: 'POST',
data: payload,
dataType: 'html',
timeout: 30000
}).done(function(html) {
refreshComplaintSectionFromServerHtml(html, form, successText || 'Complaint saved.', 'success');
}).fail(function(xhr, status, error) {
setComplaintStatus('Save failed: ' + (error || status), 'error');
});
}
function initComplaintTools() {
@ -2137,25 +2269,18 @@ $historyFields = [
return;
}
// Add to array
selectedDischargeComplaints.push({
id: 0,
term: inputVal,
frequency: '',
severity: '',
duration: '',
date: ''
});
// Refresh table
renderDischargeComplaintTable();
// Clear input
if (lookup) {
lookup.value = '';
var painValue = '';
if (painHidden) {
painValue = String(painHidden.value || '').trim();
}
// No status message needed - table update is visual confirmation
saveComplaintRowAjax({
action: 'add_complaint',
new_complaint_name: inputVal,
new_complaint_remark: '',
complaint_remark: getComplaintEditorText(),
pain_value: painValue
}, 'Complaint added.');
});
}
@ -3853,6 +3978,25 @@ $historyFields = [
}
section.dataset.toolsBound = '1';
function reloadMedicineSectionFromServer() {
if (!window.jQuery) {
return;
}
var form = getDischargeForm();
var url = form ? (form.getAttribute('action') || window.location.href) : window.location.href;
window.jQuery.get(url, function(html) {
var holder = document.createElement('div');
holder.innerHTML = String(html || '');
if (patchSectionFromHtml(holder, 'section-medicine')) {
patchNoticeFromHtml(holder);
initMedicineTools();
bindDischargeAjaxSubmit();
syncNavOnScroll();
}
});
}
if (!window.jQuery) {
return;
}
@ -4655,11 +4799,29 @@ $historyFields = [
$('#discharge_med_name').focus();
setMedicineStatus(editRowId > 0 ? 'Medicine updated successfully.' : 'Medicine saved successfully.', 'success');
// Keep UI in sync with actual DB-backed rendering rules.
reloadMedicineSectionFromServer();
} else {
var errorMsg = (data && data.error_text) ? data.error_text : 'Unable to save medicine.';
setMedicineStatus(errorMsg, 'error');
}
}).fail(function(xhr, status, error) {
// Some environments may return HTML instead of JSON for this endpoint.
var responseHtml = xhr && typeof xhr.responseText === 'string' ? xhr.responseText : '';
if (responseHtml !== '' && responseHtml.indexOf('section-medicine') !== -1) {
var holder = document.createElement('div');
holder.innerHTML = responseHtml;
if (patchSectionFromHtml(holder, 'section-medicine')) {
patchNoticeFromHtml(holder);
initMedicineTools();
bindDischargeAjaxSubmit();
syncNavOnScroll();
setMedicineStatus('Medicine saved. Section refreshed from server response.', 'success');
return;
}
}
setMedicineStatus('Network error: ' + (error || status), 'error');
});
});
@ -4718,6 +4880,8 @@ $historyFields = [
}
function syncEditorValues() {
syncDischargeComplaintJsonField();
if (!window.CKEDITOR) {
return;
}