remove duplicate bedside handlers from calculators
This commit is contained in:
parent
9a3b3643a7
commit
d2983e9a11
1 changed files with 0 additions and 565 deletions
|
|
@ -1,7 +1,6 @@
|
|||
import { parseAgeMonths, formatParsedAge } from './calculators/age.js';
|
||||
import { loadEquipmentData, renderEquipmentResult } from './calculators/equipment.js';
|
||||
import { initImageLightbox } from './calculators/lightbox.js';
|
||||
import { calcZ as calcNeonatalZ, classifyBirthWeight, classifyGA, classifyWeight, interpolateLMS, loadFentonLmsData, zToPercentile } from './calculators/neonatal.js';
|
||||
import { loadResusMedsData, renderResusMeds } from './calculators/resus.js';
|
||||
import { loadVitalsData, renderVitalsResult } from './calculators/vitals.js';
|
||||
|
||||
|
|
@ -1806,567 +1805,3 @@ initImageLightbox();
|
|||
}
|
||||
}
|
||||
})();
|
||||
|
||||
// ============================================================
|
||||
// NEONATAL ASSESSMENT
|
||||
// ============================================================
|
||||
(function() {
|
||||
var fentonLMS = { male: {}, female: {} };
|
||||
loadFentonLmsData()
|
||||
.then(function(data) { fentonLMS = data; })
|
||||
.catch(function(err) { console.warn('[calculators] Fenton LMS data unavailable:', err && err.message); });
|
||||
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.id === 'btn-neo-assess' || e.target.closest('#btn-neo-assess')) neoAssess();
|
||||
});
|
||||
|
||||
function neoAssess() {
|
||||
var weeks = parseInt(document.getElementById('neo-ga-weeks').value);
|
||||
var days = parseInt(document.getElementById('neo-ga-days').value) || 0;
|
||||
var weight = parseFloat(document.getElementById('neo-weight').value);
|
||||
var sex = document.getElementById('neo-sex').value;
|
||||
var resultDiv = document.getElementById('neo-result');
|
||||
|
||||
if (!weeks || !weight) {
|
||||
resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter GA and birth weight.</p>';
|
||||
return;
|
||||
}
|
||||
if (!fentonLMS[sex] || Object.keys(fentonLMS[sex]).length === 0) {
|
||||
resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Fenton growth data is still loading.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
var gaDecimal = weeks + days / 7;
|
||||
var gaClass = classifyGA(weeks, days);
|
||||
var bwClass = classifyBirthWeight(weight);
|
||||
|
||||
// Calculate percentile using Fenton LMS
|
||||
var lms = interpolateLMS(fentonLMS[sex], gaDecimal);
|
||||
var z = calcNeonatalZ(weight, lms.L, lms.M, lms.S);
|
||||
var percentile = zToPercentile(z);
|
||||
var wtClass = classifyWeight(percentile);
|
||||
var expectedWeight = Math.round(lms.M);
|
||||
|
||||
var html = '';
|
||||
|
||||
// GA Classification
|
||||
html += '<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px;">';
|
||||
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:' + gaClass.color + '10;border:1.5px solid ' + gaClass.color + '30;">';
|
||||
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Gestational Age Classification</div>';
|
||||
html += '<div style="font-size:18px;font-weight:700;color:' + gaClass.color + ';"><i class="fas ' + gaClass.icon + '"></i> ' + gaClass.label + '</div>';
|
||||
html += '<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + weeks + ' weeks ' + days + ' days (' + gaDecimal.toFixed(1) + ' weeks)</div>';
|
||||
html += '</div>';
|
||||
|
||||
// Weight Classification (AGA/SGA/LGA)
|
||||
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:' + wtClass.color + '10;border:1.5px solid ' + wtClass.color + '30;">';
|
||||
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Weight for Gestational Age</div>';
|
||||
html += '<div style="font-size:18px;font-weight:700;color:' + wtClass.color + ';">' + wtClass.label + '</div>';
|
||||
html += '<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + percentile.toFixed(1) + 'th percentile (' + wtClass.detail + ')</div>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
// Birth Weight Category
|
||||
html += '<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px;">';
|
||||
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:' + bwClass.color + '10;border:1.5px solid ' + bwClass.color + '30;">';
|
||||
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Birth Weight Category</div>';
|
||||
html += '<div style="font-size:18px;font-weight:700;color:' + bwClass.color + ';">' + bwClass.label + '</div>';
|
||||
html += '<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + weight + 'g (' + (weight/1000).toFixed(2) + ' kg)</div>';
|
||||
html += '</div>';
|
||||
|
||||
// Stats
|
||||
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:var(--g50);border:1.5px solid var(--g200);">';
|
||||
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Fenton Growth Data (' + (sex === 'male' ? 'Male' : 'Female') + ')</div>';
|
||||
html += '<div style="font-size:13px;color:var(--g700);line-height:1.8;">';
|
||||
html += '<strong>Expected weight (50th %ile):</strong> ' + expectedWeight + 'g<br>';
|
||||
html += '<strong>Z-score:</strong> ' + z.toFixed(2) + '<br>';
|
||||
html += '<strong>Percentile:</strong> ' + percentile.toFixed(1) + '%';
|
||||
html += '</div></div>';
|
||||
html += '</div>';
|
||||
|
||||
// Reference
|
||||
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">Fenton TR, Kim JH. A systematic review and meta-analysis to revise the Fenton growth chart for preterm infants. BMC Pediatrics 2013;13:59. GA classification per ACOG/AAP definitions.</p>';
|
||||
|
||||
resultDiv.innerHTML = html;
|
||||
}
|
||||
})();
|
||||
|
||||
// ============================================================
|
||||
// RESPIRATORY MANAGEMENT (Asthma, Croup, Bronchiolitis)
|
||||
// ============================================================
|
||||
(function() {
|
||||
// Sub-pill navigation
|
||||
document.addEventListener('click', function(e) {
|
||||
var pill = e.target.closest('[data-resp]');
|
||||
if (pill) {
|
||||
document.querySelectorAll('[data-resp]').forEach(function(p) { p.classList.remove('active'); });
|
||||
pill.classList.add('active');
|
||||
['asthma','croup','bronchiolitis'].forEach(function(s) {
|
||||
var el = document.getElementById('resp-' + s);
|
||||
if (el) el.style.display = pill.dataset.resp === s ? '' : 'none';
|
||||
});
|
||||
}
|
||||
if (e.target.closest('[data-asthma-severity]')) asthmaManagement(e.target.closest('[data-asthma-severity]').dataset.asthmaSeverity);
|
||||
if (e.target.id === 'btn-pram-calc' || e.target.closest('#btn-pram-calc')) calcPRAM();
|
||||
if (e.target.id === 'btn-croup-calc' || e.target.closest('#btn-croup-calc')) calcCroup();
|
||||
if (e.target.id === 'btn-bronch-calc' || e.target.closest('#btn-bronch-calc')) calcBronchiolitis();
|
||||
});
|
||||
|
||||
function dose(wt, mgPerKg, maxMg) { var d = Math.round(wt * mgPerKg * 10) / 10; return maxMg ? Math.min(d, maxMg) : d; }
|
||||
// Delegates to the shared _EM.dStr so the per-kg math is visible to the prescriber.
|
||||
function doseStr(wt, mgPerKg, maxMg, unit) {
|
||||
return window._EM.dStr(wt, mgPerKg, maxMg, unit);
|
||||
}
|
||||
function drugRow(name, doseText, route, notes) {
|
||||
return '<tr><td style="font-weight:600;">' + name + '</td><td>' + doseText + '</td><td>' + route + '</td><td style="font-size:12px;color:var(--g500);">' + (notes || '') + '</td></tr>';
|
||||
}
|
||||
function drugTable(rows) {
|
||||
return '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;margin:8px 0;"><table style="width:100%;min-width:500px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:var(--g100);"><th style="text-align:left;padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>' + rows + '</tbody></table></div>';
|
||||
}
|
||||
function severityBadge(label, color) { return '<span style="display:inline-block;padding:4px 12px;border-radius:6px;background:' + color + '20;color:' + color + ';font-weight:700;font-size:14px;">' + label + '</span>'; }
|
||||
|
||||
function asthmaManagement(severity) {
|
||||
var wt = parseFloat(document.getElementById('resp-weight').value);
|
||||
var resultDiv = document.getElementById('asthma-result');
|
||||
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
|
||||
|
||||
var html = '';
|
||||
if (severity === 'mild') {
|
||||
html += severityBadge('Mild Exacerbation', '#10b981');
|
||||
html += '<p style="font-size:13px;margin:8px 0;">Speaks in sentences, no accessory muscle use, SpO2 ≥94%</p>';
|
||||
html += drugTable(
|
||||
drugRow('Albuterol (MDI)', '4-8 puffs via spacer', 'Inhaled', 'q20min x 3 doses, then q1-4h') +
|
||||
drugRow('Albuterol (neb)', doseStr(wt, 0.15, 5, ' mg') + ' (min 2.5 mg)', 'Nebulized', 'q20min x 3 doses') +
|
||||
drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO/IV', 'Single dose, or 2 days') +
|
||||
drugRow('Prednisolone', doseStr(wt, 1, 60) + '/day', 'PO', 'Alternative: 3-5 day course')
|
||||
);
|
||||
html += '<div style="margin-top:8px;padding:8px 12px;background:#d1fae5;border-radius:6px;font-size:12px;color:#065f46;"><strong>Reassess after 1 hour.</strong> If improving → discharge with albuterol MDI + spacer + oral steroid course. If not improving → escalate to moderate.</div>';
|
||||
} else if (severity === 'moderate') {
|
||||
html += severityBadge('Moderate Exacerbation', '#f59e0b');
|
||||
html += '<p style="font-size:13px;margin:8px 0;">Speaks in phrases, some accessory muscle use, SpO2 90-93%</p>';
|
||||
html += drugTable(
|
||||
drugRow('Albuterol (neb)', doseStr(wt, 0.15, 5, ' mg') + ' (min 2.5 mg)', 'Nebulized', 'q20min x 3 doses, then continuous if needed') +
|
||||
drugRow('Ipratropium', wt < 20 ? '250 mcg' : '500 mcg', 'Nebulized', 'q20min x 3 doses with albuterol') +
|
||||
drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO/IV/IM', 'Single dose') +
|
||||
drugRow('O2 supplemental', 'Target SpO2 ≥94%', 'Nasal cannula/mask', 'Titrate to effect')
|
||||
);
|
||||
html += '<div style="margin-top:8px;padding:8px 12px;background:#fef3c7;border-radius:6px;font-size:12px;color:#92400e;"><strong>Reassess after 1-2 hours.</strong> If improving → step down to mild protocol. If worsening or no improvement → escalate to severe.</div>';
|
||||
} else {
|
||||
html += severityBadge('Severe / Life-Threatening', '#ef4444');
|
||||
html += '<p style="font-size:13px;margin:8px 0;">Speaks in words only, significant accessory muscle use, SpO2 <90%. Consider ICU.</p>';
|
||||
html += drugTable(
|
||||
drugRow('Albuterol continuous', doseStr(wt, 0.5, 20, ' mg') + '/hr', 'Continuous neb', 'Or 0.15-0.3 mg/kg q20min') +
|
||||
drugRow('Ipratropium', wt < 20 ? '250 mcg' : '500 mcg', 'Nebulized', 'q20min x 3 doses with albuterol') +
|
||||
drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'IV', 'Or methylprednisolone 2 mg/kg IV (max 60 mg)') +
|
||||
drugRow('Magnesium sulfate', doseStr(wt, 50, 2000) + ' IV over 20 min', 'IV', 'Single dose, monitor BP') +
|
||||
drugRow('Epinephrine (IM)', doseStr(wt, 0.01, 0.5) + ' (1:1000)', 'IM', 'If impending arrest / no IV access') +
|
||||
drugRow('Terbutaline', doseStr(wt, 0.01, 0.4) + ' SC/IV', 'SC or IV bolus', 'Then 0.1-10 mcg/kg/min infusion') +
|
||||
drugRow('O2 supplemental', 'Target SpO2 ≥94%', 'High flow / NIPPV', 'Consider BiPAP/CPAP')
|
||||
);
|
||||
html += '<div style="margin-top:8px;padding:8px 12px;background:#fee2e2;border-radius:6px;font-size:12px;color:#991b1b;"><strong>Continuous monitoring.</strong> Consider ICU admission. If no response to magnesium → terbutaline infusion. If impending respiratory failure → intubation (ketamine preferred induction agent).</div>';
|
||||
|
||||
// Clinical decision points specific to severe asthma
|
||||
html += '<div style="margin-top:10px;display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:8px;">';
|
||||
|
||||
// ABG
|
||||
html += '<div style="padding:10px 12px;background:white;border:1px solid var(--g200);border-radius:8px;font-size:12px;line-height:1.5;">' +
|
||||
'<div style="font-weight:700;color:var(--blue-dark);margin-bottom:4px;"><i class="fas fa-flask"></i> When to obtain a blood gas</div>' +
|
||||
'• Severe exacerbation <strong>not responding</strong> after 1-2 h aggressive therapy<br>' +
|
||||
'• Impending respiratory failure — altered mentation, fatigue, silent chest<br>' +
|
||||
'• SpO2 <92% despite supplemental O2<br>' +
|
||||
'• Suspected CO2 retention (rising PCO2 in a previously tachypneic patient)<br>' +
|
||||
'<strong style="color:#991b1b;">Interpretation:</strong> asthmatics hyperventilate → expect <em>low</em> PCO2. A <strong>"normal" or rising PCO2 = impending failure</strong>. Don\'t delay treatment for the gas.' +
|
||||
'</div>';
|
||||
|
||||
// Intubation
|
||||
html += '<div style="padding:10px 12px;background:white;border:1px solid var(--g200);border-radius:8px;font-size:12px;line-height:1.5;">' +
|
||||
'<div style="font-weight:700;color:#dc2626;margin-bottom:4px;"><i class="fas fa-stethoscope"></i> When to intubate (mostly clinical)</div>' +
|
||||
'• <strong>Absolute:</strong> apnea, cardiac arrest, coma, inability to protect airway<br>' +
|
||||
'• Progressive fatigue despite maximal therapy (NIV, mag, terbutaline, heliox)<br>' +
|
||||
'• Refractory hypoxemia / hypercapnia with acidosis<br>' +
|
||||
'• Silent chest + deteriorating consciousness<br>' +
|
||||
'<strong>RSI choice:</strong> <span style="color:#065f46;font-weight:600;">ketamine 1-2 mg/kg</span> (bronchodilator, preserves BP) + <span style="color:#065f46;font-weight:600;">rocuronium</span>. Avoid succs if hyperkalemic. Permissive hypercapnia after tube; allow expiration (low rate, I:E 1:3-4).' +
|
||||
'</div>';
|
||||
|
||||
// Heliox
|
||||
html += '<div style="padding:10px 12px;background:white;border:1px solid var(--g200);border-radius:8px;font-size:12px;line-height:1.5;">' +
|
||||
'<div style="font-weight:700;color:#7c3aed;margin-bottom:4px;"><i class="fas fa-wind"></i> Heliox (He/O2)</div>' +
|
||||
'• Lower gas density → less turbulence → reduced work of breathing through narrowed airways.<br>' +
|
||||
'• <strong>Consider in:</strong> severe asthma not responding to max therapy (bridge), upper airway obstruction (croup, post-extubation stridor, FB partial).<br>' +
|
||||
'• Typical mix: <strong>70:30 He:O2</strong> (or 80:20). Delivered via tight non-rebreather or in-line with neb.<br>' +
|
||||
'• <strong>Limitation:</strong> requires FiO2 ≤ 30-40%. If patient needs higher FiO2, heliox can\'t help.<br>' +
|
||||
'• Evidence in asthma is mixed — use as adjunct, not substitute.' +
|
||||
'</div>';
|
||||
|
||||
html += '</div>';
|
||||
}
|
||||
html += '<p style="font-size:11px;color:var(--g400);margin:12px 0 0;">NAEPP/GINA guidelines. Always use clinical judgment. Verify doses against institutional protocols.</p>';
|
||||
resultDiv.innerHTML = html;
|
||||
}
|
||||
|
||||
function calcPRAM() {
|
||||
var total = ['pram-spo2','pram-retractions','pram-scalene','pram-air','pram-wheeze'].reduce(function(s, id) {
|
||||
return s + parseInt(document.getElementById(id).value);
|
||||
}, 0);
|
||||
var severity = total <= 3 ? 'Mild' : total <= 7 ? 'Moderate' : 'Severe';
|
||||
var color = total <= 3 ? '#10b981' : total <= 7 ? '#f59e0b' : '#ef4444';
|
||||
document.getElementById('pram-result').innerHTML = '<div style="padding:10px 14px;border-radius:8px;background:' + color + '10;border:1.5px solid ' + color + '30;"><span style="font-size:18px;font-weight:700;color:' + color + ';">PRAM Score: ' + total + '/12 — ' + severity + '</span><p style="font-size:12px;color:var(--g600);margin:4px 0 0;">Mild (0-3): outpatient management. Moderate (4-7): consider oral steroids + frequent bronchodilators. Severe (8-12): aggressive treatment, consider ICU.</p></div>';
|
||||
}
|
||||
|
||||
function calcCroup() {
|
||||
var wt = parseFloat(document.getElementById('resp-weight').value) || 10;
|
||||
var total = ['croup-conscious','croup-cyanosis','croup-stridor','croup-air','croup-retractions'].reduce(function(s, id) {
|
||||
return s + parseInt(document.getElementById(id).value);
|
||||
}, 0);
|
||||
var severity, color, treatment;
|
||||
if (total <= 2) { severity = 'Mild'; color = '#10b981'; treatment = drugTable(drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO (single dose)', 'Preferred corticosteroid') + drugRow('Supportive care', 'Cool mist, comfort measures', '', 'Discharge if tolerating PO')); }
|
||||
else if (total <= 5) { severity = 'Moderate'; color = '#f59e0b'; treatment = drugTable(drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO/IM', 'Single dose') + drugRow('Racemic epinephrine', '0.5 mL of 2.25% solution', 'Nebulized', 'Observe 2-4 hrs after for rebound') + drugRow('Nebulized epinephrine', '0.5 mL/kg of 1:1000 (max 5 mL)', 'Nebulized', 'Alternative to racemic')); }
|
||||
else if (total <= 11) { severity = 'Severe'; color = '#ef4444'; treatment = drugTable(drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'IV/IM', 'Immediate') + drugRow('Racemic epinephrine', '0.5 mL of 2.25% solution', 'Nebulized', 'May repeat q15-20min, observe 2-4 hrs') + drugRow('Nebulized epinephrine', '0.5 mL/kg of 1:1000 (max 5 mL)', 'Nebulized', 'Alternative') + drugRow('Heliox', '70:30 or 80:20', 'Face mask', 'Consider if not responding') + drugRow('O2 supplemental', 'Target SpO2 ≥94%', 'Blow-by preferred', 'Minimize agitation')); }
|
||||
else { severity = 'Impending Respiratory Failure'; color = '#dc2626'; treatment = '<div style="padding:10px;background:#fee2e2;border-radius:6px;font-size:13px;color:#991b1b;font-weight:600;">Immediate airway management. Prepare for intubation (use ETT 0.5-1 size smaller than predicted). Call anesthesia/ENT. Continue nebulized epinephrine and dexamethasone IV.</div>'; }
|
||||
|
||||
document.getElementById('croup-result').innerHTML = '<div style="padding:10px 14px;border-radius:8px;background:' + color + '10;border:1.5px solid ' + color + '30;margin-bottom:12px;"><span style="font-size:18px;font-weight:700;color:' + color + ';">Westley Score: ' + total + '/17 — ' + severity + '</span></div>' + treatment + '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">Westley WJ et al. Nebulized racemic epinephrine by IPPB for the treatment of croup. Am J Dis Child 1978. Mild ≤2, Moderate 3-5, Severe 6-11, Impending failure ≥12.</p>';
|
||||
}
|
||||
|
||||
function calcBronchiolitis() {
|
||||
var wt = parseFloat(document.getElementById('resp-weight').value) || 5;
|
||||
var age = document.getElementById('bronch-age').value;
|
||||
var spo2 = document.getElementById('bronch-spo2').value;
|
||||
var hydration = document.getElementById('bronch-hydration').value;
|
||||
var distress = document.getElementById('bronch-distress').value;
|
||||
|
||||
var html = '<h4 style="font-size:15px;font-weight:700;color:var(--g800);margin:0 0 8px;">Bronchiolitis Management</h4>';
|
||||
var admit = distress === 'severe' || spo2 === 'low' || hydration === 'poor' || age === '<12w';
|
||||
|
||||
if (admit) {
|
||||
html += severityBadge('Admit / Observe', '#ef4444');
|
||||
html += '<div style="margin:10px 0;">';
|
||||
if (age === '<12w') html += '<p style="font-size:13px;color:var(--red);font-weight:600;">⚠ Age <12 weeks — high risk for apnea. Monitor closely.</p>';
|
||||
html += '</div>';
|
||||
} else {
|
||||
html += severityBadge('Likely Safe for Discharge', '#10b981');
|
||||
}
|
||||
|
||||
html += '<div style="margin:12px 0;"><strong style="font-size:13px;">Supportive Care (evidence-based):</strong></div>';
|
||||
html += drugTable(
|
||||
drugRow('Nasal suctioning', 'Bulb suction or NasalClear', 'Nasal', 'Before feeds and as needed') +
|
||||
drugRow('O2 supplemental', 'Target SpO2 ≥90%', 'NC / high flow', spo2 === 'low' ? 'Required' : 'If needed') +
|
||||
drugRow('Hypertonic saline 3%', '4 mL nebulized', 'Nebulized', 'Consider in inpatients (AAP weak recommendation)') +
|
||||
(hydration === 'poor' ? drugRow('IV fluids', 'NS/LR bolus ' + doseStr(wt, 20, null, ' mL'), 'IV', 'Then maintenance D5 0.45NS') + drugRow('NG feeds', 'If unable to feed orally', 'NG tube', 'Preferred over IV if gut functional') : '')
|
||||
);
|
||||
|
||||
html += '<div style="margin:12px 0;padding:10px 12px;background:var(--amber-light);border-radius:6px;font-size:12px;color:#92400e;"><strong>NOT recommended (AAP 2014/2023):</strong> Albuterol/salbutamol (no benefit in bronchiolitis), epinephrine (no evidence of benefit), systemic corticosteroids (no benefit), antibiotics (unless secondary bacterial infection), chest physiotherapy.</div>';
|
||||
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">AAP Clinical Practice Guideline: Management of Bronchiolitis in Infants and Children (2014, reaffirmed 2023). RSV is the most common cause (50-80%).</p>';
|
||||
document.getElementById('bronch-result').innerHTML = html;
|
||||
}
|
||||
})();
|
||||
|
||||
// ============================================================
|
||||
// SEIZURE MANAGEMENT
|
||||
// ============================================================
|
||||
(function() {
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.id === 'btn-seizure-calc' || e.target.closest('#btn-seizure-calc')) calcSeizure();
|
||||
});
|
||||
|
||||
function d(wt, mgPerKg, max) { var v = Math.round(wt * mgPerKg * 100) / 100; return max ? Math.min(v, max) : v; }
|
||||
function row(phase, drug, dose, route, notes) {
|
||||
return '<tr><td style="font-weight:600;color:var(--blue);">' + phase + '</td><td style="font-weight:600;">' + drug + '</td><td>' + dose + '</td><td>' + route + '</td><td style="font-size:12px;color:var(--g500);">' + notes + '</td></tr>';
|
||||
}
|
||||
|
||||
// Visual pathway row — time badge + step card linked by vertical line
|
||||
function stepRow(time, color, title, bodyHtml, isLast) {
|
||||
return '<div style="display:flex;gap:12px;align-items:stretch;">' +
|
||||
'<div style="flex:0 0 auto;width:70px;display:flex;flex-direction:column;align-items:center;">' +
|
||||
'<div style="background:' + color + ';color:white;padding:6px 0;border-radius:20px;font-size:12px;font-weight:700;width:60px;text-align:center;box-shadow:0 1px 3px rgba(0,0,0,0.15);">' + time + '</div>' +
|
||||
(isLast ? '' : '<div style="flex:1;width:3px;background:' + color + '40;margin:2px 0;"></div>') +
|
||||
'</div>' +
|
||||
'<div style="flex:1;padding:10px 14px;border-left:4px solid ' + color + ';background:' + color + '10;border-radius:0 8px 8px 0;margin-bottom:' + (isLast ? '4px' : '12px') + ';">' +
|
||||
'<div style="font-weight:700;color:' + color + ';font-size:13px;margin-bottom:6px;text-transform:uppercase;letter-spacing:0.3px;">' + title + '</div>' +
|
||||
'<div style="font-size:13px;color:var(--g700);line-height:1.55;">' + bodyHtml + '</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// Fallback inline data — mirrors the non-refractory seizure entries in
|
||||
// drugs.json. Refractory infusion drips are kept inline below because
|
||||
// their dose strings (bolus → gtt range) don't map cleanly to the
|
||||
// single-row JSON schema.
|
||||
var SEIZURE_FALLBACK = [
|
||||
{ name: 'Lorazepam', phase: '1st benzo', dose_mg_per_kg: 0.1, max_mg: 4, unit: 'mg', route: 'IV / IO', label_suffix: ' <span style="color:#065f46;font-weight:600;">(IV preferred)</span>', notes: 'Slow push over 1-2 min.' },
|
||||
{ name: 'Midazolam', phase: '1st benzo', dose_mg_per_kg: 0.2, max_mg: 10, unit: 'mg', route: 'IM / IN / buccal', notes: 'Use 5 mg/mL concentrate for IN; split between nares.' },
|
||||
{ name: 'Diazepam', phase: '1st benzo', dose_mg_per_kg: 0.5, max_mg: 20, unit: 'mg', route: 'PR', notes: 'Only if no IV/IM/IN access.' },
|
||||
{ name: 'Levetiracetam', phase: '2nd-line', dose_mg_per_kg: 60, max_mg: 4500, unit: 'mg', route: 'IV over 5-15 min', label_suffix: ' <span style="color:#065f46;font-weight:600;">(preferred)</span>', notes: 'Best tolerability. No ECG monitoring needed.' },
|
||||
{ name: 'Fosphenytoin', phase: '2nd-line', dose_mg_per_kg: 20, max_mg: 1500, unit: 'mg PE', route: 'IV over 10 min', notes: 'Max rate 3 mg PE/kg/min. Monitor ECG, BP. Avoid if cardiac dysrhythmia.' },
|
||||
{ name: 'Valproic acid', phase: '2nd-line', dose_mg_per_kg: 40, max_mg: 3000, unit: 'mg', route: 'IV over 10 min', notes: '<strong>Avoid <2 yr, hepatic / mitochondrial disease, pregnancy.</strong>' },
|
||||
{ name: 'Phenobarbital', phase: '2nd-line', dose_mg_per_kg: 20, max_mg: 1000, unit: 'mg', route: 'IV over 20 min', notes: 'Last-choice 2nd line. High risk of resp depression + hypotension.' }
|
||||
];
|
||||
|
||||
function seizureDrugs() {
|
||||
var s = window._DRUGS && window._DRUGS.sections && window._DRUGS.sections.seizure;
|
||||
if (s && s.drugs && s.drugs.length) {
|
||||
return s.drugs.map(function(d) {
|
||||
var fb = SEIZURE_FALLBACK.filter(function(x) { return x.name === d.name; })[0] || {};
|
||||
return Object.assign({}, fb, d);
|
||||
});
|
||||
}
|
||||
return SEIZURE_FALLBACK;
|
||||
}
|
||||
|
||||
// Build the joined S.drugRow output for one phase ("1st benzo" / "2nd-line").
|
||||
function seizureRowsByPhase(wt, phase) {
|
||||
var S = window._EM;
|
||||
return seizureDrugs().filter(function(dg) { return dg.phase === phase; }).map(function(dg) {
|
||||
var label = dg.name + (dg.label_suffix || '');
|
||||
var unitArg = dg.unit && dg.unit !== 'mg' ? ' ' + dg.unit : undefined;
|
||||
var dose = unitArg
|
||||
? S.dStr(wt, dg.dose_mg_per_kg, dg.max_mg, unitArg)
|
||||
: S.dStr(wt, dg.dose_mg_per_kg, dg.max_mg);
|
||||
return S.drugRow(label, dose, dg.route, dg.notes);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function calcSeizure() {
|
||||
var wt = parseFloat(document.getElementById('seizure-weight').value);
|
||||
var resultDiv = document.getElementById('seizure-result');
|
||||
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
|
||||
var S = window._EM;
|
||||
var d10Low = Math.round(wt * 2 * 10) / 10;
|
||||
var d10High = Math.round(wt * 5 * 10) / 10;
|
||||
|
||||
var html = '<div style="padding:10px 14px;border-radius:8px;background:#fee2e2;border:1.5px solid #ef4444;margin-bottom:14px;"><strong style="color:#dc2626;font-size:14px;"><i class="fas fa-bolt"></i> Status Epilepticus Pathway — ' + wt + ' kg</strong><div style="font-size:12px;color:var(--g600);margin-top:3px;">Time = 0 at seizure onset. Do not pause between steps for benzo to take effect — act on the clock.</div></div>';
|
||||
|
||||
// 0 min — STABILIZE
|
||||
html += stepRow('0 min', '#3b82f6', 'Stabilize',
|
||||
'<strong>ABCs</strong> — position, 100% O2 via NC / NRB, suction. <strong>IV or IO</strong> × 2. Continuous SpO2, ECG, BP. ' +
|
||||
'<strong>POC glucose</strong> — if <60 mg/dL: <strong>D10W ' + d10Low + '-' + d10High + ' mL IV</strong> (2-5 mL/kg). ' +
|
||||
'<strong>Labs</strong>: CBC, CMP, Mg, Ca, Phos, VBG, lactate, AED levels, toxicology if unclear etiology. ' +
|
||||
'<strong>Consider pyridoxine</strong> 100 mg IV in infants <18 mo or INH ingestion. Temperature: treat hyperthermia aggressively.'
|
||||
);
|
||||
|
||||
// 5 min — 1ST BENZO
|
||||
html += stepRow('5 min', '#8b5cf6', '1st benzodiazepine (give once, pick by access)',
|
||||
S.drugTable(seizureRowsByPhase(wt, '1st benzo'))
|
||||
);
|
||||
|
||||
// 10 min — 2ND BENZO
|
||||
html += stepRow('10 min', '#a855f7', '2nd benzodiazepine — if still seizing',
|
||||
'Repeat same agent + dose <strong>once</strong>. Prepare 2nd-line now (don\'t wait to see if benzo works). If apnea/airway compromise: BVM, consider advanced airway.'
|
||||
);
|
||||
|
||||
// 20 min — 2ND-LINE
|
||||
html += stepRow('20 min', '#f59e0b', '2nd-line anti-epileptic — pick one (ESETT: equivalent efficacy)',
|
||||
S.drugTable(seizureRowsByPhase(wt, '2nd-line'))
|
||||
);
|
||||
|
||||
// 30 min — 2nd of 2nd-line (optional)
|
||||
html += stepRow('30 min', '#ef4444', 'Still seizing? Consider 2nd agent from 2nd-line OR proceed to refractory',
|
||||
'If the first 2nd-line drug failed, give a different 2nd-line agent <strong>OR</strong> move directly to refractory therapy. Activate ICU, prepare for intubation. Confirm etiology not reversible (electrolytes, glucose, fever, toxin).'
|
||||
);
|
||||
|
||||
// 40 min — REFRACTORY
|
||||
html += stepRow('40 min', '#dc2626', 'Refractory status — intubate + continuous infusion + continuous EEG',
|
||||
S.drugTable(
|
||||
S.drugRow('Midazolam <span style="color:#065f46;font-weight:600;">(1st-line infusion)</span>', 'Bolus ' + d(wt, 0.2, 10) + ' mg → gtt ' + d(wt, 0.05, 2) + '-' + d(wt, 0.5, 18) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 0.2 mg/kg, gtt 0.05-0.5 mg/kg/hr)</span>', 'IV', 'Titrate to seizure control / burst suppression.') +
|
||||
S.drugRow('Pentobarbital', 'Bolus ' + d(wt, 5, 200) + ' mg → gtt ' + d(wt, 1, null) + '-' + d(wt, 5, null) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 5 mg/kg, gtt 1-5 mg/kg/hr)</span>', 'IV', 'Causes hypotension — often need pressors.') +
|
||||
S.drugRow('Propofol', 'Bolus ' + d(wt, 2, 100) + ' mg → gtt ' + d(wt, 2, null) + '-' + d(wt, 5, null) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 2 mg/kg, gtt 2-5 mg/kg/hr)</span>', 'IV', '<strong>PRIS risk in children</strong> — limit to <4 mg/kg/hr and duration <48 h.') +
|
||||
S.drugRow('Ketamine', 'Bolus ' + d(wt, 2, 100) + ' mg → gtt ' + d(wt, 1, null) + '-' + d(wt, 5, null) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 2 mg/kg, gtt 1-5 mg/kg/hr)</span>', 'IV', 'NMDA antagonist — rescue. Good BP profile; useful if refractory to GABAergics.')
|
||||
) +
|
||||
'<div style="margin-top:8px;font-size:12px;color:var(--g600);"><strong>Continuous EEG within 1 h</strong> — target electrographic seizure suppression × 24-48 h, then wean. Reassess etiology: CNS imaging, LP, expanded workup.</div>'
|
||||
, true);
|
||||
|
||||
// Key points
|
||||
html += '<div style="margin-top:16px;padding:10px 12px;background:#fef3c7;border-radius:6px;font-size:12px;color:#92400e;line-height:1.55;"><strong>Key points</strong><br>' +
|
||||
'• Do <strong>NOT</strong> wait for benzo response before starting the 2nd-line — parallel preparation.<br>' +
|
||||
'• Maximum <strong>2 benzo doses</strong> total (1 pre-hospital + 1 in ED, or 2 in ED).<br>' +
|
||||
'• Respiratory depression is common — have BVM, airway equipment, naloxone, flumazenil accessible (but avoid flumazenil here).<br>' +
|
||||
'• ESETT trial: levetiracetam = fosphenytoin = valproate for efficacy. Pick by tolerability / contraindications.<br>' +
|
||||
'• Always reassess: ongoing seizure? Non-convulsive status? Pseudo-seizure? → continuous EEG if any doubt.</div>';
|
||||
|
||||
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;font-style:italic;">Based on AES Guidelines 2016 and ESETT (Kapur et al., NEJM 2019). Verify all doses against institutional protocols.</p>';
|
||||
resultDiv.innerHTML = html;
|
||||
}
|
||||
})();
|
||||
|
||||
// ============================================================
|
||||
// ANAPHYLAXIS MANAGEMENT
|
||||
// ============================================================
|
||||
(function() {
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.id === 'btn-anaph-calc' || e.target.closest('#btn-anaph-calc')) calcAnaphylaxis();
|
||||
});
|
||||
|
||||
function d(wt, mgPerKg, max) { var v = Math.round(wt * mgPerKg * 100) / 100; return max ? Math.min(v, max) : v; }
|
||||
|
||||
// Lookup a drug entry (by name) from window._DRUGS.sections.anaphylaxis,
|
||||
// falling back to a hardcoded record so rendering stays identical if the
|
||||
// JSON fetch hasn't resolved (or failed). Returns an object exposing the
|
||||
// per-kg + max fields needed by S.dStr.
|
||||
var ANAPH_FALLBACK = {
|
||||
'Epinephrine IM': { dose_mg_per_kg: 0.01, max_mg: 0.5, unit: 'mg' },
|
||||
'Normal saline bolus': { dose_mg_per_kg: 20, max_mg: null, unit: 'mL' },
|
||||
'Diphenhydramine': { dose_mg_per_kg: 1.25, max_mg: 50, unit: 'mg' },
|
||||
'Ranitidine': { dose_mg_per_kg: 1, max_mg: 50, unit: 'mg' },
|
||||
'Dexamethasone': { dose_mg_per_kg: 0.6, max_mg: 16, unit: 'mg' },
|
||||
'Methylprednisolone': { dose_mg_per_kg: 2, max_mg: 125, unit: 'mg' },
|
||||
'Glucagon': { dose_mg_per_kg: 0.02, max_mg: 1, unit: 'mg' }
|
||||
};
|
||||
function anaphDrug(name) {
|
||||
var s = window._DRUGS && window._DRUGS.sections && window._DRUGS.sections.anaphylaxis;
|
||||
if (s && s.drugs) {
|
||||
var hit = s.drugs.filter(function(x) { return x.name === name; })[0];
|
||||
if (hit) return hit;
|
||||
}
|
||||
return ANAPH_FALLBACK[name] || {};
|
||||
}
|
||||
|
||||
function calcAnaphylaxis() {
|
||||
var wt = parseFloat(document.getElementById('anaph-weight').value);
|
||||
var age = document.getElementById('anaph-age').value;
|
||||
var resultDiv = document.getElementById('anaph-result');
|
||||
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
|
||||
var S = window._EM;
|
||||
|
||||
var epi = anaphDrug('Epinephrine IM');
|
||||
var fluids = anaphDrug('Normal saline bolus');
|
||||
var dph = anaphDrug('Diphenhydramine');
|
||||
var rnt = anaphDrug('Ranitidine');
|
||||
var dex = anaphDrug('Dexamethasone');
|
||||
var mpn = anaphDrug('Methylprednisolone');
|
||||
var glc = anaphDrug('Glucagon');
|
||||
|
||||
var epiDose = d(wt, epi.dose_mg_per_kg, epi.max_mg);
|
||||
var epiVol = Math.round(epiDose * 10) / 10; // 1:1000 = 1 mg/mL
|
||||
var autoInjector = wt < 10 ? 'Draw up manually' : wt <= 25 ? 'EpiPen Jr / Auvi-Q 0.15 mg' : 'EpiPen / Auvi-Q 0.3 mg';
|
||||
|
||||
var html = '<div style="padding:14px;border-radius:10px;background:#fee2e2;border:2px solid #ef4444;margin-bottom:16px;">';
|
||||
html += '<div style="font-size:18px;font-weight:700;color:#dc2626;margin-bottom:6px;"><i class="fas fa-triangle-exclamation"></i> STEP 1: Epinephrine IM — GIVE IMMEDIATELY</div>';
|
||||
html += '<div style="font-size:15px;font-weight:600;color:var(--g800);margin-bottom:4px;">Epinephrine 1:1000 (1 mg/mL): <span style="color:#dc2626;">' + epiDose + ' mg (' + epiVol + ' mL)</span> IM to lateral thigh</div>';
|
||||
html += '<div style="font-size:13px;color:var(--g600);">' + epi.dose_mg_per_kg + ' mg/kg (max ' + epi.max_mg + ' mg) | Auto-injector: ' + autoInjector + '</div>';
|
||||
html += '<div style="font-size:12px;color:#991b1b;margin-top:6px;">May repeat every 5-15 minutes if symptoms persist. No contraindications in anaphylaxis.</div>';
|
||||
html += '</div>';
|
||||
|
||||
html += '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;margin-bottom:12px;"><table style="width:100%;min-width:560px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:var(--g100);"><th style="text-align:left;padding:6px 8px;">Step</th><th style="padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>';
|
||||
|
||||
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 2</td><td style="font-weight:600;">Position</td><td>Supine + legs elevated</td><td>—</td><td style="font-size:12px;color:var(--g500);">If dyspneic: sitting position. If vomiting: recovery position</td></tr>';
|
||||
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 3</td><td style="font-weight:600;">O2</td><td>High flow 10-15 L/min</td><td>Face mask</td><td style="font-size:12px;color:var(--g500);">100% O2. Prepare for airway management</td></tr>';
|
||||
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 4</td><td style="font-weight:600;">IV fluids</td><td>NS ' + S.dStr(wt, fluids.dose_mg_per_kg, fluids.max_mg, ' mL') + ' bolus</td><td>IV/IO</td><td style="font-size:12px;color:var(--g500);">Repeat up to 60 mL/kg for hypotension</td></tr>';
|
||||
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 5</td><td style="font-weight:600;">Diphenhydramine</td><td>' + S.dStr(wt, dph.dose_mg_per_kg, dph.max_mg) + '</td><td>IV/IM/PO</td><td style="font-size:12px;color:var(--g500);">H1 blocker. NOT first-line — adjunct only</td></tr>';
|
||||
html += '<tr><td></td><td style="font-weight:600;">Ranitidine</td><td>' + S.dStr(wt, rnt.dose_mg_per_kg, rnt.max_mg) + '</td><td>IV over 5 min</td><td style="font-size:12px;color:var(--g500);">H2 blocker. Optional adjunct</td></tr>';
|
||||
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 6</td><td style="font-weight:600;">Dexamethasone</td><td>' + S.dStr(wt, dex.dose_mg_per_kg, dex.max_mg) + '</td><td>IV/IM/PO</td><td style="font-size:12px;color:var(--g500);">Prevents biphasic reaction (4-6 hrs later)</td></tr>';
|
||||
html += '<tr><td></td><td style="font-weight:600;">Methylprednisolone</td><td>' + S.dStr(wt, mpn.dose_mg_per_kg, mpn.max_mg) + '</td><td>IV</td><td style="font-size:12px;color:var(--g500);">Alternative steroid</td></tr>';
|
||||
|
||||
html += '<tr style="background:#fef3c7;"><td style="font-weight:600;color:#dc2626;">IF REFRACTORY</td><td style="font-weight:600;">Epinephrine gtt</td><td>0.1-1 mcg/kg/min</td><td>IV infusion</td><td style="font-size:12px;color:var(--g500);">For persistent hypotension despite fluids + IM epi</td></tr>';
|
||||
html += '<tr style="background:#fef3c7;"><td></td><td style="font-weight:600;">Glucagon</td><td>' + S.dStr(wt, glc.dose_mg_per_kg, glc.max_mg) + '</td><td>IV/IM</td><td style="font-size:12px;color:var(--g500);">For patients on beta-blockers not responding to epi</td></tr>';
|
||||
|
||||
html += '</tbody></table></div>';
|
||||
html += '<div style="padding:10px 12px;background:var(--amber-light);border-radius:6px;font-size:12px;color:#92400e;"><strong>Observe minimum 4-6 hours</strong> after last dose of epinephrine (biphasic reactions occur in 5-20% of cases). Discharge with EpiPen prescription and anaphylaxis action plan. Refer to allergist.</div>';
|
||||
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">ASCIA Anaphylaxis Guidelines 2021. WAO Anaphylaxis Guidance 2020. AAP/ACAAI Practice Parameters.</p>';
|
||||
resultDiv.innerHTML = html;
|
||||
}
|
||||
})();
|
||||
|
||||
// ============================================================
|
||||
// PROCEDURAL SEDATION
|
||||
// ============================================================
|
||||
(function() {
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.id === 'btn-sed-calc' || e.target.closest('#btn-sed-calc')) calcSedation();
|
||||
});
|
||||
|
||||
function d(wt, mgPerKg, max) { var v = Math.round(wt * mgPerKg * 100) / 100; return max ? Math.min(v, max) : v; }
|
||||
|
||||
// Fallback inline data — mirrors drugs.json sedation section. The first
|
||||
// table's rows group by drug (Ketamine has both IV + IM lines), hence the
|
||||
// display vs name split. `reverses` marks the final 2 rows as reversal
|
||||
// agents shown in a separate table.
|
||||
var SED_FALLBACK = [
|
||||
{ name: 'Ketamine IV', display: 'Ketamine', dose_mg_per_kg_low: 1.5, dose_mg_per_kg_high: 2, max_mg_low: 100, max_mg_high: 150, unit: 'mg', route: 'IV', onset: '1 min', duration: '15-30 min', notes: 'Dissociative. Preserves airway reflexes.' },
|
||||
{ name: 'Ketamine IM', display: '', dose_mg_per_kg_low: 4, dose_mg_per_kg_high: 5, max_mg_low: 300, max_mg_high: 400, unit: 'mg', route: 'IM', onset: '3-5 min', duration: '30-60 min', notes: 'Give atropine 0.01 mg/kg to reduce secretions.' },
|
||||
{ name: 'Midazolam IV', display: 'Midazolam', dose_mg_per_kg_low: 0.05, dose_mg_per_kg_high: 0.1, max_mg_low: 2, max_mg_high: 5, unit: 'mg', route: 'IV', onset: '2-3 min', duration: '30-60 min', notes: 'Anxiolysis. Titrate q3-5 min.' },
|
||||
{ name: 'Midazolam IN/PO', display: '', dose_mg_per_kg: 0.5, max_mg: 20, unit: 'mg', route: 'IN/PO', onset: '10-15 min', duration: '30-60 min', notes: 'IN (max 10 mg / naris) or PO (max 20 mg).' },
|
||||
{ name: 'Propofol', display: 'Propofol', dose_mg_per_kg: 1, max_mg: 40, unit: 'mg', route: 'IV', onset: '30 sec', duration: '5-10 min', notes: 'Short procedures. Causes apnea — manage airway.' },
|
||||
{ name: 'Fentanyl IV', display: 'Fentanyl', dose_mg_per_kg: 1, max_mg: 100, unit: 'mcg', route: 'IV', onset: '2-3 min', duration: '30-60 min', notes: 'Analgesic. Often combined with midazolam.' },
|
||||
{ name: 'Fentanyl IN', display: '', dose_mg_per_kg: 2, max_mg: 100, unit: 'mcg', route: 'IN', onset: '5-10 min', duration: '30-60 min', notes: 'Intranasal.' },
|
||||
{ name: 'Nitrous oxide', display: 'Nitrous oxide', dose_display: '50:50 or 70:30 mix', unit: 'mix', route: 'Inhaled',onset: '2-5 min', duration: '5 min off', notes: 'Self-administered via demand valve. Anxiolysis + mild analgesia.' },
|
||||
{ name: 'Dexmedetomidine IN', display: 'Dexmedetomidine', dose_mg_per_kg_low: 2, dose_mg_per_kg_high: 3, max_mg_low: 100, max_mg_high: null, unit: 'mcg', route: 'IN', onset: '15-30 min', duration: '60-90 min', notes: 'Intranasal. No respiratory depression. Good for imaging.' },
|
||||
{ name: 'Naloxone', display: 'Naloxone', dose_mg_per_kg: 0.1, max_mg: 2, unit: 'mg', route: 'IV/IM/IN', reverses: 'Opioids (fentanyl, morphine)', notes: 'Max 2 mg. Repeat q2-3 min. Duration shorter than opioids — monitor for re-sedation.' },
|
||||
{ name: 'Flumazenil', display: 'Flumazenil', dose_mg_per_kg: 0.01, max_mg: 0.2, unit: 'mg', route: 'IV', reverses: 'Benzodiazepines (midazolam)', notes: 'Max 0.2 mg single dose. Repeat q1 min to max 1 mg total. Risk of seizures — use cautiously.' }
|
||||
];
|
||||
|
||||
function sedDrugs() {
|
||||
var s = window._DRUGS && window._DRUGS.sections && window._DRUGS.sections.sedation;
|
||||
if (s && s.drugs && s.drugs.length) {
|
||||
return s.drugs.map(function(d) {
|
||||
var fb = SED_FALLBACK.filter(function(x) { return x.name === d.name; })[0] || {};
|
||||
return Object.assign({}, fb, d);
|
||||
});
|
||||
}
|
||||
return SED_FALLBACK;
|
||||
}
|
||||
|
||||
// perKg footer that matches the original inline format exactly.
|
||||
function sedPerKg(lo, hi, unit) {
|
||||
unit = unit || 'mg';
|
||||
return ' <span style="color:var(--g500);font-size:11px;">(' + lo + (hi != null ? '-' + hi : '') + ' ' + unit + '/kg)</span>';
|
||||
}
|
||||
|
||||
// Build the Dose cell text for a sedation drug (supports low/high range
|
||||
// and single-dose entries; honors custom dose_display for fixed doses).
|
||||
function sedDoseCell(wt, dg) {
|
||||
if (dg.dose_display) return dg.dose_display;
|
||||
var unitLabel = dg.unit === 'mcg' ? ' mcg' : (dg.unit === 'mix' ? '' : ' mg');
|
||||
var perKgUnit = dg.unit === 'mcg' ? 'mcg' : 'mg';
|
||||
if (dg.dose_mg_per_kg_low != null) {
|
||||
var lo = d(wt, dg.dose_mg_per_kg_low, dg.max_mg_low);
|
||||
if (dg.dose_mg_per_kg_high != null) {
|
||||
var hi = d(wt, dg.dose_mg_per_kg_high, dg.max_mg_high);
|
||||
return lo + '-' + hi + unitLabel + sedPerKg(dg.dose_mg_per_kg_low, dg.dose_mg_per_kg_high, perKgUnit);
|
||||
}
|
||||
return lo + unitLabel + sedPerKg(dg.dose_mg_per_kg_low, null, perKgUnit);
|
||||
}
|
||||
if (dg.dose_mg_per_kg != null) {
|
||||
var v = d(wt, dg.dose_mg_per_kg, dg.max_mg);
|
||||
return v + unitLabel + sedPerKg(dg.dose_mg_per_kg, null, perKgUnit);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function sedRow(wt, dg, showReverses) {
|
||||
var displayName = dg.display == null ? dg.name : dg.display;
|
||||
var nameCell = displayName
|
||||
? '<td style="font-weight:600;">' + displayName + '</td>'
|
||||
: '<td></td>';
|
||||
var dose = sedDoseCell(wt, dg);
|
||||
if (showReverses) {
|
||||
return '<tr>' + nameCell + '<td>' + dose + '</td><td>' + dg.route + '</td><td>' + (dg.reverses || '') + '</td><td style="font-size:12px;color:var(--g500);">' + dg.notes + '</td></tr>';
|
||||
}
|
||||
return '<tr>' + nameCell + '<td>' + dose + '</td><td>' + dg.route + '</td><td>' + (dg.onset || '') + '</td><td>' + (dg.duration || '') + '</td><td style="font-size:12px;color:var(--g500);">' + dg.notes + '</td></tr>';
|
||||
}
|
||||
|
||||
function calcSedation() {
|
||||
var wt = parseFloat(document.getElementById('sed-weight').value);
|
||||
var resultDiv = document.getElementById('sed-result');
|
||||
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
|
||||
|
||||
var all = sedDrugs();
|
||||
var agents = all.filter(function(dg) { return !dg.reverses; });
|
||||
var reversals = all.filter(function(dg) { return !!dg.reverses; });
|
||||
|
||||
var html = '<div style="padding:10px 14px;border-radius:8px;background:var(--purple-light);border:1.5px solid var(--purple);margin-bottom:12px;"><span style="font-size:14px;font-weight:700;color:var(--purple);">Procedural Sedation — ' + wt + ' kg patient</span></div>';
|
||||
|
||||
// Sedation agents
|
||||
html += '<h4 style="font-size:14px;font-weight:700;color:var(--g800);margin:0 0 8px;">Sedation Agents</h4>';
|
||||
html += '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;margin-bottom:16px;"><table style="width:100%;min-width:640px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:var(--g100);"><th style="text-align:left;padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Onset</th><th style="padding:6px 8px;">Duration</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>';
|
||||
html += agents.map(function(dg) { return sedRow(wt, dg, false); }).join('');
|
||||
html += '</tbody></table></div>';
|
||||
|
||||
// Reversal agents
|
||||
html += '<h4 style="font-size:14px;font-weight:700;color:var(--red);margin:0 0 8px;"><i class="fas fa-rotate-left"></i> Reversal Agents</h4>';
|
||||
html += '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;"><table style="width:100%;min-width:560px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:#fee2e2;"><th style="text-align:left;padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Reverses</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>';
|
||||
html += reversals.map(function(dg) { return sedRow(wt, dg, true); }).join('');
|
||||
html += '</tbody></table></div>';
|
||||
|
||||
html += '<div style="margin-top:12px;padding:10px 12px;background:var(--amber-light);border-radius:6px;font-size:12px;color:#92400e;"><strong>Pre-sedation checklist:</strong> NPO status (2h clear liquids, 6h solids), consent, monitoring equipment (pulse ox, capnography, BP), resuscitation equipment at bedside, suction ready, IV access. Minimum monitoring: continuous SpO2, HR, capnography. Provider capable of managing airway must be present.</div>';
|
||||
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">AAP Guidelines for Monitoring and Management of Pediatric Patients Before, During, and After Sedation. ASA Practice Guidelines for Sedation and Analgesia by Non-Anesthesiologists.</p>';
|
||||
resultDiv.innerHTML = html;
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
Loading…
Reference in a new issue