pediatric-ai-scribe-v3/public/js/bedside/shared.js
Daniel 2742a2a130 feat: C — extract Bedside reference into ES modules
Split the Bedside clinical reference section out of calculators.js
(~1220 lines) into 20 focused ES modules under public/js/bedside/.
Each module owns one clinical topic (cardiac, seizure, sepsis, burns,
etc.) and exports an init() wired up by bedside/index.js. Shared
helpers live in shared.js and also set window._EM for back-compat
with the 4 remaining call sites in calculators.js.

Load order: classic defer calculators.js first, then module script
bedside/index.js. Handlers bind at DOM-ready; runtime _EM lookups
resolve after both are evaluated.

Makes bedside content editable per-section, shrinks calculators.js
from 4111 to 2891 lines, and keeps the existing Playwright smoke
suite (e2e/tests/bedside-smoke.spec.js) as the behavioral contract.
2026-04-20 23:19:50 +02:00

44 lines
3.2 KiB
JavaScript

// ============================================================
// bedside/shared.js
// Shared string-building helpers used by every Bedside section.
// Pure functions with no side effects. Exports `S`; also sets
// window._EM = S for back-compat with any stray lookups.
// ============================================================
export const S = {
d: function(wt, perKg, max) { var v = Math.round(wt * perKg * 100) / 100; return max ? Math.min(v, max) : v; },
// Dose string — always shows the per-kg used (and max when capped), so the
// prescriber can verify the math without opening a drug ref.
// S.dStr(30, 0.1, 4) → "3 mg (0.1 mg/kg, max 4 mg)"
// S.dStr(60, 0.1, 4) → "4 mg (0.1 mg/kg, max 4 mg · capped)"
// S.dStr(20, 2, 150, ' mcg') → "40 mcg (2 mcg/kg, max 150 mcg)"
dStr: function(wt, perKg, max, unit) {
unit = unit || ' mg';
var uTrim = unit.trim() || 'mg';
var raw = wt * perKg;
var v = Math.round(raw * 100) / 100;
var capped = max != null && v > max;
var val = capped ? max : v;
var perKgStr = '(' + perKg + ' ' + uTrim + '/kg';
if (max != null) perKgStr += ', max ' + max + ' ' + uTrim;
if (capped) perKgStr += ' · capped';
perKgStr += ')';
return val + unit + ' <span style="color:var(--g500);font-size:11px;font-weight:400;">' + perKgStr + '</span>';
},
drugTable: function(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="text-align:left;padding:6px 8px;">Dose</th><th style="text-align:left;padding:6px 8px;">Route</th><th style="text-align:left;padding:6px 8px;">Notes</th></tr></thead><tbody>' + rows + '</tbody></table></div>';
},
drugRow: function(name, dose, route, notes) {
return '<tr><td style="font-weight:600;padding:5px 8px;border-bottom:1px solid var(--g100);">' + name + '</td><td style="padding:5px 8px;border-bottom:1px solid var(--g100);">' + dose + '</td><td style="padding:5px 8px;border-bottom:1px solid var(--g100);">' + route + '</td><td style="padding:5px 8px;border-bottom:1px solid var(--g100);font-size:12px;color:var(--g500);">' + (notes || '') + '</td></tr>';
},
stepBox: function(color, title, body) {
return '<div style="border-left:4px solid ' + color + ';background:' + color + '10;padding:10px 14px;border-radius:6px;margin-bottom:10px;">' +
'<div style="font-weight:700;color:' + color + ';font-size:13px;margin-bottom:4px;">' + title + '</div>' +
'<div style="font-size:13px;color:var(--g700);line-height:1.5;">' + body + '</div></div>';
},
arrow: '<div style="text-align:center;color:var(--g400);font-size:16px;margin:-4px 0 6px;">↓</div>',
badge: function(label, color) { return '<span style="display:inline-block;padding:3px 10px;border-radius:6px;background:' + color + '20;color:' + color + ';font-weight:700;font-size:12px;">' + label + '</span>'; },
ref: function(text) { return '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;font-style:italic;">' + text + '</p>'; }
};
if (typeof window !== 'undefined') window._EM = S;