// Generic engine for a "browse one resource type across all patients" page // (Conditions, Observations, Allergies, Medications, Encounters). Each page // just defines window.RESOURCE_PAGE_CONFIG and includes this script — no // per-page JS needed. See conditions.html for the config shape. let rpPatientsCache = []; let rpSearchTerm = ''; let rpAddModal, rpEditingRowId = null, rpEditingPatientId = null; function rpEscapeHtml(str) { if (str === null || str === undefined) return ''; return String(str) .replace(/&/g, '&').replace(//g, '>') .replace(/"/g, '"').replace(/'/g, '''); } function rpFmtDate(value) { if (!value) return '—'; const d = new Date(value); if (isNaN(d)) return '—'; return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }); } function rpShowToast(message, variant = 'success') { const container = document.getElementById('toastContainer'); if (!container) { alert(message); return; } const el = document.createElement('div'); el.className = `toast align-items-center text-bg-${variant === 'danger' ? 'danger' : 'success'} border-0 show mb-2`; el.innerHTML = `
| ${c.render(row[c.key], row)} | `; let v = row[c.key]; v = c.type === 'date' ? rpFmtDate(v) : rpEscapeHtml(v ?? '—'); return `${v} | `; }).join(''); const actions = config.readOnly ? '' : ``; return ` |
| ${rpEscapeHtml(c.label)} | `).join('')}${config.readOnly ? '' : ''} |
|---|