/** * User Manager Module * Handles user registration, preferences, and status management */ class UserManager { constructor(apiClient, uiComponents) { this.apiClient = apiClient; this.ui = uiComponents; this.currentUser = null; } /** * Check if user exists and load their preferences * @param {string} email - User email * @param {boolean} showLoading - Whether to show loading indicator */ async loadUserByEmail(email, showLoading = false) { try { if (showLoading) { this.ui.showLoading('Loading user data...'); } const user = await this.apiClient.getUserByEmail(email); if (user) { this.currentUser = user; return user; } return null; } catch (error) { console.log('User not found or error loading user:', error.message); return null; } finally { if (showLoading) { this.ui.hideLoading(); } } } /** * Register a new user or update existing user * @param {string} email - User email * @param {string} preferences - User preferences */ async registerOrUpdateUser(email, preferences) { try { // Check if user exists first const existingUser = await this.loadUserByEmail(email); let result; let message; if (existingUser) { // Update existing user result = await this.apiClient.updateUserPreferences(email, preferences); message = 'Preferences updated successfully!'; } else { // Register new user result = await this.apiClient.registerUser(email, preferences); message = 'User registered successfully!'; } if (result.success) { this.currentUser = result.user; this.ui.showSuccessMessage(message); return result; } else { throw new Error(result.message || 'Failed to register/update user'); } } catch (error) { this.ui.showError(`Failed to register/update user: ${error.message}`); throw error; } } /** * Toggle user active status * @param {string} email - User email * @param {boolean} active - Active status */ async toggleUserActive(email, active) { try { const result = await this.apiClient.toggleUserActive(email, active); if (result.success) { const action = active ? 'activated' : 'deactivated'; this.ui.showSuccessMessage(`Notifications ${action} successfully!`); // Update current user if it matches if (this.currentUser && this.currentUser.email === email) { this.currentUser.active = active; } return result; } else { throw new Error(result.message || 'Failed to toggle user status'); } } catch (error) { this.ui.showError(`Failed to toggle user status: ${error.message}`); throw error; } } /** * Deactivate user notifications * @param {string} email - User email */ async deactivateUser(email) { const confirmed = confirm(`Are you sure you want to deactivate daily notifications for ${email}?`); if (!confirmed) return false; return await this.toggleUserActive(email, false); } /** * Reactivate user notifications * @param {string} email - User email */ async reactivateUser(email) { return await this.toggleUserActive(email, true); } /** * Get current user data */ getCurrentUser() { return this.currentUser; } /** * Check if current user is active */ isCurrentUserActive() { return this.currentUser && this.currentUser.active; } /** * Clear current user data */ clearCurrentUser() { this.currentUser = null; } /** * Validate email format * @param {string} email - Email to validate */ validateEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } /** * Auto-fill user preferences if they exist * @param {string} email - User email * @param {HTMLElement} preferencesInput - Preferences input field */ async autoFillPreferences(email, preferencesInput) { if (!email || !this.validateEmail(email)) { return; } const user = await this.loadUserByEmail(email); if (user && user.preferences_text && !preferencesInput.value.trim()) { preferencesInput.value = user.preferences_text; // Auto-resize textarea if it has this functionality if (preferencesInput.style) { preferencesInput.style.height = 'auto'; preferencesInput.style.height = preferencesInput.scrollHeight + 'px'; } } return user; } /** * Create user status display for forms * @param {Object} user - User object * @param {Function} deactivateCallback - Callback for deactivate action * @param {Function} reactivateCallback - Callback for reactivate action */ createUserStatusDisplay(user, deactivateCallback, reactivateCallback) { const statusContainer = document.createElement('div'); statusContainer.id = 'userStatusDisplay'; statusContainer.style.cssText = ` margin-top: 1rem; padding: 1rem; background: #f8f9fa; border-radius: 8px; border-left: 4px solid var(--success-color); `; const isActive = user.active; const statusText = isActive ? 'Scheduled' : 'Inactive'; const statusColor = isActive ? 'var(--success-color)' : 'var(--warning-color)'; statusContainer.innerHTML = `
Daily notifications: ${statusText}
${isActive ? ` ` : ` `}
`; // Add event listeners const deactivateBtn = statusContainer.querySelector('#deactivateFromForm'); const reactivateBtn = statusContainer.querySelector('#reactivateFromForm'); if (deactivateBtn) { deactivateBtn.addEventListener('click', deactivateCallback); } if (reactivateBtn) { reactivateBtn.addEventListener('click', reactivateCallback); } return statusContainer; } /** * Remove user status display */ removeUserStatusDisplay() { const statusDisplay = document.getElementById('userStatusDisplay'); if (statusDisplay) { statusDisplay.remove(); } } }