Make IPD discharge complaint names and remarks editable like OPD form

FEATURE: Inline editing for discharge complaint table

PROBLEM: In IPD discharge form, complaint names and remarks were
read-only after adding. Unlike OPD consult form where you can edit
complaint names directly in the table.

SOLUTION:
1. VIEW Changes (discharge_create.php):
   - Changed complaint name and remark columns from static <td> to editable <input>
   - Added data attributes for complaint ID and original values
   - Added CSS classes: discharge-complaint-name-input, discharge-complaint-remark-input

2. JAVASCRIPT Changes:
   - Added saveComplaintField() function for AJAX updates
   - Event handlers on blur to save changes
   - Enter key support to blur and save
   - Visual feedback: green border on success, red on error
   - Auto-updates original value after successful save

3. CONTROLLER Changes (Ipd_discharge.php):
   - Added update_complaint_field() method for AJAX endpoint
   - Updates ipd_discharge_comp table (comp_report or comp_remark)
   - Returns JSON success/error response

BENEFITS:
- Same user experience as OPD consult form
- Edit complaints/remarks without page reload
- Immediate feedback on save success/failure
- Type correction and updates without removing and re-adding rows
This commit is contained in:
DevSoftTech Server 2026-06-06 05:12:23 +05:30
parent 5847f642d8
commit 2e6bff35a0
2 changed files with 141 additions and 3 deletions

View File

@ -2814,6 +2814,46 @@ class Ipd_discharge extends BaseController
]);
}
public function update_complaint_field()
{
if (! $this->request->isAJAX()) {
return $this->response->setStatusCode(400)->setJSON(['success' => false, 'error' => 'Invalid request']);
}
$complaintId = (int) $this->request->getPost('complaint_id');
$fieldType = trim((string) $this->request->getPost('field_type'));
$fieldValue = trim((string) $this->request->getPost('field_value'));
if ($complaintId <= 0 || !in_array($fieldType, ['name', 'remark'], true)) {
return $this->response->setJSON(['success' => false, 'error' => 'Invalid parameters']);
}
$table = 'ipd_discharge_comp';
if (! $this->db->tableExists($table)) {
return $this->response->setJSON(['success' => false, 'error' => 'Complaint table not found']);
}
$columnName = $fieldType === 'name' ? 'comp_report' : 'comp_remark';
try {
$updated = $this->db->table($table)
->where('id', $complaintId)
->update([
$columnName => $fieldValue,
'updated_at' => date('Y-m-d H:i:s')
]);
if ($updated) {
return $this->response->setJSON(['success' => true]);
} else {
return $this->response->setJSON(['success' => false, 'error' => 'No rows updated']);
}
} catch (\Throwable $e) {
log_message('error', 'Failed to update discharge complaint field: {msg}', ['msg' => $e->getMessage()]);
return $this->response->setJSON(['success' => false, 'error' => 'Database error']);
}
}
private function upsertByComposite(
string $table,
string $ipdField,

View File

@ -738,9 +738,27 @@ $allergyStatusNoKnown = in_array($allergyStatusNormalized, ['no known drug aller
<?php if (empty($complaintRows)): ?>
<tr><td colspan="3" class="text-muted text-center">No complaint rows yet.</td></tr>
<?php else: foreach ($complaintRows as $row): ?>
<tr>
<td><?= esc((string) ($row['comp_report'] ?? '')) ?></td>
<td><?= esc((string) ($row['comp_remark'] ?? '')) ?></td>
<tr data-complaint-id="<?= (int) ($row['id'] ?? 0) ?>">
<td>
<input
type="text"
class="form-control form-control-sm discharge-complaint-name-input"
data-complaint-id="<?= (int) ($row['id'] ?? 0) ?>"
data-original-value="<?= esc((string) ($row['comp_report'] ?? '')) ?>"
value="<?= esc((string) ($row['comp_report'] ?? '')) ?>"
placeholder="Enter complaint name"
>
</td>
<td>
<input
type="text"
class="form-control form-control-sm discharge-complaint-remark-input"
data-complaint-id="<?= (int) ($row['id'] ?? 0) ?>"
data-original-value="<?= esc((string) ($row['comp_remark'] ?? '')) ?>"
value="<?= esc((string) ($row['comp_remark'] ?? '')) ?>"
placeholder="Enter remark"
>
</td>
<td>
<button type="submit" class="btn btn-outline-danger btn-sm" name="action" value="remove_complaint" data-reload-section="section-complaints" onclick="document.getElementById('complaint_remove_id').value='<?= (int) ($row['id'] ?? 0) ?>';">Remove</button>
</td>
@ -3877,6 +3895,86 @@ $allergyStatusNoKnown = in_array($allergyStatusNormalized, ['no known drug aller
}, { passive: true, capture: true });
syncNavOnScroll();
// ═══════════════════════════════════════════════════════════════════
// Editable Complaint Name and Remark Fields
// ═══════════════════════════════════════════════════════════════════
function saveComplaintField(input, fieldType) {
var complaintId = input.getAttribute('data-complaint-id');
var newValue = input.value.trim();
var originalValue = input.getAttribute('data-original-value');
if (newValue === originalValue) {
return;
}
var form = document.getElementById('discharge_main_form');
if (!form) {
return;
}
var csrfPair = getCsrfPair(form);
var formData = new FormData();
formData.append(csrfPair.name, csrfPair.value);
formData.append('complaint_id', complaintId);
formData.append('field_type', fieldType);
formData.append('field_value', newValue);
fetch('<?= site_url('Ipd_discharge/update_complaint_field') ?>', {
method: 'POST',
body: formData
}).then(function(response) {
return response.json();
}).then(function(data) {
if (data.success) {
input.setAttribute('data-original-value', newValue);
input.style.borderColor = '#28a745';
setTimeout(function() {
input.style.borderColor = '';
}, 1000);
} else {
console.error('Failed to save complaint field:', data.error || 'Unknown error');
input.style.borderColor = '#dc3545';
setTimeout(function() {
input.style.borderColor = '';
}, 2000);
}
}).catch(function(err) {
console.error('Error saving complaint field:', err);
input.style.borderColor = '#dc3545';
setTimeout(function() {
input.style.borderColor = '';
}, 2000);
});
}
// Complaint Name input handlers
document.querySelectorAll('.discharge-complaint-name-input').forEach(function(input) {
input.addEventListener('blur', function() {
saveComplaintField(this, 'name');
});
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
this.blur();
}
});
});
// Complaint Remark input handlers
document.querySelectorAll('.discharge-complaint-remark-input').forEach(function(input) {
input.addEventListener('blur', function() {
saveComplaintField(this, 'remark');
});
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
this.blur();
}
});
});
})();
</script>
</section>