// static/admin/js/admin-user-edit.js // Create custom logger for admin user edit const adminUserEditLog = window.LogConfig.createLogger('ADMIN-USER-EDIT'); function adminUserEditPage() { return { // Inherit base layout functionality from init-alpine.js ...data(), // Admin user edit page specific state currentPage: 'admin-users', loading: false, adminUser: null, platforms: [], errors: {}, saving: false, userId: null, currentUserId: null, // Editable profile form editForm: { username: '', email: '', first_name: '', last_name: '' }, // Platform assignment state showPlatformModal: false, availablePlatforms: [], selectedPlatformId: null, // Confirmation modal state showRemovePlatformModal: false, platformToRemove: null, showToggleSuperAdminModal: false, showToggleStatusModal: false, showDeleteModal: false, showDeleteFinalModal: false, // Initialize async init() { try { // Load i18n translations await I18n.loadModule('tenancy'); adminUserEditLog.info('=== ADMIN USER EDIT PAGE INITIALIZING ==='); // Prevent multiple initializations if (window._adminUserEditInitialized) { adminUserEditLog.warn('Admin user edit page already initialized, skipping...'); return; } window._adminUserEditInitialized = true; // Get current user ID this.currentUserId = this.adminProfile?.id || null; // Get user ID from URL const path = window.location.pathname; const match = path.match(/\/admin\/admin-users\/(\d+)\/edit/); if (match) { this.userId = parseInt(match[1], 10); adminUserEditLog.info('Editing admin user:', this.userId); await this.loadAdminUser(); await this.loadAllPlatforms(); } else { adminUserEditLog.error('No user ID in URL'); Utils.showToast(I18n.t('tenancy.messages.invalid_admin_user_url'), 'error'); setTimeout(() => window.location.href = '/admin/admin-users', 2000); } adminUserEditLog.info('=== ADMIN USER EDIT PAGE INITIALIZATION COMPLETE ==='); } catch (error) { adminUserEditLog.error('Init failed:', error); this.error = 'Failed to initialize admin user edit page'; } }, // Load admin user data async loadAdminUser() { adminUserEditLog.info('Loading admin user data...'); this.loading = true; try { const url = `/admin/admin-users/${this.userId}`; window.LogConfig.logApiCall('GET', url, null, 'request'); const startTime = performance.now(); const response = await apiClient.get(url); const duration = performance.now() - startTime; window.LogConfig.logApiCall('GET', url, response, 'response'); window.LogConfig.logPerformance('Load Admin User', duration); // Transform API response this.adminUser = { ...response, platforms: (response.platform_assignments || []).map(pa => ({ id: pa.platform_id, code: pa.platform_code, name: pa.platform_name })), full_name: [response.first_name, response.last_name].filter(Boolean).join(' ') || null }; // Populate editable form this.editForm = { username: this.adminUser.username || '', email: this.adminUser.email || '', first_name: this.adminUser.first_name || '', last_name: this.adminUser.last_name || '' }; adminUserEditLog.info(`Admin user loaded in ${duration}ms`, { id: this.adminUser.id, username: this.adminUser.username, role: this.adminUser.role }); } catch (error) { window.LogConfig.logError(error, 'Load Admin User'); Utils.showToast(I18n.t('tenancy.messages.failed_to_load_admin_user'), 'error'); setTimeout(() => window.location.href = '/admin/admin-users', 2000); } finally { this.loading = false; } }, // Load all platforms for assignment async loadAllPlatforms() { try { adminUserEditLog.debug('Loading all platforms...'); const response = await apiClient.get('/admin/platforms'); this.platforms = response.platforms || response.items || []; adminUserEditLog.debug(`Loaded ${this.platforms.length} platforms`); } catch (error) { adminUserEditLog.error('Failed to load platforms:', error); this.platforms = []; } }, // Get available platforms (not yet assigned) get availablePlatformsForAssignment() { if (!this.adminUser || this.adminUser.role === 'super_admin') return []; const assignedIds = (this.adminUser.platforms || []).map(p => p.id); return this.platforms.filter(p => !assignedIds.includes(p.id)); }, // Format date formatDate(dateString) { if (!dateString) { return '-'; } return Utils.formatDate(dateString); }, // Check if profile form has unsaved changes get profileDirty() { if (!this.adminUser) return false; return this.editForm.username !== (this.adminUser.username || '') || this.editForm.email !== (this.adminUser.email || '') || this.editForm.first_name !== (this.adminUser.first_name || '') || this.editForm.last_name !== (this.adminUser.last_name || ''); }, // Save profile changes async saveProfile() { adminUserEditLog.info('Saving profile changes...'); this.errors = {}; // Build update payload with only changed fields const payload = {}; if (this.editForm.username !== (this.adminUser.username || '')) { payload.username = this.editForm.username; } if (this.editForm.email !== (this.adminUser.email || '')) { payload.email = this.editForm.email; } if (this.editForm.first_name !== (this.adminUser.first_name || '')) { payload.first_name = this.editForm.first_name; } if (this.editForm.last_name !== (this.adminUser.last_name || '')) { payload.last_name = this.editForm.last_name; } if (Object.keys(payload).length === 0) return; this.saving = true; try { const url = `/admin/users/${this.userId}`; window.LogConfig.logApiCall('PUT', url, payload, 'request'); const response = await apiClient.put(url, payload); window.LogConfig.logApiCall('PUT', url, response, 'response'); // Update local state this.adminUser.username = response.username; this.adminUser.email = response.email; this.adminUser.first_name = response.first_name; this.adminUser.last_name = response.last_name; this.adminUser.full_name = [response.first_name, response.last_name].filter(Boolean).join(' ') || null; // Re-sync form this.editForm = { username: response.username || '', email: response.email || '', first_name: response.first_name || '', last_name: response.last_name || '' }; Utils.showToast('Profile updated successfully', 'success'); adminUserEditLog.info('Profile updated successfully'); } catch (error) { window.LogConfig.logError(error, 'Save Profile'); if (error.details) { for (const detail of error.details) { const field = detail.loc?.[detail.loc.length - 1]; if (field) this.errors[field] = detail.msg; } } Utils.showToast(error.message || 'Failed to save profile', 'error'); } finally { this.saving = false; } }, // Toggle super admin status async toggleSuperAdmin() { const isSuperAdmin = this.adminUser.role === 'super_admin'; const newRole = isSuperAdmin ? 'platform_admin' : 'super_admin'; const action = !isSuperAdmin ? 'promote to' : 'demote from'; adminUserEditLog.info(`Toggle super admin: ${action}`); // Prevent self-demotion if (this.adminUser.id === this.currentUserId && isSuperAdmin) { Utils.showToast(I18n.t('tenancy.messages.you_cannot_demote_yourself_from_super_ad'), 'error'); return; } this.saving = true; try { const url = `/admin/admin-users/${this.userId}/super-admin`; window.LogConfig.logApiCall('PUT', url, { role: newRole }, 'request'); const response = await apiClient.put(url, { role: newRole }); window.LogConfig.logApiCall('PUT', url, response, 'response'); this.adminUser.role = response.role; // Clear platforms if promoted to super admin if (response.role === 'super_admin') { this.adminUser.platforms = []; } const actionDone = newRole === 'super_admin' ? 'promoted to' : 'demoted from'; Utils.showToast(`Admin ${actionDone} super admin successfully`, 'success'); adminUserEditLog.info(`Admin ${actionDone} super admin successfully`); } catch (error) { window.LogConfig.logError(error, `Toggle Super Admin (${action})`); Utils.showToast(error.message || `Failed to ${action} super admin`, 'error'); } finally { this.saving = false; } }, // Toggle admin user status async toggleStatus() { const action = this.adminUser.is_active ? 'deactivate' : 'activate'; adminUserEditLog.info(`Toggle status: ${action}`); // Prevent self-deactivation if (this.adminUser.id === this.currentUserId) { Utils.showToast(I18n.t('tenancy.messages.you_cannot_deactivate_your_own_account'), 'error'); return; } this.saving = true; try { const url = `/admin/admin-users/${this.userId}/status`; window.LogConfig.logApiCall('PUT', url, null, 'request'); const response = await apiClient.put(url); window.LogConfig.logApiCall('PUT', url, response, 'response'); this.adminUser.is_active = response.is_active; Utils.showToast(`Admin user ${action}d successfully`, 'success'); adminUserEditLog.info(`Admin user ${action}d successfully`); } catch (error) { window.LogConfig.logError(error, `Toggle Status (${action})`); Utils.showToast(error.message || `Failed to ${action} admin user`, 'error'); } finally { this.saving = false; } }, // Assign platform to admin async assignPlatform(platformId) { if (!platformId) return; adminUserEditLog.info('Assigning platform:', platformId); this.saving = true; try { const url = `/admin/admin-users/${this.userId}/platforms/${platformId}`; window.LogConfig.logApiCall('POST', url, null, 'request'); const response = await apiClient.post(url); window.LogConfig.logApiCall('POST', url, response, 'response'); // Reload admin user to get updated platforms await this.loadAdminUser(); Utils.showToast(I18n.t('tenancy.messages.platform_assigned_successfully'), 'success'); adminUserEditLog.info('Platform assigned successfully'); this.showPlatformModal = false; this.selectedPlatformId = null; } catch (error) { window.LogConfig.logError(error, 'Assign Platform'); Utils.showToast(error.message || 'Failed to assign platform', 'error'); } finally { this.saving = false; } }, // Show confirmation modal for platform removal removePlatform(platformId) { // Validate: platform admin must have at least one platform if (this.adminUser.platforms.length <= 1) { Utils.showToast(I18n.t('tenancy.messages.platform_admin_must_be_assigned_to_at_le'), 'error'); return; } this.platformToRemove = this.adminUser.platforms.find(p => p.id === platformId); this.showRemovePlatformModal = true; }, // Confirm and execute platform removal async confirmRemovePlatform() { if (!this.platformToRemove) return; const platformId = this.platformToRemove.id; adminUserEditLog.info('Removing platform:', platformId); this.saving = true; try { const url = `/admin/admin-users/${this.userId}/platforms/${platformId}`; window.LogConfig.logApiCall('DELETE', url, null, 'request'); await apiClient.delete(url); window.LogConfig.logApiCall('DELETE', url, null, 'response'); // Reload admin user to get updated platforms await this.loadAdminUser(); Utils.showToast(I18n.t('tenancy.messages.platform_removed_successfully'), 'success'); adminUserEditLog.info('Platform removed successfully'); } catch (error) { window.LogConfig.logError(error, 'Remove Platform'); Utils.showToast(error.message || 'Failed to remove platform', 'error'); } finally { this.saving = false; this.platformToRemove = null; } }, // Open platform assignment modal openPlatformModal() { this.showPlatformModal = true; this.selectedPlatformId = null; }, // Intermediate step for double-confirm delete confirmDeleteStep() { adminUserEditLog.info('First delete confirmation accepted, showing final confirmation'); this.showDeleteFinalModal = true; }, // Delete admin user async deleteAdminUser() { adminUserEditLog.info('Delete admin user requested:', this.userId); // Prevent self-deletion if (this.adminUser.id === this.currentUserId) { Utils.showToast(I18n.t('tenancy.messages.you_cannot_delete_your_own_account'), 'error'); return; } this.saving = true; try { const url = `/admin/admin-users/${this.userId}`; window.LogConfig.logApiCall('DELETE', url, null, 'request'); await apiClient.delete(url); window.LogConfig.logApiCall('DELETE', url, null, 'response'); Utils.showToast(I18n.t('tenancy.messages.admin_user_deleted_successfully'), 'success'); adminUserEditLog.info('Admin user deleted successfully'); // Redirect to admin users list setTimeout(() => window.location.href = '/admin/admin-users', 1500); } catch (error) { window.LogConfig.logError(error, 'Delete Admin User'); Utils.showToast(error.message || 'Failed to delete admin user', 'error'); } finally { this.saving = false; } } }; } adminUserEditLog.info('Admin user edit module loaded');