fix(opd): print multi-line complaints with frequency, severity, duration and date in {{Complaint}}

This commit is contained in:
DevSoftTech Server 2026-11-03 15:18:54 +05:30
parent 9e5f607f00
commit 337c18b0b2
3 changed files with 135 additions and 7 deletions

View File

@ -3939,6 +3939,9 @@ class Opd extends BaseController
foreach ($detailMap as $detailKey => $detailLabel) {
$value = trim((string) ($item[$detailKey] ?? ''));
if ($value !== '') {
if ($detailKey === 'date' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $value) === 1 && ($ts = strtotime($value)) !== false) {
$value = date('d-m-Y', $ts);
}
$details[] = $detailLabel . ': ' . $value;
}
}
@ -3966,6 +3969,19 @@ class Opd extends BaseController
$tokens['next_visit_raw'] = (string) ($tokens['next_visit'] ?? '');
$complaintItems = $parseClinicalJsonItems((string) ($tokens['complaint_snomed_json'] ?? ''));
if (empty($complaintItems)) {
$complaintItems = $splitClinicalText((string) ($tokens['Complaint_raw'] ?? ''));
if (! empty($complaintItems)) {
$legacySev = trim((string) ($tokens['complaint_severity'] ?? ''));
$legacyDur = trim((string) ($tokens['complaint_duration_days'] ?? ''));
if ($legacySev !== '' && empty($complaintItems[0]['severity'])) {
$complaintItems[0]['severity'] = $legacySev;
}
if ($legacyDur !== '' && empty($complaintItems[0]['duration'])) {
$complaintItems[0]['duration'] = is_numeric($legacyDur) ? ($legacyDur . ' days') : $legacyDur;
}
}
}
if (empty($complaintItems)) {
$complaintItems = $splitClinicalText((string) ($tokens['Complaint_raw'] ?? ''));
}
@ -3999,7 +4015,19 @@ class Opd extends BaseController
foreach ($diagnosisItems as $item) {
$term = trim((string) ($item['term'] ?? ''));
if ($term !== '') {
$diagnosisTerms[] = $term;
$dxDetails = [];
$dxDur = trim((string) ($item['duration'] ?? ''));
$dxDate = trim((string) ($item['date'] ?? ''));
if ($dxDur !== '') {
$dxDetails[] = 'Duration: ' . $dxDur;
}
if ($dxDate !== '') {
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $dxDate) === 1 && ($ts = strtotime($dxDate)) !== false) {
$dxDate = date('d-m-Y', $ts);
}
$dxDetails[] = 'Date: ' . $dxDate;
}
$diagnosisTerms[] = $term . (! empty($dxDetails) ? ' (' . implode(' | ', $dxDetails) . ')' : '');
}
}
$tokens['diagnosis_list_compact'] = implode(', ', array_values(array_unique($diagnosisTerms)));
@ -4008,11 +4036,21 @@ class Opd extends BaseController
$vitalCoreRaw = (string) ($tokens['vital_content_raw'] ?? '');
$tokens['vital_content'] = $vitalCoreRaw;
$tokens['vital_content_block'] = $formatBlock('Vitals', $vitalCoreRaw, false);
$complaintBlockValue = trim((string) ($tokens['complaint_list_compact'] ?? ''));
$complaintBlockValue = trim((string) ($tokens['complaint_list'] ?? ''));
if ($complaintBlockValue === '') {
$complaintBlockValue = trim((string) ($tokens['Complaint_raw'] ?? ''));
$rawComplaintFallback = trim(str_replace(["\r\n", "\r"], "\n", (string) ($tokens['Complaint_raw'] ?? '')));
$complaintBlockValue = $rawComplaintFallback !== '' ? nl2br($escape($rawComplaintFallback)) : '';
}
$tokens['Complaint'] = $formatBlock('Complaint', $escape($complaintBlockValue), false);
$tokens['Complaint'] = $formatBlock('Complaint', $complaintBlockValue, true);
$tokens['complaint'] = $tokens['Complaint'];
$tokens['complaints'] = $tokens['Complaint'];
if ($complaintBlockValue === '') {
if ($complaintBlockValue === '') {
$rawComplaintFallback = trim(str_replace(["\r\n", "\r"], "\n", (string) ($tokens['Complaint_raw'] ?? '')));
$complaintBlockValue = $rawComplaintFallback !== '' ? nl2br($escape($rawComplaintFallback)) : '';
}
}
// Keep multi-line complaint list with Frequency, Severity, Duration, Date intact.
$tokens['complaint'] = $tokens['Complaint'];
$diagnosisBlockValue = trim((string) ($tokens['diagnosis_list_compact'] ?? ''));
if ($diagnosisBlockValue === '') {

View File

@ -285,7 +285,36 @@ $toLocalText = static function (string $input): string {
<?php if ($showPart3) : ?>
<?php if (!empty($rx['complaints'] ?? '')) : ?>
<?php
$complaintRawJson = trim((string) ($rx['complaint_snomed_json'] ?? ''));
$complaintJsonRows = $complaintRawJson !== '' ? json_decode($complaintRawJson, true) : null;
if (is_array($complaintJsonRows) && ! empty($complaintJsonRows)) :
?>
<div class="section-line">
<span class="label">Complaint :</span>
<ul style="margin:3px 0 0 16px;padding:0;">
<?php foreach ($complaintJsonRows as $cRow) :
$cTerm = trim((string) ($cRow['term'] ?? $cRow['name'] ?? ''));
if ($cTerm === '') continue;
$cMeta = [];
if (! empty($cRow['frequency'])) $cMeta[] = 'Freq: ' . trim((string) $cRow['frequency']);
if (! empty($cRow['severity'])) $cMeta[] = 'Severity: ' . trim((string) $cRow['severity']);
if (! empty($cRow['duration'])) $cMeta[] = 'Duration: ' . trim((string) $cRow['duration']);
if (! empty($cRow['date'])) {
$cDate = trim((string) $cRow['date']);
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $cDate) === 1 && ($ts = strtotime($cDate)) !== false) {
$cDate = date('d-m-Y', $ts);
}
$cMeta[] = 'Date: ' . $cDate;
}
?>
<li><?= esc($cTerm) ?><?= ! empty($cMeta) ? ' <span class="muted">(' . esc(implode(' | ', $cMeta)) . ')</span>' : '' ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php else : ?>
<div class="section-line"><span class="label">Complaint :</span> <?= nl2br(esc((string) ($rx['complaints'] ?? ''))) ?></div>
<?php endif; ?>
<?php endif; ?>
<?php if (!empty($vitals)) : ?>

View File

@ -4023,6 +4023,9 @@
}
function getPayload() {
if (typeof syncComplaintSnomedJson === 'function') {
syncComplaintSnomedJson();
}
var normalizedVitals = normalizeVitalsInputs(true);
var morbidities = [];
var morbiditiesText = [];
@ -4398,6 +4401,9 @@
});
function openLegacyPrescriptionPrint(printType) {
if (typeof syncComplaintSnomedJson === 'function') {
syncComplaintSnomedJson();
}
var openPrint = function() {
var opdId = $('#opd_id').val() || '0';
var sessionId = $('#opd_session_id').val() || '0';
@ -5266,6 +5272,22 @@
}
function syncComplaintSnomedJson() {
$('#complaint_tbody tr[data-idx]').each(function() {
var $tr = $(this);
var idx = parseInt($tr.attr('data-idx'), 10);
if (!isNaN(idx) && idx >= 0 && idx < selectedComplaintItems.length) {
var $nameInp = $tr.find('.complaint-name-input');
var $freqInp = $tr.find('.complaint-freq-input');
var $sevInp = $tr.find('.complaint-sev-input');
var $durInp = $tr.find('.complaint-dur-input');
var $dateInp = $tr.find('.complaint-date-input');
if ($nameInp.length) selectedComplaintItems[idx].term = ($nameInp.val() || '').toString().trim();
if ($freqInp.length) selectedComplaintItems[idx].frequency = ($freqInp.val() || '').toString().trim();
if ($sevInp.length) selectedComplaintItems[idx].severity = ($sevInp.val() || '').toString().trim();
if ($durInp.length) selectedComplaintItems[idx].duration = ($durInp.val() || '').toString().trim();
if ($dateInp.length) selectedComplaintItems[idx].date = ($dateInp.val() || '').toString().trim();
}
});
var json = JSON.stringify(selectedComplaintItems.map(function(item) {
return {
term: item.term,
@ -5579,7 +5601,16 @@
var _freqDdIdx = -1;
$(document).on('input focus', '.complaint-freq-input', function() {
$(document).on('input focus', '.complaint-freq-input', function(e) {
if (e && e.type === 'input') {
var idxInp = parseInt($(this).attr('data-idx'), 10);
if (!isNaN(idxInp) && idxInp >= 0 && idxInp < selectedComplaintItems.length) {
selectedComplaintItems[idxInp].frequency = ($(this).val() || '').trim();
syncComplaintSnomedJson();
markDirty('Complaint detail updated');
scheduleAutoSave();
}
}
_freqDdIdx = -1;
var $inp = $(this);
var q = ($inp.val() || '').trim().toLowerCase();
@ -5594,6 +5625,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].frequency = val;
syncComplaintSnomedJson();
markDirty('Complaint detail updated');
scheduleAutoSave();
syncComplaintSnomedJson();
}
$('#_freq_dd').remove();
_freqDdIdx = -1;
@ -5630,6 +5664,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].frequency = ($(this).val() || '').trim();
syncComplaintSnomedJson();
markDirty('Complaint detail updated');
scheduleAutoSave();
syncComplaintSnomedJson();
}
setTimeout(function() { $('#_freq_dd').remove(); }, 150);
});
@ -5653,7 +5690,16 @@
});
// ─── Duration: event delegation on table rows ────────────────────────────
$(document).on('input focus', '.complaint-dur-input', function() {
$(document).on('input focus', '.complaint-dur-input', function(e) {
if (e && e.type === 'input') {
var idxInp = parseInt($(this).attr('data-idx'), 10);
if (!isNaN(idxInp) && idxInp >= 0 && idxInp < selectedComplaintItems.length) {
selectedComplaintItems[idxInp].duration = ($(this).val() || '').trim();
syncComplaintSnomedJson();
markDirty('Complaint detail updated');
scheduleAutoSave();
}
}
_durDdIdx = -1;
var $inp = $(this);
var sugs = getDurationSuggestions($inp.val());
@ -5666,6 +5712,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].duration = val;
syncComplaintSnomedJson();
markDirty('Complaint detail updated');
scheduleAutoSave();
syncComplaintSnomedJson();
}
$dd.hide().empty();
// Done with this row — move to lookup for next complaint
@ -5716,7 +5765,16 @@
return _SEVERITY_OPTIONS.filter(function(s) { return s.startsWith(q); });
}
$(document).on('input focus', '.complaint-sev-input', function() {
$(document).on('input focus', '.complaint-sev-input', function(e) {
if (e && e.type === 'input') {
var idxInp = parseInt($(this).attr('data-idx'), 10);
if (!isNaN(idxInp) && idxInp >= 0 && idxInp < selectedComplaintItems.length) {
selectedComplaintItems[idxInp].severity = ($(this).val() || '').trim();
syncComplaintSnomedJson();
markDirty('Complaint detail updated');
scheduleAutoSave();
}
}
_sevDdIdx = -1;
var $inp = $(this);
var sugs = getSeveritySuggestions($inp.val());
@ -5729,6 +5787,9 @@
if (idx >= 0 && idx < selectedComplaintItems.length) {
selectedComplaintItems[idx].severity = val;
syncComplaintSnomedJson();
markDirty('Complaint detail updated');
scheduleAutoSave();
syncComplaintSnomedJson();
}
$dd.hide().empty();
// Move focus to Duration input in same row