// ===== GLOBAL STATE ===== let currentResults = null; let explanations = null; let sessionId = null; // Store session ID // ===== INITIALIZATION ===== document.addEventListener('DOMContentLoaded', () => { initNavigation(); initFileUpload(); initScrollAnimations(); }); // ===== NAVIGATION ===== function initNavigation() { const navLinks = document.querySelectorAll('.nav-link'); navLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const target = link.getAttribute('href'); // Update active state navLinks.forEach(l => l.classList.remove('active')); link.classList.add('active'); // Smooth scroll document.querySelector(target).scrollIntoView({ behavior: 'smooth', block: 'start' }); }); }); // Mobile menu toggle const mobileToggle = document.querySelector('.mobile-menu-toggle'); const navMenu = document.querySelector('.nav-menu'); if (mobileToggle) { mobileToggle.addEventListener('click', () => { navMenu.classList.toggle('active'); }); } } // ===== SCROLL ANIMATIONS ===== function initScrollAnimations() { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; } }); }, { threshold: 0.1 }); document.querySelectorAll('.about-card, .feature-card').forEach(card => { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; card.style.transition = 'all 0.6s ease-out'; observer.observe(card); }); } // ===== FILE UPLOAD ===== function initFileUpload() { const fileInput = document.getElementById('fileInput'); const uploadArea = document.getElementById('uploadArea'); if (!fileInput || !uploadArea) return; // Click to upload fileInput.addEventListener('change', handleFileSelect); // Drag and drop uploadArea.addEventListener('dragover', (e) => { e.preventDefault(); uploadArea.classList.add('dragover'); }); uploadArea.addEventListener('dragleave', () => { uploadArea.classList.remove('dragover'); }); uploadArea.addEventListener('drop', (e) => { e.preventDefault(); uploadArea.classList.remove('dragover'); const file = e.dataTransfer.files[0]; if (file && file.type === 'application/pdf') { uploadFile(file); } else { showToast('Please upload a PDF file', 'error'); } }); } function handleFileSelect(e) { const file = e.target.files[0]; if (file) { uploadFile(file); } } async function uploadFile(file) { const formData = new FormData(); formData.append('file', file); // Show progress document.getElementById('uploadArea').classList.add('hidden'); document.getElementById('uploadProgress').classList.remove('hidden'); try { const response = await fetch('/api/upload', { method: 'POST', body: formData }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Upload failed'); } // Store session ID and results sessionId = data.session_id; currentResults = data.results; console.log('Session ID:', sessionId); console.log('Results:', currentResults); showToast(`✓ Found ${data.count} lab results!`, 'success'); // Generate explanations await generateExplanations(); // Display results displayResults(); // Scroll to results setTimeout(() => { document.getElementById('results').scrollIntoView({ behavior: 'smooth' }); }, 500); } catch (error) { showToast(error.message, 'error'); resetUploadArea(); } } async function generateExplanations() { showLoading('Generating AI explanations... This may take 30-60 seconds.'); try { const response = await fetch('/api/explain', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ session_id: sessionId }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to generate explanations'); } explanations = data.explanations; console.log('Explanations:', explanations); } catch (error) { showToast('Error generating explanations: ' + error.message, 'error'); // Continue anyway to show results } finally { hideLoading(); } } function displayResults() { const resultsSection = document.getElementById('results'); const container = document.getElementById('resultsContainer'); if (!currentResults || currentResults.length === 0) { container.innerHTML = '
'; return; } // Show results section resultsSection.classList.remove('hidden'); // Update summary stats updateSummaryStats(); // Clear container container.innerHTML = ''; // Create result cards currentResults.forEach((result, index) => { const card = createResultCard(result, index); container.appendChild(card); }); // Reset upload area resetUploadArea(); } function updateSummaryStats() { const stats = { normal: 0, high: 0, low: 0 }; currentResults.forEach(result => { if (result.status in stats) { stats[result.status]++; } }); document.getElementById('normalCount').textContent = stats.normal; document.getElementById('highCount').textContent = stats.high; document.getElementById('lowCount').textContent = stats.low; } function createResultCard(result, index) { const card = document.createElement('div'); card.className = 'result-card'; card.style.setProperty('--i', index + 1); const statusClass = `status-${result.status}`; const explanation = explanations && explanations[result.test_name] ? explanations[result.test_name] : 'Explanation is being generated. Click "Ask Questions" to learn more about this result.'; card.innerHTML = `Reference: ${escapeHtml(result.reference_range || 'N/A')}
${escapeHtml(explanation)}