diff --git a/app/routes/admin_pages.py b/app/routes/admin_pages.py
index d0aaf037..1c6193e5 100644
--- a/app/routes/admin_pages.py
+++ b/app/routes/admin_pages.py
@@ -499,7 +499,7 @@ async def admin_user_edit_page(
raise HTTPException(status_code=403, detail="Super admin access required")
return templates.TemplateResponse(
- "admin/user-edit.html",
+ "admin/admin-user-edit.html",
{
"request": request,
"user": current_user,
diff --git a/app/templates/admin/admin-user-edit.html b/app/templates/admin/admin-user-edit.html
new file mode 100644
index 00000000..071700a9
--- /dev/null
+++ b/app/templates/admin/admin-user-edit.html
@@ -0,0 +1,259 @@
+{# app/templates/admin/admin-user-edit.html #}
+{% extends "admin/base.html" %}
+{% from 'shared/macros/alerts.html' import loading_state %}
+{% from 'shared/macros/headers.html' import edit_page_header %}
+
+{% block title %}Edit Admin User{% endblock %}
+
+{% block alpine_data %}adminUserEditPage(){% endblock %}
+
+{% block content %}
+{% call edit_page_header('Edit Admin User', '/admin/admin-users', subtitle_show='adminUser', back_label='Back to Admin Users') %}
+ @
+{% endcall %}
+
+{{ loading_state('Loading admin user...', show_condition='loading') }}
+
+
+
+
+
+
+ Quick Actions
+
+
+
+
+
+
+
+
+
+
+
+ Super Admin
+
+
+ Platform Admin
+
+
+ Active
+
+
+ Inactive
+
+
+
+
+
+
+
+
+ Admin Information
+
+
+
+
+
+
+
+
+
+ Platform Assignments
+
+
+
+
+
+
+
+
+
+
+
No platforms assigned
+
+
+
+
+ Platform admins must be assigned to at least one platform.
+
+
+
+
+
+
+
+
+
+
+
Super Admin Access
+
This user has full access to all platforms and administrative functions.
+
+
+
+
+
+
+
+
+ Danger Zone
+
+
+
+
+
+
+
+ Deleting an admin user is permanent and cannot be undone.
+
+
+
+
+
+
+
+
+
+ Assign Platform
+
+
+
+
+
+
+
+
+
+
+
+ All available platforms have been assigned to this admin.
+
+
+
+
+
+
+
+
+
+{% endblock %}
+
+{% block extra_scripts %}
+
+{% endblock %}
diff --git a/static/admin/js/admin-user-edit.js b/static/admin/js/admin-user-edit.js
new file mode 100644
index 00000000..e4f3872d
--- /dev/null
+++ b/static/admin/js/admin-user-edit.js
@@ -0,0 +1,333 @@
+// 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,
+
+ // Platform assignment state
+ showPlatformModal: false,
+ availablePlatforms: [],
+ selectedPlatformId: null,
+
+ // Initialize
+ async init() {
+ 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('Invalid admin user URL', 'error');
+ setTimeout(() => window.location.href = '/admin/admin-users', 2000);
+ }
+
+ adminUserEditLog.info('=== ADMIN USER EDIT PAGE INITIALIZATION COMPLETE ===');
+ },
+
+ // 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
+ };
+
+ adminUserEditLog.info(`Admin user loaded in ${duration}ms`, {
+ id: this.adminUser.id,
+ username: this.adminUser.username,
+ is_super_admin: this.adminUser.is_super_admin
+ });
+
+ } catch (error) {
+ window.LogConfig.logError(error, 'Load Admin User');
+ Utils.showToast('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.is_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);
+ },
+
+ // Toggle super admin status
+ async toggleSuperAdmin() {
+ const newStatus = !this.adminUser.is_super_admin;
+ const action = newStatus ? 'promote to' : 'demote from';
+ adminUserEditLog.info(`Toggle super admin: ${action}`);
+
+ // Prevent self-demotion
+ if (this.adminUser.id === this.currentUserId && !newStatus) {
+ Utils.showToast('You cannot demote yourself from super admin', 'error');
+ return;
+ }
+
+ if (!confirm(`Are you sure you want to ${action} super admin "${this.adminUser.username}"?`)) {
+ adminUserEditLog.info('Super admin toggle cancelled by user');
+ return;
+ }
+
+ this.saving = true;
+ try {
+ const url = `/admin/admin-users/${this.userId}/super-admin`;
+ window.LogConfig.logApiCall('PUT', url, { is_super_admin: newStatus }, 'request');
+
+ const response = await apiClient.put(url, { is_super_admin: newStatus });
+
+ window.LogConfig.logApiCall('PUT', url, response, 'response');
+
+ this.adminUser.is_super_admin = response.is_super_admin;
+ // Clear platforms if promoted to super admin
+ if (response.is_super_admin) {
+ this.adminUser.platforms = [];
+ }
+
+ const actionDone = newStatus ? '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('You cannot deactivate your own account', 'error');
+ return;
+ }
+
+ if (!confirm(`Are you sure you want to ${action} "${this.adminUser.username}"?`)) {
+ adminUserEditLog.info('Status toggle cancelled by user');
+ 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('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;
+ }
+ },
+
+ // Remove platform from admin
+ async removePlatform(platformId) {
+ const platform = this.adminUser.platforms.find(p => p.id === platformId);
+ const platformName = platform ? platform.name : platformId;
+
+ // Validate: platform admin must have at least one platform
+ if (this.adminUser.platforms.length <= 1) {
+ Utils.showToast('Platform admin must be assigned to at least one platform', 'error');
+ return;
+ }
+
+ if (!confirm(`Are you sure you want to remove "${platformName}" from this admin?`)) {
+ adminUserEditLog.info('Platform removal cancelled by user');
+ return;
+ }
+
+ 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('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;
+ }
+ },
+
+ // Open platform assignment modal
+ openPlatformModal() {
+ this.showPlatformModal = true;
+ this.selectedPlatformId = null;
+ },
+
+ // Delete admin user
+ async deleteAdminUser() {
+ adminUserEditLog.info('Delete admin user requested:', this.userId);
+
+ // Prevent self-deletion
+ if (this.adminUser.id === this.currentUserId) {
+ Utils.showToast('You cannot delete your own account', 'error');
+ return;
+ }
+
+ if (!confirm(`Are you sure you want to delete admin user "${this.adminUser.username}"?\n\nThis action cannot be undone.`)) {
+ adminUserEditLog.info('Delete cancelled by user');
+ return;
+ }
+
+ // Second confirmation for safety
+ if (!confirm(`FINAL CONFIRMATION\n\nAre you absolutely sure you want to delete "${this.adminUser.username}"?`)) {
+ adminUserEditLog.info('Delete cancelled by user (second confirmation)');
+ 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('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');