import Api from './api.js';
import Storage from './storage.js';
class Users {
#api;
#storage;
loginForm;
usernameInput;
passcodeInput;
loginButton;
errorMessageDiv;
logoutButton;
// Admin Panel Elements
userTableContainer;
userIdInput;
adminUsernameInput;
adminPasscodeInput;
adminNameInput;
adminEmailInput;
adminCheckbox;
saveUserButton;
clearUserFormButton;
adminForm;
addFundsForm;
addFundsUserIdInput;
addFundsAmountInput;
globalSummaryContainer;
constructor() {
this.loadTheme();
this.#api = new Api();
this.#storage = new Storage();
this.init_elements();
this.init_interactions();
this.checkAdminStatusAndLoadUsers();
}
init_elements() {
this.loginForm = document.getElementById('login-form');
this.usernameInput = document.getElementById('username');
this.passcodeInput = document.getElementById('passcode');
this.loginButton = document.getElementById('login-button');
this.errorMessageDiv = document.getElementById('login-error-message');
this.logoutButton = document.getElementById('id-btn-logout');
// Admin Panel Elements
this.userTableContainer = document.getElementById('id-div-user-table-container');
this.userIdInput = document.getElementById('id-user-id');
this.adminUsernameInput = document.getElementById('id-username');
this.adminPasscodeInput = document.getElementById('id-passcode');
this.adminNameInput = document.getElementById('id-name');
this.adminEmailInput = document.getElementById('id-email');
this.adminCheckbox = document.getElementById('id-admin');
this.saveUserButton = document.getElementById('id-btn-save-user');
this.clearUserFormButton = document.getElementById('id-btn-clear-user-form');
this.adminForm = document.getElementById('id-form-admin-options');
this.addFundsForm = document.getElementById('id-form-add-funds');
this.addFundsUserIdInput = document.getElementById('id-add-funds-user-id');
this.addFundsAmountInput = document.getElementById('id-add-funds-amount');
this.globalSummaryContainer = document.getElementById('id-div-global-summary-container');
}
init_interactions() {
if (this.loginForm) {
this.loginForm.addEventListener('submit', (event) => {
event.preventDefault();
this.handle_login();
});
}
if (this.logoutButton) {
this.logoutButton.addEventListener('click', (event) => {
event.preventDefault();
this.handle_logout();
});
}
// Admin Panel Interactions
if (this.saveUserButton) {
this.saveUserButton.addEventListener('click', (event) => {
event.preventDefault();
this.handleAddOrUpdateUser();
});
}
if (this.clearUserFormButton) {
this.clearUserFormButton.addEventListener('click', () => {
this.clearUserForm();
});
}
if (this.addFundsForm) {
this.addFundsForm.addEventListener('submit', (event) => {
event.preventDefault();
this.handleAddFunds();
});
}
const btnAppOptions = document.getElementById('btn-app-options');
if (btnAppOptions) {
btnAppOptions.addEventListener('click', () => {
this.toggleAdminFormVisibility(true);
this.checkAdminStatusAndLoadUsers();
});
}
const btnConvOptions = document.getElementById('id-btn-conversation-options');
if (btnConvOptions) {
btnConvOptions.addEventListener('click', () => this.toggleAdminFormVisibility(false));
}
const btnCloseOptions = document.getElementById('btn-options-close');
if (btnCloseOptions) {
btnCloseOptions.addEventListener('click', () => this.toggleAdminFormVisibility(false));
}
}
toggleAdminFormVisibility(show) {
if (this.adminForm) {
this.adminForm.style.display = show ? 'block' : 'none';
}
}
handle_login() {
const username = this.usernameInput.value;
const passcode = this.passcodeInput.value;
this.errorMessageDiv.textContent = '';
this.login(username, passcode,
(response) => {
if (response.session_guid) {
window.location.reload();
} else {
this.errorMessageDiv.textContent = response.error || 'Login failed. Please check your credentials.';
}
},
(error) => {
console.error('Login API error:', error);
this.errorMessageDiv.textContent = 'An error occurred during login. Please try again later.';
}
);
}
handle_logout() {
this.logout(
(response) => {
if(response.success){
window.location.reload();
}
},
(error) => {
console.error('Logout API error:', error);
}
);
}
login(username, passcode, on_success, on_failure) {
let data = {
'action': 'login',
'username': username,
'passcode': passcode,
'location_id': this.#storage.get_location_id()
};
this.#api.post(data, on_success, on_failure, 'users');
}
logout(on_success, on_failure) {
let data = {
'action': 'logout',
'location_id': this.#storage.get_location_id()
};
this.#api.post(data, on_success, on_failure, 'users');
}
checkAdminStatusAndLoadUsers() {
this.#api.post({'action': 'session'}, (response) => {
if (response.isLoggedIn && response.isAdmin) {
this.loadUsers();
this.loadGlobalSummary();
}
}, (error) => {
console.error('Session check API error:', error);
}, 'users');
}
loadUsers() {
this.#api.post({'action': 'get_all_users'}, (response) => {
if (response.success) {
this.renderUserTable(response.users);
} else {
console.error('Failed to load users:', response.error);
}
}, (error) => {
console.error('Get all users API error:', error);
}, 'users');
}
renderUserTable(users) {
if (!this.userTableContainer) return;
let tableHtml = `
<table border="1" width="100%">
<thead>
<tr>
<th>ID</th>
<th>Username</th>
<th>Name</th>
<th>Email</th>
<th>Admin</th>
<th>Budget</th>
<th>Spent</th>
<th>Profit</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
`;
users.forEach(user => {
tableHtml += `
<tr data-user-id="${user.id}">
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.name || ''}</td>
<td>${user.email || ''}</td>
<td>${user.admin == 1 ? 'Yes' : 'No'}</td>
<td>${user.lifetime_budget || 0}</td>
<td>${user.lifetime_spend || 0}</td>
<td>${user.lifetime_profit || 0}</td>
<td>
<button class="btn-edit-user" data-id="${user.id}">Edit</button>
<button class="btn-delete-user" data-id="${user.id}">Delete</button>
<button class="btn-add-funds" data-id="${user.id}">Add Funds</button>
</td>
</tr>
`;
});
tableHtml += `
</tbody>
</table>
`;
this.userTableContainer.innerHTML = tableHtml;
this.userTableContainer.querySelectorAll('.btn-edit-user').forEach(button => {
button.addEventListener('click', (event) => this.editUser(event.target.dataset.id));
});
this.userTableContainer.querySelectorAll('.btn-delete-user').forEach(button => {
button.addEventListener('click', (event) => this.deleteUser(event.target.dataset.id));
});
this.userTableContainer.querySelectorAll('.btn-add-funds').forEach(button => {
button.addEventListener('click', (event) => this.showAddFundsForm(event.target.dataset.id));
});
}
editUser(userId) {
this.#api.post({'action': 'get_user_by_id', 'id': userId}, (response) => {
if (response.success && response.user) {
const user = response.user;
this.userIdInput.value = user.id;
this.adminUsernameInput.value = user.username;
this.adminPasscodeInput.value = ''; // Passcode is not retrieved for security
this.adminNameInput.value = user.name || '';
this.adminEmailInput.value = user.email || '';
this.adminCheckbox.checked = user.admin == 1;
} else {
console.error('Failed to get user details:', response.error);
}
}, (error) => {
console.error('Get user by ID API error:', error);
}, 'users');
}
handleAddOrUpdateUser() {
const id = this.userIdInput.value || null;
const username = this.adminUsernameInput.value;
const passcode = this.adminPasscodeInput.value;
const name = this.adminNameInput.value;
const email = this.adminEmailInput.value;
const admin = this.adminCheckbox.checked;
if (!username) {
alert('Username is required.');
return;
}
if (!id && !passcode) { // Passcode is required only for new users
alert('Passcode is required for new users.');
return;
}
const data = {
'action': 'add_or_update_user',
'id': id,
'username': username,
'name': name,
'email': email,
'admin': admin
};
if (passcode) { // Only add passcode to data if it's not empty
data.passcode = passcode;
}
this.#api.post(data, (response) => {
if (response.success) {
alert(response.message);
this.clearUserForm();
this.loadUsers();
} else {
alert('Error: ' + response.error);
}
}, (error) => {
console.error('Add/Update user API error:', error);
alert('An error occurred while saving the user.');
}, 'users');
}
deleteUser(userId) {
if (!confirm('Are you sure you want to delete this user?')) {
return;
}
this.#api.post({'action': 'delete_user', 'id': userId}, (response) => {
if (response.success) {
alert(response.message);
this.loadUsers();
} else {
alert('Error: ' + response.error);
}
}, (error) => {
console.error('Delete user API error:', error);
alert('An error occurred while deleting the user.');
}, 'users');
}
clearUserForm() {
this.userIdInput.value = '';
this.adminUsernameInput.value = '';
this.adminPasscodeInput.value = '';
this.adminNameInput.value = '';
this.adminEmailInput.value = '';
this.adminCheckbox.checked = false;
}
showAddFundsForm(userId) {
this.addFundsUserIdInput.value = userId;
this.addFundsForm.style.display = 'block';
}
handleAddFunds() {
const userId = this.addFundsUserIdInput.value;
const amount = this.addFundsAmountInput.value;
if (!amount) {
alert('Amount is required.');
return;
}
this.#api.post({
'action': 'add_funds',
'id': userId,
'amount': amount
}, (response) => {
if (response.success) {
alert(response.message);
this.addFundsForm.style.display = 'none';
this.addFundsAmountInput.value = '';
this.loadUsers();
this.loadGlobalSummary();
} else {
alert('Error: ' + response.error);
}
}, (error) => {
console.error('Add funds API error:', error);
alert('An error occurred while adding funds.');
}, 'users');
}
loadGlobalSummary() {
this.#api.post({'action': 'get_global_budget_summary'}, (response) => {
if (response.success) {
this.renderGlobalSummary(response.summary);
} else {
console.error('Failed to load global summary:', response.error);
}
}, (error) => {
console.error('Get global summary API error:', error);
}, 'users');
}
renderGlobalSummary(summary) {
if (!this.globalSummaryContainer) return;
this.globalSummaryContainer.innerHTML = `
<h3>Global Budget Summary</h3>
<p>Total Budget: ${summary.total_budget}</p>
<p>Total Spent: ${summary.total_spend}</p>
<p>Total Profit: ${summary.total_profit}</p>
`;
}
loadTheme() {
const KEY_APP_CONFIG = 'APP_CONFIG';
const KEY_CONFIG_THEME = 'THEME';
const config = JSON.parse(localStorage.getItem(KEY_APP_CONFIG) || '{}');
let theme = (config && config[KEY_CONFIG_THEME]) ? config[KEY_CONFIG_THEME] : 'theme_dark';
const themes = ['theme_dark', 'theme_light'];
if (!themes.includes(theme)) {
theme = 'theme_dark';
}
const required_hrefs = [
'dynamic.php?s=base&t=' + theme,
'dynamic.php?s=style&t=' + theme
];
const existing_links = Array.from(document.querySelectorAll('link[rel="stylesheet"]'));
const current_hrefs = existing_links.map(link => link.getAttribute('href'));
const is_already_applied = required_hrefs.every(href => current_hrefs.includes(href));
if (!is_already_applied) {
const old_links = existing_links.filter(link => {
const href = link.getAttribute('href') || '';
return href.includes('dynamic.php?s=');
});
let loaded_count = 0;
const on_link_load = () => {
loaded_count++;
if (loaded_count === required_hrefs.length) {
old_links.forEach(link => link.remove());
this.fadeOutLoader();
}
};
required_hrefs.forEach(href => {
let link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
link.onload = on_link_load;
link.onerror = on_link_load;
document.head.appendChild(link);
});
} else {
this.fadeOutLoader();
}
}
fadeOutLoader() {
const loader = document.querySelector('.page-loader');
if (loader) {
loader.style.opacity = '0';
setTimeout(() => {
loader.style.display = 'none';
}, 500);
}
}
}
export default Users;