pediatric-ai-scribe-v3/public/js/calculators/resus.js
2026-05-08 03:18:37 +02:00

101 lines
6.4 KiB
JavaScript

var resusCache = null;
export function loadResusMedsData() {
if (resusCache) return Promise.resolve(resusCache);
return fetch('/data/calculators/resus-meds.json', { credentials: 'same-origin' })
.then(function(response) {
if (!response.ok) throw new Error('Failed to load resus meds data');
return response.json();
})
.then(function(data) {
resusCache = data;
return resusCache;
});
}
export function calculateResusDose(formula, w) {
var d, d1, d2, d3, ett, grams, detail, full, im, iv, ivVol, partial;
switch (formula) {
case 'adenosine':
d1 = +(w * 0.1).toFixed(2);
d2 = +(w * 0.2).toFixed(2);
d3 = +(w * 0.3).toFixed(2);
return { dose: d1 + ' mg (0.1 mg/kg)', extra: 'May repeat: ' + Math.min(d2, 12) + ' mg (0.2 mg/kg), then ' + Math.min(d3, 12) + ' mg (0.3 mg/kg)', max: 'Max first dose 6 mg, max subsequent 12 mg' };
case 'amiodarone':
d = +(w * 5).toFixed(1);
return { dose: Math.min(d, 300) + ' mg (5 mg/kg)', extra: 'No pulse: push undiluted. Pulse: over 20-60 min. Subsequent max 150 mg.', max: 'Max first 300 mg, max total 15 mg/kg/24hr or 2200 mg' };
case 'atropine':
d = +(w * 0.02).toFixed(3);
ett = (w * 0.04).toFixed(3) + '-' + (w * 0.06).toFixed(3);
return { dose: Math.min(d, 0.5) + ' mg (0.02 mg/kg)', extra: 'ETT dose: ' + ett + ' mg (0.04-0.06 mg/kg)', max: 'Max single 0.5 mg, max total 1 mg' };
case 'calciumChloride':
d = +(w * 20).toFixed(0);
return { dose: Math.min(d, 1000) + ' mg (20 mg/kg)', extra: 'Give slowly. Central line preferred.', max: 'Max 1 g (1000 mg)' };
case 'calciumGluconate':
d = +(w * 60).toFixed(0);
return { dose: Math.min(d, 3000) + ' mg (60 mg/kg)', extra: 'Give slowly over 10-20 min with cardiac monitoring.', max: 'Max 3 g (3000 mg)' };
case 'dextrose':
grams = +(w * 0.5).toFixed(1) + '-' + +(w * 1).toFixed(1);
if (w < 5) detail = 'D10W: ' + (w * 5).toFixed(1) + '-' + (w * 10).toFixed(1) + ' mL (5-10 mL/kg)';
else if (w < 45) detail = 'D25W: ' + (w * 2).toFixed(1) + '-' + (w * 4).toFixed(1) + ' mL (2-4 mL/kg)';
else detail = 'D50W: ' + (w * 1).toFixed(1) + '-' + (w * 2).toFixed(1) + ' mL (1-2 mL/kg)';
return { dose: grams + ' g (0.5-1 g/kg)', extra: detail, max: 'Max 25 g' };
case 'epinephrine':
iv = +(w * 0.01).toFixed(3);
ivVol = +(w * 0.1).toFixed(2);
ett = +(w * 0.1).toFixed(2);
im = +(w * 0.01).toFixed(3);
return { dose: Math.min(iv, 1) + ' mg IV/IO (0.01 mg/kg of 0.1 mg/mL = ' + Math.min(ivVol, 10) + ' mL) q3-5 min', extra: 'ETT: ' + Math.min(ett, 2.5) + ' mg (0.1 mg/kg of 1 mg/mL). Anaphylaxis IM: ' + Math.min(im, 0.5) + ' mg (0.01 mg/kg)', max: 'Max IV 1 mg, max ETT 2.5 mg, max IM 0.5 mg' };
case 'hydrocortisone':
d = +(w * 2).toFixed(1);
return { dose: Math.min(d, 100) + ' mg (2 mg/kg)', extra: 'Stress dosing for adrenal insufficiency.', max: 'Max 100 mg' };
case 'insulin':
d = +(w * 0.1).toFixed(2);
return { dose: Math.min(d, 5) + ' units (0.1 units/kg)', extra: 'Give with ' + +(w * 0.5).toFixed(1) + ' g/kg dextrose (0.5 g/kg). Monitor glucose closely.', max: 'Max 5 units' };
case 'lidocaine':
d = +(w * 1).toFixed(1);
ett = (w * 2).toFixed(1) + '-' + (w * 3).toFixed(1);
return { dose: Math.min(d, 100) + ' mg (1 mg/kg)', extra: 'ETT: ' + ett + ' mg (2-3 mg/kg). May repeat q5 min.', max: 'Max 100 mg/dose, max total 3 mg/kg' };
case 'magnesiumSulfate':
d = +(w * 50).toFixed(0);
return { dose: Math.min(d, 2000) + ' mg (50 mg/kg)', extra: 'Give over 10-20 min (faster if pulseless).', max: 'Max 2 g (2000 mg)' };
case 'naloxone':
partial = +(w * 0.001).toFixed(4) + '-' + +(w * 0.005).toFixed(4);
full = +(w * 0.1).toFixed(3);
return { dose: 'Partial: ' + partial + ' mg (0.001-0.005 mg/kg)', extra: 'Full reversal: ' + Math.min(full, 2) + ' mg (0.1 mg/kg)', max: 'Max partial first dose 0.1 mg, max full 2 mg' };
case 'sodiumBicarbonate':
d = +(w * 1).toFixed(1);
return { dose: Math.min(d, 50) + ' mEq (1 mEq/kg)', extra: w < 10 ? 'Dilute to 0.5 mEq/mL (use 4.2% solution) for neonates/small infants.' : 'Use 8.4% solution (1 mEq/mL).', max: 'Max 50 mEq' };
}
return { dose: '', extra: '', max: '' };
}
export function renderResusMeds(data, weightKg) {
var categories = data.categories || {};
var html = '<div style="margin-bottom:12px;font-size:14px;font-weight:700;color:var(--g800);">Doses for ' + weightKg + ' kg patient</div>';
html += '<div style="display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px;font-size:11px;">';
Object.keys(categories).forEach(function(cat) {
html += '<span style="display:inline-flex;align-items:center;gap:4px;"><span style="width:10px;height:10px;border-radius:50%;background:' + categories[cat].color + ';display:inline-block;"></span>' + categories[cat].label + '</span>';
});
html += '</div>';
html += '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px;">';
(data.medications || []).forEach(function(med) {
var r = calculateResusDose(med.formula, weightKg);
var color = categories[med.category] ? categories[med.category].color : '#6b7280';
html += '<div style="border:1.5px solid ' + color + '33;border-radius:10px;overflow:hidden;background:#fff;">' +
'<div style="padding:10px 14px;background:' + color + '0d;border-bottom:1px solid ' + color + '22;">' +
'<div style="font-size:14px;font-weight:700;color:' + color + ';">' + med.name + '</div>' +
'<div style="font-size:11px;color:var(--g500);margin-top:2px;">' + med.indication + '</div>' +
'</div>' +
'<div style="padding:12px 14px;font-size:13px;">' +
'<div style="margin-bottom:6px;"><strong>Dose:</strong> ' + r.dose + '</div>' +
'<div style="margin-bottom:6px;font-size:12px;color:var(--g600);">' + r.extra + '</div>' +
'<div style="font-size:11px;color:var(--g500);"><strong>Max:</strong> ' + r.max + '</div>' +
'<div style="font-size:11px;color:var(--g400);margin-top:4px;"><strong>Route:</strong> ' + med.route + '</div>' +
'</div>' +
'</div>';
});
html += '</div>';
html += '<div style="margin-top:14px;padding:10px;background:#fef3c7;border-radius:8px;font-size:11px;color:#92400e;"><strong>Disclaimer:</strong> Always verify doses against institutional protocols and current guidelines. This tool is for educational reference only.</div>';
return html;
}