/** * Settings Management System * Handles loading, saving, and applying user preferences */ let userPreferences = {}; // Load preferences on page load async function loadUserPreferences() { try { const response = await fetch('/api/user_preferences.php', { credentials: 'same-origin' }); const data = await response.json(); if (data.success) { userPreferences = data.preferences; applyPreferences(); } } catch (error) { console.error('Error loading preferences:', error); } } // Apply preferences to UI function applyPreferences() { // Rows per page const rowsPerPage = userPreferences.rows_per_page || '15'; const rowsSelect = document.getElementById('rowsPerPage'); if (rowsSelect) { rowsSelect.value = rowsPerPage; } // Default filters const defaultFilters = (userPreferences.default_status_filters || 'Open,Pending,In Progress').split(','); document.querySelectorAll('[name="defaultFilters"]').forEach(cb => { cb.checked = defaultFilters.includes(cb.value); }); // Table density const density = userPreferences.table_density || 'normal'; const densitySelect = document.getElementById('tableDensity'); if (densitySelect) { densitySelect.value = density; } document.body.classList.remove('table-compact', 'table-comfortable'); if (density !== 'normal') { document.body.classList.add(`table-${density}`); } // Timezone - use server default if not set const timezone = userPreferences.timezone || window.APP_TIMEZONE || 'America/New_York'; const timezoneSelect = document.getElementById('userTimezone'); if (timezoneSelect) { timezoneSelect.value = timezone; } // Notifications const notificationsCheckbox = document.getElementById('notificationsEnabled'); if (notificationsCheckbox) { notificationsCheckbox.checked = userPreferences.notifications_enabled !== '0'; } const soundCheckbox = document.getElementById('soundEffects'); if (soundCheckbox) { soundCheckbox.checked = userPreferences.sound_effects !== '0'; } // Toast duration const toastDuration = userPreferences.toast_duration || '3000'; const toastSelect = document.getElementById('toastDuration'); if (toastSelect) { toastSelect.value = toastDuration; } } // Save preferences async function saveSettings() { const rowsPerPage = document.getElementById('rowsPerPage'); const tableDensity = document.getElementById('tableDensity'); const userTimezone = document.getElementById('userTimezone'); const notificationsEnabled = document.getElementById('notificationsEnabled'); const soundEffects = document.getElementById('soundEffects'); const toastDuration = document.getElementById('toastDuration'); const prefs = { rows_per_page: rowsPerPage ? rowsPerPage.value : '15', default_status_filters: Array.from(document.querySelectorAll('[name="defaultFilters"]:checked')) .map(cb => cb.value).join(',') || 'Open,Pending,In Progress', table_density: tableDensity ? tableDensity.value : 'normal', timezone: userTimezone ? userTimezone.value : (window.APP_TIMEZONE || 'America/New_York'), notifications_enabled: notificationsEnabled ? (notificationsEnabled.checked ? '1' : '0') : '1', sound_effects: soundEffects ? (soundEffects.checked ? '1' : '0') : '1', toast_duration: toastDuration ? toastDuration.value : '3000' }; try { // Save each preference for (const [key, value] of Object.entries(prefs)) { const response = await fetch('/api/user_preferences.php', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': window.CSRF_TOKEN }, body: JSON.stringify({ key, value }) }); const result = await response.json(); if (!result.success) { throw new Error(`Failed to save ${key}`); } } if (typeof toast !== 'undefined') { toast.success('Preferences saved successfully!'); } closeSettingsModal(); // Reload page to apply new preferences setTimeout(() => window.location.reload(), 1000); } catch (error) { if (typeof toast !== 'undefined') { toast.error('Error saving preferences'); } console.error('Error saving preferences:', error); } } // Modal controls function openSettingsModal() { const modal = document.getElementById('settingsModal'); if (modal) { modal.style.display = 'flex'; document.body.classList.add('modal-open'); loadUserPreferences(); } } function closeSettingsModal() { const modal = document.getElementById('settingsModal'); if (modal) { modal.style.display = 'none'; document.body.classList.remove('modal-open'); } } // Close modal when clicking on backdrop (outside the settings content) function closeOnBackdropClick(event) { const modal = document.getElementById('settingsModal'); // Only close if clicking directly on the modal backdrop, not on content if (event.target === modal) { closeSettingsModal(); } } // Keyboard shortcut to open settings (Alt+S) document.addEventListener('keydown', (e) => { if (e.altKey && e.key === 's') { e.preventDefault(); openSettingsModal(); } // ESC to close modal if (e.key === 'Escape') { const modal = document.getElementById('settingsModal'); if (modal && modal.style.display !== 'none' && modal.style.display !== '') { closeSettingsModal(); } } }); // Initialize on page load document.addEventListener('DOMContentLoaded', loadUserPreferences);