Phase 1 — Critical Fixes: - Fix SOAP instructions not clearing on Clear button - Show transcription provider (AWS/OpenAI) in UI toast - Fix silent transcription failures in dictation and SOAP modules - Add IndexedDB audio backup system (24hr retention, retry from Settings) - Prevent duplicate encounter saves with idempotency keys - Add Save/Load/New bar to SOAP note generator Phase 2 — Features: - Dragon-like AI memory: auto-track user corrections, inject into prompts - Per-section template categories (SOAP, HPI, well visit, sick visit) - Bigger textarea for SOAP instructions - S3 document upload/management (AWS S3, Backblaze B2, MinIO compatible) - Faster transcription via lower bitrate recording (16kbps opus) Phase 3 — APK & CI/CD: - GitHub Actions: Docker build+push on version tags - GitHub Actions: TWA APK build for Obtainium auto-updates - Android TWA project with foreground service for background recording - Enhanced PWA manifest with shortcuts and maskable icons
324 lines
14 KiB
HTML
324 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Pediatric AI Scribe</title>
|
|
<link rel="stylesheet" href="/css/styles.css">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="preconnect" href="https://cdnjs.cloudflare.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
|
|
<link rel="manifest" href="/manifest.json">
|
|
<meta name="theme-color" content="#2563eb">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<meta name="apple-mobile-web-app-title" content="PedScribe">
|
|
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
|
<link rel="icon" type="image/svg+xml" href="/icons/icon.svg">
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/icons/icon-32.png">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/icons/icon-16.png">
|
|
<link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192.png">
|
|
<link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512.png">
|
|
<!-- Auth screen hidden by default — auth.js shows it only when no valid session exists -->
|
|
<style>#auth-screen { display: none; }</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- AUTH SCREEN -->
|
|
<div id="auth-screen" class="auth-screen">
|
|
<div class="auth-box">
|
|
<div class="auth-logo">
|
|
<i class="fas fa-stethoscope"></i>
|
|
<h1>Pediatric AI Scribe</h1>
|
|
<p>AI-Powered Clinical Documentation</p>
|
|
</div>
|
|
|
|
<!-- Login Form -->
|
|
<form id="login-form" class="auth-form" autocomplete="off">
|
|
<h2>Sign In</h2>
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="login-email" required placeholder="your@email.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Password</label>
|
|
<input type="password" id="login-password" required placeholder="••••••••">
|
|
</div>
|
|
<div id="totp-group" class="form-group hidden">
|
|
<label>2FA Code</label>
|
|
<input type="text" id="login-totp" placeholder="6-digit code" maxlength="6">
|
|
</div>
|
|
<button type="submit" class="btn-auth" id="btn-local-login">Sign In</button>
|
|
<div id="sso-divider" class="hidden" style="display:none;text-align:center;margin:16px 0 12px;position:relative;">
|
|
<span style="background:white;padding:0 12px;color:#9ca3af;font-size:12px;position:relative;z-index:1;">or</span>
|
|
<hr style="border:none;border-top:1px solid #e5e7eb;position:absolute;top:50%;left:0;right:0;margin:0;">
|
|
</div>
|
|
<a href="/api/auth/oidc" id="btn-sso" class="btn-auth" style="display:none;text-align:center;text-decoration:none;background:linear-gradient(135deg,#0f172a,#334155);margin-top:0;">
|
|
<i class="fas fa-shield-halved"></i> <span id="sso-label">Sign in with SSO</span>
|
|
</a>
|
|
<div id="resend-verify-box" class="hidden" style="margin:12px 0;padding:12px;background:#fef3c7;border-radius:8px;text-align:center;">
|
|
<p style="margin:0 0 8px;font-size:13px;color:#92400e;">Your email is not verified yet.</p>
|
|
<a href="#" id="resend-verify-link" style="font-size:13px;font-weight:600;color:#2563eb;">Resend verification link</a>
|
|
</div>
|
|
<div class="auth-links">
|
|
<a href="#" id="show-register" style="display:none">Create account</a>
|
|
<a href="#" id="show-forgot">Forgot password?</a>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Register Form -->
|
|
<form id="register-form" class="auth-form hidden">
|
|
<h2>Create Account</h2>
|
|
<div class="form-group">
|
|
<label>Full Name</label>
|
|
<input type="text" id="reg-name" required placeholder="Dr. Jane Smith">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="reg-email" required placeholder="your@email.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Password (8+ characters)</label>
|
|
<input type="password" id="reg-password" required minlength="8" placeholder="••••••••">
|
|
</div>
|
|
<button type="submit" class="btn-auth">Create Account</button>
|
|
<div class="auth-links">
|
|
<a href="#" id="show-login">Back to sign in</a>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Forgot Password Form -->
|
|
<form id="forgot-form" class="auth-form hidden">
|
|
<h2>Reset Password</h2>
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="forgot-email" required placeholder="your@email.com">
|
|
</div>
|
|
<button type="submit" class="btn-auth">Send Reset Link</button>
|
|
<div class="auth-links">
|
|
<a href="#" id="show-login-2">Back to sign in</a>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="hipaa-notice">
|
|
<i class="fas fa-triangle-exclamation"></i>
|
|
<span>AWS Bedrock available with BAA for HIPAA compliance. Check with your institution's guidelines before use. Not intended for production clinical use without proper authorization.</span>
|
|
</div>
|
|
</div>
|
|
<footer class="app-footer">
|
|
Committed to healthcare equity — always consult a qualified healthcare professional for medical advice.
|
|
•
|
|
© <script>document.write(new Date().getFullYear())</script> Pediatric AI Scribe. All rights reserved.
|
|
</footer>
|
|
</div>
|
|
|
|
<!-- MAIN APP (hidden until authenticated) -->
|
|
<div id="main-app" class="hidden">
|
|
|
|
<!-- HEADER -->
|
|
<header class="app-header">
|
|
<div class="header-content">
|
|
<div class="header-top">
|
|
<div style="display:flex;align-items:center;gap:10px;">
|
|
<button id="btn-menu-toggle" class="btn-header btn-menu-toggle" title="Menu" aria-label="Toggle menu">
|
|
<i class="fas fa-bars"></i>
|
|
</button>
|
|
<div class="logo">
|
|
<i class="fas fa-stethoscope"></i>
|
|
<div>
|
|
<h1>Pediatric AI Scribe</h1>
|
|
<p class="tagline">Welcome, <span id="user-name">Doctor</span></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="header-right">
|
|
<div class="model-selector">
|
|
<label><i class="fas fa-robot"></i></label>
|
|
<select id="global-model-select"></select>
|
|
<span id="model-cost-badge" class="cost-badge"></span>
|
|
</div>
|
|
<div class="header-buttons">
|
|
<button id="btn-settings" class="btn-header" title="Settings">
|
|
<i class="fas fa-cog"></i>
|
|
</button>
|
|
<button id="btn-logout" class="btn-header" title="Logout">
|
|
<i class="fas fa-right-from-bracket"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- ANNOUNCEMENT BANNER -->
|
|
<div id="announcement-banner" class="announcement-banner hidden" role="alert">
|
|
<i id="announcement-icon" class="fas fa-info-circle"></i>
|
|
<span id="announcement-text"></span>
|
|
<button class="announcement-close" onclick="this.parentElement.classList.add('hidden')" aria-label="Dismiss"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
|
|
<div class="app-body">
|
|
|
|
<!-- SIDEBAR NAVIGATION -->
|
|
<nav class="sidebar" id="sidebar">
|
|
<div class="sidebar-header">
|
|
<span class="sidebar-title"><i class="fas fa-stethoscope"></i> Menu</span>
|
|
<button id="btn-sidebar-close" class="btn-sm btn-ghost" title="Close menu" style="padding:4px 8px;">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
<div class="sidebar-nav">
|
|
<span class="sidebar-section-label">Encounters</span>
|
|
<button class="tab-btn active" data-tab="encounter">
|
|
<i class="fas fa-comments"></i>
|
|
<span>Encounter HPI</span>
|
|
</button>
|
|
<button class="tab-btn" data-tab="dictation">
|
|
<i class="fas fa-microphone"></i>
|
|
<span>Dictation HPI</span>
|
|
</button>
|
|
<span class="sidebar-section-label">Notes</span>
|
|
<button class="tab-btn" data-tab="hospital">
|
|
<i class="fas fa-hospital"></i>
|
|
<span>Hospital Course</span>
|
|
</button>
|
|
<button class="tab-btn" data-tab="chart">
|
|
<i class="fas fa-clipboard-list"></i>
|
|
<span>Chart Review</span>
|
|
</button>
|
|
<button class="tab-btn" data-tab="soap">
|
|
<i class="fas fa-file-waveform"></i>
|
|
<span>SOAP Note</span>
|
|
</button>
|
|
<span class="sidebar-section-label">Pediatric</span>
|
|
<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>
|
|
</button>
|
|
<button class="tab-btn" data-tab="catchup">
|
|
<i class="fas fa-rotate"></i>
|
|
<span>Catch-Up Schedule</span>
|
|
</button>
|
|
<button class="tab-btn" data-tab="learning">
|
|
<i class="fas fa-graduation-cap"></i>
|
|
<span>Learning Hub</span>
|
|
</button>
|
|
<button class="tab-btn hidden" data-tab="cms" id="cms-tab-btn">
|
|
<i class="fas fa-pen-to-square"></i>
|
|
<span>Content Manager</span>
|
|
</button>
|
|
<span class="sidebar-section-label">Account</span>
|
|
<button class="tab-btn" data-tab="settings">
|
|
<i class="fas fa-cog"></i>
|
|
<span>Settings</span>
|
|
</button>
|
|
<button class="tab-btn hidden" data-tab="admin" id="admin-tab-btn">
|
|
<i class="fas fa-user-shield"></i>
|
|
<span>Admin</span>
|
|
</button>
|
|
</div>
|
|
<!-- Desktop collapse button (hidden on mobile) -->
|
|
<button id="btn-sidebar-pin" class="sidebar-pin-btn" title="Collapse sidebar">
|
|
<i class="fas fa-angles-left"></i>
|
|
</button>
|
|
</nav>
|
|
<!-- Desktop sidebar expand button (shown when sidebar is collapsed) -->
|
|
<button id="btn-sidebar-expand" class="sidebar-expand-btn" title="Expand sidebar" style="display:none;">
|
|
<i class="fas fa-angles-right"></i>
|
|
</button>
|
|
|
|
<div class="sidebar-overlay" id="sidebar-overlay"></div>
|
|
|
|
<main class="main-content">
|
|
|
|
|
|
<!-- Tab components (lazy-loaded from /components/*.html) -->
|
|
<section id="encounter-tab" class="tab-content active" data-component="encounter"></section>
|
|
<section id="dictation-tab" class="tab-content" data-component="dictation"></section>
|
|
<section id="hospital-tab" class="tab-content" data-component="hospital"></section>
|
|
<section id="chart-tab" class="tab-content" data-component="chart"></section>
|
|
<section id="soap-tab" class="tab-content" data-component="soap"></section>
|
|
<section id="vaxschedule-tab" class="tab-content" data-component="vaxschedule"></section>
|
|
<section id="catchup-tab" class="tab-content" data-component="catchup"></section>
|
|
<section id="learning-tab" class="tab-content" data-component="learning"></section>
|
|
<section id="cms-tab" class="tab-content" data-component="cms"></section>
|
|
<section id="admin-tab" class="tab-content" data-component="admin"></section>
|
|
<section id="wellvisit-tab" class="tab-content" data-component="wellvisit"></section>
|
|
<section id="sickvisit-tab" class="tab-content" data-component="sickvisit"></section>
|
|
<section id="settings-tab" class="tab-content" data-component="settings"></section>
|
|
|
|
</main>
|
|
|
|
</div><!-- /.app-body -->
|
|
|
|
|
|
<!-- dummy settings-modal kept for any stale JS references -->
|
|
<div id="settings-modal" class="hidden" style="display:none !important;"></div>
|
|
|
|
</div>
|
|
|
|
<!-- LOADING -->
|
|
<div id="loading-overlay" class="loading-overlay hidden">
|
|
<div class="loading-box"><div class="spinner"></div><p id="loading-text">Processing...</p></div>
|
|
</div>
|
|
|
|
<!-- TOAST -->
|
|
<div id="toast-container" class="toast-container"></div>
|
|
|
|
<!-- SLIDE PREVIEW MODAL -->
|
|
<div id="slide-preview-modal" class="slide-preview-modal hidden" role="dialog" aria-modal="true">
|
|
<div class="slide-preview-overlay" id="slide-preview-overlay"></div>
|
|
<div class="slide-preview-shell">
|
|
<div class="slide-preview-topbar">
|
|
<span class="slide-preview-counter" id="slide-preview-counter">1 / 1</span>
|
|
<span style="font-size:13px;color:rgba(255,255,255,0.6);">Use arrow keys or swipe to navigate</span>
|
|
<button class="slide-preview-close" id="slide-preview-close" aria-label="Close preview">✕ Close</button>
|
|
</div>
|
|
<div class="slide-preview-stage" id="slide-preview-stage">
|
|
<button class="slide-nav-btn slide-nav-prev" id="slide-nav-prev" aria-label="Previous slide">‹</button>
|
|
<div class="slide-preview-frame" id="slide-preview-frame">
|
|
<style id="slide-preview-css"></style>
|
|
<div id="slide-preview-content"></div>
|
|
</div>
|
|
<button class="slide-nav-btn slide-nav-next" id="slide-nav-next" aria-label="Next slide">›</button>
|
|
</div>
|
|
<div class="slide-preview-dots" id="slide-preview-dots"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- SCRIPTS (defer for faster initial paint) -->
|
|
<script src="/vendor/tiptap.bundle.js"></script>
|
|
<script defer src="/js/milestonesData.js"></script>
|
|
<script defer src="/js/pediatricScheduleData.js"></script>
|
|
<script defer src="/js/audioBackup.js"></script>
|
|
<script defer src="/js/correctionTracker.js"></script>
|
|
<script defer src="/js/app.js"></script>
|
|
<script defer src="/js/auth.js"></script>
|
|
<script defer src="/js/liveEncounter.js"></script>
|
|
<script defer src="/js/voiceDictation.js"></script>
|
|
<script defer src="/js/hospitalCourse.js"></script>
|
|
<script defer src="/js/chartReview.js"></script>
|
|
<script defer src="/js/soap.js"></script>
|
|
<script defer src="/js/milestones.js"></script>
|
|
<script defer src="/js/nextcloud.js"></script>
|
|
<script defer src="/js/wellVisit.js"></script>
|
|
<script defer src="/js/shadess.js"></script>
|
|
<script defer src="/js/sickVisit.js"></script>
|
|
<script defer src="/js/encounters.js"></script>
|
|
<script defer src="/js/memories.js"></script>
|
|
<script defer src="/js/documents.js"></script>
|
|
<script defer src="/js/learningHub.js"></script>
|
|
<script defer src="/js/admin.js"></script>
|
|
|
|
</body>
|
|
</html>
|