This commit is contained in:
2026-04-20 13:45:29 +07:00
parent ee10a7e480
commit 30e326f92a

View File

@@ -1586,10 +1586,16 @@ class AccountManager {
<div class="users-page p-4 md:p-6 w-full h-full flex flex-col overflow-hidden"> <div class="users-page p-4 md:p-6 w-full h-full flex flex-col overflow-hidden">
<div class="page-header flex justify-between items-center mb-6 shrink-0"> <div class="page-header flex justify-between items-center mb-6 shrink-0">
<h1 class="text-2xl font-bold text-slate-900 dark:text-slate-50">Users Management</h1> <h1 class="text-2xl font-bold text-slate-900 dark:text-slate-50">Users Management</h1>
<button id="addUserBtn" class="bg-primary hover:bg-primary-dim text-on-primary font-bold py-2 px-4 rounded-lg transition-all active:scale-95 flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="material-symbols-outlined text-base">add</span> <button id="addRoleBtn" class="border border-outline-variant/40 hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200 font-bold py-2 px-4 rounded-lg transition-all active:scale-95 flex items-center gap-2">
<span>Add User</span> <span class="material-symbols-outlined text-base">badge</span>
</button> <span>Add Role</span>
</button>
<button id="addUserBtn" class="bg-primary hover:bg-primary-dim text-on-primary font-bold py-2 px-4 rounded-lg transition-all active:scale-95 flex items-center gap-2">
<span class="material-symbols-outlined text-base">add</span>
<span>Add User</span>
</button>
</div>
</div> </div>
<!-- Search and Filter --> <!-- Search and Filter -->
@@ -1716,6 +1722,11 @@ class AccountManager {
if (addBtn) { if (addBtn) {
addBtn.onclick = () => this.openUserModal(); addBtn.onclick = () => this.openUserModal();
} }
const addRoleBtn = document.getElementById('addRoleBtn');
if (addRoleBtn) {
addRoleBtn.onclick = () => this.openRoleModal();
}
} }
getFilteredUsers() { getFilteredUsers() {
@@ -1799,6 +1810,102 @@ class AccountManager {
this.showUserFormModal(null); this.showUserFormModal(null);
} }
openRoleModal() {
this.showRoleFormModal();
}
showRoleFormModal() {
const html = `
<div class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 modal-backdrop open" id="roleModal">
<div class="bg-white dark:bg-slate-900 rounded-lg p-6 w-full max-w-md modal-content">
<h2 class="text-xl font-bold mb-4 text-slate-900 dark:text-slate-50">Add New Role</h2>
<form id="roleForm" class="space-y-4">
<div>
<label class="block text-sm font-medium mb-1">Role Name</label>
<input type="text" id="roleName" placeholder="Manager" class="w-full px-3 py-2 border border-outline-variant/30 rounded-lg bg-surface-container-low dark:bg-slate-800" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Description</label>
<textarea id="roleDescription" placeholder="Describe this role permissions" class="w-full px-3 py-2 border border-outline-variant/30 rounded-lg bg-surface-container-low dark:bg-slate-800 min-h-[90px]"></textarea>
</div>
<div class="flex gap-3 pt-2">
<button type="button" onclick="closeRoleModal()" class="flex-1 px-4 py-2 bg-outline/10 hover:bg-outline/20 rounded-lg transition-colors">Cancel</button>
<button type="submit" class="flex-1 px-4 py-2 bg-primary hover:bg-primary-dim text-on-primary font-bold rounded-lg transition-colors">Save Role</button>
</div>
</form>
</div>
</div>
`;
const editingContainer = document.getElementById('roleModalContainer');
if (editingContainer) {
editingContainer.innerHTML = html;
} else {
const container = document.createElement('div');
container.id = 'roleModalContainer';
document.body.appendChild(container);
container.innerHTML = html;
}
const form = document.getElementById('roleForm');
if (form) {
form.addEventListener('submit', (e) => this.saveRole(e));
}
const modal = document.getElementById('roleModal');
if (modal) {
modal.addEventListener('click', function(e) {
if (e.target === this) {
closeRoleModal();
}
});
}
}
async saveRole(e) {
e.preventDefault();
const roleName = document.getElementById('roleName')?.value.trim();
const description = document.getElementById('roleDescription')?.value.trim();
if (!roleName) {
this.notifyFailure('Role name is required');
return;
}
const roleExists = this.roles.some(role =>
String(role.RoleName || '').trim().toLowerCase() === roleName.toLowerCase()
);
if (roleExists) {
this.notifyWarning('Role already exists');
return;
}
try {
const response = await fetch(`${this.apiBase}/roles`, {
method: 'POST',
headers: this.getAuthHeaders(true),
body: JSON.stringify({ roleName, description: description || null })
});
const data = await response.json();
if (!response.ok || !data.success) {
this.notifyFailure(data.message || 'Create role failed');
return;
}
this.notifySuccess('Role created');
closeRoleModal();
await this.fetchRoles();
if (this.currentPage === 'users') {
this.renderView('users');
}
} catch (err) {
console.error(err);
this.notifyFailure('Create role failed');
}
}
showUserFormModal(userId) { showUserFormModal(userId) {
const user = userId ? this.users.find(u => u.UserId == userId) : null; const user = userId ? this.users.find(u => u.UserId == userId) : null;
@@ -2178,6 +2285,13 @@ function closeUserModal() {
} }
} }
function closeRoleModal() {
const roleModalContainer = document.getElementById('roleModalContainer');
if (roleModalContainer) {
roleModalContainer.innerHTML = '';
}
}
function closeUserDetailsModal() { function closeUserDetailsModal() {
const detailsContainer = document.getElementById('userDetailsModalContainer'); const detailsContainer = document.getElementById('userDetailsModalContainer');
if (detailsContainer) { if (detailsContainer) {