// User preferences management // Stores preferences in the users collection PRISM column as JSON // Uses "Job-Pages" key to avoid conflicts with other applications /** * Get user preferences from PRISM column */ async function getUserPreferences() { try { const user = pb.authStore.model; if (!user) { return getDefaultPreferences(); } // Get current user record const userRecord = await pb.collection('users').getOne(user.id); // Parse PRISM JSON if it exists let prism = {}; if (userRecord.PRISM) { try { prism = typeof userRecord.PRISM === 'string' ? JSON.parse(userRecord.PRISM) : userRecord.PRISM; } catch (e) { console.warn('Error parsing PRISM data:', e); prism = {}; } } // Get Job-Pages preferences (isolated from other apps) const jobPagesPrefs = prism['Job-Pages'] || {}; // Merge with defaults return { darkMode: jobPagesPrefs.darkMode ?? false, defaultView: jobPagesPrefs.defaultView ?? 'table' }; } catch (error) { console.error('Error loading preferences:', error); return getDefaultPreferences(); } } /** * Get default preferences */ function getDefaultPreferences() { return { darkMode: false, defaultView: 'table' }; } /** * Save user preferences to PRISM column */ async function saveUserPreferences(preferences) { try { const user = pb.authStore.model; if (!user) { throw new Error('User not authenticated'); } // Get current user record const userRecord = await pb.collection('users').getOne(user.id); // Parse existing PRISM JSON let prism = {}; if (userRecord.PRISM) { try { prism = typeof userRecord.PRISM === 'string' ? JSON.parse(userRecord.PRISM) : userRecord.PRISM; } catch (e) { console.warn('Error parsing PRISM data:', e); prism = {}; } } // Update only Job-Pages preferences (preserve other app data) prism['Job-Pages'] = { darkMode: preferences.darkMode, defaultView: preferences.defaultView }; // Save back to PRISM column await pb.collection('users').update(user.id, { PRISM: JSON.stringify(prism) }); return true; } catch (error) { console.error('Error saving preferences:', error); throw error; } } /** * Apply dark mode to the page */ function applyDarkMode(enabled) { const html = document.documentElement; if (enabled) { html.classList.add('dark'); localStorage.setItem('darkMode', 'true'); } else { html.classList.remove('dark'); localStorage.setItem('darkMode', 'false'); } } /** * Initialize dark mode from preferences */ async function initializeDarkMode() { try { const preferences = await getUserPreferences(); applyDarkMode(preferences.darkMode); } catch (error) { console.error('Error initializing dark mode:', error); } } /** * Update view option visual state */ function updateViewOptionVisuals() { const selectedView = document.querySelector('input[name="defaultView"]:checked')?.value || 'table'; const options = document.querySelectorAll('.view-option'); options.forEach(option => { const input = option.querySelector('input[type="radio"]'); const icon = option.querySelector('.view-icon'); const title = option.querySelector('.view-title'); const isSelected = input.value === selectedView; if (isSelected) { option.classList.add('border-indigo-500', 'bg-indigo-50/50', 'shadow-md'); option.classList.remove('border-white/30', 'bg-white/40'); if (icon) icon.classList.add('text-indigo-600'); if (icon) icon.classList.remove('text-gray-400'); if (title) title.classList.add('text-indigo-600'); if (title) title.classList.remove('text-gray-900'); } else { option.classList.remove('border-indigo-500', 'bg-indigo-50/50', 'shadow-md'); option.classList.add('border-white/30', 'bg-white/40'); if (icon) icon.classList.remove('text-indigo-600'); if (icon) icon.classList.add('text-gray-400'); if (title) title.classList.remove('text-indigo-600'); if (title) title.classList.add('text-gray-900'); } }); } /** * Load preferences and populate form */ async function loadPreferences() { try { const preferences = await getUserPreferences(); // Set dark mode toggle const darkModeToggle = document.getElementById('darkModeToggle'); if (darkModeToggle) { darkModeToggle.checked = preferences.darkMode; applyDarkMode(preferences.darkMode); } // Set default view radio buttons const viewTable = document.getElementById('viewTable'); const viewCard = document.getElementById('viewCard'); if (viewTable && viewCard) { if (preferences.defaultView === 'table') { viewTable.checked = true; } else { viewCard.checked = true; } // Update visual state updateViewOptionVisuals(); } // Add change listeners to radio buttons const radioButtons = document.querySelectorAll('input[name="defaultView"]'); radioButtons.forEach(radio => { radio.addEventListener('change', updateViewOptionVisuals); }); } catch (error) { console.error('Error loading preferences:', error); } } /** * Save preferences from form */ async function savePreferences() { try { const darkMode = document.getElementById('darkModeToggle').checked; const defaultView = document.querySelector('input[name="defaultView"]:checked')?.value || 'table'; const preferences = { darkMode: darkMode, defaultView: defaultView }; await saveUserPreferences(preferences); applyDarkMode(darkMode); showMessage('Preferences saved successfully', 'success'); } catch (error) { console.error('Error saving preferences:', error); showMessage('Error saving preferences: ' + (error.message || 'Unknown error'), 'error'); } } /** * Show message to user */ function showMessage(message, type = 'success') { const container = document.getElementById('messageContainer'); if (!container) return; const bgColor = type === 'success' ? 'bg-green-50 border-green-200 text-green-700' : 'bg-red-50 border-red-200 text-red-700'; container.innerHTML = `
${message}
`; // Auto-hide after 5 seconds setTimeout(() => { container.innerHTML = ''; }, 5000); } // Form submission handler if (typeof document !== 'undefined') { document.addEventListener('DOMContentLoaded', () => { const form = document.getElementById('preferencesForm'); if (form) { form.addEventListener('submit', async (e) => { e.preventDefault(); await savePreferences(); }); } // Dark mode toggle change handler const darkModeToggle = document.getElementById('darkModeToggle'); if (darkModeToggle) { darkModeToggle.addEventListener('change', (e) => { applyDarkMode(e.target.checked); }); } }); } // Make functions globally accessible if (typeof window !== 'undefined') { window.getUserPreferences = getUserPreferences; window.saveUserPreferences = saveUserPreferences; window.initializeDarkMode = initializeDarkMode; window.loadPreferences = loadPreferences; window.savePreferences = savePreferences; }