inou/templates/input.tmpl

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}}