// ============================================================ // bedside/burns.js // BURNS — Lund-Browder body parts + Parkland formula. // ============================================================ import { S } from './shared.js'; // Lund-Browder age-adjusted region percentages. Regions marked "*" change with age. // Column order: infant, young (1-5), child (5-10), adol (10-15), adult (>15). var LB = { head: { label: 'Head', vals: [18, 13, 11, 9, 7], ageSensitive: true }, neck: { label: 'Neck', vals: [2, 2, 2, 2, 2] }, ant_trunk: { label: 'Anterior trunk', vals: [13, 13, 13, 13, 13] }, post_trunk:{ label: 'Posterior trunk', vals: [13, 13, 13, 13, 13] }, r_buttock: { label: 'Right buttock', vals: [2.5, 2.5, 2.5, 2.5, 2.5] }, l_buttock: { label: 'Left buttock', vals: [2.5, 2.5, 2.5, 2.5, 2.5] }, genital: { label: 'Genitalia', vals: [1, 1, 1, 1, 1] }, r_uparm: { label: 'R upper arm', vals: [4, 4, 4, 4, 4] }, l_uparm: { label: 'L upper arm', vals: [4, 4, 4, 4, 4] }, r_forearm: { label: 'R forearm', vals: [3, 3, 3, 3, 3] }, l_forearm: { label: 'L forearm', vals: [3, 3, 3, 3, 3] }, r_hand: { label: 'R hand', vals: [2.5, 2.5, 2.5, 2.5, 2.5] }, l_hand: { label: 'L hand', vals: [2.5, 2.5, 2.5, 2.5, 2.5] }, r_thigh: { label: 'R thigh', vals: [5.5, 8, 8.5, 9, 9.5], ageSensitive: true }, l_thigh: { label: 'L thigh', vals: [5.5, 8, 8.5, 9, 9.5], ageSensitive: true }, r_leg: { label: 'R lower leg', vals: [5, 5.5, 6, 6.5, 7], ageSensitive: true }, l_leg: { label: 'L lower leg', vals: [5, 5.5, 6, 6.5, 7], ageSensitive: true }, r_foot: { label: 'R foot', vals: [3.5, 3.5, 3.5, 3.5, 3.5] }, l_foot: { label: 'L foot', vals: [3.5, 3.5, 3.5, 3.5, 3.5] } }; var AGE_KEYS = ['infant','young','child','adol','adult']; function ageIdx() { return Math.max(0, AGE_KEYS.indexOf(document.getElementById('burn-age').value)); } function renderBodyParts() { var wrap = document.getElementById('burn-bodyparts-wrapper'); if (!wrap) return; var idx = ageIdx(); var html = '
'; html += '
For each involved body region, enter % of that region burned (2° or deeper). Leave 0 if uninvolved. TBSA = sum of (region size × % involvement).
'; html += '
'; Object.keys(LB).forEach(function(key) { var r = LB[key]; var max = r.vals[idx]; var isAgeDep = r.ageSensitive; html += '
' + '' + ' %' + '
'; }); html += '
'; wrap.innerHTML = html; updateLive(); } function resetParts() { var inputs = document.querySelectorAll('[data-burn-region]'); inputs.forEach(function(i) { i.value = 0; }); document.getElementById('burn-tbsa').value = ''; updateLive(); } function computeTbsa() { var idx = ageIdx(); var total = 0; Object.keys(LB).forEach(function(key) { var el = document.querySelector('[data-burn-region="' + key + '"]'); if (!el) return; var pct = parseFloat(el.value) || 0; if (pct < 0) pct = 0; if (pct > 100) pct = 100; total += LB[key].vals[idx] * (pct / 100); }); return Math.round(total * 10) / 10; } function updateLive() { var t = computeTbsa(); var live = document.getElementById('burn-tbsa-live'); if (live) live.textContent = t > 0 ? 'Computed TBSA: ' + t + '%' : ''; } function calcBurn() { var wt = parseFloat(document.getElementById('burn-weight').value); var override = document.getElementById('burn-tbsa').value; var tbsa = override !== '' ? parseFloat(override) : computeTbsa(); var el = document.getElementById('burn-result'); if (!wt) { el.innerHTML = '

Enter weight (kg).

'; return; } if (!tbsa || tbsa <= 0) { el.innerHTML = '

Enter % involvement per region, or override TBSA.

'; return; } var total = Math.round(4 * wt * tbsa); var first8 = Math.round(total / 2); var rateFirst = Math.round(first8 / 8); var next16 = total - first8; var rateNext = Math.round(next16 / 16); var maint = wt <= 10 ? wt * 4 : wt <= 20 ? 40 + (wt - 10) * 2 : 60 + (wt - 20); maint = Math.round(maint); var html = '
Burn fluid resuscitation — ' + wt + ' kg, ' + tbsa + '% TBSA (2° or deeper)
'; html += '
Parkland formula: 4 mL × kg × %TBSA = ' + total + ' mL LR over 24 hours' + '
  First 8 h (from time of burn): ' + first8 + ' mL (~' + rateFirst + ' mL/hr)' + '
  Next 16 h: ' + next16 + ' mL (~' + rateNext + ' mL/hr)
'; html += '
Plus maintenance fluids (4-2-1): ' + maint + ' mL/hr (D5 1/2NS ± 20 mEq KCl/L once UOP established). Consider dextrose in children <30 kg.
'; html += '
Titrate to UOP: target 1-2 mL/kg/hr (infants / children), 0.5-1 mL/kg/hr (adolescents). Clinical response trumps formula.
'; // Breakdown of what regions contributed var idx = ageIdx(); var breakdown = ''; Object.keys(LB).forEach(function(key) { var el2 = document.querySelector('[data-burn-region="' + key + '"]'); if (!el2) return; var pct = parseFloat(el2.value) || 0; if (pct > 0) { var contrib = Math.round(LB[key].vals[idx] * pct / 100 * 10) / 10; breakdown += '
' + LB[key].label + ': ' + pct + '% of ' + LB[key].vals[idx] + '% = ' + contrib + '%
'; } }); if (breakdown) { html += '
Region breakdown
' + breakdown + '
'; } html += '
Other pearls
'; html += '
'; html += 'Rule of palm: Patient\'s palm + fingers ≈ 1% TBSA — good for scattered burns.
'; html += 'First-degree burns DO NOT count toward TBSA or Parkland.
'; html += 'Analgesia: Morphine 0.05-0.1 mg/kg IV q2h, or fentanyl 1-2 mcg/kg IV q30-60 min.
'; html += 'Tetanus prophylaxis if indicated. Tdap/Td ± tetanus immunoglobulin.'; html += '
'; html += '
Burn center referral (ABA)
'; html += '
Partial-thickness >10% TBSA; any full-thickness; face/hands/feet/genital/perineum/major joints; electrical/chemical/inhalation; associated trauma; significant comorbidities; pediatric burns in non-pediatric center.
'; html += S.ref('ABA Advanced Burn Life Support (ABLS) 2018. Parkland formula: Baxter 1968. Lund-Browder 1944 chart (age-adjusted regions).'); el.innerHTML = html; } export function init() { document.addEventListener('click', function(e) { if (e.target.id === 'btn-burn-calc' || e.target.closest('#btn-burn-calc')) calcBurn(); if (e.target.id === 'btn-burn-reset' || e.target.closest('#btn-burn-reset')) resetParts(); // Render body-parts table the first (or any) time the Burns sub-pill is activated var bp = e.target.closest && e.target.closest('[data-em="burns"]'); if (bp) setTimeout(renderBodyParts, 0); // Also render if the top-level Bedside tab is clicked (ensures table ready before user navigates) var nav = e.target.closest && e.target.closest('[data-calc="bedside"]'); if (nav) setTimeout(renderBodyParts, 50); }); document.addEventListener('change', function(e) { if (e.target && e.target.id === 'burn-age') renderBodyParts(); }); document.addEventListener('input', function(e) { if (e.target && e.target.dataset && e.target.dataset.burnRegion) updateLive(); }); // Also attempt render on these events in case component mounts later document.addEventListener('DOMContentLoaded', renderBodyParts); document.addEventListener('tabChanged', function() { setTimeout(renderBodyParts, 100); }); if (document.readyState !== 'loading') setTimeout(renderBodyParts, 0); }