diff --git a/app/Controllers/DoctorDocument.php b/app/Controllers/DoctorDocument.php index 9b24c2a..8b74c30 100644 --- a/app/Controllers/DoctorDocument.php +++ b/app/Controllers/DoctorDocument.php @@ -153,7 +153,14 @@ class DoctorDocument extends BaseController $logoSrc = str_replace('\\', '/', $logoAbsPath); } if ($logoSrc === '') { - $logoSrc = base_url('assets/images/' . $logoFile); + $globMatches = glob(FCPATH . 'assets/images/hospital_logo_*'); + if (is_array($globMatches) && ! empty($globMatches)) { + usort($globMatches, fn($a, $b) => filemtime($b) <=> filemtime($a)); + $logoSrc = $this->buildImageDataUriFromPath($globMatches[0]); + } + } + if ($logoSrc === '') { + $logoSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAA='; } $logoHtml = ''; @@ -171,20 +178,22 @@ class DoctorDocument extends BaseController $drSignSrc = str_replace('\\', '/', $drSignAbsPath); } if ($drSignSrc === '') { - $drSignSrc = base_url('assets/images/' . $drSignFile); + $drSignSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAA='; } $drSignImg = ''; } $map = [ + 'assets/images/{{H_logo}}' => $logoSrc, + 'assets/images/{{h_logo}}' => $logoSrc, '{{H_Name}}' => defined('H_Name') ? (string) constant('H_Name') : '', '{{H_address_1}}' => defined('H_address_1') ? (string) constant('H_address_1') : '', '{{H_address_2}}' => defined('H_address_2') ? (string) constant('H_address_2') : '', '{{H_phone_No}}' => defined('H_phone_No') ? (string) constant('H_phone_No') : '', '{{H_Email}}' => defined('H_Email') ? (string) constant('H_Email') : '', - '{{H_logo}}' => $logoFile, - '{{H_logo_abs}}' => $logoAbsPath, + '{{H_logo}}' => $logoSrc, + '{{H_logo_abs}}' => $logoSrc, '{{hospital_logo_html}}' => $logoHtml, '{{PATIENT_NAME}}' => (string) ($doc['p_fname'] ?? ''), '{{pName}}' => (string) ($doc['p_fname'] ?? ''), @@ -264,7 +273,7 @@ class DoctorDocument extends BaseController return str_replace('\\', '/', $logoAbsPath); } - return base_url('assets/images/' . ($logoFile !== '' ? $logoFile : 'logo.png')); + return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAA='; } private function hasColumn(string $table, string $column): bool @@ -314,14 +323,16 @@ class DoctorDocument extends BaseController public function health_document_fhir_preview(int $patientDocId = 0) { if ($patientDocId <= 0) { - $patientDocId = (int) ($this->request->getGet('patient_doc_id') ?? $this->request->getGet('doc_id') ?? $this->request->getGet('health_doc_id') ?? 0); + $patientDocId = (int) ($this->request->getGet('patient_doc_id') ?? $this->request->getGet('doc_id') ?? $this->request->getGet('health_doc_id') ?? $this->request->getGet('record_id') ?? 0); } + $entityType = trim((string) ($this->request->getGet('entity_type') ?? '')); + if ($patientDocId <= 0) { return $this->response->setStatusCode(400)->setJSON(['ok' => 0, 'error_text' => 'patient_doc_id is required']); } - $source = $this->buildHealthDocumentSource($patientDocId); + $source = $this->buildHealthDocumentSource($patientDocId, $entityType); if (empty($source)) { return $this->response->setStatusCode(404)->setJSON(['ok' => 0, 'error_text' => 'Health document source data not found for ID: ' . $patientDocId]); } @@ -336,6 +347,9 @@ class DoctorDocument extends BaseController 'ok' => 1, 'bundle' => $bundle, 'fhir_bundle' => $bundle, + 'patient_id' => (int) ($source['patient']['id'] ?? 0), + 'abha_id' => (string) ($source['patient']['abha_id'] ?? ''), + 'document_title' => (string) ($source['document_title'] ?? ''), 'hi_type' => 'HealthDocumentRecord', 'care_context_reference' => $res['care_context_reference'] ?? '', 'care_context_display' => $res['care_context_display'] ?? '', @@ -798,7 +812,15 @@ class DoctorDocument extends BaseController 'session_id' => (string) $opdSessionId, 'visit_date' => $visitDate, 'completed_at' => $completedAt, + 'encounter' => [ + 'id' => (string) ($rxRow['id'] ?? $patientId), + 'class_code' => 'AMB', + 'class_display' => 'ambulatory', + 'start' => $completedAt, + 'end' => $completedAt, + ], 'vitals' => $vitals, + 'physical_examination' => $physicalExam, 'women_wellness' => $womenWellness, 'advice' => $lifestyle, @@ -2026,12 +2048,22 @@ class DoctorDocument extends BaseController return ''; } - private function buildHealthDocumentSource(int $patientDocId): array + public function buildHealthDocumentSource(int $patientDocId, string $entityType = ''): array { if ($patientDocId <= 0) { return []; } + if ($entityType === 'patient_document') { + if ($this->db->tableExists('file_upload_data')) { + $fileRow = $this->db->table('file_upload_data')->where('id', $patientDocId)->get(1)->getRowArray(); + if (is_array($fileRow) && ! empty($fileRow)) { + return $this->buildFileUploadHealthDocumentSource($fileRow); + } + } + return []; + } + $patientDoc = $this->db->table('patient_doc')->where('id', $patientDocId)->get(1)->getRowArray(); if (! is_array($patientDoc) || empty($patientDoc)) { if ($this->db->tableExists('file_upload_data')) { @@ -2057,7 +2089,70 @@ class DoctorDocument extends BaseController $templateRow = $this->db->table('doc_format_master')->where('df_id', $docFormatId)->get(1)->getRowArray() ?? []; } - $docTitle = trim((string) ($templateRow['doc_name'] ?? 'Medical Certificate')); + $docTitle = trim((string) ($templateRow['doc_name'] ?? '')); + + $rawDataStr = trim((string) ($patientDoc['raw_data'] ?? '')); + $pdfBytes = null; + $contentType = 'application/pdf'; + $existingDocPath = ''; + + // Check if raw_data is a JSON payload describing an uploaded/scanned document (e.g. NABH scan) + if (str_starts_with($rawDataStr, '{') && str_ends_with($rawDataStr, '}')) { + $decoded = json_decode($rawDataStr, true); + if (is_array($decoded)) { + if (! empty($decoded['title'])) { + $docTitle = trim((string) $decoded['title']); + } + $fileName = trim((string) ($decoded['file_name'] ?? '')); + if ($fileName !== '') { + $candidates = [ + FCPATH . 'uploads/nabh_ipd/' . $fileName, + FCPATH . 'uploads/' . $fileName, + WRITEPATH . 'uploads/nabh_ipd/' . $fileName, + defined('ROOTPATH') ? ROOTPATH . 'public/uploads/nabh_ipd/' . $fileName : '', + ]; + foreach ($candidates as $cand) { + if ($cand !== '' && is_file($cand) && is_readable($cand)) { + $existingDocPath = $cand; + break; + } + } + } + } + } + + // Also check nabh_ipd_scans table if present + if ($existingDocPath === '' && $this->db->tableExists('nabh_ipd_scans')) { + $scanRow = $this->db->table('nabh_ipd_scans') + ->where('patient_doc_id', $patientDocId) + ->get(1) + ->getRowArray(); + if (is_array($scanRow) && ! empty($scanRow['file_name'])) { + if (! empty($scanRow['category_title'])) { + $docTitle = trim((string) $scanRow['category_title']); + } + $cand = FCPATH . 'uploads/nabh_ipd/' . trim((string) $scanRow['file_name']); + if (is_file($cand) && is_readable($cand)) { + $existingDocPath = $cand; + } + } + } + + if ($existingDocPath !== '') { + $pdfBytes = @file_get_contents($existingDocPath); + $ext = strtolower(pathinfo($existingDocPath, PATHINFO_EXTENSION)); + $contentType = match ($ext) { + 'pdf' => 'application/pdf', + 'png' => 'image/png', + 'webp' => 'image/webp', + 'jpg', 'jpeg' => 'image/jpeg', + default => 'application/pdf', + }; + } elseif ($docFormatId > 0 && ! empty($rawDataStr)) { + // It's a formatted certificate / letterhead document + $pdfBytes = $this->generatePatientDocPdfBytes($patientDocId); + } + if ($docTitle === '') { $docTitle = 'Medical Certificate'; } @@ -2094,9 +2189,7 @@ class DoctorDocument extends BaseController $doctorName = 'Doctor'; } - $pdfBytes = $this->generatePatientDocPdfBytes($patientDocId); $docDataBase64 = ($pdfBytes !== null && $pdfBytes !== '') ? base64_encode($pdfBytes) : ''; - $contentType = ($pdfBytes !== null && $pdfBytes !== '') ? 'application/pdf' : 'text/html'; if ($docDataBase64 === '') { $rawHtml = trim((string) ($patientDoc['raw_data'] ?? '')); @@ -2109,6 +2202,20 @@ class DoctorDocument extends BaseController } } + $encounterId = 'encounter-' . $patientDocId; + $encounter = [ + 'id' => $encounterId, + 'status' => 'finished', + 'class' => 'AMB', + 'start' => $visitDate . 'T09:00:00+05:30', + 'end' => $visitDate . 'T09:30:00+05:30', + 'period' => [ + 'start' => $visitDate . 'T09:00:00+05:30', + 'end' => $visitDate . 'T09:30:00+05:30', + ], + 'hospitalization' => false, + ]; + return [ 'record_id' => (string) $patientDocId, 'session_id' => (string) $patientDocId, @@ -2124,6 +2231,8 @@ class DoctorDocument extends BaseController 'id' => $hfrId, 'name' => $hospitalName, ], + 'encounter' => $encounter, + 'encounter_reference' => 'urn:uuid:' . $encounterId, 'patient' => [ 'id' => (string) $patientId, 'uhid' => (string) ($patientRow['uhid_no'] ?? $patientRow['uhid'] ?? $patientRow['patient_code'] ?? $patientId), @@ -2285,7 +2394,7 @@ class DoctorDocument extends BaseController } } - private function buildFileUploadHealthDocumentSource(array $fileRow): array + public function buildFileUploadHealthDocumentSource(array $fileRow): array { $fileUploadId = (int) ($fileRow['id'] ?? 0); $pid = (int) ($fileRow['pid'] ?? 0); @@ -2365,6 +2474,20 @@ class DoctorDocument extends BaseController $drName = 'Medical Officer'; } + $encounterId = 'encounter-file-' . $fileUploadId; + $encounter = [ + 'id' => $encounterId, + 'status' => 'finished', + 'class' => 'AMB', + 'start' => $visitDate . 'T09:00:00+05:30', + 'end' => $visitDate . 'T09:30:00+05:30', + 'period' => [ + 'start' => $visitDate . 'T09:00:00+05:30', + 'end' => $visitDate . 'T09:30:00+05:30', + ], + 'hospitalization' => false, + ]; + return [ 'record_id' => 'file-' . $fileUploadId, 'session_id' => (string) ($fileRow['opd_id'] ?? $fileUploadId), @@ -2379,6 +2502,8 @@ class DoctorDocument extends BaseController 'id' => $hfrId, 'name' => $hospitalName, ], + 'encounter' => $encounter, + 'encounter_reference' => 'urn:uuid:' . $encounterId, 'patient' => [ 'id' => (string) $pid, 'uhid' => (string) ($patientRow['uhid_no'] ?? $patientRow['uhid'] ?? $patientRow['patient_code'] ?? $pid), diff --git a/app/Libraries/Abdm/Fhir/Generators/AbstractModuleFhirGenerator.php b/app/Libraries/Abdm/Fhir/Generators/AbstractModuleFhirGenerator.php index e622465..ba7e140 100644 --- a/app/Libraries/Abdm/Fhir/Generators/AbstractModuleFhirGenerator.php +++ b/app/Libraries/Abdm/Fhir/Generators/AbstractModuleFhirGenerator.php @@ -201,9 +201,11 @@ abstract class AbstractModuleFhirGenerator if ($patientName === '' || strcasecmp($patientName, 'NA') === 0) { $patientName = 'Patient'; } - $encounterRef = isset($source['encounter']) ? 'urn:uuid:encounter-' . ((string) ($source['encounter']['id'] ?? $recordId)) : null; + $encId = trim((string) ($source['encounter']['id'] ?? $source['record_id'] ?? $recordId)); + $encounterRef = $encId !== '' ? 'urn:uuid:encounter-' . $encId : null; $drId = (string) ($source['practitioner']['id'] ?? $source['doctor']['id'] ?? '1'); + if ($drId === '' || $drId === '0') { $drId = '1'; } @@ -278,7 +280,14 @@ abstract class AbstractModuleFhirGenerator if ($id === '') { return null; } - $classCode = strtoupper(trim((string) ($enc['class_code'] ?? 'IMP'))); + $isIpd = (isset($source['hi_type']) && $source['hi_type'] === 'DischargeSummary') + || (isset($source['ipd_no']) && $source['ipd_no'] !== '') + || (isset($source['discharge_status'])) + || (isset($source['admission_date'])) + || (isset($enc['class_code']) && strtoupper((string) $enc['class_code']) === 'IMP'); + + $defaultClass = $isIpd ? 'IMP' : 'AMB'; + $classCode = strtoupper(trim((string) ($enc['class_code'] ?? $defaultClass))); $classDisplay = $classCode === 'IMP' ? 'inpatient encounter' : 'ambulatory'; $identifiers = [[ @@ -315,6 +324,10 @@ abstract class AbstractModuleFhirGenerator $statusInput = $enc['discharge_disposition'] ?? $enc['outcome'] ?? $source['discharge_status'] ?? $source['discarge_patient_status'] ?? 'home'; $disposition = $this->resolveDischargeDisposition($statusInput); + $divText = $classCode === 'IMP' + ? '

Encounter: ' . $this->escapeXhtml($classDisplay) . ' ' . $this->escapeXhtml($id) . ' - ' . $this->escapeXhtml($disposition['text']) . '

' + : '

Encounter: ' . $this->escapeXhtml($classDisplay) . ' ' . $this->escapeXhtml($id) . '

'; + $encounterResource = [ 'resourceType' => 'Encounter', 'id' => 'encounter-' . $id, @@ -323,7 +336,7 @@ abstract class AbstractModuleFhirGenerator ]], 'text' => [ 'status' => 'generated', - 'div' => '

Encounter: ' . $this->escapeXhtml($classDisplay) . ' ' . $this->escapeXhtml($id) . ' - ' . $this->escapeXhtml($disposition['text']) . '

', + 'div' => $divText, ], 'identifier' => $identifiers, 'status' => 'finished', @@ -340,7 +353,10 @@ abstract class AbstractModuleFhirGenerator 'start' => $start, 'end' => $end, ], - 'hospitalization' => [ + ]; + + if ($classCode === 'IMP') { + $encounterResource['hospitalization'] = [ 'dischargeDisposition' => [ 'coding' => [[ 'system' => 'http://terminology.hl7.org/CodeSystem/discharge-disposition', @@ -349,10 +365,11 @@ abstract class AbstractModuleFhirGenerator ]], 'text' => $disposition['text'], ], - ], - ]; + ]; + } return $encounterResource; + } /** diff --git a/app/Libraries/Abdm/Fhir/Generators/HealthDocumentFhirGenerator.php b/app/Libraries/Abdm/Fhir/Generators/HealthDocumentFhirGenerator.php index d704fba..79893cc 100644 --- a/app/Libraries/Abdm/Fhir/Generators/HealthDocumentFhirGenerator.php +++ b/app/Libraries/Abdm/Fhir/Generators/HealthDocumentFhirGenerator.php @@ -147,11 +147,11 @@ class HealthDocumentFhirGenerator extends AbstractModuleFhirGenerator 'description' => $docTitle . ' PDF', 'content' => [[ 'attachment' => [ - 'contentType' => 'application/pdf', + 'contentType' => $contentType, 'language' => 'en-IN', 'data' => $docData, 'size' => $fileSize, - 'title' => $docTitle . ' PDF', + 'title' => $docTitle, 'creation' => $timestamp, ], ]], @@ -210,10 +210,11 @@ class HealthDocumentFhirGenerator extends AbstractModuleFhirGenerator $ext = str_contains($contentType, 'png') ? 'png' : 'jpg'; $tempImg = $mpdfTempDir . DIRECTORY_SEPARATOR . 'img_' . md5($rawBytes) . '.' . $ext; @file_put_contents($tempImg, $rawBytes); + $tempImgUrl = str_replace('\\', '/', $tempImg); $html = '' . '

' . htmlspecialchars($docTitle, ENT_QUOTES, 'UTF-8') . '

' - . '' + . '' . ''; $mpdf->WriteHTML($html); @unlink($tempImg); diff --git a/app/Libraries/Abdm/Fhir/Generators/WellnessFhirGenerator.php b/app/Libraries/Abdm/Fhir/Generators/WellnessFhirGenerator.php index e2bdd01..e6b0c8a 100644 --- a/app/Libraries/Abdm/Fhir/Generators/WellnessFhirGenerator.php +++ b/app/Libraries/Abdm/Fhir/Generators/WellnessFhirGenerator.php @@ -28,7 +28,7 @@ class WellnessFhirGenerator extends AbstractModuleFhirGenerator [ 'system' => 'http://snomed.info/sct', 'code' => '419891008', - 'display' => 'Record artifact', + 'display' => 'Wellness Record', ], ], 'text' => 'Wellness Record', @@ -47,8 +47,13 @@ class WellnessFhirGenerator extends AbstractModuleFhirGenerator $encounter = $this->buildEncounter($source); if (is_array($encounter)) { $builder->addEncounter($encounter); + $composition['encounter'] = [ + 'reference' => 'urn:uuid:' . (string) ($encounter['id'] ?? ('encounter-' . $recordId)), + 'display' => 'Encounter', + ]; } + $practitioner = $this->buildPractitioner($source); if (is_array($practitioner)) { $builder->addPractitioner($practitioner); diff --git a/app/Views/abdm/task_board.php b/app/Views/abdm/task_board.php index a09847a..7df0a56 100644 --- a/app/Views/abdm/task_board.php +++ b/app/Views/abdm/task_board.php @@ -1118,13 +1118,17 @@ } else if (taskType === 'health_document_publish') { var healthDocId = parseInt(row.getAttribute('data-entity-id') || '0', 10) || 0; var healthPatientId = parseInt(row.getAttribute('data-patient-id') || '0', 10) || 0; + var healthEntityType = (row.getAttribute('data-entity-type') || '').trim(); if (healthDocId <= 0 || healthPatientId <= 0) { setStatus('Task data missing for Health Document FHIR preview.', true); return true; } - previewUrl = '/' + healthDocId; + previewUrl = '/' + healthDocId + + '?entity_type=' + encodeURIComponent(healthEntityType) + + '&patient_id=' + encodeURIComponent(healthPatientId) + + '&abha_id=' + encodeURIComponent(abhaId); title = 'HealthDocumentRecord FHIR Preview - Document #' + healthDocId; } else if (taskType === 'wellness_record_publish') { var wellnessPatientId = parseInt(row.getAttribute('data-patient-id') || '0', 10) || 0; @@ -2180,19 +2184,67 @@ html += ''; } - // -- Embedded invoice PDF + // -- Health Document Record metadata + if (composition && !invoice && (documentRefs.length || (composition.title && (composition.title.toLowerCase().includes('document') || composition.title.toLowerCase().includes('certificate') || composition.title.toLowerCase().includes('form'))))) { + var compCoding = ((((composition.type || {}).coding) || [])[0]) || {}; + var compIdentifier = (composition.identifier || {}).value || ''; + var bundleIdentifier = (bundle.identifier || {}).value || ''; + html += '
'; + html += '' + hesc(composition.title || 'Health Document Record') + ''; + html += '' + hesc(composition.status || 'final') + '
'; + html += '
'; + html += '
Document Title
' + hesc(composition.title || 'Health Document') + '
'; + html += '
Document Date
' + hesc(fmtDate(composition.date || bundle.timestamp) || '-') + '
'; + html += '
Record / Bundle ID
' + hesc(bundleIdentifier || compIdentifier || '-') + '
'; + html += '
Type
' + hesc(compCoding.display || (composition.type || {}).text || 'Record artifact') + '
'; + if (compCoding.code) { + html += '
Code
' + hesc(compCoding.code) + '
'; + } + html += '
'; + } + + // -- Embedded Document / PDF / Image attachments documentRefs.forEach(function(documentReference) { var attachment = (((documentReference.content || [])[0] || {}).attachment) || {}; - if (attachment.contentType !== 'application/pdf') return; - var pdfUrl = attachmentObjectUrl(attachment); - html += '
'; - html += '
' + hesc(attachment.title || 'Invoice PDF') + '
'; - html += 'Attached to this FHIR InvoiceRecord
'; - if (pdfUrl) { - html += 'Open PDF'; - html += 'Download'; + var cType = (attachment.contentType || '').toLowerCase(); + var docName = attachment.title || documentReference.description || (invoice ? 'Invoice PDF' : 'Health Document'); + var isPdf = cType.indexOf('pdf') !== -1; + var isImage = cType.indexOf('image/') === 0; + var docUrl = attachmentObjectUrl(attachment); + + html += '
'; + html += '' + hesc(docName) + ''; + html += '' + hesc(cType || 'document') + '
'; + html += '
'; + html += '
'; + html += '
' + hesc(docName) + '
'; + if (attachment.size) { + var sizeKb = (attachment.size / 1024).toFixed(1) + ' KB'; + if (attachment.size > 1048576) sizeKb = (attachment.size / 1048576).toFixed(2) + ' MB'; + html += 'Size: ' + sizeKb + ' • ' + hesc(cType) + ''; } else { - html += 'Invalid PDF attachment'; + html += '' + (invoice ? 'Attached to this FHIR InvoiceRecord' : 'Attached health document payload') + ''; + } + html += '
'; + if (docUrl) { + if (isPdf) { + html += 'Open PDF'; + html += 'Download PDF'; + } else if (isImage) { + html += 'View Full Image'; + html += 'Download'; + } else { + html += 'Open Document'; + } + } else { + html += 'Invalid document attachment'; + } + html += '
'; + + if (isImage && docUrl) { + html += '
Document Preview
'; + } else if (isPdf && docUrl) { + html += '
'; } html += '
'; }); @@ -2723,8 +2775,18 @@ fhirPreviewModal.show(); - fetch(url, { method: 'GET', headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } }) - .then(function (r) { return r.text().then(function (b) { return { ok: r.ok, status: r.status, body: b }; }); }) + var controller = typeof AbortController !== 'undefined' ? new AbortController() : null; + var timeoutId = controller ? setTimeout(function () { controller.abort(); }, 25000) : null; + + fetch(url, { + method: 'GET', + headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }, + signal: controller ? controller.signal : undefined + }) + .then(function (r) { + if (timeoutId) clearTimeout(timeoutId); + return r.text().then(function (b) { return { ok: r.ok, status: r.status, body: b }; }); + }) .then(function (res) { var parsed = null; try { parsed = JSON.parse(res.body || '{}'); } catch (e) { parsed = { raw: res.body || '' }; } @@ -2757,10 +2819,13 @@ } }) .catch(function (e) { - if (fhirFormView) fhirFormView.innerHTML = '

Request failed: ' + hesc(e.message) + '

'; - if (fhirModalMeta) { fhirModalMeta.textContent = 'Request failed: ' + e.message; fhirModalMeta.className = 'flex-grow-1 small text-danger'; } + if (timeoutId) clearTimeout(timeoutId); + var isTimeout = e.name === 'AbortError'; + var msg = isTimeout ? 'Request timed out after 25 seconds. Please check server or retry.' : e.message; + if (fhirFormView) fhirFormView.innerHTML = '
Request failed: ' + hesc(msg) + '
'; + if (fhirModalMeta) { fhirModalMeta.textContent = 'Request failed: ' + msg; fhirModalMeta.className = 'flex-grow-1 small text-danger'; } if (fhirModalDataBadge) { fhirModalDataBadge.className = 'badge bg-danger'; fhirModalDataBadge.textContent = 'ERROR'; } - if (fhirModalHttpBadge) { fhirModalHttpBadge.className = 'badge bg-danger'; fhirModalHttpBadge.textContent = 'HTTP ERR'; } + if (fhirModalHttpBadge) { fhirModalHttpBadge.className = 'badge bg-danger'; fhirModalHttpBadge.textContent = isTimeout ? 'TIMEOUT' : 'HTTP ERR'; } }); } diff --git a/app/Views/doctor_document/doc_letterhead_print.php b/app/Views/doctor_document/doc_letterhead_print.php index cce958d..4afe2bb 100644 --- a/app/Views/doctor_document/doc_letterhead_print.php +++ b/app/Views/doctor_document/doc_letterhead_print.php @@ -10,8 +10,8 @@ $customHeaderHtml = (string) ($custom_header_html ?? ''); $customFooterHtml = (string) ($custom_footer_html ?? ''); $hasSelectedPrintTemplate = ! empty($has_selected_print_template); $hospitalLogoSrc = trim((string) ($hospital_logo_src ?? '')); -if ($hospitalLogoSrc === '') { - $hospitalLogoSrc = base_url('assets/images/' . (defined('H_logo') ? constant('H_logo') : 'logo.png')); +if ($hospitalLogoSrc === '' || str_starts_with($hospitalLogoSrc, 'http://') || str_starts_with($hospitalLogoSrc, 'https://')) { + $hospitalLogoSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAA='; } ?>