/** * Spaxel Dashboard - Simple Mode * * Card-based mobile-first UI for non-technical users. * Progressive disclosure from simple to expert mode. */ (function() { 'use strict'; // ============================================ // Configuration // ============================================ const STORAGE_KEY_MODE = 'spaxel_ui_mode'; const STORAGE_KEY_DISMISSED = 'spaxel_briefing_dismissed'; const UPDATE_INTERVAL = 10000; // 10 seconds // ============================================ // State // ============================================ let isSimpleMode = false; let updateTimer = null; let currentState = { zones: [], events: [], alerts: [], securityMode: false, sleepSummary: null, briefing: null, blobs: [], nodes: [], triggers: [], lastUpdate: null }; // ============================================ // Initialization // ============================================ /** * Initialize simple mode */ function init() { console.log('[Simple Mode] Initializing...'); // Check if simple mode is active const savedMode = localStorage.getItem(STORAGE_KEY_MODE); isSimpleMode = savedMode !== 'expert'; // Set up mode toggle if not exists setupModeToggle(); // Register WebSocket message handler for real-time updates registerWebSocketHandler(); // Start periodic updates (for data that doesn't come via WebSocket) startUpdates(); // Initial data fetch fetchAllData(); console.log('[Simple Mode] Initialized'); } /** * Register WebSocket message handler for real-time updates */ function registerWebSocketHandler() { // Register with SpaxelApp to receive WebSocket messages if (window.SpaxelApp && window.SpaxelApp.registerMessageHandler) { window.SpaxelApp.registerMessageHandler(handleWebSocketMessage); } } /** * Handle WebSocket message from mothership */ function handleWebSocketMessage(msg) { if (!isSimpleMode) return; // Handle different message types switch (msg.type) { case 'loc_update': case 'incremental': // Blob/localization updates if (msg.blobs) { currentState.blobs = msg.blobs; updateRoomCardsFromBlobs(msg.blobs); } if (msg.zones) { currentState.zones = msg.zones; updateRoomCards(); } break; case 'event': // Real-time events if (msg.event) { addEventToFeed(msg.event); } break; case 'alert': // Real-time alerts if (msg.alert) { handleAlert(msg.alert); } break; case 'trigger_state': // Trigger state changes if (msg.trigger) { updateTriggerState(msg.trigger); } break; case 'system_health': // System health updates if (msg.health) { currentState.detectionQuality = msg.health.detection_quality || 0; } break; default: // Log unknown message types console.log('[Simple Mode] Unknown message type:', msg.type); } } /** * Set up the mode toggle between simple and expert */ function setupModeToggle() { // Create header if not exists if (!document.getElementById('simple-mode-header')) { createHeader(); } // Create content container if (!document.getElementById('simple-mode-content')) { createContentContainer(); } // Create quick actions bar if (!document.getElementById('simple-quick-actions')) { createQuickActions(); } // Apply initial mode if (isSimpleMode) { enableSimpleMode(); } } /** * Create the simple mode header */ function createHeader() { const header = document.createElement('div'); header.id = 'simple-mode-header'; header.className = 'simple-mode-header'; header.innerHTML = `