backnforth/index.html
2025-11-24 19:22:10 +10:00

266 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bilataral Stimulation Simulator Admin</title>
<style>
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 0; background: #f7f7f7; color: #111; }
header { padding: 16px 20px; background: #222; color: #fff; display: flex; align-items: center; justify-content: space-between; }
header h1 { font-size: 18px; margin: 0; }
main { display: grid; grid-template-columns: 380px 1fr; gap: 16px; padding: 16px; }
.panel { background: #fff; border: 1px solid #ddd; border-radius: 8px; padding: 12px; }
.panel h2 { font-size: 14px; margin: 0 0 8px; color: #333; }
.row { display: flex; gap: 10px; align-items: center; margin: 8px 0; flex-wrap: wrap; }
.row label { font-size: 13px; color: #333; }
.controls button { padding: 8px 10px; border: 1px solid #ccc; border-radius: 6px; background: #fafafa; cursor: pointer; }
.controls button.active { background: #1f6feb; color: #fff; border-color: #1f6feb; box-shadow: 0 0 0 2px rgba(31,111,235,0.4) inset; }
#easingControls button.active { background: #1f6feb; color: #fff; border-color: #1f6feb; box-shadow: 0 0 0 2px rgba(31,111,235,0.4) inset; }
.controls input[type="range"] { width: 180px; }
.preview { display: flex; align-items: center; justify-content: center; height: 220px; background: #000; border-radius: 8px; overflow: hidden; }
.preview { width: 360px; margin: 0 auto; }
.previewContainer { justify-content: flex-start; }
.previewCanvas { display: block; margin: 0; }
.footer { display: flex; gap: 8px; }
.footer button { padding: 10px 12px; border: none; border-radius: 6px; cursor: pointer; }
.footer .primary { background: #1f6feb; color: #fff; }
.footer .danger { background: #b31d1d; color: #fff; }
.primary { background: #2da44e; color: #fff; border: none; padding: 12px 18px; border-radius: 8px; font-weight: 600; }
.danger { background: #d1242f; color: #fff; border: none; padding: 12px 18px; border-radius: 8px; font-weight: 600; }
#patientControls .danger { background: transparent; color: #d1242f; border: 1px solid #d1242f; padding: 6px 10px; border-radius: 6px; font-weight: 500; }
.metrics { display: flex; gap: 12px; font-size: 13px; color: #444; }
.small { font-size: 12px; color: #666; display: inline-block; min-width: 60px; }
.field { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.field label { min-width: 90px; }
#speed { width: 360px; }
</style>
</head>
<body>
<header>
<h1>BILATERAL STIMULATION SIMULATOR</h1>
<div>
<button id="openPatient">Open Patient View</button>
</div>
</header>
<main>
<section class="panel">
<h2>Session Controls</h2>
<div class="row controls" id="shapeControls">
<label>Shape:</label>
<button data-shape="circle" class="active">Circle</button>
<button data-shape="square">Square</button>
<button data-shape="triangle">Triangle</button>
</div>
<div class="row">
<label>Shape Color:</label>
<input type="color" id="shapeColor" value="#00ff88">
<div id="shapePreset" class="controls">
<button data-color="#00ff00" style="background:#00ff00;color:#000">Green</button>
<button data-color="#0066ff" style="background:#0066ff;color:#fff">Blue</button>
<button data-color="#ffd400" style="background:#ffd400;color:#000">Yellow</button>
<button data-color="#ff2a2a" style="background:#ff2a2a;color:#fff">Red</button>
<button data-color="#ffffff" style="background:#ffffff;color:#000">White</button>
</div>
</div>
<div class="row">
<label>Background:</label>
<input type="color" id="bgColor" value="#000000">
<div id="bgPreset" class="controls">
<button data-color="#00ff00" style="background:#00ff00;color:#000">Green</button>
<button data-color="#0066ff" style="background:#0066ff;color:#fff">Blue</button>
<button data-color="#ffd400" style="background:#ffd400;color:#000">Yellow</button>
<button data-color="#ff2a2a" style="background:#ff2a2a;color:#fff">Red</button>
<button data-color="#ffffff" style="background:#ffffff;color:#000">White</button>
</div>
</div>
<div class="row controls" id="directionControls">
<label>Direction:</label>
<button data-direction="lr" class="active">Left ↔ Right</button>
<button data-direction="ud">Up ↕ Down</button>
<button data-direction="diag_down">Diagonal ↘︎</button>
<button data-direction="diag_up">Diagonal ↗︎</button>
</div>
<div class="row">
<label>Size:</label>
<input type="range" id="size" min="10" max="100" step="2" value="28">
<span id="sizeLabel" class="small">28 px</span>
</div>
<div class="row">
<label>Vertical Position:</label>
<input type="range" id="yPercent" min="0" max="100" step="1" value="50">
<span id="yPercentLabel" class="small">50%</span>
<button id="yReset">Reset</button>
</div>
<div class="row">
<label>Glow Pulse:</label>
<label class="small"><input type="checkbox" id="glowEnable"> Enable</label>
<div class="field">
<label>Glow Radius:</label>
<input type="range" id="glowIntensity" min="0" max="200" step="5" value="100">
<span id="glowIntensityLabel" class="small">100%</span>
</div>
<div class="field">
<label>Glow Rate:</label>
<input type="range" id="glowRate" min="0.1" max="3" step="0.1" value="0.5">
<span id="glowRateLabel" class="small">0.5 Hz</span>
</div>
</div>
<div class="row">
<label>Ramp Speed:</label>
<label class="small"><input type="checkbox" id="rampEnable"> Enable</label>
<input type="range" id="rampSeconds" min="1" max="60" step="1" value="10">
<span id="rampLabel" class="small">10 s</span>
</div>
<div class="row controls" id="easingControls">
<label>Smoothness:</label>
<button data-easing="linear" class="active">Linear</button>
<button data-easing="ease">Ease In-Out</button>
</div>
<div class="row">
<label>Edge Pause:</label>
<input type="range" id="edgePause" min="0" max="150" step="10" value="0">
<span id="edgePauseLabel" class="small">0 ms</span>
</div>
<div class="row">
<label>Wiggle:</label>
<label class="small"><input type="checkbox" id="wiggleEnable"> Enable</label>
<input type="range" id="wiggleAmplitude" min="0" max="10" step="1" value="0">
<span id="wiggleLabel" class="small">0 px</span>
</div>
<div class="row" id="presetControls">
<label>Presets:</label>
<div class="field">
<label>Name:</label>
<input type="text" id="presetName" placeholder="My Preset" style="width:160px">
<button id="savePreset">Save</button>
</div>
<div class="field">
<label>Apply:</label>
<select id="presetList"></select>
<button id="applyPreset">Apply</button>
<button id="deletePreset">Delete</button>
</div>
<div class="field">
<label>Import/Export:</label>
<button id="exportPresets">Export JSON</button>
<button id="importPresets">Import JSON</button>
</div>
</div>
<div class="row" id="audioControls">
<label>Audio:</label>
<select id="audioMode">
<option value="programmatic">Programmatic</option>
<option value="file">From Files</option>
<option value="off">Off</option>
</select>
<label class="small"><input type="checkbox" id="audioEnable"> Enable</label>
<button id="testSound">Test Sound</button>
<div id="programmaticControls" class="row">
<div class="field">
<label>Preset:</label>
<select id="programPreset">
<option value="pink">Pink Noise</option>
<option value="hybrid">Hybrid (noise + edge cues)</option>
<option value="click">Click</option>
<option value="ping">Ping</option>
<option value="woodblock">Woodblock</option>
<option value="bell">Bell</option>
<option value="bass">Bass</option>
<option value="kick">Kick</option>
<option value="snare">Snare</option>
<option value="hihat">Hi-Hat</option>
<option value="sweep">Sweep</option>
<option value="zap">Zap</option>
<option value="bubble">Bubble</option>
</select>
</div>
<label class="small"><input type="checkbox" id="syncPan" checked> Pan sync to movement</label>
<div class="field">
<label>Pan Rate:</label>
<input type="range" id="panRate" min="0.1" max="2" step="0.1" value="0.5">
<span id="panRateLabel" class="small">0.5 Hz</span>
</div>
<div class="field">
<label>Cue Rate:</label>
<input type="range" id="cueRate" min="0.1" max="3" step="0.1" value="1.2">
<span id="cueRateLabel" class="small">1.2 Hz</span>
</div>
<div class="field">
<label>Volume:</label>
<input type="range" id="volume" min="0" max="100" step="5" value="60">
<span id="volumeLabel" class="small">60%</span>
</div>
</div>
<div id="fileControls" class="row">
<button id="pickAudioFolder">Choose Folder</button>
<select id="audioSelect"><option value="">No audio</option></select>
</div>
</div>
<div class="row" id="deviceControls">
<label>Controller:</label>
<button id="connectHID">Connect HID Device</button>
<span id="deviceStatus" class="small">Not connected</span>
<label>Sensitivity:</label>
<input type="range" id="knobSens" min="1" max="50" step="1" value="5">
<span id="knobSensLabel" class="small">x5</span>
</div>
</section>
<section class="panel">
<h2>Preview</h2>
<div class="preview previewContainer" id="previewContainer">
<canvas class="previewCanvas" id="previewCanvas" width="640" height="360"></canvas>
</div>
<div class="row">
<label>Speed:</label>
<input type="range" id="speed" min="50" max="600" step="10" value="250">
<span id="speedLabel" class="small">250 px/s</span>
</div>
<div class="row controls" id="speedBoost">
<label>Speed Boost:</label>
<button data-mult="1" class="active">1×</button>
<button data-mult="2">2×</button>
<button data-mult="3">3×</button>
<button data-mult="4">4×</button>
</div>
<div class="row">
<label>Timer (minutes):</label>
<input type="number" id="timerMinutes" min="0" value="10" style="width:80px">
<span id="timerDisplay" class="small">10:00</span>
</div>
<div class="row">
<button class="primary" id="startSession">Start Session</button>
<button class="danger" id="endSession">End Session</button>
</div>
<div class="metrics">
<div>Status: <span id="statusText">Idle</span></div>
<div>Elapsed: <span id="elapsedText">00:00</span></div>
</div>
<div class="row" id="patientControls">
<label>Patient:</label>
<input type="text" id="patientName" placeholder="Patient Name" style="width:180px">
<button id="savePatient">Save Patient</button>
<select id="patientList" style="min-width:160px"></select>
<button id="loadPatient">Load Patient</button>
<button id="clearSessions">Clear Sessions</button>
<button id="deletePatient" class="danger">Delete Patient</button>
<span class="small">Sessions: <span id="sessionCount">0</span></span>
<span class="small">Last: <span id="lastSessionInfo"></span></span>
</div>
<div class="row" id="patientHistory">
<label>Session History:</label>
<div id="sessionHistory" class="small" style="max-height:160px; overflow:auto; flex:1"></div>
</div>
<div class="small">This preview mirrors the patient's view.</div>
</section>
</main>
<script src="js/bls.js"></script>
<script src="js/audio.js"></script>
<script src="js/admin.js"></script>
</body>
</html>