1019 lines
48 KiB
PHP
1019 lines
48 KiB
PHP
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>ABDM Work Task Board</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<style>
|
|
body { background: #f5f7fb; }
|
|
.container-wrap { width: 100%; margin: 0; padding: 20px 24px; box-sizing: border-box; }
|
|
.table td, .table th { vertical-align: middle; }
|
|
.status-pill { text-transform: uppercase; font-size: 11px; letter-spacing: .4px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container-wrap">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<h4 class="mb-0">ABDM Work Task Board</h4>
|
|
<div class="small text-muted">Unupdated ABHA Patient List + Separate ABDM Task Queues</div>
|
|
</div>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="btnRefresh">Refresh</button>
|
|
</div>
|
|
|
|
<div class="d-flex flex-wrap gap-2 mb-3" id="taskFilters">
|
|
<button class="btn btn-sm btn-primary filter-btn" data-filter="patient_abha_create">Unupdated ABHA</button>
|
|
<button class="btn btn-sm btn-outline-primary filter-btn" data-filter="patient_abha_update">ABHA Verify Pending</button>
|
|
<button class="btn btn-sm btn-outline-primary filter-btn" data-filter="opd_book">OPD Book</button>
|
|
<button class="btn btn-sm btn-outline-primary filter-btn" data-filter="opd_consult_publish">OPD Consult Publish</button>
|
|
<button class="btn btn-sm btn-outline-primary filter-btn" data-filter="lab_report_publish">Lab Reports</button>
|
|
<button class="btn btn-sm btn-outline-primary filter-btn" data-filter="radiology_report_publish">Radiology Reports</button>
|
|
<button class="btn btn-sm btn-outline-primary filter-btn" data-filter="ipd_admission_publish">IPD Admission</button>
|
|
<button class="btn btn-sm btn-outline-primary filter-btn" data-filter="ipd_discharge_publish">IPD Discharge</button>
|
|
</div>
|
|
|
|
<div class="card shadow-sm mb-3">
|
|
<div class="card-body py-2">
|
|
<div class="row g-2 align-items-end">
|
|
<div class="col-md-4">
|
|
<label class="form-label mb-1 small">Quick FHIR Preview OPD ID</label>
|
|
<input type="number" min="1" class="form-control form-control-sm" id="tb_quick_opd_id" placeholder="Enter OPD ID">
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label mb-1 small">Session ID (optional)</label>
|
|
<input type="number" min="1" class="form-control form-control-sm" id="tb_quick_session_id" placeholder="Enter OPD Session ID">
|
|
</div>
|
|
<div class="col-md-4">
|
|
<button type="button" class="btn btn-sm btn-outline-primary w-100" id="btn_quick_fhir_preview">Show FHIR JSON Inline</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm mb-3" id="todayCreditOpdCard">
|
|
<div class="card-header py-2 d-flex justify-content-between align-items-center">
|
|
<strong>Today Credit OPD Consult (FHIR Debug)</strong>
|
|
<small class="text-muted">Current date credit consults with quick inline preview</small>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>OPD</th>
|
|
<th>Patient</th>
|
|
<th>ABHA</th>
|
|
<th>Consult Time</th>
|
|
<th>Credit Ref</th>
|
|
<th>FHIR Session</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (! empty($today_credit_opd_rows ?? [])): ?>
|
|
<?php foreach (($today_credit_opd_rows ?? []) as $r): ?>
|
|
<tr>
|
|
<td>#<?= (int) ($r['opd_id'] ?? 0) ?></td>
|
|
<td><?= esc((string) ($r['patient_name'] ?? '')) ?></td>
|
|
<td><?= esc((string) ($r['abha_id'] ?? '')) ?></td>
|
|
<td><?= esc((string) ($r['consult_datetime'] ?? '')) ?></td>
|
|
<td><?= esc((string) ($r['credit_ref'] ?? '')) ?></td>
|
|
<td>
|
|
<?php if (! empty($r['has_fhir'])): ?>
|
|
<?= (int) ($r['opd_session_id'] ?? 0) ?>
|
|
<?php else: ?>
|
|
<span class="text-muted">Not generated</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<button
|
|
type="button"
|
|
class="btn btn-sm btn-outline-primary inline-json-btn"
|
|
data-preview-url="<?= esc((string) ($r['preview_url'] ?? '')) ?>"
|
|
data-title="OPD <?= (int) ($r['opd_id'] ?? 0) ?><?= !empty($r['opd_session_id']) ? (' / Session ' . (int) $r['opd_session_id']) : '' ?>"
|
|
>Preview JSON</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr>
|
|
<td colspan="7" class="text-muted px-2 py-2">No current date credit OPD consult rows found.</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm mb-3 d-none" id="fhirDebugCard">
|
|
<div class="card-header py-2 d-flex justify-content-between align-items-center">
|
|
<div class="d-flex align-items-center gap-2 flex-wrap">
|
|
<strong id="fhirDebugTitle">FHIR JSON Debug</strong>
|
|
<span class="badge bg-secondary" id="fhirDataBadge">UNKNOWN</span>
|
|
<span class="badge bg-secondary" id="fhirHttpBadge">HTTP -</span>
|
|
</div>
|
|
<div class="d-flex align-items-center gap-2">
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="btnCopyFhirDebug">Copy JSON</button>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="btnHideFhirDebug">Hide</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="small text-muted mb-2" id="fhirDebugMeta">Ready</div>
|
|
<pre id="fhirDebugJson" class="mb-0" style="max-height:420px; overflow:auto; background:#0b1020; color:#d9e2ff; padding:12px; border-radius:8px;">{}</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm" id="taskTableCard">
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm table-striped mb-0" id="taskTable">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Task</th>
|
|
<th>Patient</th>
|
|
<th>ABHA</th>
|
|
<th>Entity</th>
|
|
<th>Status</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach (($tasks ?? []) as $t): ?>
|
|
<?php
|
|
$type = strtolower((string) ($t['task_type'] ?? ''));
|
|
$abhaId = trim((string) ($t['abha_id'] ?? ''));
|
|
$hasValidAbha = preg_match('/^\d{14}$/', $abhaId) === 1;
|
|
|
|
$payload = json_decode((string) ($t['payload_json'] ?? ''), true);
|
|
if (! is_array($payload)) {
|
|
$payload = [];
|
|
}
|
|
$meta = (isset($payload['meta']) && is_array($payload['meta'])) ? $payload['meta'] : [];
|
|
$opdId = (int) ($meta['opd_id'] ?? 0);
|
|
$opdSessionId = (int) ($meta['opd_session_id'] ?? 0);
|
|
$showSandbox = ($type === 'opd_prescription_publish' && $opdId > 0);
|
|
$showPreview = ($type === 'opd_prescription_publish' && $opdId > 0);
|
|
?>
|
|
<tr
|
|
data-task-id="<?= (int) ($t['id'] ?? 0) ?>"
|
|
data-task-type="<?= esc((string) ($t['task_type'] ?? '')) ?>"
|
|
data-entity-id="<?= esc((string) ($t['entity_id'] ?? '')) ?>"
|
|
data-patient-id="<?= (int) ($t['patient_id'] ?? 0) ?>"
|
|
data-abha-id="<?= esc($abhaId) ?>"
|
|
data-opd-id="<?= $opdId ?>"
|
|
data-opd-session-id="<?= $opdSessionId ?>"
|
|
data-sandbox-eligible="<?= $showSandbox ? '1' : '0' ?>"
|
|
>
|
|
<td><?= (int) ($t['id'] ?? 0) ?></td>
|
|
<td>
|
|
<div><strong><?= esc((string) ($t['task_code'] ?? '')) ?></strong></div>
|
|
<div class="text-muted small"><?= esc((string) ($t['task_type'] ?? '')) ?></div>
|
|
</td>
|
|
<td>
|
|
<div><?= esc((string) ($t['patient_name'] ?? '')) ?></div>
|
|
<div class="text-muted small">#<?= (int) ($t['patient_id'] ?? 0) ?></div>
|
|
</td>
|
|
<td><input type="text" class="form-control form-control-sm abha-input" value="<?= esc((string) ($t['abha_id'] ?? '')) ?>" placeholder="14-digit ABHA"></td>
|
|
<td>
|
|
<div><?= esc((string) ($t['entity_type'] ?? '')) ?></div>
|
|
<div class="text-muted small"><?= esc((string) ($t['entity_id'] ?? '')) ?></div>
|
|
</td>
|
|
<td><span class="badge bg-secondary status-pill"><?= esc((string) ($t['status'] ?? 'pending')) ?></span></td>
|
|
<td>
|
|
<div class="d-flex gap-1 flex-wrap">
|
|
<?php if ($type === 'patient_abha_create' || $type === 'patient_abha_link'): ?>
|
|
<button class="btn btn-sm btn-outline-success action-btn" data-action="create_abha">Create ABHA</button>
|
|
<?php elseif ($type === 'patient_abha_update'): ?>
|
|
<button class="btn btn-sm btn-outline-primary action-btn" data-action="update_abha">Update ABHA</button>
|
|
<?php else: ?>
|
|
<button class="btn btn-sm btn-outline-warning action-btn" data-action="submit">Submit</button>
|
|
<?php endif; ?>
|
|
<?php if ($showSandbox): ?>
|
|
<button class="btn btn-sm btn-outline-info sandbox-btn">Sandbox</button>
|
|
<?php endif; ?>
|
|
<?php if ($showPreview): ?>
|
|
<button class="btn btn-sm btn-outline-primary preview-fhir-btn">Preview FHIR</button>
|
|
<?php endif; ?>
|
|
<button class="btn btn-sm btn-outline-dark close-btn">Close</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm mt-3 d-none" id="abdmSandboxCard">
|
|
<div class="card-header py-2 d-flex justify-content-between align-items-center">
|
|
<strong>ABDM Sandbox Actions</strong>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="btnSandboxHide">Hide</button>
|
|
</div>
|
|
<div class="card-body p-3">
|
|
<div class="small text-muted mb-2" id="abdmSandboxContext">Select eligible OPD Publish task to use sandbox actions.</div>
|
|
|
|
<div class="row g-2 mb-2">
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1 small">ABHA Number</label>
|
|
<input type="text" class="form-control form-control-sm" id="tb_abha_id" maxlength="14" placeholder="14-digit ABHA">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label mb-1 small">QR Payload (Scan & Share)</label>
|
|
<input type="text" class="form-control form-control-sm" id="tb_abdm_qr_payload" placeholder="Paste scanned QR payload">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex flex-wrap gap-2 mb-2">
|
|
<button type="button" class="btn btn-outline-primary btn-sm" id="tb_btn_abdm_scan_lookup">Scan Lookup</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-sm" id="tb_btn_abdm_validate_abha">Validate ABHA</button>
|
|
</div>
|
|
|
|
<div class="row g-2 mb-2">
|
|
<div class="col-md-6">
|
|
<input type="text" class="form-control form-control-sm" id="tb_abdm_purpose_code" placeholder="Purpose (ex: CAREMGT)">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<input type="datetime-local" class="form-control form-control-sm" id="tb_abdm_consent_expires_at">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex flex-wrap gap-2 mb-2">
|
|
<button type="button" class="btn btn-outline-success btn-sm" id="tb_btn_abdm_consent_request">Request Consent</button>
|
|
<button type="button" class="btn btn-outline-primary btn-sm" id="tb_btn_abdm_preview_fhir">Preview FHIR JSON</button>
|
|
<button type="button" class="btn btn-outline-warning btn-sm" id="tb_btn_abdm_share_fhir">Share FHIR</button>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label class="form-label mb-1 small">Consent Handle</label>
|
|
<input type="text" class="form-control form-control-sm" id="tb_abdm_consent_handle" placeholder="Auto-filled after consent request">
|
|
</div>
|
|
|
|
<div class="row g-2 mb-2">
|
|
<div class="col-md-7">
|
|
<input type="number" min="1" class="form-control form-control-sm" id="tb_abdm_claim_document_id" placeholder="Claim Document ID">
|
|
</div>
|
|
<div class="col-md-5">
|
|
<button type="button" class="btn btn-outline-dark btn-sm w-100" id="tb_btn_abdm_claim_status">Claim Status</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="small text-muted" id="abdmSandboxStatus">Ready</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- OPD Book Card -->
|
|
<div class="card shadow-sm mt-3 d-none" id="opdBookCard">
|
|
<div class="card-header py-2 d-flex justify-content-between align-items-center flex-wrap gap-2">
|
|
<div>
|
|
<strong>OPD Book — ABDM Patients</strong>
|
|
<span class="badge bg-primary ms-2" id="hmsOpdBadge"><?= count($opd_book_rows ?? []) ?></span>
|
|
</div>
|
|
<div class="d-flex gap-2 align-items-center">
|
|
<input type="date" class="form-control form-control-sm" id="opdBookDate" value="<?= date('Y-m-d') ?>" style="width:145px">
|
|
<button type="button" class="btn btn-sm btn-outline-info" id="btnFetchAbdmQueue">Fetch ABDM Queue</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="px-3 pt-2 pb-1 bg-light border-bottom d-flex align-items-center gap-2">
|
|
<strong class="small">ABDM Gateway Queue</strong>
|
|
<span class="badge bg-secondary" id="abdmQueueBadge">-</span>
|
|
<span class="text-muted small" id="abdmQueueStatus">Click "Fetch ABDM Queue" to load</span>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-sm mb-0">
|
|
<thead class="table-light">
|
|
<tr><th>Token</th><th>ABHA</th><th>Name</th><th>Status</th><th>Time</th><th>HMS Patient</th></tr>
|
|
</thead>
|
|
<tbody id="abdmQueueTbody"><tr><td colspan="6" class="text-muted px-2 py-2">Not loaded yet.</td></tr></tbody>
|
|
</table>
|
|
</div>
|
|
<div class="px-3 pt-2 pb-1 bg-light border-bottom border-top d-flex align-items-center gap-2 mt-1">
|
|
<strong class="small">HMS Direct OPD with ABHA</strong>
|
|
<span class="badge bg-success"><?= count($opd_book_rows ?? []) ?></span>
|
|
<span class="text-muted small">Last 7 days · patient has 14-digit ABHA</span>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-sm mb-0">
|
|
<thead class="table-light">
|
|
<tr><th>OPD ID</th><th>Patient</th><th>ABHA</th><th>Date</th><th>Doctor</th><th>Status</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (! empty($opd_book_rows ?? [])): ?>
|
|
<?php foreach (($opd_book_rows ?? []) as $r): ?>
|
|
<tr>
|
|
<td>#<?= (int) ($r['opd_id'] ?? 0) ?></td>
|
|
<td><?= esc((string) ($r['P_name'] ?? '')) ?></td>
|
|
<td><span class="text-primary small"><?= esc((string) ($r['abha_id'] ?? '')) ?></span></td>
|
|
<td><?= esc(substr((string) ($r['apointment_date'] ?? ''), 0, 16)) ?></td>
|
|
<td><?= esc((string) ($r['doc_name'] ?? '')) ?></td>
|
|
<td><span class="badge bg-<?= (int) ($r['opd_status'] ?? 0) >= 2 ? 'success' : 'warning text-dark' ?>"><?= (int) ($r['opd_status'] ?? 0) >= 2 ? 'Done' : 'Pending' ?></span></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr><td colspan="6" class="text-muted px-2 py-2">No OPD with ABHA found in last 7 days.</td></tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- OPD Consult Publish Card -->
|
|
<div class="card shadow-sm mt-3 d-none" id="opdConsultCard">
|
|
<div class="card-header py-2 d-flex align-items-center gap-2">
|
|
<strong>OPD Consult Publish — Done Appointments with ABHA</strong>
|
|
<span class="badge bg-success"><?= count($opd_consult_rows ?? []) ?></span>
|
|
<small class="text-muted ms-1">Last 30 days · opd_status=Done · ABHA linked</small>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm mb-0">
|
|
<thead class="table-light">
|
|
<tr><th>OPD ID</th><th>Patient</th><th>ABHA</th><th>Consult Date</th><th>Doctor</th><th>Action</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (! empty($opd_consult_rows ?? [])): ?>
|
|
<?php foreach (($opd_consult_rows ?? []) as $r): ?>
|
|
<tr>
|
|
<td>#<?= (int) ($r['opd_id'] ?? 0) ?></td>
|
|
<td><?= esc((string) ($r['P_name'] ?? '')) ?></td>
|
|
<td><span class="text-primary small"><?= esc((string) ($r['abha_id'] ?? '')) ?></span></td>
|
|
<td><?= esc(substr((string) ($r['apointment_date'] ?? ''), 0, 16)) ?></td>
|
|
<td><?= esc((string) ($r['doc_name'] ?? '')) ?></td>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-outline-primary btn-opd-consult-fhir" data-opd-id="<?= (int) ($r['opd_id'] ?? 0) ?>">Preview FHIR</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<tr><td colspan="6" class="text-muted px-2 py-2">No done OPD with ABHA found in last 30 days.</td></tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="small text-muted mt-2" id="statusBox">Ready</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="taskActionModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">ABDM Guided Action</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-2 small text-muted" id="modalTaskSummary"></div>
|
|
<label class="form-label">ABHA Number</label>
|
|
<input type="text" class="form-control" id="modalAbhaInput" maxlength="14" placeholder="Enter 14-digit ABHA">
|
|
<div class="form-text">ABHA validation is required before queueing the ABDM API action.</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-primary" id="modalConfirmBtn">Queue Action</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
(function () {
|
|
var csrfName = '<?= csrf_token() ?>';
|
|
var csrfHash = '<?= csrf_hash() ?>';
|
|
var refreshUrl = '<?= base_url('AbdmTaskBoard') ?>';
|
|
var statusBox = document.getElementById('statusBox');
|
|
var modalEl = document.getElementById('taskActionModal');
|
|
var actionModal = new bootstrap.Modal(modalEl);
|
|
var modalAbhaInput = document.getElementById('modalAbhaInput');
|
|
var modalTaskSummary = document.getElementById('modalTaskSummary');
|
|
var modalConfirmBtn = document.getElementById('modalConfirmBtn');
|
|
var sandboxCard = document.getElementById('abdmSandboxCard');
|
|
var sandboxContext = document.getElementById('abdmSandboxContext');
|
|
var sandboxStatus = document.getElementById('abdmSandboxStatus');
|
|
var sandboxAbhaInput = document.getElementById('tb_abha_id');
|
|
var sandboxQrPayloadInput = document.getElementById('tb_abdm_qr_payload');
|
|
var sandboxPurposeCodeInput = document.getElementById('tb_abdm_purpose_code');
|
|
var sandboxConsentExpiresInput = document.getElementById('tb_abdm_consent_expires_at');
|
|
var sandboxConsentHandleInput = document.getElementById('tb_abdm_consent_handle');
|
|
var sandboxClaimDocumentInput = document.getElementById('tb_abdm_claim_document_id');
|
|
var quickOpdInput = document.getElementById('tb_quick_opd_id');
|
|
var quickSessionInput = document.getElementById('tb_quick_session_id');
|
|
var fhirDebugCard = document.getElementById('fhirDebugCard');
|
|
var fhirDebugTitle = document.getElementById('fhirDebugTitle');
|
|
var fhirDebugMeta = document.getElementById('fhirDebugMeta');
|
|
var fhirDebugJson = document.getElementById('fhirDebugJson');
|
|
var fhirDataBadge = document.getElementById('fhirDataBadge');
|
|
var fhirHttpBadge = document.getElementById('fhirHttpBadge');
|
|
var selectedAction = '';
|
|
var selectedRow = null;
|
|
var sandboxRow = null;
|
|
|
|
function setBadge(el, text, tone) {
|
|
if (!el) {
|
|
return;
|
|
}
|
|
el.classList.remove('bg-secondary', 'bg-success', 'bg-danger', 'bg-warning', 'text-dark');
|
|
if (tone === 'success') {
|
|
el.classList.add('bg-success');
|
|
} else if (tone === 'danger') {
|
|
el.classList.add('bg-danger');
|
|
} else if (tone === 'warning') {
|
|
el.classList.add('bg-warning', 'text-dark');
|
|
} else {
|
|
el.classList.add('bg-secondary');
|
|
}
|
|
el.textContent = text;
|
|
}
|
|
|
|
var opdBookCard = document.getElementById('opdBookCard');
|
|
var opdConsultCard = document.getElementById('opdConsultCard');
|
|
var taskTableCard = document.getElementById('taskTableCard');
|
|
|
|
function applyFilter(filter) {
|
|
// Hide dedicated section cards
|
|
if (opdBookCard) opdBookCard.classList.add('d-none');
|
|
if (opdConsultCard) opdConsultCard.classList.add('d-none');
|
|
|
|
if (filter === 'opd_book') {
|
|
if (taskTableCard) taskTableCard.classList.add('d-none');
|
|
if (opdBookCard) opdBookCard.classList.remove('d-none');
|
|
} else if (filter === 'opd_consult_publish') {
|
|
if (taskTableCard) taskTableCard.classList.add('d-none');
|
|
if (opdConsultCard) opdConsultCard.classList.remove('d-none');
|
|
} else {
|
|
if (taskTableCard) taskTableCard.classList.remove('d-none');
|
|
var rows = document.querySelectorAll('#taskTable tbody tr');
|
|
rows.forEach(function (row) {
|
|
var type = (row.getAttribute('data-task-type') || '').toLowerCase();
|
|
row.style.display = (type === filter.toLowerCase()) ? '' : 'none';
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll('.filter-btn').forEach(function (btn) {
|
|
btn.classList.remove('btn-primary');
|
|
btn.classList.add('btn-outline-primary');
|
|
});
|
|
var active = document.querySelector('.filter-btn[data-filter="' + filter + '"]');
|
|
if (active) {
|
|
active.classList.remove('btn-outline-primary');
|
|
active.classList.add('btn-primary');
|
|
}
|
|
}
|
|
|
|
function showInlineFhirPreview(previewUrl, titleText) {
|
|
if (!previewUrl) {
|
|
setStatus('FHIR preview URL is missing.', true);
|
|
return;
|
|
}
|
|
|
|
if (fhirDebugTitle) {
|
|
fhirDebugTitle.textContent = titleText || 'FHIR JSON Debug';
|
|
}
|
|
if (fhirDebugMeta) {
|
|
fhirDebugMeta.textContent = 'Loading...';
|
|
fhirDebugMeta.className = 'small text-muted mb-2';
|
|
}
|
|
setBadge(fhirDataBadge, 'CHECKING', 'warning');
|
|
setBadge(fhirHttpBadge, 'HTTP ...', 'warning');
|
|
if (fhirDebugJson) {
|
|
fhirDebugJson.textContent = '{\n "loading": true\n}';
|
|
}
|
|
if (fhirDebugCard) {
|
|
fhirDebugCard.classList.remove('d-none');
|
|
fhirDebugCard.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
}
|
|
|
|
fetch(previewUrl, {
|
|
method: 'GET',
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
'Accept': 'application/json'
|
|
}
|
|
}).then(function (r) {
|
|
return r.text().then(function (body) {
|
|
return {
|
|
ok: r.ok,
|
|
status: r.status,
|
|
body: body
|
|
};
|
|
});
|
|
}).then(function (res) {
|
|
var parsed = null;
|
|
try {
|
|
parsed = JSON.parse(res.body || '{}');
|
|
} catch (e) {
|
|
parsed = { raw: res.body || '' };
|
|
}
|
|
|
|
var hasFhir = false;
|
|
if (parsed && typeof parsed === 'object') {
|
|
if (parsed.status === 'ok' && parsed.bundle && typeof parsed.bundle === 'object') {
|
|
hasFhir = true;
|
|
}
|
|
if (parsed.resourceType === 'Bundle') {
|
|
hasFhir = true;
|
|
}
|
|
}
|
|
|
|
if (fhirDebugMeta) {
|
|
if (res.ok) {
|
|
fhirDebugMeta.textContent = 'Loaded successfully (' + res.status + ')';
|
|
fhirDebugMeta.className = 'small text-success mb-2';
|
|
} else {
|
|
fhirDebugMeta.textContent = 'Loaded with error status (' + res.status + ')';
|
|
fhirDebugMeta.className = 'small text-danger mb-2';
|
|
}
|
|
}
|
|
setBadge(fhirHttpBadge, 'HTTP ' + res.status, res.ok ? 'success' : 'danger');
|
|
setBadge(fhirDataBadge, hasFhir ? 'HAS FHIR' : 'NOT GENERATED', hasFhir ? 'success' : 'danger');
|
|
if (fhirDebugJson) {
|
|
fhirDebugJson.textContent = JSON.stringify(parsed, null, 2);
|
|
}
|
|
}).catch(function (e) {
|
|
if (fhirDebugMeta) {
|
|
fhirDebugMeta.textContent = 'Request failed: ' + e.message;
|
|
fhirDebugMeta.className = 'small text-danger mb-2';
|
|
}
|
|
setBadge(fhirHttpBadge, 'HTTP ERR', 'danger');
|
|
setBadge(fhirDataBadge, 'NOT GENERATED', 'danger');
|
|
if (fhirDebugJson) {
|
|
fhirDebugJson.textContent = JSON.stringify({
|
|
error: e.message
|
|
}, null, 2);
|
|
}
|
|
});
|
|
}
|
|
|
|
function setStatus(msg, isError) {
|
|
statusBox.textContent = msg;
|
|
statusBox.style.color = isError ? '#dc3545' : '#6c757d';
|
|
}
|
|
|
|
function post(url, payload, cb) {
|
|
payload[csrfName] = csrfHash;
|
|
var body = Object.keys(payload).map(function (key) {
|
|
return encodeURIComponent(key) + '=' + encodeURIComponent(payload[key]);
|
|
}).join('&');
|
|
fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
},
|
|
body: body
|
|
}).then(function (r) {
|
|
return r.json();
|
|
}).then(function (json) {
|
|
if (json && json.csrfHash) {
|
|
csrfHash = json.csrfHash;
|
|
}
|
|
cb(json || {});
|
|
}).catch(function (e) {
|
|
setStatus('Request failed: ' + e.message, true);
|
|
});
|
|
}
|
|
|
|
function setSandboxStatus(msg, level) {
|
|
if (!sandboxStatus) {
|
|
return;
|
|
}
|
|
sandboxStatus.classList.remove('text-muted', 'text-success', 'text-danger', 'text-warning');
|
|
if (level === 'success') {
|
|
sandboxStatus.classList.add('text-success');
|
|
} else if (level === 'danger') {
|
|
sandboxStatus.classList.add('text-danger');
|
|
} else if (level === 'warning') {
|
|
sandboxStatus.classList.add('text-warning');
|
|
} else {
|
|
sandboxStatus.classList.add('text-muted');
|
|
}
|
|
sandboxStatus.textContent = msg || 'Ready';
|
|
}
|
|
|
|
function currentSandboxContext() {
|
|
if (!sandboxRow) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
taskId: parseInt(sandboxRow.getAttribute('data-task-id') || '0', 10) || 0,
|
|
patientId: parseInt(sandboxRow.getAttribute('data-patient-id') || '0', 10) || 0,
|
|
opdId: parseInt(sandboxRow.getAttribute('data-opd-id') || '0', 10) || 0,
|
|
opdSessionId: parseInt(sandboxRow.getAttribute('data-opd-session-id') || '0', 10) || 0,
|
|
abhaId: (sandboxAbhaInput.value || '').trim()
|
|
};
|
|
}
|
|
|
|
function openSandboxForRow(row) {
|
|
if (!row || !sandboxCard) {
|
|
return;
|
|
}
|
|
if ((row.getAttribute('data-sandbox-eligible') || '0') !== '1') {
|
|
setSandboxStatus('Sandbox actions are available only for OPD Publish rows with printed consult.', 'warning');
|
|
return;
|
|
}
|
|
|
|
sandboxRow = row;
|
|
|
|
var taskCode = '';
|
|
var patientName = '';
|
|
var taskCodeEl = row.querySelector('td:nth-child(2) strong');
|
|
var patientNameEl = row.querySelector('td:nth-child(3) div');
|
|
if (taskCodeEl) {
|
|
taskCode = taskCodeEl.textContent.trim();
|
|
}
|
|
if (patientNameEl) {
|
|
patientName = patientNameEl.textContent.trim();
|
|
}
|
|
|
|
var rowAbha = (row.getAttribute('data-abha-id') || '').trim();
|
|
sandboxAbhaInput.value = rowAbha;
|
|
sandboxQrPayloadInput.value = '';
|
|
sandboxPurposeCodeInput.value = sandboxPurposeCodeInput.value || 'CAREMGT';
|
|
sandboxConsentHandleInput.value = '';
|
|
sandboxClaimDocumentInput.value = '';
|
|
|
|
var opdId = row.getAttribute('data-opd-id') || '0';
|
|
var opdSessionId = row.getAttribute('data-opd-session-id') || '0';
|
|
sandboxContext.textContent = 'Task: ' + taskCode + ' | Patient: ' + patientName + ' | OPD: ' + opdId + ' | Session: ' + opdSessionId;
|
|
sandboxCard.classList.remove('d-none');
|
|
setSandboxStatus('Ready');
|
|
sandboxCard.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
}
|
|
|
|
function runAction(row, action) {
|
|
var taskId = row.getAttribute('data-task-id');
|
|
var abha = modalAbhaInput.value.trim();
|
|
|
|
setStatus('Submitting action...');
|
|
post('<?= base_url('AbdmTaskBoard/perform_action') ?>', {
|
|
task_id: taskId,
|
|
action: action,
|
|
abha_id: abha,
|
|
opd_session_id: ''
|
|
}, function (res) {
|
|
if (res.ok !== 1) {
|
|
setStatus(res.error_text || 'Action failed', true);
|
|
return;
|
|
}
|
|
|
|
var badge = row.querySelector('.status-pill');
|
|
if (badge) {
|
|
badge.textContent = 'IN_PROGRESS';
|
|
badge.className = 'badge bg-info status-pill';
|
|
}
|
|
setStatus('Action queued: ' + (res.event_type || '-'));
|
|
actionModal.hide();
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll('.action-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
selectedRow = btn.closest('tr');
|
|
if (!selectedRow) {
|
|
return;
|
|
}
|
|
selectedAction = btn.getAttribute('data-action') || 'submit';
|
|
|
|
var abhaInput = selectedRow.querySelector('.abha-input');
|
|
var taskType = selectedRow.getAttribute('data-task-type') || '';
|
|
modalAbhaInput.value = abhaInput ? abhaInput.value.trim() : '';
|
|
modalTaskSummary.textContent = 'Task: ' + taskType + ' | Action: ' + selectedAction.toUpperCase();
|
|
actionModal.show();
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.filter-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
applyFilter(btn.getAttribute('data-filter') || 'all');
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.sandbox-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
openSandboxForRow(btn.closest('tr'));
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.preview-fhir-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
var row = btn.closest('tr');
|
|
if (!row) {
|
|
return;
|
|
}
|
|
|
|
var opdId = parseInt(row.getAttribute('data-opd-id') || '0', 10) || 0;
|
|
var opdSessionId = parseInt(row.getAttribute('data-opd-session-id') || '0', 10) || 0;
|
|
if (opdId <= 0) {
|
|
setStatus('FHIR preview unavailable for this row.', true);
|
|
return;
|
|
}
|
|
|
|
var previewUrl = opdSessionId > 0
|
|
? '<?= base_url('Opd_prescription/fhir_bundle_preview') ?>/' + opdId + '/' + opdSessionId
|
|
: '<?= base_url('Opd_prescription/fhir_bundle_preview') ?>/' + opdId;
|
|
showInlineFhirPreview(previewUrl, 'Task Row OPD ' + opdId + (opdSessionId > 0 ? (' / Session ' + opdSessionId) : ''));
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.inline-json-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
var previewUrl = (btn.getAttribute('data-preview-url') || '').trim();
|
|
var titleText = (btn.getAttribute('data-title') || 'FHIR JSON Debug').trim();
|
|
showInlineFhirPreview(previewUrl, titleText);
|
|
});
|
|
});
|
|
|
|
applyFilter('patient_abha_create');
|
|
|
|
modalConfirmBtn.addEventListener('click', function () {
|
|
if (!selectedRow || !selectedAction) {
|
|
return;
|
|
}
|
|
var abha = modalAbhaInput.value.trim();
|
|
if (!/^\d{14}$/.test(abha)) {
|
|
setStatus('ABHA must be a 14-digit number.', true);
|
|
return;
|
|
}
|
|
var rowInput = selectedRow.querySelector('.abha-input');
|
|
if (rowInput) {
|
|
rowInput.value = abha;
|
|
}
|
|
runAction(selectedRow, selectedAction);
|
|
});
|
|
|
|
document.querySelectorAll('.close-btn').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
var row = btn.closest('tr');
|
|
if (!row) {
|
|
return;
|
|
}
|
|
var taskId = row.getAttribute('data-task-id');
|
|
post('<?= base_url('AbdmTaskBoard/mark_status') ?>', {
|
|
task_id: taskId,
|
|
status: 'completed',
|
|
note: 'Closed from task board'
|
|
}, function (res) {
|
|
if (res.ok !== 1) {
|
|
setStatus(res.error_text || 'Close failed', true);
|
|
return;
|
|
}
|
|
if (sandboxRow === row && sandboxCard) {
|
|
sandboxCard.classList.add('d-none');
|
|
sandboxRow = null;
|
|
}
|
|
row.remove();
|
|
setStatus('Task closed');
|
|
});
|
|
});
|
|
});
|
|
|
|
document.getElementById('btnSandboxHide').addEventListener('click', function () {
|
|
if (sandboxCard) {
|
|
sandboxCard.classList.add('d-none');
|
|
}
|
|
sandboxRow = null;
|
|
});
|
|
|
|
document.getElementById('tb_btn_abdm_scan_lookup').addEventListener('click', function () {
|
|
var qrPayload = (sandboxQrPayloadInput.value || '').trim();
|
|
if (!qrPayload) {
|
|
setSandboxStatus('Paste QR payload first.', 'warning');
|
|
return;
|
|
}
|
|
setSandboxStatus('Queuing Scan & Share lookup...');
|
|
post('<?= base_url('AbdmGateway/scan_share_lookup') ?>', {
|
|
qr_payload: qrPayload
|
|
}, function (res) {
|
|
if (res.ok !== 1) {
|
|
setSandboxStatus(res.error_text || 'Scan lookup failed.', 'danger');
|
|
return;
|
|
}
|
|
if (res.abha_id_hint) {
|
|
sandboxAbhaInput.value = (res.abha_id_hint || '').toString().trim();
|
|
}
|
|
setSandboxStatus('Scan lookup queued. Queue ID: ' + (res.queue_id || '-'), 'success');
|
|
});
|
|
});
|
|
|
|
document.getElementById('tb_btn_abdm_validate_abha').addEventListener('click', function () {
|
|
var abha = (sandboxAbhaInput.value || '').trim();
|
|
if (!/^\d{14}$/.test(abha)) {
|
|
setSandboxStatus('ABHA must be a 14-digit number.', 'warning');
|
|
return;
|
|
}
|
|
setSandboxStatus('Queuing ABHA validation...');
|
|
post('<?= base_url('AbdmGateway/abha_validate') ?>', {
|
|
abha_id: abha
|
|
}, function (res) {
|
|
if (res.ok !== 1) {
|
|
setSandboxStatus(res.error_text || 'ABHA validation queue failed.', 'danger');
|
|
return;
|
|
}
|
|
setSandboxStatus('ABHA validation queued. Queue ID: ' + (res.queue_id || '-'), 'success');
|
|
});
|
|
});
|
|
|
|
document.getElementById('tb_btn_abdm_consent_request').addEventListener('click', function () {
|
|
var ctx = currentSandboxContext();
|
|
if (!ctx || ctx.patientId <= 0) {
|
|
setSandboxStatus('Select an eligible OPD Publish row first.', 'warning');
|
|
return;
|
|
}
|
|
if (!/^\d{14}$/.test(ctx.abhaId)) {
|
|
setSandboxStatus('ABHA must be a 14-digit number.', 'warning');
|
|
return;
|
|
}
|
|
|
|
setSandboxStatus('Requesting consent...');
|
|
post('<?= base_url('AbdmGateway/consent_request') ?>', {
|
|
patient_id: ctx.patientId,
|
|
abha_id: ctx.abhaId,
|
|
purpose_code: (sandboxPurposeCodeInput.value || '').trim(),
|
|
expires_at: (sandboxConsentExpiresInput.value || '').trim().replace('T', ' ')
|
|
}, function (res) {
|
|
if (res.ok !== 1) {
|
|
setSandboxStatus(res.error_text || 'Consent request failed.', 'danger');
|
|
return;
|
|
}
|
|
if (res.consent_handle) {
|
|
sandboxConsentHandleInput.value = (res.consent_handle || '').toString();
|
|
}
|
|
setSandboxStatus('Consent requested. Handle: ' + (res.consent_handle || '-'), 'success');
|
|
});
|
|
});
|
|
|
|
document.getElementById('tb_btn_abdm_share_fhir').addEventListener('click', function () {
|
|
var ctx = currentSandboxContext();
|
|
if (!ctx || ctx.patientId <= 0 || ctx.opdId <= 0) {
|
|
setSandboxStatus('Select an eligible OPD Publish row first.', 'warning');
|
|
return;
|
|
}
|
|
if (!/^\d{14}$/.test(ctx.abhaId)) {
|
|
setSandboxStatus('ABHA must be a 14-digit number.', 'warning');
|
|
return;
|
|
}
|
|
|
|
setSandboxStatus('Checking consent and queuing FHIR share...');
|
|
post('<?= base_url('AbdmGateway/share_prescription_bundle') ?>', {
|
|
opd_id: ctx.opdId,
|
|
opd_session_id: ctx.opdSessionId,
|
|
patient_id: ctx.patientId,
|
|
abha_id: ctx.abhaId,
|
|
consent_handle: (sandboxConsentHandleInput.value || '').trim()
|
|
}, function (res) {
|
|
if (res.ok !== 1) {
|
|
setSandboxStatus(res.error_text || 'FHIR share queue failed.', 'danger');
|
|
return;
|
|
}
|
|
if (res.consent_handle) {
|
|
sandboxConsentHandleInput.value = (res.consent_handle || '').toString();
|
|
}
|
|
setSandboxStatus('FHIR share queued. Queue ID: ' + (res.queue_id || '-'), 'success');
|
|
});
|
|
});
|
|
|
|
document.getElementById('tb_btn_abdm_preview_fhir').addEventListener('click', function () {
|
|
var ctx = currentSandboxContext();
|
|
if (!ctx || ctx.opdId <= 0) {
|
|
setSandboxStatus('Select an eligible OPD Publish row first.', 'warning');
|
|
return;
|
|
}
|
|
|
|
var previewUrl = ctx.opdSessionId > 0
|
|
? '<?= base_url('Opd_prescription/fhir_bundle_preview') ?>/' + ctx.opdId + '/' + ctx.opdSessionId
|
|
: '<?= base_url('Opd_prescription/fhir_bundle_preview') ?>/' + ctx.opdId;
|
|
|
|
window.open(previewUrl, '_blank');
|
|
setSandboxStatus('Opened FHIR preview for OPD ' + ctx.opdId + (ctx.opdSessionId > 0 ? (' / Session ' + ctx.opdSessionId) : ''), 'success');
|
|
});
|
|
|
|
document.getElementById('tb_btn_abdm_claim_status').addEventListener('click', function () {
|
|
var docId = parseInt((sandboxClaimDocumentInput.value || '0').toString(), 10) || 0;
|
|
if (docId <= 0) {
|
|
setSandboxStatus('Enter Claim Document ID first.', 'warning');
|
|
return;
|
|
}
|
|
|
|
setSandboxStatus('Queuing claim status request...');
|
|
post('<?= base_url('AbdmGateway/nhcx_claim_status_request') ?>', {
|
|
document_id: docId
|
|
}, function (res) {
|
|
if (res.ok !== 1) {
|
|
setSandboxStatus(res.error_text || 'Claim status queue failed.', 'danger');
|
|
return;
|
|
}
|
|
setSandboxStatus('Claim status queued. Queue ID: ' + (res.queue_id || '-'), 'success');
|
|
});
|
|
});
|
|
|
|
document.getElementById('btn_quick_fhir_preview').addEventListener('click', function () {
|
|
var opdId = parseInt((quickOpdInput.value || '0').toString(), 10) || 0;
|
|
var sessionId = parseInt((quickSessionInput.value || '0').toString(), 10) || 0;
|
|
if (opdId <= 0) {
|
|
setStatus('Enter a valid OPD ID for quick preview.', true);
|
|
return;
|
|
}
|
|
|
|
var url = sessionId > 0
|
|
? '<?= base_url('Opd_prescription/fhir_bundle_preview') ?>/' + opdId + '/' + sessionId
|
|
: '<?= base_url('Opd_prescription/fhir_bundle_preview') ?>/' + opdId;
|
|
showInlineFhirPreview(url, 'Quick Preview OPD ' + opdId + (sessionId > 0 ? (' / Session ' + sessionId) : ''));
|
|
});
|
|
|
|
document.getElementById('btnHideFhirDebug').addEventListener('click', function () {
|
|
if (fhirDebugCard) {
|
|
fhirDebugCard.classList.add('d-none');
|
|
}
|
|
});
|
|
|
|
document.getElementById('btnCopyFhirDebug').addEventListener('click', function () {
|
|
var btn = this;
|
|
var originalText = btn.textContent;
|
|
var originalClass = btn.className;
|
|
var jsonText = fhirDebugJson ? (fhirDebugJson.textContent || '{}') : '{}';
|
|
if (!navigator.clipboard || !navigator.clipboard.writeText) {
|
|
setStatus('Clipboard API unavailable in this browser context.', true);
|
|
return;
|
|
}
|
|
navigator.clipboard.writeText(jsonText).then(function () {
|
|
setStatus('FHIR JSON copied to clipboard.');
|
|
btn.textContent = 'Copied ✓';
|
|
btn.className = 'btn btn-sm btn-success';
|
|
window.setTimeout(function () {
|
|
btn.textContent = originalText;
|
|
btn.className = originalClass;
|
|
}, 1500);
|
|
}).catch(function (e) {
|
|
setStatus('Copy failed: ' + e.message, true);
|
|
});
|
|
});
|
|
|
|
// ABDM Gateway Queue fetch for OPD Book
|
|
document.getElementById('btnFetchAbdmQueue').addEventListener('click', function () {
|
|
var date = (document.getElementById('opdBookDate').value || '').trim() || '<?= date('Y-m-d') ?>';
|
|
var statusEl = document.getElementById('abdmQueueStatus');
|
|
var badge = document.getElementById('abdmQueueBadge');
|
|
var tbody = document.getElementById('abdmQueueTbody');
|
|
if (statusEl) statusEl.textContent = 'Fetching...';
|
|
fetch('<?= base_url('AbdmOpdQueue/fetch') ?>?date=' + encodeURIComponent(date) + '&status=PENDING', {
|
|
method: 'GET',
|
|
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }
|
|
}).then(function (r) { return r.json(); }).then(function (data) {
|
|
var tokens = data.data || data.tokens || [];
|
|
if (badge) badge.textContent = tokens.length;
|
|
if (statusEl) statusEl.textContent = 'Loaded ' + tokens.length + ' token(s)';
|
|
if (! tbody) return;
|
|
if (! tokens.length) {
|
|
tbody.innerHTML = '<tr><td colspan="6" class="text-muted px-2 py-2">No PENDING tokens for ' + date + '.</td></tr>';
|
|
return;
|
|
}
|
|
tbody.innerHTML = tokens.map(function (t) {
|
|
var abha = (t.abha_id || t.abha_number || t.abhaId || '').toString().trim();
|
|
var name = (t.patient_name || t.name || t.patientName || '').toString();
|
|
var stat = (t.status || t.queue_status || '').toString();
|
|
var token = (t.token_number || t.tokenNumber || t.gateway_token_id || t.id || '').toString();
|
|
var time = (t.created_at || t.token_time || t.arrival_time || '').toString();
|
|
var hms = t.patient_id ? ('#' + t.patient_id + (t.p_fname ? ' ' + t.p_fname : '')) : '<span class="text-muted">—</span>';
|
|
return '<tr>' +
|
|
'<td>' + (token || '—') + '</td>' +
|
|
'<td><span class="text-primary small">' + (abha || '<span class="text-muted">—</span>') + '</span></td>' +
|
|
'<td>' + (name || '—') + '</td>' +
|
|
'<td><span class="badge bg-' + (stat === 'PENDING' ? 'warning text-dark' : 'secondary') + '">' + (stat || '—') + '</span></td>' +
|
|
'<td class="small">' + (time ? time.substring(0, 16) : '—') + '</td>' +
|
|
'<td>' + hms + '</td>' +
|
|
'</tr>';
|
|
}).join('');
|
|
}).catch(function (e) {
|
|
if (statusEl) statusEl.textContent = 'Fetch failed: ' + e.message;
|
|
});
|
|
});
|
|
|
|
// OPD Consult Publish — FHIR preview buttons
|
|
document.querySelectorAll('.btn-opd-consult-fhir').forEach(function (btn) {
|
|
btn.addEventListener('click', function () {
|
|
var opdId = parseInt(btn.getAttribute('data-opd-id') || '0', 10);
|
|
if (opdId <= 0) return;
|
|
showInlineFhirPreview('<?= base_url('Opd_prescription/fhir_bundle_preview') ?>/' + opdId, 'OPD Consult FHIR ' + opdId);
|
|
});
|
|
});
|
|
|
|
document.getElementById('btnRefresh').addEventListener('click', function () {
|
|
if (typeof window.load_form === 'function') {
|
|
window.load_form(refreshUrl, 'ABDM Task Board');
|
|
return;
|
|
}
|
|
window.location.href = refreshUrl;
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|