#2 — Don't-miss tooltip (encounters HPI + sick visit, max 5) - New POST /api/dont-miss returning {points: [{point, why}]} capped at 5 (cap defended both in the prompt and server-side .slice(0,5)) - New dontMissTooltip prompt in prompts.js - New suggestDontMiss() helper in app.js mirroring suggestBillingCodes; inserts an orange-bordered card next to the note output, silent on empty - Wired into liveEncounter.js (encounter HPI) and sickVisit.js. Not added to wellvisit/soap/hospital/chart per spec. #1 — Bedside suture selector - New ES module public/js/bedside/sutures.js (~300L) following the burns.js pattern: site × age × tension × cosmetic × contamination × hours-since-injury → material, size, technique, removal day range, glue/Steri-strip alternative, warnings, tetanus reminder. - 15 anatomic sites covered (face, eyelid, lip vermilion, intraoral, ear, scalp, neck, trunk, upper/lower ext, hand, foot, joint surface, genitalia, fingertip). - Bites: cat/human → don't-close-primarily warning; dog bite to hand → loose-approximation note. Heavy contamination → delayed primary closure. >12h non-face/scalp → judgment call note. - Removal days shown as ranges (3–5, 7–10, 10–14) per source norms, not single midpoints. - Subungual hematoma trephination guidance corrected: any painful hematoma with intact nail and no displaced fracture (especially if 25–50% or more), per current UpToDate guidance. - Inline citation: Roberts & Hedges 7e (2019), Fleisher & Ludwig 8e, AAP Section on EM, UpToDate (Pope JV). - Pill registered in sub-nav SECTIONS + bedside/index.js. Persists active state via existing UIState helper. All 46 tests pass.
320 lines
16 KiB
JavaScript
320 lines
16 KiB
JavaScript
// ============================================================
|
||
// bedside/sutures.js
|
||
// SUTURE SELECTOR — site × age × tension × wound state →
|
||
// material, size, technique, removal day, alternatives, and
|
||
// contraindication warnings.
|
||
//
|
||
// Sources cited inline in the result via S.ref():
|
||
// Roberts & Hedges' Clinical Procedures in Emergency Medicine, 7e (2019)
|
||
// Fleisher & Ludwig's Textbook of Pediatric Emergency Medicine, 8e (2021)
|
||
// AAP Section on Emergency Medicine — Pediatric laceration repair
|
||
// UpToDate: Pope JV — Skin laceration repair with sutures
|
||
// ============================================================
|
||
|
||
import { S } from './shared.js';
|
||
|
||
// ── Site table ──────────────────────────────────────────────────────
|
||
// sutureSize/removalDays are the "moderate tension, clean, school-age" defaults.
|
||
// recommendFn() below adjusts for tension, age, contamination.
|
||
var SITES = {
|
||
face: {
|
||
label: 'Face (non-cosmetic-critical)',
|
||
materialFamily: 'monofilament-nonabsorbable', // nylon / polypropylene
|
||
sutureSize: '6-0',
|
||
removalDays: '3–5',
|
||
glueOK: true,
|
||
glueNote: 'Tissue adhesive (Dermabond) excellent for clean linear lacs ≤4 cm with low tension and good apposition. Avoid near eyes, lips, joints, mucosa.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Smallest practical size to minimize scar. Approximate edges precisely — eversion is more important than knot count.'
|
||
},
|
||
eyelid_eyebrow: {
|
||
label: 'Eyelid / eyebrow',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '6-0',
|
||
removalDays: '3–5',
|
||
glueOK: false,
|
||
glueNote: 'No tissue adhesive — risk of ocular irritation.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Do NOT shave eyebrow (regrowth unpredictable). Refer full-thickness eyelid, lid-margin, or lacrimal-system lacerations to ophthalmology / plastics.'
|
||
},
|
||
lip_vermilion: {
|
||
label: 'Lip — crossing vermilion border',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '6-0',
|
||
removalDays: '3–5',
|
||
glueOK: false,
|
||
glueNote: 'No glue across vermilion.',
|
||
techniqueDefault: 'Simple interrupted, FIRST stitch precisely aligning the vermilion border',
|
||
notes: 'Vermilion misalignment as small as 1 mm is visible. If a deep layer (orbicularis oris) is involved, close it with 5-0 absorbable first. Intraoral side: 4-0 chromic or Vicryl Rapide.'
|
||
},
|
||
intraoral: {
|
||
label: 'Intraoral / tongue / mucosa',
|
||
materialFamily: 'absorbable-chromic-or-vicryl',
|
||
sutureSize: '4-0 or 5-0',
|
||
removalDays: null, // absorbable
|
||
glueOK: false,
|
||
glueNote: 'No glue on mucosa.',
|
||
techniqueDefault: 'Simple interrupted, generous bites (mucosa is friable)',
|
||
notes: 'Many intraoral lacs heal well without closure. Suture if: through-and-through, gaping >1 cm, flap, or interfering with feeding/airway. Tongue: sedation often required; absorbable only.'
|
||
},
|
||
ear: {
|
||
label: 'Ear',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '5-0',
|
||
removalDays: '4–5',
|
||
glueOK: false,
|
||
glueNote: 'No glue on ear.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Cover exposed cartilage with skin (do not suture cartilage in ED). Hematoma → drain to prevent cauliflower ear. Auricular block before repair.'
|
||
},
|
||
scalp: {
|
||
label: 'Scalp',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '3-0 or 4-0',
|
||
removalDays: '7–10',
|
||
glueOK: true,
|
||
glueNote: 'Hair apposition technique (HAT) — twist hair across the wound and secure with a drop of glue — reasonable for clean linear scalp lacs ≤10 cm with hair ≥3 cm.',
|
||
techniqueDefault: 'Simple interrupted, or staples (faster, equivalent cosmesis under hair)',
|
||
notes: 'Highly vascular — pressure controls bleeding. Galea aponeurotica may need closure with 3-0 absorbable for hemostasis. Staples acceptable in non-visible scalp.'
|
||
},
|
||
neck: {
|
||
label: 'Neck',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '5-0',
|
||
removalDays: '5–7',
|
||
glueOK: true,
|
||
glueNote: 'Glue acceptable for superficial low-tension lacs only.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Rule out deep neck-structure injury (zone-based assessment) before closing. Posterior neck heals well; anterior neck — be alert for vascular/airway involvement.'
|
||
},
|
||
trunk: {
|
||
label: 'Trunk',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '4-0 or 3-0',
|
||
removalDays: '7–10',
|
||
glueOK: false,
|
||
glueNote: 'Glue not first-line for trunk; tension is too variable.',
|
||
techniqueDefault: 'Simple interrupted; deep dermal 4-0 absorbable for wounds >0.5 cm deep',
|
||
notes: 'Layered closure for any wound deeper than mid-dermis. Watch for through-and-through abdominal/chest injury; image if mechanism warrants.'
|
||
},
|
||
upper_ext: {
|
||
label: 'Upper extremity (arm / forearm)',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '4-0',
|
||
removalDays: '7–10',
|
||
glueOK: true,
|
||
glueNote: 'Glue OK for clean linear lacs ≤5 cm with low tension; not over joints.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Examine neurovascular function distally before and after repair.'
|
||
},
|
||
lower_ext: {
|
||
label: 'Lower extremity (thigh / leg)',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '4-0 or 3-0',
|
||
removalDays: '10–14',
|
||
glueOK: true,
|
||
glueNote: 'Glue OK for clean linear lacs ≤5 cm with low tension; not over joints; not on shin where tension is high.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Pre-tibial skin is thin and fragile — handle gently, avoid horizontal mattress. Leave in longer than upper extremity.'
|
||
},
|
||
hand: {
|
||
label: 'Hand / fingers',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '5-0',
|
||
removalDays: '10–14',
|
||
glueOK: false,
|
||
glueNote: 'Generally avoid glue on hand (high tension, frequent movement).',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Examine tendon function (extensor and flexor) and 2-point discrimination BEFORE local anesthetic. Image if mechanism suggests fracture or foreign body. Bite to hand → consider not closing.'
|
||
},
|
||
foot: {
|
||
label: 'Foot / toes',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '4-0 or 5-0',
|
||
removalDays: '10–14',
|
||
glueOK: false,
|
||
glueNote: 'Generally avoid glue on plantar surface.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Plantar punctures: high infection risk — irrigate, do not close primarily. Consider Pseudomonas coverage in shoe-puncture.'
|
||
},
|
||
joint_surface: {
|
||
label: 'Over a joint (knee, elbow, etc.)',
|
||
materialFamily: 'monofilament-nonabsorbable',
|
||
sutureSize: '4-0',
|
||
removalDays: '10–14',
|
||
glueOK: false,
|
||
glueNote: 'No glue across joint surfaces — repeated flexion separates the bond.',
|
||
techniqueDefault: 'Simple interrupted; consider vertical mattress for high tension',
|
||
notes: 'Splint joint in slight flexion for 5–7 d to reduce wound tension. Rule out joint capsule penetration (saline-load test if uncertain).'
|
||
},
|
||
genitalia: {
|
||
label: 'Genitalia / perineum',
|
||
materialFamily: 'absorbable-chromic-or-vicryl',
|
||
sutureSize: '5-0 or 4-0',
|
||
removalDays: null, // absorbable
|
||
glueOK: false,
|
||
glueNote: 'No glue on genitalia.',
|
||
techniqueDefault: 'Simple interrupted',
|
||
notes: 'Significant labial / scrotal / penile lacs — consider OR repair under sedation. Always consider non-accidental trauma evaluation in pediatric genital injuries.'
|
||
},
|
||
fingertip: {
|
||
label: 'Fingertip / nail bed',
|
||
materialFamily: 'absorbable-chromic-or-vicryl',
|
||
sutureSize: '6-0',
|
||
removalDays: null,
|
||
glueOK: false,
|
||
glueNote: 'No glue on nail bed.',
|
||
techniqueDefault: 'Simple interrupted with 6-0 absorbable for nail bed; replace and secure nail as a stent',
|
||
notes: 'Painful subungual hematoma — trephinate (especially if 25–50% or more of the nail), provided the nail is intact and there is no displaced distal-phalanx fracture. Open nail-bed lac → repair with absorbable, suture nail back as biologic dressing or use Coban. X-ray any crush mechanism (tuft fracture is common).'
|
||
}
|
||
};
|
||
|
||
// ── Recommendation engine ───────────────────────────────────────────
|
||
function recommend(input) {
|
||
var s = SITES[input.site];
|
||
if (!s) return null;
|
||
var notes = [];
|
||
var warnings = [];
|
||
|
||
// Closure decision (contamination + age of wound)
|
||
var closure = 'Primary closure';
|
||
if (input.contamination === 'heavy' || input.contamination === 'bite_other') {
|
||
closure = 'Consider DELAYED primary closure (cleanse, pack, reassess in 3–5 days) or healing by secondary intention';
|
||
warnings.push('Heavily contaminated wound — primary closure increases infection risk. Irrigate copiously before any closure decision.');
|
||
}
|
||
if (input.contamination === 'bite_human' || input.contamination === 'bite_cat') {
|
||
closure = 'Generally DO NOT close primarily';
|
||
warnings.push((input.contamination === 'bite_cat' ? 'Cat bite' : 'Human bite') + ' — leave open or use loose approximation. High infection risk (Pasteurella for cat, Eikenella for human). Irrigate, debride, give amox-clavulanate prophylaxis. Consider hand-surgery consult for hand bites.');
|
||
}
|
||
if (input.contamination === 'bite_dog' && input.site === 'hand') {
|
||
warnings.push('Dog bite to the hand — many EPs do not close primarily. If closing, loose approximation only.');
|
||
}
|
||
if (input.hours === '>12' && input.site !== 'face' && input.site !== 'scalp') {
|
||
closure = closure === 'Primary closure' ? 'Delayed primary closure (>12 h since injury, non-face/scalp)' : closure;
|
||
notes.push('>12 h since injury for a non-face/scalp wound — closure decision is judgment-based; clean linear wounds in well-perfused areas can still be closed.');
|
||
}
|
||
|
||
// Material — switch to absorbable for very young if non-mucosal default
|
||
var material = s.materialFamily;
|
||
if (s.materialFamily === 'monofilament-nonabsorbable' && (input.age === 'lt1' || input.age === '1to5')) {
|
||
if (input.removalAvoid === 'yes') {
|
||
material = 'fast-absorbing-gut';
|
||
notes.push('Young child — fast-absorbing gut suture (or Vicryl Rapide) avoids the trauma of suture removal. Slightly more reactive than nylon but cosmetic outcome at 3 months is similar in low-tension wounds.');
|
||
}
|
||
}
|
||
var materialDisplay = ({
|
||
'monofilament-nonabsorbable': 'Monofilament non-absorbable (nylon — Ethilon, OR polypropylene — Prolene)',
|
||
'absorbable-chromic-or-vicryl': 'Absorbable (chromic gut OR Vicryl / Vicryl Rapide)',
|
||
'fast-absorbing-gut': 'Fast-absorbing plain gut (or Vicryl Rapide) — no removal needed'
|
||
})[material];
|
||
|
||
// Size — bump up one for high tension, down one for cosmetic priority + low tension face
|
||
var size = s.sutureSize;
|
||
if (input.tension === 'high' && size === '4-0') size = '3-0';
|
||
if (input.tension === 'high' && size === '5-0') size = '4-0';
|
||
if (input.tension === 'high' && size === '6-0') size = '5-0';
|
||
if (input.cosmetic === 'yes' && input.tension === 'low' && size === '4-0') size = '5-0';
|
||
|
||
// Technique
|
||
var technique = s.techniqueDefault;
|
||
if (input.tension === 'high') technique = 'Vertical mattress (or simple interrupted with deep dermal absorbable layer first)';
|
||
if (input.cosmetic === 'yes' && input.tension === 'low' && (input.site === 'face' || input.site === 'eyelid_eyebrow')) {
|
||
technique = 'Simple interrupted; consider running subcuticular if skill permits — best cosmesis';
|
||
}
|
||
|
||
// Glue alternative (if applicable)
|
||
var glue = null;
|
||
if (s.glueOK && input.tension !== 'high' && input.contamination === 'clean') {
|
||
glue = s.glueNote;
|
||
}
|
||
|
||
// Removal day range (null when an absorbable material was selected)
|
||
var removal = s.removalDays;
|
||
if (material !== 'monofilament-nonabsorbable') removal = null;
|
||
|
||
// Tetanus
|
||
var tetanus = 'Confirm tetanus status. Tdap if last booster >5 y for tetanus-prone (contaminated, deep, crush, burn, bite); >10 y for clean wound. Add TIG if unimmunized or unknown immunization history with tetanus-prone wound.';
|
||
|
||
return {
|
||
site: s.label,
|
||
closure: closure,
|
||
material: materialDisplay,
|
||
size: size,
|
||
technique: technique,
|
||
glue: glue,
|
||
removalDays: removal,
|
||
notes: [s.notes].concat(notes),
|
||
warnings: warnings,
|
||
tetanus: tetanus
|
||
};
|
||
}
|
||
|
||
// ── Render ──────────────────────────────────────────────────────────
|
||
function readInput() {
|
||
return {
|
||
site: getVal('sut-site'),
|
||
age: getVal('sut-age'),
|
||
tension: getVal('sut-tension'),
|
||
cosmetic: getVal('sut-cosmetic'),
|
||
contamination: getVal('sut-contam'),
|
||
hours: getVal('sut-hours'),
|
||
removalAvoid: getVal('sut-removal-avoid')
|
||
};
|
||
}
|
||
function getVal(id) { var el = document.getElementById(id); return el ? el.value : ''; }
|
||
|
||
function render() {
|
||
var el = document.getElementById('sut-result');
|
||
if (!el) return;
|
||
var inp = readInput();
|
||
if (!inp.site) { el.innerHTML = '<p style="color:var(--g500);font-size:13px;">Select a site to see recommendation.</p>'; return; }
|
||
var r = recommend(inp);
|
||
if (!r) { el.innerHTML = '<p style="color:var(--red);font-size:13px;">Unknown site.</p>'; return; }
|
||
|
||
var html = '<div style="padding:10px 14px;border-radius:8px;background:#eef2ff;border:1.5px solid #6366f1;margin-bottom:10px;">' +
|
||
'<strong style="color:#4338ca;">Suture recommendation — ' + r.site + '</strong></div>';
|
||
|
||
html += '<div style="padding:12px;background:var(--g50);border-radius:6px;margin-bottom:10px;font-size:13px;line-height:1.6;">';
|
||
html += '<div><strong>Closure plan:</strong> ' + r.closure + '</div>';
|
||
html += '<div><strong>Material:</strong> ' + r.material + '</div>';
|
||
html += '<div><strong>Size:</strong> ' + r.size + '</div>';
|
||
html += '<div><strong>Technique:</strong> ' + r.technique + '</div>';
|
||
if (r.removalDays) html += '<div><strong>Suture removal:</strong> ' + r.removalDays + ' days</div>';
|
||
else html += '<div><strong>Suture removal:</strong> not required (absorbable)</div>';
|
||
html += '</div>';
|
||
|
||
if (r.glue) {
|
||
html += '<div style="padding:10px 12px;background:#ecfdf5;border-left:3px solid #10b981;border-radius:6px;margin-bottom:10px;font-size:13px;">' +
|
||
'<strong style="color:#047857;">Adhesive alternative:</strong> ' + r.glue + '</div>';
|
||
}
|
||
|
||
if (r.warnings.length) {
|
||
html += '<div style="padding:10px 12px;background:#fef2f2;border-left:3px solid #ef4444;border-radius:6px;margin-bottom:10px;font-size:13px;">' +
|
||
'<strong style="color:#dc2626;">Warning:</strong><ul style="margin:4px 0 0 18px;padding:0;">' +
|
||
r.warnings.map(function(w) { return '<li>' + w + '</li>'; }).join('') + '</ul></div>';
|
||
}
|
||
|
||
if (r.notes.length) {
|
||
html += '<div style="padding:10px 12px;background:#fffbeb;border-left:3px solid #f59e0b;border-radius:6px;margin-bottom:10px;font-size:13px;">' +
|
||
'<strong style="color:#92400e;">Site notes:</strong><ul style="margin:4px 0 0 18px;padding:0;">' +
|
||
r.notes.map(function(n) { return '<li>' + n + '</li>'; }).join('') + '</ul></div>';
|
||
}
|
||
|
||
html += '<div style="padding:10px 12px;background:var(--g50);border-radius:6px;font-size:12px;color:var(--g600);"><strong>Tetanus:</strong> ' + r.tetanus + '</div>';
|
||
|
||
html += S.ref('Roberts & Hedges Clinical Procedures in Emergency Medicine, 7e (2019), Ch. 36. Fleisher & Ludwig Pediatric Emergency Medicine, 8e (2021). AAP Section on Emergency Medicine — Pediatric laceration repair. UpToDate (Pope JV) — Skin laceration repair with sutures. Suggestions only — verify against your local protocol and the patient in front of you.');
|
||
|
||
el.innerHTML = html;
|
||
}
|
||
|
||
export function init() {
|
||
document.addEventListener('change', function(e) {
|
||
if (!e.target || !e.target.id) return;
|
||
if (e.target.id.indexOf('sut-') === 0) render();
|
||
});
|
||
document.addEventListener('click', function(e) {
|
||
var pill = e.target.closest && e.target.closest('[data-em="sutures"]');
|
||
if (pill) setTimeout(render, 0);
|
||
});
|
||
document.addEventListener('tabChanged', function() { setTimeout(render, 100); });
|
||
}
|