/** * Offline mode settings management * * Stores settings in localStorage following the existing pattern * used by theme and movement_settings. */ const STORAGE_KEY = 'workorder_offline'; // Default settings const defaultSettings = { enabled: false, autoSync: true, lastSyncTimestamp: null, deviceId: null // Generated on first enable }; // In-memory cache of settings let cachedSettings = null; /** * Generate a unique device ID using crypto API */ function generateDeviceId() { if (crypto.randomUUID) { return crypto.randomUUID(); } // Fallback for older browsers return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } /** * Load settings from localStorage */ export function loadOfflineSettings() { try { const saved = localStorage.getItem(STORAGE_KEY); if (saved) { cachedSettings = { ...defaultSettings, ...JSON.parse(saved) }; } else { cachedSettings = { ...defaultSettings }; } } catch (error) { console.error('[OfflineSettings] Failed to load settings:', error); cachedSettings = { ...defaultSettings }; } return cachedSettings; } /** * Save settings to localStorage */ export function saveOfflineSettings(settings) { try { cachedSettings = { ...cachedSettings, ...settings }; localStorage.setItem(STORAGE_KEY, JSON.stringify(cachedSettings)); return true; } catch (error) { console.error('[OfflineSettings] Failed to save settings:', error); return false; } } /** * Get current settings (from cache or load) */ export function getOfflineSettings() { if (!cachedSettings) { loadOfflineSettings(); } return { ...cachedSettings }; } /** * Check if offline mode is enabled */ export function isOfflineModeEnabled() { const settings = getOfflineSettings(); return settings.enabled === true; } /** * Check if auto-sync is enabled */ export function isAutoSyncEnabled() { const settings = getOfflineSettings(); return settings.autoSync === true; } /** * Enable offline mode * Generates device ID if not exists */ export function enableOfflineMode() { const settings = getOfflineSettings(); if (!settings.deviceId) { settings.deviceId = generateDeviceId(); } settings.enabled = true; return saveOfflineSettings(settings); } /** * Disable offline mode * Does NOT clear cached data (user must do that explicitly) */ export function disableOfflineMode() { return saveOfflineSettings({ enabled: false }); } /** * Toggle offline mode */ export function toggleOfflineMode() { if (isOfflineModeEnabled()) { return disableOfflineMode(); } else { return enableOfflineMode(); } } /** * Set auto-sync preference */ export function setAutoSync(enabled) { return saveOfflineSettings({ autoSync: enabled }); } /** * Get device ID (generates if needed) */ export function getDeviceId() { const settings = getOfflineSettings(); if (!settings.deviceId) { settings.deviceId = generateDeviceId(); saveOfflineSettings(settings); } return settings.deviceId; } /** * Update last sync timestamp */ export function updateLastSyncTimestamp() { return saveOfflineSettings({ lastSyncTimestamp: Date.now() }); } /** * Get last sync timestamp */ export function getLastSyncTimestamp() { const settings = getOfflineSettings(); return settings.lastSyncTimestamp; } /** * Get last sync as human-readable string */ export function getLastSyncText() { const timestamp = getLastSyncTimestamp(); if (!timestamp) { return 'Nie synchronisiert'; } const now = Date.now(); const diff = now - timestamp; const minutes = Math.floor(diff / 60000); const hours = Math.floor(diff / 3600000); const days = Math.floor(diff / 86400000); if (minutes < 1) { return 'Gerade eben'; } else if (minutes < 60) { return `Vor ${minutes} Minute${minutes === 1 ? '' : 'n'}`; } else if (hours < 24) { return `Vor ${hours} Stunde${hours === 1 ? '' : 'n'}`; } else { return `Vor ${days} Tag${days === 1 ? '' : 'en'}`; } } /** * Get data freshness level based on last sync * Returns: 'fresh' (<1h), 'stale' (1-24h), 'old' (>24h) */ export function getDataFreshness() { const timestamp = getLastSyncTimestamp(); if (!timestamp) { return 'unknown'; } const now = Date.now(); const diff = now - timestamp; const hours = diff / 3600000; if (hours < 1) { return 'fresh'; // Green } else if (hours < 24) { return 'stale'; // Yellow } else { return 'old'; // Red } } /** * Clear all offline settings (for logout) */ export function clearOfflineSettings() { try { localStorage.removeItem(STORAGE_KEY); cachedSettings = null; return true; } catch (error) { console.error('[OfflineSettings] Failed to clear settings:', error); return false; } } // Reactive state for Vue components export const offlineSettingsState = { get enabled() { return isOfflineModeEnabled(); }, get autoSync() { return isAutoSyncEnabled(); }, get lastSync() { return getLastSyncTimestamp(); }, get lastSyncText() { return getLastSyncText(); }, get freshness() { return getDataFreshness(); }, get deviceId() { return getDeviceId(); } }; export default { load: loadOfflineSettings, save: saveOfflineSettings, get: getOfflineSettings, isEnabled: isOfflineModeEnabled, isAutoSyncEnabled, enable: enableOfflineMode, disable: disableOfflineMode, toggle: toggleOfflineMode, setAutoSync, getDeviceId, updateLastSync: updateLastSyncTimestamp, getLastSync: getLastSyncTimestamp, getLastSyncText, getFreshness: getDataFreshness, clear: clearOfflineSettings, state: offlineSettingsState };