231 lines
10 KiB
Cheetah
231 lines
10 KiB
Cheetah
{{define "input"}}
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<title>Add Health Data — inou</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="/static/style.css">
|
|
<link rel="stylesheet" href="/static/input.css">
|
|
</head>
|
|
<body>
|
|
<div class="input-container">
|
|
<!-- Header -->
|
|
<header class="input-header">
|
|
<h1>What's on your mind?</h1>
|
|
<p class="input-subtitle">Add symptoms, notes, or scan documents</p>
|
|
</header>
|
|
|
|
<!-- Segmented Control -->
|
|
<div class="segment-control">
|
|
<button class="segment-btn active" data-mode="type">
|
|
<svg class="segment-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M17 3a2.85 2.85 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/>
|
|
</svg>
|
|
<span>Type</span>
|
|
</button>
|
|
<button class="segment-btn" data-mode="speak">
|
|
<svg class="segment-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
|
|
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
|
|
<line x1="12" y1="19" x2="12" y2="23"/>
|
|
<line x1="8" y1="23" x2="16" y2="23"/>
|
|
</svg>
|
|
<span>Speak</span>
|
|
</button>
|
|
<button class="segment-btn" data-mode="scan">
|
|
<svg class="segment-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M3 7V5a2 2 0 0 1 2-2h2"/>
|
|
<path d="M17 3h2a2 2 0 0 1 2 2v2"/>
|
|
<path d="M21 17v2a2 2 0 0 1-2 2h-2"/>
|
|
<path d="M7 21H5a2 2 0 0 1-2-2v-2"/>
|
|
<line x1="7" y1="12" x2="17" y2="12"/>
|
|
</svg>
|
|
<span>Scan</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Mode Panels -->
|
|
<div class="mode-panels">
|
|
<!-- Type Panel -->
|
|
<div class="mode-panel active" data-panel="type">
|
|
<div class="text-input-wrap">
|
|
<textarea
|
|
id="text-input"
|
|
class="text-input"
|
|
placeholder="Describe your symptoms, how you're feeling, or any health notes..."
|
|
rows="4"
|
|
></textarea>
|
|
<div class="text-input-footer">
|
|
<span class="char-count"><span id="char-count">0</span> characters</span>
|
|
<div class="input-hints">
|
|
<span class="hint-tag">symptoms</span>
|
|
<span class="hint-tag">mood</span>
|
|
<span class="hint-tag">medication</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Speak Panel -->
|
|
<div class="mode-panel" data-panel="speak">
|
|
<div class="voice-container">
|
|
<button id="mic-btn" class="mic-btn" aria-label="Start recording">
|
|
<svg class="mic-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
|
|
<path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
|
|
<line x1="12" y1="19" x2="12" y2="23"/>
|
|
<line x1="8" y1="23" x2="16" y2="23"/>
|
|
</svg>
|
|
<div class="mic-pulse"></div>
|
|
</button>
|
|
<p class="mic-status" id="mic-status">Tap to start speaking</p>
|
|
<div class="transcript-area" id="transcript-area">
|
|
<p class="transcript-text" id="transcript-text"></p>
|
|
<p class="transcript-interim" id="transcript-interim"></p>
|
|
</div>
|
|
<div class="voice-unsupported" id="voice-unsupported" style="display: none;">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="32" height="32">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
<line x1="12" y1="16" x2="12.01" y2="16"/>
|
|
</svg>
|
|
<p>Voice input isn't supported in this browser.</p>
|
|
<p class="voice-fallback-hint">Try Chrome, Safari, or Edge on desktop/mobile.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scan Panel -->
|
|
<div class="mode-panel" data-panel="scan">
|
|
<div class="camera-container" id="camera-container">
|
|
<!-- Camera not started state -->
|
|
<div class="camera-start" id="camera-start">
|
|
<button class="camera-start-btn" id="start-camera-btn">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="48" height="48">
|
|
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/>
|
|
<circle cx="12" cy="13" r="4"/>
|
|
</svg>
|
|
<span>Open Camera</span>
|
|
</button>
|
|
<p class="camera-hint">Scan medication barcodes, lab results, or medical documents</p>
|
|
</div>
|
|
|
|
<!-- Camera viewfinder -->
|
|
<div class="camera-viewfinder" id="camera-viewfinder" style="display: none;">
|
|
<video id="camera-video" autoplay playsinline muted></video>
|
|
<div class="viewfinder-overlay">
|
|
<div class="viewfinder-frame"></div>
|
|
</div>
|
|
<div class="camera-controls">
|
|
<button class="camera-ctrl-btn" id="switch-camera-btn" aria-label="Switch camera">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/>
|
|
<path d="M7 13l3 3 7-7"/>
|
|
</svg>
|
|
</button>
|
|
<button class="capture-btn" id="capture-btn" aria-label="Capture photo">
|
|
<div class="capture-btn-inner"></div>
|
|
</button>
|
|
<button class="camera-ctrl-btn" id="close-camera-btn" aria-label="Close camera">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<line x1="18" y1="6" x2="6" y2="18"/>
|
|
<line x1="6" y1="6" x2="18" y2="18"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Photo preview -->
|
|
<div class="photo-preview" id="photo-preview" style="display: none;">
|
|
<img id="preview-img" src="" alt="Captured photo">
|
|
<div class="preview-actions">
|
|
<button class="btn btn-secondary" id="retake-btn">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18">
|
|
<path d="M23 4v6h-6"/>
|
|
<path d="M1 20v-6h6"/>
|
|
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
|
|
</svg>
|
|
Retake
|
|
</button>
|
|
<button class="btn btn-primary" id="process-btn">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18">
|
|
<polyline points="9 11 12 14 22 4"/>
|
|
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/>
|
|
</svg>
|
|
Extract Text
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scan result (barcode or OCR text) -->
|
|
<div class="ocr-result" id="ocr-result" style="display: none;">
|
|
<div class="ocr-header">
|
|
<!-- Header content is dynamically set by JS based on result type -->
|
|
<div class="result-type-badge text">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
<polyline points="14 2 14 8 20 8"/>
|
|
<line x1="16" y1="13" x2="8" y2="13"/>
|
|
<line x1="16" y1="17" x2="8" y2="17"/>
|
|
</svg>
|
|
Extracted Text
|
|
</div>
|
|
<button class="btn-icon" id="ocr-edit-btn" aria-label="Edit">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18">
|
|
<path d="M17 3a2.85 2.85 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<div class="ocr-text" id="ocr-text" contenteditable="false"></div>
|
|
<div class="ocr-actions">
|
|
<button class="btn btn-secondary" id="scan-another-btn">Scan Another</button>
|
|
<button class="btn btn-primary" id="use-ocr-btn">Use This</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Processing state -->
|
|
<div class="ocr-processing" id="ocr-processing" style="display: none;">
|
|
<div class="processing-spinner"></div>
|
|
<p>Scanning for barcode...</p>
|
|
</div>
|
|
|
|
<!-- Camera error -->
|
|
<div class="camera-error" id="camera-error" style="display: none;">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="48" height="48">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
<line x1="12" y1="16" x2="12.01" y2="16"/>
|
|
</svg>
|
|
<p id="camera-error-msg">Camera access denied</p>
|
|
<button class="btn btn-secondary" id="retry-camera-btn">Try Again</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Submit Section -->
|
|
<div class="submit-section">
|
|
<button class="btn btn-primary btn-full submit-btn" id="submit-btn" disabled>
|
|
<span class="submit-text">Add Entry</span>
|
|
<svg class="submit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<line x1="22" y1="2" x2="11" y2="13"/>
|
|
<polygon points="22 2 15 22 11 13 2 9 22 2"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Hidden canvas for photo capture -->
|
|
<canvas id="capture-canvas" style="display: none;"></canvas>
|
|
</div>
|
|
|
|
<script src="/static/input.js"></script>
|
|
</body>
|
|
</html>
|
|
{{end}}
|