Feat: v2.7 — sidebar UX, well visit subtabs, larger boxes, sick visit reorder
- Remove duplicate milestones sidebar button; well visit button now works correctly - Move Sick Visit sidebar entry to just below Well Visit (before Vaccine/Catch-Up) - Sick Visit remains its own standalone tab (not a subtab) - Well Visit subtabs: By Visit Age | Milestones | SSHADESS (12+) | Visit Note - Dramatically larger transcript boxes (min-height 240px, max-height 600px) - Dramatically larger note output boxes (min-height 480px) — beautiful scrollable - Collapsible desktop sidebar with localStorage persistence - Update README with full feature list - Bump docker-compose to v2.7
This commit is contained in:
parent
78730a669f
commit
38d07ff37f
4 changed files with 103 additions and 99 deletions
|
|
@ -9,12 +9,19 @@ AI-powered clinical documentation platform for pediatric medicine. Generates HPI
|
|||
- **Hospital Course Generator** — paste progress notes, AI generates prose, day-by-day, organ-system (ICU), or psych format summaries
|
||||
- **Chart Review / Precharting** — summarize outpatient, subspecialty, and ED notes into a precharting brief
|
||||
- **SOAP Note Generator** — full SOAP or subjective-only from dictation
|
||||
- **Developmental Milestones** — AAP/Nelson milestone tracker with narrative, structured list, or 3-sentence summary output
|
||||
- **Well Visit / Preventive Care** — AAP 2025 Bright Futures periodicity; vaccines, screenings, billing codes; By Visit Age, Milestones, SSHADESS (12+), and Visit Note subtabs
|
||||
- **Sick Visit Note** — quick documentation with auto-suggested ROS and PE systems from chief complaint
|
||||
- **Developmental Milestones** — AAP/Nelson milestone tracker (birth–11 years) with narrative, structured list, or 3-sentence summary; copy to Visit Note
|
||||
- **SSHADESS Assessment** — adolescent psychosocial screening for ages 12+; auto-fills into Visit Note
|
||||
- **Vaccine Schedule** — full AAP immunization schedule reference
|
||||
- **Catch-Up Schedule** — catch-up immunization guide
|
||||
- **Plain text output** — all documents generated without markdown, ready to paste into any EHR
|
||||
- **Read Aloud** — browser TTS reads generated documents; ElevenLabs (Adam voice) supported
|
||||
- **Copy & Export** — one-click copy or export to Nextcloud
|
||||
- **Refine & Shorten** — edit any document with plain-language AI instructions
|
||||
- **Per-tab model selector** — choose fast vs. smart vs. reasoning models per task
|
||||
- **Collapsible sidebar** — desktop sidebar collapses to icon rail, state persisted
|
||||
- **Save & Resume** — encounters saved with unique IDs; persist across page refresh
|
||||
- **Admin Panel** — user management, registration control, audit logs
|
||||
- **2FA** — TOTP-based two-factor authentication
|
||||
- **Multi-provider AI** — OpenRouter, AWS Bedrock, or Azure OpenAI
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
services:
|
||||
pediatric-scribe:
|
||||
image: danielonyejesi/pediatric-ai-scribe-v3:v2.6
|
||||
image: danielonyejesi/pediatric-ai-scribe-v3:v2.7
|
||||
ports:
|
||||
- "3552:3000"
|
||||
env_file:
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
|
|||
.card-header h3{font-size:13px;font-weight:600;color:var(--g700);display:flex;align-items:center;gap:6px;}
|
||||
|
||||
/* EDITABLE BOX */
|
||||
.editable-box{min-height:100px;max-height:280px;overflow-y:auto;padding:12px 16px;font-size:13px;line-height:1.8;outline:none;}
|
||||
.editable-box{min-height:240px;max-height:600px;overflow-y:auto;padding:14px 18px;font-size:13px;line-height:1.8;outline:none;border-radius:0 0 var(--radius) var(--radius);}
|
||||
.editable-box:empty::before{content:attr(data-placeholder);color:var(--g400);}
|
||||
|
||||
/* NOTE ENTRY (hospital course, chart review) */
|
||||
|
|
@ -148,7 +148,7 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
|
|||
.output-card.hidden{display:none;}
|
||||
.output-header{background:var(--green-light);border-bottom-color:var(--green);}
|
||||
.output-actions{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
|
||||
.output-text{padding:16px;font-size:13px;line-height:1.8;outline:none;min-height:80px;white-space:pre-wrap;}
|
||||
.output-text{padding:20px 24px;font-size:13px;line-height:1.9;outline:none;min-height:480px;white-space:pre-wrap;overflow-y:auto;}
|
||||
.model-tag{font-size:10px;padding:2px 7px;background:var(--g200);border-radius:4px;color:var(--g600);}
|
||||
|
||||
/* REFINE BAR */
|
||||
|
|
|
|||
|
|
@ -174,14 +174,14 @@
|
|||
<span>SOAP Note</span>
|
||||
</button>
|
||||
<span class="sidebar-section-label">Pediatric</span>
|
||||
<button class="tab-btn" data-tab="wellvisit" data-subtab="milestones">
|
||||
<i class="fas fa-baby"></i>
|
||||
<span>Milestones</span>
|
||||
</button>
|
||||
<button class="tab-btn" data-tab="wellvisit">
|
||||
<i class="fas fa-calendar-check"></i>
|
||||
<span>Well Visit</span>
|
||||
</button>
|
||||
<button class="tab-btn" data-tab="sickvisit">
|
||||
<i class="fas fa-thermometer-half"></i>
|
||||
<span>Sick Visit</span>
|
||||
</button>
|
||||
<button class="tab-btn" data-tab="vaxschedule">
|
||||
<i class="fas fa-table"></i>
|
||||
<span>Vaccine Schedule</span>
|
||||
|
|
@ -190,10 +190,6 @@
|
|||
<i class="fas fa-rotate"></i>
|
||||
<span>Catch-Up Schedule</span>
|
||||
</button>
|
||||
<button class="tab-btn" data-tab="sickvisit">
|
||||
<i class="fas fa-thermometer-half"></i>
|
||||
<span>Sick Visit</span>
|
||||
</button>
|
||||
<span class="sidebar-section-label">Account</span>
|
||||
<button class="tab-btn" data-tab="settings">
|
||||
<i class="fas fa-cog"></i>
|
||||
|
|
@ -1273,107 +1269,108 @@
|
|||
<p>Quick sick visit documentation with auto-suggested ROS and PE systems</p>
|
||||
</div>
|
||||
|
||||
<!-- Save/Load bar -->
|
||||
<div class="save-bar-wrap">
|
||||
<div class="save-bar" id="sick-save-bar">
|
||||
<div style="display:flex;align-items:center;gap:8px;flex:1;">
|
||||
<i class="fas fa-tag" style="color:var(--g400);font-size:13px;"></i>
|
||||
<input type="text" id="sick-label" class="save-label-input" placeholder="Patient label (e.g. John D, 5y fever)">
|
||||
<!-- Save/Load bar -->
|
||||
<div class="save-bar-wrap">
|
||||
<div class="save-bar" id="sick-save-bar">
|
||||
<div style="display:flex;align-items:center;gap:8px;flex:1;">
|
||||
<i class="fas fa-tag" style="color:var(--g400);font-size:13px;"></i>
|
||||
<input type="text" id="sick-label" class="save-label-input" placeholder="Patient label (e.g. John D, 5y fever)">
|
||||
</div>
|
||||
<button id="btn-sick-save" class="btn-sm btn-ghost"><i class="fas fa-floppy-disk"></i> Save</button>
|
||||
<button id="btn-sick-load" class="btn-sm btn-ghost"><i class="fas fa-folder-open"></i> Load</button>
|
||||
<button id="btn-sick-new" class="btn-sm btn-ghost" title="Clear and start new patient" style="color:var(--red);"><i class="fas fa-rotate-left"></i> New</button>
|
||||
</div>
|
||||
<button id="btn-sick-save" class="btn-sm btn-ghost"><i class="fas fa-floppy-disk"></i> Save</button>
|
||||
<button id="btn-sick-load" class="btn-sm btn-ghost"><i class="fas fa-folder-open"></i> Load</button>
|
||||
<button id="btn-sick-new" class="btn-sm btn-ghost" title="Clear and start new patient" style="color:var(--red);"><i class="fas fa-rotate-left"></i> New</button>
|
||||
</div>
|
||||
<div id="sick-load-popover" class="enc-load-popover hidden">
|
||||
<div class="enc-load-popover-inner">
|
||||
<input type="text" id="sick-load-search" class="enc-load-search" placeholder="Search saved encounters...">
|
||||
<button class="enc-pop-close btn-sm btn-ghost"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
<div id="sick-pop-list" class="enc-pop-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Demographics -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header"><h3><i class="fas fa-user"></i> Patient Info</h3></div>
|
||||
<div style="padding:12px 16px;display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;">
|
||||
<div class="demo-field"><label>Age</label><input type="text" id="sick-age" placeholder="e.g., 5 years" style="width:110px;"></div>
|
||||
<div class="demo-field"><label>Gender</label><select id="sick-gender"><option value="">Select</option><option>Male</option><option>Female</option><option>Non-binary/Other</option></select></div>
|
||||
<div class="demo-field" style="flex:1;min-width:200px;"><label>Chief Complaint</label><input type="text" id="sick-cc" placeholder="e.g., fever, ear pain, cough" style="width:100%;"></div>
|
||||
<div class="demo-field demo-field-model"><label><i class="fas fa-robot"></i> Model</label><select id="sick-model-select" class="tab-model-select"></select></div>
|
||||
<button id="btn-sick-infer" class="btn-sm btn-primary" style="align-self:flex-end;"><i class="fas fa-wand-magic-sparkles"></i> Update ROS/PE</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recording -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-microphone"></i> Encounter Recording / Dictation</h3>
|
||||
<div style="display:flex;gap:6px;align-items:center;">
|
||||
<button id="sick-record-btn" class="btn-sm btn-ghost"><i class="fas fa-microphone"></i> Listen In</button>
|
||||
<button id="sick-pause-btn" class="btn-sm btn-ghost hidden"><i class="fas fa-pause"></i> Pause</button>
|
||||
<div id="sick-rec-indicator" class="recording-indicator hidden" style="font-size:12px;"><div class="pulse-dot"></div><span>Recording... <span id="sick-timer">00:00</span></span></div>
|
||||
<div id="sick-load-popover" class="enc-load-popover hidden">
|
||||
<div class="enc-load-popover-inner">
|
||||
<input type="text" id="sick-load-search" class="enc-load-search" placeholder="Search saved encounters...">
|
||||
<button class="enc-pop-close btn-sm btn-ghost"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
<div id="sick-pop-list" class="enc-pop-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:8px 16px;">
|
||||
<div id="sick-transcript" class="editable-box" contenteditable="true" style="min-height:80px;" data-placeholder="Transcript appears here. Physician can dictate the HPI and encounter details."></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ROS (4 systems auto-inferred) -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
|
||||
<h3><i class="fas fa-list-check"></i> Review of Systems</h3>
|
||||
<div style="display:flex;gap:6px;align-items:center;">
|
||||
<button id="sick-ros-all-wnl" class="btn-sm btn-ghost" style="font-size:11px;"><i class="fas fa-check-double"></i> All WNL</button>
|
||||
<select id="sick-ros-add" class="btn-sm" style="font-size:11px;padding:3px 6px;border:1px solid var(--g300);border-radius:6px;">
|
||||
<option value="">+ Add system</option>
|
||||
</select>
|
||||
<!-- Demographics -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header"><h3><i class="fas fa-user"></i> Patient Info</h3></div>
|
||||
<div style="padding:12px 16px;display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;">
|
||||
<div class="demo-field"><label>Age</label><input type="text" id="sick-age" placeholder="e.g., 5 years" style="width:110px;"></div>
|
||||
<div class="demo-field"><label>Gender</label><select id="sick-gender"><option value="">Select</option><option>Male</option><option>Female</option><option>Non-binary/Other</option></select></div>
|
||||
<div class="demo-field" style="flex:1;min-width:200px;"><label>Chief Complaint</label><input type="text" id="sick-cc" placeholder="e.g., fever, ear pain, cough" style="width:100%;"></div>
|
||||
<div class="demo-field demo-field-model"><label><i class="fas fa-robot"></i> Model</label><select id="sick-model-select" class="tab-model-select"></select></div>
|
||||
<button id="btn-sick-infer" class="btn-sm btn-primary" style="align-self:flex-end;"><i class="fas fa-wand-magic-sparkles"></i> Update ROS/PE</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sick-ros-container" style="padding:8px 16px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- PE (7 systems auto-inferred) -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
|
||||
<h3><i class="fas fa-stethoscope"></i> Physical Examination</h3>
|
||||
<div style="display:flex;gap:6px;align-items:center;">
|
||||
<button id="sick-pe-all-normal" class="btn-sm btn-ghost" style="font-size:11px;"><i class="fas fa-check-double"></i> All Normal</button>
|
||||
<select id="sick-pe-add" class="btn-sm" style="font-size:11px;padding:3px 6px;border:1px solid var(--g300);border-radius:6px;">
|
||||
<option value="">+ Add system</option>
|
||||
</select>
|
||||
<!-- Recording -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-microphone"></i> Encounter Recording / Dictation</h3>
|
||||
<div style="display:flex;gap:6px;align-items:center;">
|
||||
<button id="sick-record-btn" class="btn-sm btn-ghost"><i class="fas fa-microphone"></i> Listen In</button>
|
||||
<button id="sick-pause-btn" class="btn-sm btn-ghost hidden"><i class="fas fa-pause"></i> Pause</button>
|
||||
<div id="sick-rec-indicator" class="recording-indicator hidden" style="font-size:12px;"><div class="pulse-dot"></div><span>Recording... <span id="sick-timer">00:00</span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:8px 16px;">
|
||||
<div id="sick-transcript" class="editable-box" contenteditable="true" data-placeholder="Transcript appears here. Physician can dictate the HPI and encounter details."></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sick-pe-container" style="padding:8px 16px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Diagnoses -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header"><h3><i class="fas fa-tag"></i> Diagnoses (ICD-10)</h3></div>
|
||||
<div id="sick-dx-container" style="padding:12px 16px;"></div>
|
||||
</div>
|
||||
<!-- ROS (4 systems auto-inferred) -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
|
||||
<h3><i class="fas fa-list-check"></i> Review of Systems</h3>
|
||||
<div style="display:flex;gap:6px;align-items:center;">
|
||||
<button id="sick-ros-all-wnl" class="btn-sm btn-ghost" style="font-size:11px;"><i class="fas fa-check-double"></i> All WNL</button>
|
||||
<select id="sick-ros-add" class="btn-sm" style="font-size:11px;padding:3px 6px;border:1px solid var(--g300);border-radius:6px;">
|
||||
<option value="">+ Add system</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sick-ros-container" style="padding:8px 16px;"></div>
|
||||
</div>
|
||||
|
||||
<button id="btn-sick-generate" class="btn-generate"><i class="fas fa-wand-magic-sparkles"></i> Generate Sick Visit Note</button>
|
||||
<!-- PE (7 systems auto-inferred) -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
|
||||
<h3><i class="fas fa-stethoscope"></i> Physical Examination</h3>
|
||||
<div style="display:flex;gap:6px;align-items:center;">
|
||||
<button id="sick-pe-all-normal" class="btn-sm btn-ghost" style="font-size:11px;"><i class="fas fa-check-double"></i> All Normal</button>
|
||||
<select id="sick-pe-add" class="btn-sm" style="font-size:11px;padding:3px 6px;border:1px solid var(--g300);border-radius:6px;">
|
||||
<option value="">+ Add system</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sick-pe-container" style="padding:8px 16px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- Output -->
|
||||
<div id="sick-note-output" class="card output-card hidden">
|
||||
<div class="card-header output-header">
|
||||
<h3><i class="fas fa-file-medical"></i> Sick Visit Note</h3>
|
||||
<div class="output-actions">
|
||||
<span id="sick-note-model-tag" class="model-tag"></span>
|
||||
<button class="btn-sm btn-ghost" id="btn-sick-new-patient"><i class="fas fa-rotate-left"></i> New Patient</button>
|
||||
<button class="btn-sm btn-primary" onclick="copyText('sick-note-text')"><i class="fas fa-copy"></i> Copy</button>
|
||||
<button class="btn-sm btn-ghost" onclick="speakText('sick-note-text')"><i class="fas fa-volume-high"></i> Read</button>
|
||||
<!-- Diagnoses -->
|
||||
<div class="card" style="margin-bottom:10px;">
|
||||
<div class="card-header"><h3><i class="fas fa-tag"></i> Diagnoses (ICD-10)</h3></div>
|
||||
<div id="sick-dx-container" style="padding:12px 16px;"></div>
|
||||
</div>
|
||||
|
||||
<button id="btn-sick-generate" class="btn-generate"><i class="fas fa-wand-magic-sparkles"></i> Generate Sick Visit Note</button>
|
||||
|
||||
<!-- Output -->
|
||||
<div id="sick-note-output" class="card output-card hidden">
|
||||
<div class="card-header output-header">
|
||||
<h3><i class="fas fa-file-medical"></i> Sick Visit Note</h3>
|
||||
<div class="output-actions">
|
||||
<span id="sick-note-model-tag" class="model-tag"></span>
|
||||
<button class="btn-sm btn-ghost" id="btn-sick-new-patient"><i class="fas fa-rotate-left"></i> New Patient</button>
|
||||
<button class="btn-sm btn-primary" onclick="copyText('sick-note-text')"><i class="fas fa-copy"></i> Copy</button>
|
||||
<button class="btn-sm btn-ghost" onclick="speakText('sick-note-text')"><i class="fas fa-volume-high"></i> Read</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sick-note-text" class="output-text" contenteditable="true"></div>
|
||||
<div class="refine-bar">
|
||||
<input type="text" id="sick-refine-input" class="refine-input" placeholder="Tell AI to modify (e.g., 'add that patient received amoxicillin')">
|
||||
<button class="btn-sm btn-primary" id="sick-refine-btn"><i class="fas fa-edit"></i> Refine</button>
|
||||
<button class="btn-sm btn-ghost" id="sick-shorten-btn"><i class="fas fa-compress"></i> Shorter</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sick-note-text" class="output-text" contenteditable="true"></div>
|
||||
<div class="refine-bar">
|
||||
<input type="text" id="sick-refine-input" class="refine-input" placeholder="Tell AI to modify (e.g., 'add that patient received amoxicillin')">
|
||||
<button class="btn-sm btn-primary" id="sick-refine-btn"><i class="fas fa-edit"></i> Refine</button>
|
||||
<button class="btn-sm btn-ghost" id="sick-shorten-btn"><i class="fas fa-compress"></i> Shorter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- ===== TAB: SETTINGS ===== -->
|
||||
|
|
|
|||
Loading…
Reference in a new issue