// Object Detection Interface Handler document.addEventListener('DOMContentLoaded', () => { // Mode switching const modeButtons = document.querySelectorAll('.mode-btn'); const sections = { 'mode-webcam': document.getElementById('webcam-section'), 'mode-video': document.getElementById('video-section'), 'mode-image': document.getElementById('image-section') }; modeButtons.forEach(btn => { btn.addEventListener('click', () => { // Update button styles modeButtons.forEach(b => { b.classList.remove('active', 'bg-white', 'text-zinc-900'); b.classList.add('bg-zinc-800', 'text-white'); }); btn.classList.add('active', 'bg-white', 'text-zinc-900'); btn.classList.remove('bg-zinc-800', 'text-white'); // Show/hide sections Object.values(sections).forEach(s => s?.classList.add('hidden')); sections[btn.id]?.classList.remove('hidden'); // Stop webcam if switching away if (btn.id !== 'mode-webcam') { stopWebcam(); } }); }); // ===== WEBCAM MODE ===== const startWebcamBtn = document.getElementById('start-webcam'); const stopWebcamBtn = document.getElementById('stop-webcam'); const webcamStream = document.getElementById('webcam-stream'); const webcamStatus = document.getElementById('webcam-status'); let webcamInterval = null; startWebcamBtn?.addEventListener('click', startWebcam); stopWebcamBtn?.addEventListener('click', stopWebcam); function startWebcam() { webcamStatus.textContent = 'Starting webcam...'; webcamStream.src = '/webcam_feed'; webcamStream.classList.remove('hidden'); startWebcamBtn.classList.add('hidden'); stopWebcamBtn.classList.remove('hidden'); webcamStatus.textContent = 'Webcam active - detecting exercises...'; // Handle errors webcamStream.onerror = () => { webcamStatus.textContent = 'Error: Could not access webcam'; stopWebcam(); }; } function stopWebcam() { if (webcamStream) { webcamStream.src = ''; webcamStream.classList.add('hidden'); } if (webcamInterval) { clearInterval(webcamInterval); webcamInterval = null; } startWebcamBtn?.classList.remove('hidden'); stopWebcamBtn?.classList.add('hidden'); webcamStatus.textContent = ''; } // ===== VIDEO UPLOAD MODE ===== const videoForm = document.getElementById('video-form'); const videoInput = document.getElementById('video-input'); const videoStream = document.getElementById('video-stream'); const videoStatus = document.getElementById('video-status'); videoForm?.addEventListener('submit', async (e) => { e.preventDefault(); const file = videoInput.files?.[0]; if (!file) return; videoStatus.textContent = 'Uploading video...'; try { const formData = new FormData(); formData.append('video', file); const res = await fetch('/upload_video', { method: 'POST', body: formData }); const data = await res.json(); if (!res.ok || !data.ok) { throw new Error(data.error || 'Upload failed'); } videoStatus.textContent = 'Processing video...'; videoStream.src = `/video_feed/${data.video_id}`; videoStream.classList.remove('hidden'); videoStatus.textContent = 'Video processing complete!'; } catch (err) { console.error(err); videoStatus.textContent = `Error: ${err.message}`; } }); // ===== IMAGE UPLOAD MODE ===== const imageForm = document.getElementById('image-form'); const imageInput = document.getElementById('image-input'); const previewBox = document.getElementById('preview'); const previewImg = document.getElementById('preview-img'); const imageStatus = document.getElementById('image-status'); const imageResult = document.getElementById('image-result'); // Preview handler imageInput?.addEventListener('change', () => { const file = imageInput.files?.[0]; if (!file) return; const url = URL.createObjectURL(file); previewImg.src = url; previewBox.classList.remove('hidden'); imageStatus.textContent = ''; }); // Submit handler imageForm?.addEventListener('submit', async (e) => { e.preventDefault(); const file = imageInput.files?.[0]; if (!file) return; imageStatus.textContent = 'Analyzing image...'; imageResult.innerHTML = '
Processing...
'; try { const formData = new FormData(); formData.append('image', file); const res = await fetch('/analyze_image', { method: 'POST', body: formData }); const data = await res.json(); if (!res.ok || !data.ok) { throw new Error(data.error || 'Analysis failed'); } // Display results const detections = data.detections || []; const detectionCount = detections.length; let resultsHTML = `
Detected exercises
Found ${detectionCount} exercise${detectionCount !== 1 ? 's' : ''}
`; if (detections.length > 0) { resultsHTML += '
'; detections.forEach((det, idx) => { const conf = (det.confidence * 100).toFixed(1); resultsHTML += `
${det.label} ${conf}% confident
`; }); resultsHTML += '
'; // Add tips if (data.tips && data.tips.length > 0) { resultsHTML += '
'; resultsHTML += '
Form Tips:
'; data.tips.forEach(tip => { if (tip) { resultsHTML += `

• ${tip}

`; } }); resultsHTML += '
'; } } resultsHTML += '
'; imageResult.innerHTML = resultsHTML; imageStatus.textContent = ''; } catch (err) { console.error(err); imageStatus.textContent = `Error: ${err.message}`; imageResult.innerHTML = '
Analysis failed. Please try again.
'; } }); });