| |
| |
| |
| |
|
|
| class UserManager { |
| constructor(apiClient, uiComponents) { |
| this.apiClient = apiClient; |
| this.ui = uiComponents; |
| this.currentUser = null; |
| } |
|
|
| |
| |
| |
| |
| |
| 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(); |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| async registerOrUpdateUser(email, preferences) { |
| try { |
| |
| const existingUser = await this.loadUserByEmail(email); |
| |
| let result; |
| let message; |
| |
| if (existingUser) { |
| |
| result = await this.apiClient.updateUserPreferences(email, preferences); |
| message = 'Preferences updated successfully!'; |
| } else { |
| |
| 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; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| 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!`); |
| |
| |
| 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; |
| } |
| } |
|
|
| |
| |
| |
| |
| 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); |
| } |
|
|
| |
| |
| |
| |
| async reactivateUser(email) { |
| return await this.toggleUserActive(email, true); |
| } |
|
|
| |
| |
| |
| getCurrentUser() { |
| return this.currentUser; |
| } |
|
|
| |
| |
| |
| isCurrentUserActive() { |
| return this.currentUser && this.currentUser.active; |
| } |
|
|
| |
| |
| |
| clearCurrentUser() { |
| this.currentUser = null; |
| } |
|
|
| |
| |
| |
| |
| validateEmail(email) { |
| const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; |
| return emailRegex.test(email); |
| } |
|
|
| |
| |
| |
| |
| |
| 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; |
| |
| |
| if (preferencesInput.style) { |
| preferencesInput.style.height = 'auto'; |
| preferencesInput.style.height = preferencesInput.scrollHeight + 'px'; |
| } |
| } |
| |
| return user; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| 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 = ` |
| <div style="display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1rem;"> |
| <div style="display: flex; align-items: center; gap: 0.5rem;"> |
| <i class="fas fa-${isActive ? 'check-circle' : 'pause-circle'}" style="color: ${statusColor};"></i> |
| <span style="font-weight: 500;">Daily notifications: <span style="color: ${statusColor};">${statusText}</span></span> |
| </div> |
| <div style="display: flex; gap: 0.5rem;"> |
| ${isActive ? ` |
| <button type="button" class="btn btn-success btn-sm" style="pointer-events: none;"> |
| <i class="fas fa-check"></i> Scheduled |
| </button> |
| <button type="button" class="btn btn-danger btn-sm" id="deactivateFromForm"> |
| <i class="fas fa-times"></i> Deactivate |
| </button> |
| ` : ` |
| <button type="button" class="btn btn-primary btn-sm" id="reactivateFromForm"> |
| <i class="fas fa-play"></i> Reactivate |
| </button> |
| `} |
| </div> |
| </div> |
| `; |
| |
| |
| const deactivateBtn = statusContainer.querySelector('#deactivateFromForm'); |
| const reactivateBtn = statusContainer.querySelector('#reactivateFromForm'); |
| |
| if (deactivateBtn) { |
| deactivateBtn.addEventListener('click', deactivateCallback); |
| } |
| if (reactivateBtn) { |
| reactivateBtn.addEventListener('click', reactivateCallback); |
| } |
| |
| return statusContainer; |
| } |
|
|
| |
| |
| |
| removeUserStatusDisplay() { |
| const statusDisplay = document.getElementById('userStatusDisplay'); |
| if (statusDisplay) { |
| statusDisplay.remove(); |
| } |
| } |
| } |
|
|