screeing-tool / index.html
dineshcce's picture
You are an expert AI web developer and UI/UX designer. I want you to create a **fully-featured, mobile-first NeuroScreen web app** for smartphones that is low-cost, ultra-lightweight, and ideal for rural or low-resource areas. Generate **complete HTML, CSS, and JavaScript** with a modern, clean, and user-friendly design. Include comments for each section and placeholders for AI integration via serverless functions.
8302fb5 verified
<!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">
<title>NeuroScreen</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<style>
/* Custom CSS for animations and specific components */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.pulse-animation {
animation: pulse 2s infinite;
}
.waveform {
background: linear-gradient(90deg, #3b82f6 0%, #3b82f6 var(--progress, 0%), #e5e7eb var(--progress, 0%), #e5e7eb 100%);
}
.dot-follow {
transition: all 0.3s ease-out;
}
.test-card {
transition: all 0.2s ease;
}
.test-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
/* Hide scrollbar but keep functionality */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>
</head>
<body class="bg-gray-50 font-sans text-gray-800 min-h-screen">
<!-- Main App Container -->
<div id="app" class="max-w-md mx-auto bg-white min-h-screen shadow-lg overflow-hidden flex flex-col">
<!-- Header -->
<header class="bg-gradient-to-r from-blue-500 to-purple-600 text-white p-4 shadow-md">
<div class="flex items-center justify-between">
<h1 class="text-2xl font-bold flex items-center">
<i data-feather="activity" class="mr-2"></i>
NeuroScreen
</h1>
<button id="menu-btn" class="p-2 rounded-full hover:bg-white/10">
<i data-feather="menu"></i>
</button>
</div>
</header>
<!-- Main Content Area - Will be dynamically updated -->
<main id="content" class="flex-1 overflow-y-auto no-scrollbar p-4">
<!-- Home Screen (default view) -->
<div id="home-screen">
<div class="mb-6">
<h2 class="text-xl font-semibold mb-2">Welcome to NeuroScreen</h2>
<p class="text-gray-600 mb-4">A simple neurological screening tool for early detection of potential issues.</p>
<div class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-4">
<p class="text-blue-700">For best results: Find a quiet space, ensure good lighting, and complete all tests.</p>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Cognitive Test Card -->
<div class="test-card bg-white rounded-lg shadow p-4 border border-gray-200 cursor-pointer" onclick="showScreen('cognitive')">
<div class="text-blue-500 mb-2">
<i data-feather="cpu" class="w-8 h-8"></i>
</div>
<h3 class="font-medium mb-1">Cognitive Test</h3>
<p class="text-sm text-gray-500">Memory & reaction time</p>
</div>
<!-- Speech Test Card -->
<div class="test-card bg-white rounded-lg shadow p-4 border border-gray-200 cursor-pointer" onclick="showScreen('speech')">
<div class="text-purple-500 mb-2">
<i data-feather="mic" class="w-8 h-8"></i>
</div>
<h3 class="font-medium mb-1">Speech Test</h3>
<p class="text-sm text-gray-500">Voice analysis</p>
</div>
<!-- Eye Tracking Card -->
<div class="test-card bg-white rounded-lg shadow p-4 border border-gray-200 cursor-pointer" onclick="showScreen('eye')">
<div class="text-green-500 mb-2">
<i data-feather="eye" class="w-8 h-8"></i>
</div>
<h3 class="font-medium mb-1">Eye Tracking</h3>
<p class="text-sm text-gray-500">Visual attention</p>
</div>
<!-- Tremor Test Card -->
<div class="test-card bg-white rounded-lg shadow p-4 border border-gray-200 cursor-pointer" onclick="showScreen('tremor')">
<div class="text-yellow-500 mb-2">
<i data-feather="wind" class="w-8 h-8"></i>
</div>
<h3 class="font-medium mb-1">Tremor Test</h3>
<p class="text-sm text-gray-500">Movement analysis</p>
</div>
</div>
<!-- Results Button -->
<button onclick="showScreen('results')" class="w-full mt-6 bg-gradient-to-r from-blue-500 to-purple-600 text-white py-3 px-4 rounded-lg shadow hover:shadow-md transition-all flex items-center justify-center">
<i data-feather="clipboard" class="mr-2"></i>
View Results
</button>
</div>
<!-- Cognitive Test Screen -->
<div id="cognitive-screen" class="hidden">
<div class="flex items-center mb-4">
<button onclick="showScreen('home')" class="p-2 rounded-full hover:bg-gray-100 mr-2">
<i data-feather="arrow-left"></i>
</button>
<h2 class="text-xl font-semibold">Cognitive Test</h2>
</div>
<div class="bg-gray-100 rounded-lg p-4 mb-4">
<div class="flex justify-between mb-2">
<span class="text-sm font-medium">Test Progress</span>
<span class="text-sm">1/2</span>
</div>
<div class="w-full bg-gray-300 rounded-full h-2">
<div class="bg-blue-500 h-2 rounded-full" style="width: 50%"></div>
</div>
</div>
<!-- Memory Test -->
<div id="memory-test" class="mb-6">
<h3 class="font-medium mb-2">Memory Recall</h3>
<p class="text-gray-600 mb-4">Remember the sequence of numbers shown below:</p>
<div id="memory-display" class="bg-blue-50 rounded-lg p-6 text-center mb-4">
<p class="text-4xl font-bold text-blue-600">3 7 2 5</p>
</div>
<div class="grid grid-cols-3 gap-2 mb-4">
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">1</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">2</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">3</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">4</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">5</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">6</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">7</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">8</button>
<button class="bg-gray-200 hover:bg-gray-300 p-4 rounded-lg font-medium">9</button>
</div>
<button id="memory-submit" class="w-full bg-blue-500 text-white py-2 px-4 rounded-lg hover:bg-blue-600">
Submit Sequence
</button>
</div>
<!-- Reaction Test -->
<div id="reaction-test" class="hidden">
<h3 class="font-medium mb-2">Reaction Time</h3>
<p class="text-gray-600 mb-4">Tap the button when it turns green:</p>
<div id="reaction-box" class="bg-red-500 h-40 rounded-lg flex items-center justify-center mb-4 cursor-pointer">
<p class="text-white font-bold">Wait for green...</p>
</div>
<div class="flex justify-between items-center">
<span class="text-sm text-gray-600">Reaction time: <span id="reaction-time">0</span>ms</span>
<button id="reaction-start" class="bg-blue-500 text-white py-2 px-4 rounded-lg hover:bg-blue-600">
Start Test
</button>
</div>
</div>
<!-- AI Analysis Placeholder -->
<div id="cognitive-analysis" class="hidden mt-6 p-4 bg-gray-50 rounded-lg border border-gray-200">
<h3 class="font-medium mb-2 flex items-center">
<i data-feather="activity" class="mr-2 text-blue-500"></i>
Analysis Results
</h3>
<p id="cognitive-feedback" class="text-gray-700 mb-2">Processing cognitive test results...</p>
<div class="text-right">
<button onclick="analyzeCognitiveTest()" class="text-blue-500 text-sm hover:underline">
<i data-feather="refresh-cw" class="w-4 h-4 inline mr-1"></i>
Re-analyze
</button>
</div>
</div>
</div>
<!-- Speech Test Screen -->
<div id="speech-screen" class="hidden">
<div class="flex items-center mb-4">
<button onclick="showScreen('home')" class="p-2 rounded-full hover:bg-gray-100 mr-2">
<i data-feather="arrow-left"></i>
</button>
<h2 class="text-xl font-semibold">Speech Test</h2>
</div>
<div class="bg-gray-100 rounded-lg p-4 mb-4">
<p class="text-gray-700 mb-2">Read the following sentence aloud:</p>
<div class="bg-white p-4 rounded border border-gray-200 mb-4">
<p class="text-lg font-medium">"The quick brown fox jumps over the lazy dog."</p>
</div>
</div>
<!-- Recording UI -->
<div class="mb-6">
<div id="waveform" class="waveform h-16 rounded-lg mb-4" style="--progress: 0%"></div>
<div class="flex justify-center">
<button id="record-btn" class="bg-red-500 text-white p-4 rounded-full hover:bg-red-600 flex items-center justify-center">
<i data-feather="mic" class="w-6 h-6"></i>
</button>
</div>
<p id="record-status" class="text-center text-gray-600 mt-2">Press and hold to record</p>
</div>
<!-- AI Analysis Placeholder -->
<div id="speech-analysis" class="hidden p-4 bg-gray-50 rounded-lg border border-gray-200">
<h3 class="font-medium mb-2 flex items-center">
<i data-feather="activity" class="mr-2 text-purple-500"></i>
Speech Analysis
</h3>
<p id="speech-feedback" class="text-gray-700 mb-2">No recording analyzed yet.</p>
<div class="text-right">
<button onclick="analyzeSpeech()" class="text-purple-500 text-sm hover:underline">
<i data-feather="refresh-cw" class="w-4 h-4 inline mr-1"></i>
Analyze Recording
</button>
</div>
</div>
</div>
<!-- Eye Tracking Test Screen -->
<div id="eye-screen" class="hidden">
<div class="flex items-center mb-4">
<button onclick="showScreen('home')" class="p-2 rounded-full hover:bg-gray-100 mr-2">
<i data-feather="arrow-left"></i>
</button>
<h2 class="text-xl font-semibold">Eye Tracking Test</h2>
</div>
<div class="bg-gray-100 rounded-lg p-4 mb-4">
<p class="text-gray-700 mb-2">Follow the dot with your eyes. Keep your head still.</p>
</div>
<!-- Camera Feed -->
<div class="relative bg-black rounded-lg overflow-hidden mb-4" style="height: 300px;">
<video id="eye-video" autoplay playsinline class="w-full h-full object-cover"></video>
<div id="eye-dot" class="dot-follow absolute w-8 h-8 bg-red-500 rounded-full" style="top: 50%; left: 50%; transform: translate(-50%, -50%);"></div>
<div class="absolute inset-0 flex items-center justify-center" id="eye-instructions">
<p class="text-white bg-black/50 p-4 rounded-lg">Allow camera access to begin</p>
</div>
</div>
<div class="grid grid-cols-2 gap-2 mb-4">
<button id="start-eye-test" class="bg-green-500 text-white py-2 px-4 rounded-lg hover:bg-green-600">
Start Test
</button>
<button id="stop-eye-test" class="bg-gray-300 text-gray-700 py-2 px-4 rounded-lg hover:bg-gray-400">
Stop Test
</button>
</div>
<!-- AI Analysis Placeholder -->
<div id="eye-analysis" class="hidden p-4 bg-gray-50 rounded-lg border border-gray-200">
<h3 class="font-medium mb-2 flex items-center">
<i data-feather="activity" class="mr-2 text-green-500"></i>
Eye Tracking Analysis
</h3>
<p id="eye-feedback" class="text-gray-700 mb-2">No test data to analyze.</p>
<div class="text-right">
<button onclick="analyzeEyeTracking()" class="text-green-500 text-sm hover:underline">
<i data-feather="refresh-cw" class="w-4 h-4 inline mr-1"></i>
Analyze Results
</button>
</div>
</div>
</div>
<!-- Tremor Test Screen -->
<div id="tremor-screen" class="hidden">
<div class="flex items-center mb-4">
<button onclick="showScreen('home')" class="p-2 rounded-full hover:bg-gray-100 mr-2">
<i data-feather="arrow-left"></i>
</button>
<h2 class="text-xl font-semibold">Tremor Test</h2>
</div>
<div class="bg-gray-100 rounded-lg p-4 mb-4">
<p class="text-gray-700 mb-2">Hold your device steady for 15 seconds to detect tremors.</p>
</div>
<!-- Visual Guide -->
<div class="bg-blue-50 rounded-lg p-6 text-center mb-4">
<div class="relative mx-auto w-32 h-48 border-4 border-gray-300 rounded-lg mb-4">
<div class="absolute inset-0 flex items-center justify-center">
<div class="w-16 h-16 bg-yellow-400 rounded-full flex items-center justify-center">
<i data-feather="smartphone" class="text-white"></i>
</div>
</div>
</div>
<p class="text-gray-700">Hold your phone like this</p>
</div>
<!-- Test Controls -->
<div class="mb-6">
<div id="tremor-visual" class="bg-white border border-gray-200 rounded-lg p-4 mb-4 h-32 flex items-center justify-center">
<p id="tremor-status" class="text-gray-600">Ready to begin test</p>
</div>
<button id="start-tremor-test" class="w-full bg-yellow-500 text-white py-3 px-4 rounded-lg hover:bg-yellow-600">
Start Tremor Test
</button>
</div>
<!-- AI Analysis Placeholder -->
<div id="tremor-analysis" class="hidden p-4 bg-gray-50 rounded-lg border border-gray-200">
<h3 class="font-medium mb-2 flex items-center">
<i data-feather="activity" class="mr-2 text-yellow-500"></i>
Tremor Analysis
</h3>
<p id="tremor-feedback" class="text-gray-700 mb-2">No test data to analyze.</p>
<div class="text-right">
<button onclick="analyzeTremor()" class="text-yellow-500 text-sm hover:underline">
<i data-feather="refresh-cw" class="w-4 h-4 inline mr-1"></i>
Analyze Results
</button>
</div>
</div>
</div>
<!-- Results Screen -->
<div id="results-screen" class="hidden">
<div class="flex items-center mb-4">
<button onclick="showScreen('home')" class="p-2 rounded-full hover:bg-gray-100 mr-2">
<i data-feather="arrow-left"></i>
</button>
<h2 class="text-xl font-semibold">Test Results</h2>
</div>
<!-- Summary Card -->
<div class="bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg p-4 mb-6">
<div class="flex items-center justify-between mb-2">
<h3 class="font-medium">Overall Assessment</h3>
<span id="overall-status" class="bg-white text-blue-600 px-3 py-1 rounded-full text-sm font-medium">Pending</span>
</div>
<p id="overall-feedback" class="text-sm">Complete all tests for a full assessment.</p>
</div>
<!-- Test Results -->
<div class="space-y-4">
<!-- Cognitive Results -->
<div class="bg-white rounded-lg shadow p-4 border border-gray-200">
<div class="flex items-center justify-between mb-2">
<h3 class="font-medium flex items-center">
<i data-feather="cpu" class="mr-2 text-blue-500"></i>
Cognitive Test
</h3>
<span id="cognitive-status" class="text-sm px-3 py-1 rounded-full bg-gray-100">Not taken</span>
</div>
<p id="cognitive-result" class="text-sm text-gray-600">No data available</p>
</div>
<!-- Speech Results -->
<div class="bg-white rounded-lg shadow p-4 border border-gray-200">
<div class="flex items-center justify-between mb-2">
<h3 class="font-medium flex items-center">
<i data-feather="mic" class="mr-2 text-purple-500"></i>
Speech Test
</h3>
<span id="speech-status" class="text-sm px-3 py-1 rounded-full bg-gray-100">Not taken</span>
</div>
<p id="speech-result" class="text-sm text-gray-600">No data available</p>
</div>
<!-- Eye Tracking Results -->
<div class="bg-white rounded-lg shadow p-4 border border-gray-200">
<div class="flex items-center justify-between mb-2">
<h3 class="font-medium flex items-center">
<i data-feather="eye" class="mr-2 text-green-500"></i>
Eye Tracking
</h3>
<span id="eye-status" class="text-sm px-3 py-1 rounded-full bg-gray-100">Not taken</span>
</div>
<p id="eye-result" class="text-sm text-gray-600">No data available</p>
</div>
<!-- Tremor Results -->
<div class="bg-white rounded-lg shadow p-4 border border-gray-200">
<div class="flex items-center justify-between mb-2">
<h3 class="font-medium flex items-center">
<i data-feather="wind" class="mr-2 text-yellow-500"></i>
Tremor Test
</h3>
<span id="tremor-status-result" class="text-sm px-3 py-1 rounded-full bg-gray-100">Not taken</span>
</div>
<p id="tremor-result" class="text-sm text-gray-600">No data available</p>
</div>
</div>
<!-- Actions -->
<div class="mt-6 grid grid-cols-2 gap-2">
<button onclick="saveResults()" class="bg-gray-200 text-gray-700 py-2 px-4 rounded-lg hover:bg-gray-300 flex items-center justify-center">
<i data-feather="save" class="mr-2"></i>
Save
</button>
<button onclick="shareResults()" class="bg-blue-500 text-white py-2 px-4 rounded-lg hover:bg-blue-600 flex items-center justify-center">
<i data-feather="share-2" class="mr-2"></i>
Share
</button>
</div>
</div>
</main>
<!-- Footer Navigation -->
<footer class="bg-white border-t border-gray-200 p-2">
<div class="flex justify-around">
<button onclick="showScreen('home')" class="p-2 rounded-full hover:bg-gray-100 text-gray-700">
<i data-feather="home"></i>
</button>
<button onclick="showScreen('cognitive')" class="p-2 rounded-full hover:bg-gray-100 text-gray-700">
<i data-feather="cpu"></i>
</button>
<button onclick="showScreen('speech')" class="p-2 rounded-full hover:bg-gray-100 text-gray-700">
<i data-feather="mic"></i>
</button>
<button onclick="showScreen('results')" class="p-2 rounded-full hover:bg-gray-100 text-gray-700">
<i data-feather="clipboard"></i>
</button>
</div>
</footer>
</div>
<script>
// Initialize Feather Icons
feather.replace();
// Global state object to store test results
const testResults = {
cognitive: null,
speech: null,
eye: null,
tremor: null
};
// Screen navigation function
function showScreen(screenId) {
// Hide all screens
document.querySelectorAll('[id$="-screen"]').forEach(screen => {
screen.classList.add('hidden');
});
// Show requested screen
document.getElementById(`${screenId}-screen`).classList.remove('hidden');
// Special cases for screens that need initialization
if (screenId === 'eye') {
initializeEyeTest();
}
// Update results display if showing results screen
if (screenId === 'results') {
updateResultsDisplay();
}
}
// Cognitive Test Logic
document.addEventListener('DOMContentLoaded', () => {
// Memory test
const memorySubmit = document.getElementById('memory-submit');
memorySubmit.addEventListener('click', () => {
// In a real app, we'd check the sequence
document.getElementById('memory-test').classList.add('hidden');
document.getElementById('reaction-test').classList.remove('hidden');
// Update progress bar
document.querySelector('#cognitive-screen .bg-blue-500').style.width = '100%';
document.querySelector('#cognitive-screen .text-sm:last-child').textContent = '2/2';
// Store dummy result
testResults.cognitive = {
memory: { score: 0.75, feedback: "Good recall of 3 out of 4 numbers" },
reaction: null
};
});
// Reaction test
const reactionBox = document.getElementById('reaction-box');
const reactionStart = document.getElementById('reaction-start');
let reactionStartTime;
reactionStart.addEventListener('click', () => {
reactionStart.classList.add('hidden');
reactionBox.textContent = '';
reactionBox.classList.remove('bg-red-500');
reactionBox.classList.add('bg-gray-500');
// Random delay before turning green (1-3 seconds)
const delay = 1000 + Math.random() * 2000;
setTimeout(() => {
reactionBox.classList.remove('bg-gray-500');
reactionBox.classList.add('bg-green-500');
reactionStartTime = Date.now();
}, delay);
});
reactionBox.addEventListener('click', function() {
if (this.classList.contains('bg-green-500')) {
const reactionTime = Date.now() - reactionStartTime;
document.getElementById('reaction-time').textContent = reactionTime;
// Store result
testResults.cognitive.reaction = {
time: reactionTime,
feedback: reactionTime < 300 ? "Excellent reaction time" :
reactionTime < 600 ? "Normal reaction time" : "Slow reaction time"
};
// Show analysis section
document.getElementById('cognitive-analysis').classList.remove('hidden');
analyzeCognitiveTest();
}
});
});
// Speech Test Logic
let mediaRecorder;
let audioChunks = [];
document.getElementById('record-btn').addEventListener('mousedown', startRecording);
document.getElementById('record-btn').addEventListener('touchstart', startRecording);
document.getElementById('record-btn').addEventListener('mouseup', stopRecording);
document.getElementById('record-btn').addEventListener('touchend', stopRecording);
function startRecording() {
document.getElementById('record-status').textContent = "Recording...";
document.getElementById('record-btn').classList.add('pulse-animation');
// In a real app, we'd initialize the MediaRecorder here
// This is a placeholder for the actual implementation
simulateWaveform();
}
function stopRecording() {
document.getElementById('record-status').textContent = "Recording complete";
document.getElementById('record-btn').classList.remove('pulse-animation');
// Stop the waveform simulation
clearInterval(window.waveformInterval);
// Show analysis section
document.getElementById('speech-analysis').classList.remove('hidden');
// Store dummy result
testResults.speech = {
recording: "placeholder-audio-data",
analyzed: false
};
}
function simulateWaveform() {
let progress = 0;
window.waveformInterval = setInterval(() => {
progress = (progress + 5) % 100;
document.getElementById('waveform').style.setProperty('--progress', progress);
}, 100);
}
// Eye Tracking Test Logic
function initializeEyeTest() {
const video = document.getElementById('eye-video');
const startBtn = document.getElementById('start-eye-test');
const stopBtn = document.getElementById('stop-eye-test');
const instructions = document.getElementById('eye-instructions');
startBtn.addEventListener('click', async () => {
try {
// Request camera access
const stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'user',
width: 640,
height: 480
}
});
video.srcObject = stream;
instructions.classList.add('hidden');
startEyeTrackingTest();
} catch (err) {
instructions.textContent = "Camera access denied. Please enable camera permissions.";
console.error("Error accessing camera:", err);
}
});
stopBtn.addEventListener('click', () => {
if (video.srcObject) {
video.srcObject.getTracks().forEach(track => track.stop());
video.srcObject = null;
instructions.classList.remove('hidden');
instructions.textContent = "Test stopped. You can start again.";
// Store dummy result
testResults.eye = {
trackingData: "placeholder-eye-data",
analyzed: false
};
// Show analysis section
document.getElementById('eye-analysis').classList.remove('hidden');
}
});
}
function startEyeTrackingTest() {
const dot = document.getElementById('eye-dot');
let pos = 0;
const positions = [
{ top: '20%', left: '20%' },
{ top: '20%', left: '80%' },
{ top: '80%', left: '80%' },
{ top: '80%', left: '20%' },
{ top: '50%', left: '50%' }
];
let moveInterval = setInterval(() => {
dot.style.top = positions[pos].top;
dot.style.left = positions[pos].left;
pos = (pos + 1) % positions.length;
}, 2000);
// In a real app, we'd track eye movement here
}
// Tremor Test Logic
document.getElementById('start-tremor-test').addEventListener('click', function() {
const tremorVisual = document.getElementById('tremor-visual');
const tremorStatus = document.getElementById('tremor-status');
this.disabled = true;
this.textContent = "Testing...";
tremorStatus.textContent = "Hold steady...";
// Create a visual representation of movement
let movement = 0;
let movementInterval = setInterval(() => {
movement += Math.random() * 4 - 2; // Random movement between -2 and 2
tremorVisual.style.backgroundPosition = `${50 + movement}% 50%`;
// Add some background pattern to visualize movement
tremorVisual.style.backgroundImage = `
radial-gradient(circle at ${50 + movement}% 50%,
rgba(255, 200, 0, 0.3) 0%,
rgba(255, 200, 0, 0) 70%)
`;
}, 100);
// Stop after 15 seconds
setTimeout(() => {
clearInterval(movementInterval);
this.disabled = false;
this.textContent = "Start Tremor Test";
tremorStatus.textContent = "Test complete";
tremorVisual.style.backgroundImage = '';
tremorVisual.style.backgroundPosition = '';
// Store dummy result
testResults.tremor = {
movementData: "placeholder-tremor-data",
analyzed: false
};
// Show analysis section
document.getElementById('tremor-analysis').classList.remove('hidden');
}, 15000);
});
// AI Analysis Placeholder Functions
function analyzeCognitiveTest() {
const feedback = document.getElementById('cognitive-feedback');
feedback.innerHTML = "Analysis complete:<br><br>" +
"• Memory recall: 3/4 items correct (expected for age)<br>" +
"• Reaction time: 420ms (slightly above average)<br>" +
"<br>No significant cognitive impairments detected.";
testResults.cognitive.analyzed = true;
updateResultsDisplay();
}
function analyzeSpeech() {
const feedback = document.getElementById('speech-feedback');
feedback.textContent = "Speech analysis complete. No irregularities detected in articulation or fluency.";
testResults.speech.analyzed = true;
updateResultsDisplay();
}
function analyzeEyeTracking() {
const feedback = document.getElementById('eye-feedback');
feedback.textContent = "Eye tracking patterns appear normal with appropriate saccades and smooth pursuit movements.";
testResults.eye.analyzed = true;
updateResultsDisplay();
}
function analyzeTremor() {
const feedback = document.getElementById('tremor-feedback');
feedback.textContent = "Minimal tremor detected (0.8 Hz, 1.2mm amplitude) - within normal limits for resting tremor.";
testResults.tremor.analyzed = true;
updateResultsDisplay();
}
// Results Display
function updateResultsDisplay() {
// Cognitive results
if (testResults.cognitive) {
document.getElementById('cognitive-status').textContent = testResults.cognitive.analyzed ? "Completed" : "Partial";
document.getElementById('cognitive-status').className = testResults.cognitive.analyzed ?
"text-sm px-3 py-1 rounded-full bg-green-100 text-green-800" :
"text-sm px-3 py-1 rounded-full bg-yellow-100 text-yellow-800";
if (testResults.cognitive.analyzed) {
document.getElementById('cognitive-result').textContent = "Normal memory and reaction time";
} else if (testResults.cognitive.memory) {
document.getElementById('cognitive-result').textContent = "Memory test completed";
} else {
document.getElementById('cognitive-result').textContent = "Not taken";
}
}
// Speech results
if (testResults.speech) {
document.getElementById('speech-status').textContent = testResults.speech.analyzed ? "Completed" : "Partial";
document.getElementById('speech-status').className = testResults.speech.analyzed ?
"text-sm px-3 py-1 rounded-full bg-green-100 text-green-800" :
"text-sm px-3 py-1 rounded-full bg-yellow-100 text-yellow-800";
document.getElementById('speech-result').textContent = testResults.speech.analyzed ?
"Normal speech patterns detected" :
(testResults.speech.recording ? "Recording complete" : "Not taken");
}
// Eye tracking results
if (testResults.eye) {
document.getElementById('eye-status').textContent = testResults.eye.analyzed ? "Completed" : "Partial";
document.getElementById('eye-status').className = testResults.eye.analyzed ?
"text-sm px-3 py-1 rounded-full bg-green-100 text-green-800" :
"text-sm px-3 py-1 rounded-full bg-yellow-100 text-yellow-800";
document.getElementById('eye-result').textContent = testResults.eye.analyzed ?
"Normal eye movement patterns" :
(testResults.eye.trackingData ? "Test completed" : "Not taken");
}
// Tremor results
if (testResults.tremor) {
document.getElementById('tremor-status-result').textContent = testResults.tremor.analyzed ? "Completed" : "Partial";
document.getElementById('tremor-status-result').className = testResults.tremor.analyzed ?
"text-sm px-3 py-1 rounded-full bg-green-100 text-green-800" :
"text-sm px-3 py-1 rounded-full bg-yellow-100 text-yellow-800";
document.getElementById('tremor-result').textContent = testResults.tremor.analyzed ?
"Minimal tremor detected" :
(testResults.tremor.movementData ? "Test completed" : "Not taken");
}
// Overall assessment
if (testResults.cognitive?.analyzed && testResults.speech?.analyzed &&
testResults.eye?.analyzed && testResults.tremor?.analyzed) {
document.getElementById('overall-status').textContent = "Normal";
document.getElementById('overall-status').className = "bg-white text-green-600 px-3 py-1 rounded-full text-sm font-medium";
document.getElementById('overall-feedback').textContent = "All tests indicate normal neurological function. No immediate concerns detected.";
} else if (testResults.cognitive || testResults.speech || testResults.eye || testResults.tremor) {
document.getElementById('overall-status').textContent = "Partial";
document.getElementById('overall-status').className = "bg-white text-yellow-600 px-3 py-1 rounded-full text-sm font-medium";
document.getElementById('overall-feedback').textContent = "Complete all tests for a full assessment.";
} else {
document.getElementById('overall-status').textContent = "Pending";
document.getElementById('overall-status').className = "bg-white text-blue-600 px-3 py-1 rounded-full text-sm font-medium";
document.getElementById('overall-feedback').textContent = "No tests completed yet.";
}
}
// Save and Share Functions
function saveResults() {
// In a real app, we'd save to localStorage or IndexedDB
alert("Results saved locally");
}
function shareResults() {
// In a real app, we'd use the Web Share API
alert("Share functionality would be implemented here");
}
// Serverless AI Integration Placeholders
async function callCognitiveAnalysisAPI(data) {
/* In a real implementation:
const response = await fetch('https://api.example.com/analyze-cognitive', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
return await response.json();
*/
return new Promise(resolve => {
setTimeout(() => {
resolve({
success: true,
analysis: "This is a placeholder for actual AI analysis"
});
}, 1000);
});
}
async function callSpeechAnalysisAPI(audioData) {
/* In a real implementation:
const response = await fetch('https://api.example.com/analyze-speech', {
method: 'POST',
headers: { 'Content-Type': 'audio/wav' },
body: audioData
});
return await response.json();
*/
return new Promise(resolve => {
setTimeout(() => {
resolve({
success: true,
analysis: "This is a placeholder for actual speech analysis"
});
}, 1000);
});
}
</script>
</body>
</html>