2 directories, 30 files

tinai

Home / testing / ai / tinai
import Api from './api.js';
import Storage from './storage.js';
import { getEl, addSafeEventListener, setElementDisplay } from './util/dom-utils.js';
import { applyTheme, fadeOutLoader } from './util/theme-utils.js';
import { customConfirm } from './util/confirm-dialog.js';

/**
 * Users authentication, profile management, and administrative control.
 */
class Users {

	static instance = null;
	static isAdmin = false;
	static currentUser = null;

	#api;
	#storage;

	// Auth elements
	loginForm;
	usernameInput;
	passcodeInput;
	loginButton;
	errorMessageDiv;
	logoutButton;

	// Profile Form Elements
	profileForm;
	profileNameInput;
	profileEmailInput;
	profileStatusDiv;
	saveProfileButton;

	// Account Elements
	accountBalanceSpan;
	accountCostMonthSpan;
	accountCostAllSpan;

	// Admin Elements - Main
	adminForm;
	btnAdminShowCreateUser;
	btnAdminShowAddFunds;
	adminUsersTbody;
	adminStatusDiv;

	// Admin Elements - Create User
	adminCreateUserPanel;
	newUsernameInput;
	newPasswordInput;
	newNameInput;
	newEmailInput;
	newRoleSelect;
	newBalanceInput;
	btnAdminCancelCreate;
	btnAdminSubmitCreate;

	// Admin Elements - Edit User
	adminEditUserPanel;
	editUserIdInput;
	editUsernameDisplay;
	editUsernameInput;
	editPasswordInput;
	editNameInput;
	editEmailInput;
	editRoleSelect;
	btnAdminCancelEdit;
	btnAdminSubmitEdit;

	// Admin Elements - Add Funds
	adminAddFundsPanel;
	adminFundsUserSelect;
	adminFundsAmountInput;
	btnAdminCancelAddFunds;
	btnAdminSubmitAddFunds;

	/**
	 * Initializes the Users class, UI element bindings, and session check.
	 */
	constructor() {
		Users.instance = this;
		this.#api = new Api();
		this.#storage = new Storage();

		// Apply theme on initialization
		this.applySavedTheme();

		// Auth elements
		this.loginForm = getEl('login-form') || getEl('form-login');
		this.usernameInput = getEl('username') || getEl('login-username');
		this.passcodeInput = getEl('passcode') || getEl('login-passcode');
		this.loginButton = getEl('login-button') || getEl('btn-login');
		this.errorMessageDiv = getEl('login-error-message');
		this.logoutButton = getEl('id-btn-logout') || getEl('btn-logout');

		// Profile elements
		this.profileForm = getEl('id-form-profile-options');
		this.profileNameInput = getEl('profile-name');
		this.profileEmailInput = getEl('profile-email');
		this.profileStatusDiv = getEl('profile-status-message');
		this.saveProfileButton = getEl('btn-save-profile');

		// Account elements
		this.accountBalanceSpan = getEl('account-balance-amount');
		this.accountCostMonthSpan = getEl('account-cost-month');
		this.accountCostAllSpan = getEl('account-cost-all');

		// Admin elements - Main
		this.adminForm = getEl('id-form-admin-options');
		this.btnAdminShowCreateUser = getEl('btn-admin-show-create-user');
		this.btnAdminShowAddFunds = getEl('btn-admin-show-add-funds');
		this.adminUsersTbody = getEl('admin-users-tbody');
		this.adminStatusDiv = getEl('admin-management-status');

		// Admin elements - Create User
		this.adminCreateUserPanel = getEl('admin-create-user-panel');
		this.newUsernameInput = getEl('new-user-username');
		this.newPasswordInput = getEl('new-user-password');
		this.newNameInput = getEl('new-user-name');
		this.newEmailInput = getEl('new-user-email');
		this.newRoleSelect = getEl('new-user-role');
		this.newBalanceInput = getEl('new-user-balance');
		this.btnAdminCancelCreate = getEl('btn-admin-cancel-create');
		this.btnAdminSubmitCreate = getEl('btn-admin-submit-create');

		// Admin elements - Edit User
		this.adminEditUserPanel = getEl('admin-edit-user-panel');
		this.editUserIdInput = getEl('admin-edit-user-id');
		this.editUsernameDisplay = getEl('admin-edit-username-display');
		this.editUsernameInput = getEl('admin-edit-username');
		this.editPasswordInput = getEl('admin-edit-password');
		this.editNameInput = getEl('admin-edit-name');
		this.editEmailInput = getEl('admin-edit-email');
		this.editRoleSelect = getEl('admin-edit-role');
		this.btnAdminCancelEdit = getEl('btn-admin-cancel-edit');
		this.btnAdminSubmitEdit = getEl('btn-admin-submit-edit');

		// Admin elements - Add Funds
		this.adminAddFundsPanel = getEl('admin-add-funds-panel');
		this.adminFundsUserSelect = getEl('admin-funds-user-select');
		this.adminFundsAmountInput = getEl('admin-funds-amount');
		this.btnAdminCancelAddFunds = getEl('btn-admin-cancel-add-funds');
		this.btnAdminSubmitAddFunds = getEl('btn-admin-submit-add-funds');

		this.initEventListeners();
		this.checkLoginStatus();
	}

	/**
	 * Applies the saved theme from configuration.
	 */
	applySavedTheme() {
		const config = this.#storage.get_app_config();
		const theme = (config && config[this.#storage.KEY_CONFIG_THEME]) ? config[this.#storage.KEY_CONFIG_THEME] : 'theme_dark';
		applyTheme(theme, true);
	}

	/**
	 * Binds event listeners for user login, logout, profile, and admin forms.
	 */
	initEventListeners() {
		if (this.loginForm) {
			addSafeEventListener(this.loginForm, 'submit', (e) => {
				e.preventDefault();
				this.handleLogin();
			});
		}
		addSafeEventListener(this.loginButton, 'click', (e) => {
			if (e) e.preventDefault();
			this.handleLogin();
		});
		addSafeEventListener(this.logoutButton, 'click', (e) => {
			if (e) e.preventDefault();
			this.handleLogout();
		});

		// Profile form
		if (this.profileForm) {
			addSafeEventListener(this.profileForm, 'submit', (e) => {
				e.preventDefault();
				this.handleSaveProfile();
			});
		}
		addSafeEventListener(this.saveProfileButton, 'click', (e) => {
			if (e) e.preventDefault();
			this.handleSaveProfile();
		});

		// Admin management - Create user
		addSafeEventListener(this.btnAdminShowCreateUser, 'click', (e) => {
			if (e) e.preventDefault();
			if (this.adminAddFundsPanel) setElementDisplay(this.adminAddFundsPanel, 'none');
			if (this.adminEditUserPanel) setElementDisplay(this.adminEditUserPanel, 'none');
			if (this.adminCreateUserPanel) {
				const isHidden = this.adminCreateUserPanel.style.display === 'none' || !this.adminCreateUserPanel.style.display;
				setElementDisplay(this.adminCreateUserPanel, isHidden ? 'block' : 'none');
			}
		});
		addSafeEventListener(this.btnAdminCancelCreate, 'click', (e) => {
			if (e) e.preventDefault();
			this.resetCreateUserPanel();
		});
		addSafeEventListener(this.btnAdminSubmitCreate, 'click', (e) => {
			if (e) e.preventDefault();
			this.handleCreateUser();
		});

		// Admin management - Edit user
		addSafeEventListener(this.btnAdminCancelEdit, 'click', (e) => {
			if (e) e.preventDefault();
			this.resetEditUserPanel();
		});
		addSafeEventListener(this.btnAdminSubmitEdit, 'click', (e) => {
			if (e) e.preventDefault();
			this.handleSaveEditUser();
		});

		// Admin management - Add funds
		addSafeEventListener(this.btnAdminShowAddFunds, 'click', (e) => {
			if (e) e.preventDefault();
			if (this.adminCreateUserPanel) setElementDisplay(this.adminCreateUserPanel, 'none');
			if (this.adminEditUserPanel) setElementDisplay(this.adminEditUserPanel, 'none');
			if (this.adminAddFundsPanel) {
				const isHidden = this.adminAddFundsPanel.style.display === 'none' || !this.adminAddFundsPanel.style.display;
				setElementDisplay(this.adminAddFundsPanel, isHidden ? 'block' : 'none');
			}
		});
		addSafeEventListener(this.btnAdminCancelAddFunds, 'click', (e) => {
			if (e) e.preventDefault();
			this.resetAddFundsPanel();
		});
		addSafeEventListener(this.btnAdminSubmitAddFunds, 'click', (e) => {
			if (e) e.preventDefault();
			this.handleAddFundsFromAdmin();
		});
	}

	/**
	 * Handles authentication request on login form submission.
	 */
	handleLogin() {
		if (!this.usernameInput || !this.passcodeInput) return;
		const username = this.usernameInput.value.trim();
		const passcode = this.passcodeInput.value.trim();

		if (!username || !passcode) {
			this.displayErrorMessage('Please enter both username and passcode.');
			return;
		}

		this.displayErrorMessage('');

		this.#api.post(
			{ action: 'login', username, passcode },
			(response) => {
				if (response.success) {
					window.location.reload();
				} else {
					this.displayErrorMessage(response.error || response.message || 'Login failed.');
				}
			},
			(error) => {
				this.displayErrorMessage('An error occurred during login. Please try again.');
				console.error('Login error:', error);
			},
			'users'
		);
	}

	/**
	 * Handles user logout and reloads the application.
	 */
	handleLogout() {
		this.#api.post(
			{ action: 'logout' },
			(response) => {
				if (response.success) {
					window.location.reload();
				} else {
					alert(response.message || response.error || 'Logout failed.');
				}
			},
			(error) => {
				alert('An error occurred during logout. Please try again.');
				console.error('Logout error:', error);
			},
			'users'
		);
	}

	/**
	 * Displays an authentication error message.
	 * @param {string} message - Error message text.
	 */
	displayErrorMessage(message) {
		if (this.errorMessageDiv) {
			this.errorMessageDiv.textContent = message;
			setElementDisplay(this.errorMessageDiv, message ? 'block' : 'none');
		}
	}

	/**
	 * Checks current session authentication status with the server.
	 */
	checkLoginStatus() {
		this.#api.post(
			{ action: 'session' },
			(response) => {
				if (response['isLoggedIn']) {
					Users.isAdmin = !!response['isAdmin'];
					setElementDisplay(this.loginForm, 'none');
					setElementDisplay(this.logoutButton, 'block');

					this.loadProfile();
					if (Users.isAdmin) {
						this.loadAdminUsers();
					}
				} else {
					Users.isAdmin = false;
					setElementDisplay(this.loginForm, 'block');
					setElementDisplay(this.logoutButton, 'none');
					fadeOutLoader();
				}
			},
			(error) => {
				console.error('Check login status error:', error);
				fadeOutLoader();
			},
			'users'
		);
	}

	/**
	 * Fetches user profile and balance data from the server.
	 */
	loadProfile() {
		this.#api.post(
			{ action: 'get_profile' },
			(response) => {
				if (response.success && response['profile']) {
					Users.currentUser = response['profile'];
					this.displayProfile(response['profile']);
				}
				fadeOutLoader();
			},
			(error) => {
				console.error('Load profile error:', error);
				fadeOutLoader();
			},
			'users'
		);
	}

	/**
	 * Populates profile and account balance information into the UI.
	 * @param {object} profile - User profile data object.
	 */
	displayProfile(profile) {
		if (this.profileNameInput) {
			this.profileNameInput.value = profile.name || profile.username || '';
		}
		if (this.profileEmailInput) {
			this.profileEmailInput.value = profile.email || '';
		}
		const balance = parseFloat(profile.balance || 0);
		const lifetimeSpend = parseFloat(profile.lifetime_spend || 0);

		if (this.accountBalanceSpan) {
			this.accountBalanceSpan.textContent = `$${balance.toFixed(6)}`;
		}
		if (this.accountCostMonthSpan) {
			this.accountCostMonthSpan.textContent = `$${lifetimeSpend.toFixed(6)}`;
		}
		if (this.accountCostAllSpan) {
			this.accountCostAllSpan.textContent = `$${lifetimeSpend.toFixed(6)}`;
		}
	}

	/**
	 * Submits updated user profile information (name, email) to the server.
	 */
	handleSaveProfile() {
		const name = this.profileNameInput ? this.profileNameInput.value.trim() : '';
		const email = this.profileEmailInput ? this.profileEmailInput.value.trim() : '';

		this.#api.post(
			{ action: 'update_profile', name, email },
			(response) => {
				if (response.success) {
					this.displayProfileStatus('Profile saved successfully!', false);
					this.loadProfile();
				} else {
					this.displayProfileStatus(response.error || response.message || 'Failed to save profile.', true);
				}
			},
			(error) => {
				this.displayProfileStatus('An error occurred while saving profile.', true);
				console.error('Save profile error:', error);
			},
			'users'
		);
	}

	/**
	 * Displays a temporary status message in the profile form.
	 * @param {string} message - Status message text.
	 * @param {boolean} isError - Whether the status represents an error.
	 */
	displayProfileStatus(message, isError) {
		if (this.profileStatusDiv) {
			this.profileStatusDiv.textContent = message;
			this.profileStatusDiv.className = isError ? 'status-msg status-error' : 'status-msg status-success';
			setElementDisplay(this.profileStatusDiv, 'block');
			setTimeout(() => {
				setElementDisplay(this.profileStatusDiv, 'none');
			}, 4000);
		}
	}

	/**
	 * Loads all users for the admin management table and user dropdown.
	 */
	loadAdminUsers() {
		if (!Users.isAdmin) return;

		this.#api.post(
			{ action: 'get_all_users' },
			(response) => {
				if (response.success && Array.isArray(response.users)) {
					this.renderAdminUsersTable(response.users);
					this.populateAdminFundsUserSelect(response.users);
				} else {
					this.displayAdminStatus(response.error || response.message || 'Failed to load users.', true);
				}
			},
			(error) => {
				this.displayAdminStatus('An error occurred while loading users.', true);
				console.error('Load admin users error:', error);
			},
			'users'
		);
	}

	/**
	 * Populates user select dropdown in the admin add funds panel.
	 * @param {Array<object>} users
	 */
	populateAdminFundsUserSelect(users) {
		if (!this.adminFundsUserSelect) return;
		const currentSelected = this.adminFundsUserSelect.value;
		this.adminFundsUserSelect.innerHTML = users.map(user => {
			const label = user.name ? `${user.username} (${user.name})` : user.username;
			const balance = parseFloat(user.balance || 0).toFixed(2);
			return `<option value="${user.id}">${this.escapeHtml(label)} — Balance: $${balance}</option>`;
		}).join('');

		if (currentSelected && users.some(u => String(u.id) === String(currentSelected))) {
			this.adminFundsUserSelect.value = currentSelected;
		}
	}

	/**
	 * Renders the users into the admin table.
	 * @param {Array<object>} users - List of user objects.
	 */
	renderAdminUsersTable(users) {
		if (!this.adminUsersTbody) return;

		this.adminUsersTbody.innerHTML = '';

		users.forEach(user => {
			const tr = document.createElement('tr');

			const balance = parseFloat(user.balance || 0).toFixed(2);
			const spend = parseFloat(user.lifetime_spend || 0).toFixed(2);
			const isUserAdmin = Number(user.admin) === 1;
			const isCurrent = Users.currentUser && String(Users.currentUser.id) === String(user.id);

			tr.innerHTML = `
				<td style="padding: 6px 4px;">
					<strong>${this.escapeHtml(user.username)}</strong>
					${user.name ? `<br/><small style="opacity: 0.7;">${this.escapeHtml(user.name)}</small>` : ''}
					${user.email ? `<br/><small style="opacity: 0.5;">${this.escapeHtml(user.email)}</small>` : ''}
				</td>
				<td style="padding: 6px 4px;">${isUserAdmin ? '<span class="badge-admin">Admin</span>' : 'User'}</td>
				<td style="padding: 6px 4px; font-family: monospace;">$${balance}</td>
				<td style="padding: 6px 4px; font-family: monospace;">$${spend}</td>
				<td style="padding: 6px 4px; text-align: right; white-space: nowrap;">
					<button type="button" class="btn-table-edit-user as-icon" data-user-id="${user.id}" title="Edit User">Edit</button>
					<button type="button" class="btn-table-add-funds as-icon" data-user-id="${user.id}" title="Add Funds">+ Funds</button>
					${!isCurrent ? `<button type="button" class="btn-delete-user as-icon" data-user-id="${user.id}" title="Delete User">Delete</button>` : ''}
				</td>
			`;

			const editBtn = tr.querySelector('.btn-table-edit-user');
			if (editBtn) {
				addSafeEventListener(editBtn, 'click', () => {
					this.openEditUserPanel(user);
				});
			}

			const addFundsBtn = tr.querySelector('.btn-table-add-funds');
			if (addFundsBtn) {
				addSafeEventListener(addFundsBtn, 'click', () => {
					this.openAddFundsPanelForUser(user.id);
				});
			}

			const deleteBtn = tr.querySelector('.btn-delete-user');
			if (deleteBtn) {
				addSafeEventListener(deleteBtn, 'click', async () => {
					if (await customConfirm('Delete User', `Are you sure you want to delete user "${user.username}"?`)) {
						this.handleDeleteUser(user.id);
					}
				});
			}

			this.adminUsersTbody.appendChild(tr);
		});
	}

	/**
	 * Opens Edit User panel with the selected user's details.
	 * @param {object} user
	 */
	openEditUserPanel(user) {
		if (this.adminCreateUserPanel) setElementDisplay(this.adminCreateUserPanel, 'none');
		if (this.adminAddFundsPanel) setElementDisplay(this.adminAddFundsPanel, 'none');
		if (this.adminEditUserPanel) setElementDisplay(this.adminEditUserPanel, 'block');

		if (this.editUserIdInput) this.editUserIdInput.value = user.id;
		if (this.editUsernameDisplay) this.editUsernameDisplay.textContent = user.username;
		if (this.editUsernameInput) this.editUsernameInput.value = user.username;
		if (this.editPasswordInput) this.editPasswordInput.value = '';
		if (this.editNameInput) this.editNameInput.value = user.name || '';
		if (this.editEmailInput) this.editEmailInput.value = user.email || '';
		if (this.editRoleSelect) this.editRoleSelect.value = Number(user.admin) === 1 ? 'admin' : 'user';
	}

	/**
	 * Handles saving edited user changes (including password update).
	 */
	handleSaveEditUser() {
		if (!this.editUserIdInput || !this.editUsernameInput) return;
		const id = parseInt(this.editUserIdInput.value, 10);
		const username = this.editUsernameInput.value.trim();
		const password = this.editPasswordInput ? this.editPasswordInput.value.trim() : '';
		const name = this.editNameInput ? this.editNameInput.value.trim() : '';
		const email = this.editEmailInput ? this.editEmailInput.value.trim() : '';
		const role = this.editRoleSelect ? this.editRoleSelect.value : 'user';

		if (!id || !username) {
			this.displayAdminStatus('User ID and username are required.', true);
			return;
		}

		const payload = {
			action: 'add_or_update_user',
			id,
			username,
			name,
			email,
			admin: role === 'admin'
		};

		if (password) {
			payload.passcode = password;
		}

		this.#api.post(
			payload,
			(response) => {
				if (response.success) {
					this.displayAdminStatus(`User "${username}" updated successfully!`, false);
					this.resetEditUserPanel();
					this.loadProfile();
					this.loadAdminUsers();
				} else {
					this.displayAdminStatus(response.error || response.message || 'Failed to update user.', true);
				}
			},
			(error) => {
				this.displayAdminStatus('An error occurred while updating user.', true);
				console.error('Update user error:', error);
			},
			'users'
		);
	}

	/**
	 * Resets and closes the admin edit user panel.
	 */
	resetEditUserPanel() {
		if (this.adminEditUserPanel) {
			setElementDisplay(this.adminEditUserPanel, 'none');
		}
		if (this.editUserIdInput) this.editUserIdInput.value = '';
		if (this.editUsernameDisplay) this.editUsernameDisplay.textContent = '';
		if (this.editUsernameInput) this.editUsernameInput.value = '';
		if (this.editPasswordInput) this.editPasswordInput.value = '';
		if (this.editNameInput) this.editNameInput.value = '';
		if (this.editEmailInput) this.editEmailInput.value = '';
		if (this.editRoleSelect) this.editRoleSelect.value = 'user';
	}

	/**
	 * Opens Add Funds panel pre-selecting a specific user.
	 * @param {string|number} userId
	 */
	openAddFundsPanelForUser(userId) {
		if (this.adminCreateUserPanel) setElementDisplay(this.adminCreateUserPanel, 'none');
		if (this.adminEditUserPanel) setElementDisplay(this.adminEditUserPanel, 'none');
		if (this.adminAddFundsPanel) setElementDisplay(this.adminAddFundsPanel, 'block');
		if (this.adminFundsUserSelect) this.adminFundsUserSelect.value = String(userId);
		if (this.adminFundsAmountInput) this.adminFundsAmountInput.focus();
	}

	/**
	 * Handles adding funds to a user from the admin Add Funds form.
	 */
	handleAddFundsFromAdmin() {
		if (!this.adminFundsUserSelect || !this.adminFundsAmountInput) return;
		const userId = this.adminFundsUserSelect.value;
		const amount = parseFloat(this.adminFundsAmountInput.value);

		if (!userId) {
			this.displayAdminStatus('Please select a user.', true);
			return;
		}
		if (isNaN(amount) || amount <= 0) {
			this.displayAdminStatus('Please enter a valid amount greater than 0.', true);
			return;
		}

		this.#api.post(
			{ action: 'add_funds', id: userId, amount },
			(response) => {
				if (response.success) {
					this.displayAdminStatus(`Successfully added $${amount.toFixed(2)} in funds!`, false);
					this.resetAddFundsPanel();
					this.loadProfile();
					this.loadAdminUsers();
				} else {
					this.displayAdminStatus(response.error || response.message || 'Failed to add funds.', true);
				}
			},
			(error) => {
				this.displayAdminStatus('An error occurred while adding funds.', true);
				console.error('Add funds error:', error);
			},
			'users'
		);
	}

	/**
	 * Resets and closes the admin add funds panel.
	 */
	resetAddFundsPanel() {
		if (this.adminAddFundsPanel) {
			setElementDisplay(this.adminAddFundsPanel, 'none');
		}
		if (this.adminFundsAmountInput) this.adminFundsAmountInput.value = '10.00';
	}

	/**
	 * Handles creating a new user from the admin create panel.
	 */
	handleCreateUser() {
		const username = this.newUsernameInput ? this.newUsernameInput.value.trim() : '';
		const password = this.newPasswordInput ? this.newPasswordInput.value.trim() : '';
		const name = this.newNameInput ? this.newNameInput.value.trim() : '';
		const email = this.newEmailInput ? this.newEmailInput.value.trim() : '';
		const role = this.newRoleSelect ? this.newRoleSelect.value : 'user';
		const balance = this.newBalanceInput ? parseFloat(this.newBalanceInput.value) || 0 : 0;

		if (!username || !password) {
			this.displayAdminStatus('Username and password are required.', true);
			return;
		}

		this.#api.post(
			{
				action: 'add_or_update_user',
				username,
				passcode: password,
				name,
				email,
				admin: role === 'admin',
				initial_balance: balance
			},
			(response) => {
				if (response.success) {
					this.displayAdminStatus('User created successfully!', false);
					this.resetCreateUserPanel();
					this.loadAdminUsers();
				} else {
					this.displayAdminStatus(response.error || response.message || 'Failed to create user.', true);
				}
			},
			(error) => {
				this.displayAdminStatus('An error occurred while creating user.', true);
				console.error('Create user error:', error);
			},
			'users'
		);
	}

	/**
	 * Resets and closes the admin create user panel.
	 */
	resetCreateUserPanel() {
		if (this.adminCreateUserPanel) {
			setElementDisplay(this.adminCreateUserPanel, 'none');
		}
		if (this.newUsernameInput) this.newUsernameInput.value = '';
		if (this.newPasswordInput) this.newPasswordInput.value = '';
		if (this.newNameInput) this.newNameInput.value = '';
		if (this.newEmailInput) this.newEmailInput.value = '';
		if (this.newRoleSelect) this.newRoleSelect.value = 'user';
		if (this.newBalanceInput) this.newBalanceInput.value = '0.00';
	}

	/**
	 * Handles deleting a user by ID.
	 * @param {number|string} userId
	 */
	handleDeleteUser(userId) {
		this.#api.post(
			{ action: 'delete_user', id: userId },
			(response) => {
				if (response.success) {
					this.displayAdminStatus('User deleted successfully!', false);
					this.loadAdminUsers();
				} else {
					this.displayAdminStatus(response.error || response.message || 'Failed to delete user.', true);
				}
			},
			(error) => {
				this.displayAdminStatus('An error occurred while deleting user.', true);
				console.error('Delete user error:', error);
			},
			'users'
		);
	}

	/**
	 * Displays a temporary status message in the admin panel.
	 * @param {string} message - Status message text.
	 * @param {boolean} isError - Whether the status represents an error.
	 */
	displayAdminStatus(message, isError) {
		if (this.adminStatusDiv) {
			this.adminStatusDiv.textContent = message;
			this.adminStatusDiv.className = isError ? 'status-msg status-error' : 'status-msg status-success';
			setElementDisplay(this.adminStatusDiv, 'block');
			setTimeout(() => {
				setElementDisplay(this.adminStatusDiv, 'none');
			}, 4000);
		}
	}

	/**
	 * Utility method to escape HTML text.
	 * @param {string} str
	 * @returns {string}
	 */
	escapeHtml(str) {
		if (!str) return '';
		const div = document.createElement('div');
		div.textContent = str;
		return div.innerHTML;
	}
}

export default Users;
🌐
users.js ×
Type: Web, text/plain
23.71 Kilobytes
Last Modified 2026-09-05 04:03:23
⬇ Download File