/** * Spaxel Dashboard - Guided Troubleshooting * * Proactive contextual help that appears when users encounter problems. * Provides step-by-step guidance and explains what went wrong. */ (function() { 'use strict'; // ===== State ===== let activeGuide = null; let dismissedGuides = new Set(); let helpPanelVisible = false; // ===== DOM Elements ===== const helpContainer = document.createElement('div'); helpContainer.id = 'guided-help-container'; helpContainer.className = 'guided-help-container'; document.body.appendChild(helpContainer); // ===== Guide Definitions ===== const guides = { // No nodes detected 'no-nodes': { title: 'No Nodes Detected', icon: '📡', trigger: 'no-nodes', steps: [ { title: 'Check Power', content: 'Ensure each Spaxel node is powered on. The LED should be breathing blue.', action: null }, { title: 'Check WiFi', content: 'Nodes must connect to your WiFi network. Verify your WiFi is working.', action: null }, { title: 'Add Missing Nodes', content: 'If nodes are powered but not showing, click "+ Add Node" to onboard them.', action: 'add-node' } ], dismissible: true }, // Poor detection quality 'poor-detection': { title: 'Detection Quality Issues', icon: '📉', trigger: 'poor-quality', steps: [ { title: 'Check Node Placement', content: 'Nodes should be placed at least 2 meters apart for best accuracy.', action: null }, { title: 'Review Coverage', content: 'Enable GDOP view to see coverage gaps in your space.', action: 'toggle-gdop' }, { title: 'Add More Nodes', content: 'Large spaces or areas with obstacles may need additional nodes.', action: 'add-node' } ], dismissible: true }, // Node went offline 'node-offline': { title: 'Node Offline', icon: '⚠️', trigger: 'node-offline', steps: [ { title: 'Check Power', content: 'Verify the node is still receiving power. Check cables and connections.', action: null }, { title: 'Check WiFi Signal', content: 'The node may be out of WiFi range. Move it closer to your router.', action: null }, { title: 'Restart Node', content: 'Try power cycling the node by unplugging and replugging it.', action: null } ], dismissible: true }, // First anomaly detected 'first-anomaly': { title: 'Anomaly Detected', icon: '🔔', trigger: 'first-anomaly', steps: [ { title: 'Review the Event', content: 'An unusual pattern was detected. Check the timeline for details.', action: 'view-timeline' }, { title: 'Verify Accuracy', content: 'Was this a real event or a false positive? Your feedback helps us improve.', action: 'give-feedback' }, { title: 'Adjust Sensitivity', content: 'If this keeps triggering falsely, you can adjust anomaly sensitivity in settings.', action: 'open-settings' } ], dismissible: true }, // Security mode first use 'security-first-use': { title: 'Security Mode Enabled', icon: '🔒', trigger: 'security-first-use', steps: [ { title: 'What is Security Mode?', content: 'Security mode enhances detection sensitivity and triggers alerts for any presence.', action: null }, { title: 'Set Up Alerts', content: 'Configure webhooks or notifications to be alerted of security events.', action: 'open-automations' }, { title: 'Test the System', content: 'Walk through your space to verify detection is working as expected.', action: null } ], dismissible: true }, // High GDOP area 'high-gdop': { title: 'Poor Positioning Coverage', icon: '📍', trigger: 'high-gdop', steps: [ { title: 'Understanding GDOP', content: 'GDOP measures positioning accuracy. Red areas have poor accuracy.', action: null }, { title: 'Add Virtual Nodes', content: 'Use the simulator to test if adding a node would improve coverage.', action: 'open-simulator' }, { title: 'Reposition Existing Nodes', content: 'Small adjustments to node placement can significantly improve coverage.', action: null } ], dismissible: true }, // Frequent false positives 'false-positives': { title: 'Reducing False Detections', icon: '✅', trigger: 'false-positives', steps: [ { title: 'Review Recent Events', content: 'Check the timeline to see when false detections are occurring.', action: 'view-timeline' }, { title: 'Provide Feedback', content: 'Mark false detections to help the system learn and improve.', action: 'give-feedback' }, { title: 'Adjust Diurnal Settings', content: 'Ensure your home patterns are fully learned (7+ days of data).', action: null } ], dismissible: true }, // Sleep tracking not working 'sleep-not-working': { title: 'Sleep Tracking Setup', icon: '😴', trigger: 'sleep-not-working', steps: [ { title: 'Define Bedroom Zone', content: 'Create a zone for your bedroom to track sleep patterns.', action: 'create-zone' }, { title: 'Add Bed Trigger', content: 'Place a virtual trigger at your bed location for accurate detection.', action: 'add-trigger' }, { title: 'Wait for Learning', content: 'Sleep patterns need 7+ nights of data to establish baselines.', action: null } ], dismissible: true }, // Automation not firing 'automation-not-firing': { title: 'Automation Troubleshooting', icon: '⚡', trigger: 'automation-failed', steps: [ { title: 'Check Trigger Conditions', content: 'Verify the zone, person, and time conditions match your setup.', action: 'view-automations' }, { title: 'Test Webhook', content: 'Use the test button to verify your webhook endpoint is responding.', action: 'test-webhook' }, { title: 'Check Automation Logs', content: 'Review recent automation events to see why it didn\'t fire.', action: 'view-logs' } ], dismissible: true } }; // ===== Guide Execution ===== function showGuide(guideId, context = {}) { if (dismissedGuides.has(guideId)) { return; // Don't show dismissed guides } const guide = guides[guideId]; if (!guide) { console.warn('Guide not found:', guideId); return; } activeGuide = { id: guideId, data: guide, currentStep: 0, context: context }; renderGuide(); helpPanelVisible = true; } function renderGuide() { if (!activeGuide) return; const guide = activeGuide.data; const step = guide.steps[activeGuide.currentStep]; const isLastStep = activeGuide.currentStep === guide.steps.length - 1; helpContainer.innerHTML = `
${step.content}