Add user roles
This commit is contained in:
+60
-20
@@ -71,16 +71,36 @@ function showMainApp() {
|
||||
document.getElementById('loginPage').style.display = 'none';
|
||||
document.getElementById('mainApp').style.display = 'block';
|
||||
|
||||
// Handle backward compatibility: convert old is_admin format to role
|
||||
if (!currentUser.role && currentUser.is_admin !== undefined) {
|
||||
currentUser.role = currentUser.is_admin ? 'admin' : 'user';
|
||||
}
|
||||
// Default to 'user' if role is still undefined
|
||||
if (!currentUser.role) {
|
||||
currentUser.role = 'user';
|
||||
}
|
||||
|
||||
const userDisplay = document.getElementById('currentUser');
|
||||
if (userDisplay) {
|
||||
userDisplay.textContent = `👤 ${currentUser.username}`;
|
||||
const roleLabel = currentUser.role.charAt(0).toUpperCase() + currentUser.role.slice(1);
|
||||
userDisplay.textContent = `👤 ${currentUser.username} [${roleLabel}]`;
|
||||
}
|
||||
|
||||
const adminBtn = document.getElementById('adminBtn');
|
||||
if (adminBtn) {
|
||||
adminBtn.style.display = currentUser.is_admin ? 'block' : 'none';
|
||||
adminBtn.style.display = currentUser.role === 'admin' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
// Hide action buttons for read-only users
|
||||
const isReadOnly = currentUser.role === 'readonly';
|
||||
const addDrugBtn = document.getElementById('addDrugBtn');
|
||||
const dispenseBtn = document.getElementById('dispenseBtn');
|
||||
const printNotesBtn = document.getElementById('printNotesBtn');
|
||||
|
||||
if (addDrugBtn) addDrugBtn.style.display = isReadOnly ? 'none' : 'block';
|
||||
if (dispenseBtn) dispenseBtn.style.display = isReadOnly ? 'none' : 'block';
|
||||
if (printNotesBtn) printNotesBtn.style.display = isReadOnly ? 'none' : 'block';
|
||||
|
||||
setupEventListeners();
|
||||
loadDrugs();
|
||||
}
|
||||
@@ -384,6 +404,7 @@ function renderDrugs() {
|
||||
const totalQuantity = drug.variants.reduce((sum, v) => sum + v.quantity, 0);
|
||||
const isLowStock = lowStockVariants > 0;
|
||||
const isExpanded = expandedDrugs.has(drug.id);
|
||||
const isReadOnly = currentUser.role === 'readonly';
|
||||
|
||||
const variantsHtml = isExpanded ? `
|
||||
${drug.variants.map(variant => {
|
||||
@@ -402,10 +423,12 @@ function renderDrugs() {
|
||||
</div>
|
||||
</div>
|
||||
<div class="variant-actions">
|
||||
<button class="btn btn-primary btn-small" onclick="prescribeVariant(${variant.id}, '${drug.name.replace(/'/g, "\\'")}', '${variant.strength.replace(/'/g, "\\'")}', '${variant.unit.replace(/'/g, "\\'")}')">🏷️ Prescribe & Print</button>
|
||||
<button class="btn btn-success btn-small" onclick="dispenseVariant(${variant.id})">💊 Dispense</button>
|
||||
<button class="btn btn-warning btn-small" onclick="openEditVariantModal(${variant.id})">Edit</button>
|
||||
<button class="btn btn-danger btn-small" onclick="deleteVariant(${variant.id})">Delete</button>
|
||||
${!isReadOnly ? `
|
||||
<button class="btn btn-primary btn-small" onclick="prescribeVariant(${variant.id}, '${drug.name.replace(/'/g, "\\'")}', '${variant.strength.replace(/'/g, "\\'")}', '${variant.unit.replace(/'/g, "\\'")}')">🏷️ Prescribe & Print</button>
|
||||
<button class="btn btn-success btn-small" onclick="dispenseVariant(${variant.id})">💊 Dispense</button>
|
||||
<button class="btn btn-warning btn-small" onclick="openEditVariantModal(${variant.id})">Edit</button>
|
||||
<button class="btn btn-danger btn-small" onclick="deleteVariant(${variant.id})">Delete</button>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -424,10 +447,14 @@ function renderDrugs() {
|
||||
</div>
|
||||
</div>
|
||||
<div class="drug-actions">
|
||||
<button class="btn btn-primary btn-small" onclick="event.stopPropagation(); openAddVariantModal(${drug.id})">➕ Add</button>
|
||||
${!isReadOnly ? `
|
||||
<button class="btn btn-primary btn-small" onclick="event.stopPropagation(); openAddVariantModal(${drug.id})">➕ Add</button>
|
||||
` : ''}
|
||||
<button class="btn btn-info btn-small" onclick="event.stopPropagation(); showDrugHistory(${drug.id})">📋 History</button>
|
||||
<button class="btn btn-warning btn-small" onclick="event.stopPropagation(); openEditModal(${drug.id})">Edit Drug</button>
|
||||
<button class="btn btn-danger btn-small" onclick="event.stopPropagation(); deleteDrug(${drug.id})">Delete</button>
|
||||
${!isReadOnly ? `
|
||||
<button class="btn btn-warning btn-small" onclick="event.stopPropagation(); openEditModal(${drug.id})">Edit Drug</button>
|
||||
<button class="btn btn-danger btn-small" onclick="event.stopPropagation(); deleteDrug(${drug.id})">Delete</button>
|
||||
` : ''}
|
||||
<span class="expand-icon">${isExpanded ? '▼' : '▶'}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1089,6 +1116,7 @@ async function openUserManagement() {
|
||||
const modal = document.getElementById('userManagementModal');
|
||||
document.getElementById('newUsername').value = '';
|
||||
document.getElementById('newUserPassword').value = '';
|
||||
document.getElementById('newUserRole').value = '';
|
||||
|
||||
const usersList = document.getElementById('usersList');
|
||||
usersList.innerHTML = '<h3>Users</h3><p class="loading">Loading users...</p>';
|
||||
@@ -1102,16 +1130,21 @@ async function openUserManagement() {
|
||||
const usersHtml = `
|
||||
<h3>Users</h3>
|
||||
<div class="users-table">
|
||||
${users.map(user => `
|
||||
<div class="user-item">
|
||||
<span>${user.username}</span>
|
||||
<span class="admin-badge">${user.is_admin ? '👑 Admin' : 'User'}</span>
|
||||
<button class="btn btn-secondary btn-small" onclick="openAdminChangePasswordModal(${user.id}, '${escapeHtml(user.username)}')">🔑 Password</button>
|
||||
${user.id !== currentUser.id ? `
|
||||
<button class="btn btn-danger btn-small" onclick="deleteUser(${user.id})">Delete</button>
|
||||
` : ''}
|
||||
</div>
|
||||
`).join('')}
|
||||
${users.map(user => {
|
||||
const roleLabel = user.role.charAt(0).toUpperCase() + user.role.slice(1);
|
||||
const roleBadge = user.role === 'admin' ? '👑 Admin' :
|
||||
user.role === 'readonly' ? '👁️ Read-Only' : '👤 Regular';
|
||||
return `
|
||||
<div class="user-item">
|
||||
<span>${user.username}</span>
|
||||
<span class="admin-badge">${roleBadge}</span>
|
||||
<button class="btn btn-secondary btn-small" onclick="openAdminChangePasswordModal(${user.id}, '${escapeHtml(user.username)}')">🔑 Password</button>
|
||||
${user.id !== currentUser.id ? `
|
||||
<button class="btn btn-danger btn-small" onclick="deleteUser(${user.id})">Delete</button>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}).join('')}
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1135,11 +1168,17 @@ async function createUser(e) {
|
||||
|
||||
const username = document.getElementById('newUsername').value;
|
||||
const password = document.getElementById('newUserPassword').value;
|
||||
const role = document.getElementById('newUserRole').value;
|
||||
|
||||
if (!role) {
|
||||
showToast('Please select a role', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await apiCall('/users', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ username, password })
|
||||
body: JSON.stringify({ username, password, role })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -1149,6 +1188,7 @@ async function createUser(e) {
|
||||
|
||||
document.getElementById('newUsername').value = '';
|
||||
document.getElementById('newUserPassword').value = '';
|
||||
document.getElementById('newUserRole').value = '';
|
||||
showToast('User created successfully!', 'success');
|
||||
openUserManagement();
|
||||
} catch (error) {
|
||||
|
||||
@@ -416,6 +416,12 @@
|
||||
<div class="form-row">
|
||||
<input type="text" id="newUsername" placeholder="Username" required>
|
||||
<input type="password" id="newUserPassword" placeholder="Password" required>
|
||||
<select id="newUserRole" required>
|
||||
<option value="">-- Select Role --</option>
|
||||
<option value="admin">Admin</option>
|
||||
<option value="user">Regular User</option>
|
||||
<option value="readonly">Read-Only</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-small">Create User</button>
|
||||
</form>
|
||||
|
||||
+4
-1
@@ -868,10 +868,13 @@ footer {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.user-management-content input {
|
||||
.user-management-content input,
|
||||
.user-management-content select {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 6px;
|
||||
|
||||
Reference in New Issue
Block a user