Files
2026-05-16 23:00:37 -05:00

268 lines
12 KiB
PHP

<?php
ob_start();
/**
* Tom's Java Jive - Admin Users Management
*/
$pageTitle = 'Admin Users';
require_once __DIR__ . '/includes/header.php';
// Handle actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'create' || $action === 'update') {
$userId = $_POST['user_id'] ?? '';
$email = trim($_POST['email'] ?? '');
$name = trim($_POST['name'] ?? '');
$password = $_POST['password'] ?? '';
$isMaster = isset($_POST['is_master']) ? 1 : 0;
$permissions = [
'dashboard' => isset($_POST['perm_dashboard']),
'pos' => isset($_POST['perm_pos']),
'products' => isset($_POST['perm_products']),
'orders' => isset($_POST['perm_orders']),
'customers' => isset($_POST['perm_customers']),
'settings_payment' => isset($_POST['perm_settings']),
'settings_shipping' => isset($_POST['perm_settings']),
'settings_email' => isset($_POST['perm_settings']),
'admin_management' => isset($_POST['perm_admin'])
];
if (empty($email) || empty($name)) {
setFlash('error', 'Email and name are required');
} else {
$data = [
'email' => strtolower($email),
'name' => $name,
'is_master' => $isMaster,
'permissions' => json_encode($permissions)
];
if ($action === 'update' && $userId) {
if (!empty($password)) {
$data['password_hash'] = hashPassword($password);
}
db()->update('admin_users', $data, 'user_id = :id', ['id' => $userId]);
setFlash('success', 'Admin user updated');
} else {
if (empty($password)) {
setFlash('error', 'Password is required for new users');
} else {
$existing = db()->fetch("SELECT id FROM admin_users WHERE email = :email", ['email' => strtolower($email)]);
if ($existing) {
setFlash('error', 'Email already exists');
} else {
$data['user_id'] = generateId('admin_');
$data['password_hash'] = hashPassword($password);
$data['is_admin'] = 1;
db()->insert('admin_users', $data);
setFlash('success', 'Admin user created');
}
}
}
}
header('Location: /admin/users.php');
exit;
}
if ($action === 'delete' && !empty($_POST['user_id'])) {
// Don't allow deleting self or last master
$user = db()->fetch("SELECT is_master FROM admin_users WHERE user_id = :id", ['id' => $_POST['user_id']]);
if ($user && $user['is_master']) {
$masterCount = db()->count('admin_users', 'is_master = 1');
if ($masterCount <= 1) {
setFlash('error', 'Cannot delete the last master admin');
header('Location: /admin/users.php');
exit;
}
}
db()->delete('admin_users', 'user_id = :id', ['id' => $_POST['user_id']]);
setFlash('success', 'Admin user deleted');
header('Location: /admin/users.php');
exit;
}
}
$users = db()->fetchAll("SELECT * FROM admin_users ORDER BY is_master DESC, name ASC");
?>
<div class="page-header">
<h1 class="page-title">Admin Users</h1>
<button class="btn btn-primary" onclick="openUserModal()">
<i class="fas fa-plus"></i> Add Admin User
</button>
</div>
<?php if (hasFlash('success')): ?>
<div class="alert alert-success"><i class="fas fa-check-circle"></i> <?= getFlash('success') ?></div>
<?php endif; ?>
<?php if (hasFlash('error')): ?>
<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> <?= getFlash('error') ?></div>
<?php endif; ?>
<div class="admin-card">
<div class="admin-card-body" style="padding: 0;">
<table class="admin-table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td>
<strong><?= htmlspecialchars($user['name']) ?></strong>
<?php if ($user['user_id'] === $adminUser['user_id']): ?>
<span class="badge badge-primary">You</span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($user['email']) ?></td>
<td>
<?php if ($user['is_master']): ?>
<span class="badge badge-warning">Master Admin</span>
<?php else: ?>
<span class="badge badge-primary">Admin</span>
<?php endif; ?>
</td>
<td class="text-muted"><?= formatDate($user['created_at']) ?></td>
<td>
<button class="btn btn-sm btn-secondary" onclick='openUserModal(<?= json_encode($user) ?>)'>
<i class="fas fa-edit"></i>
</button>
<?php if ($user['user_id'] !== $adminUser['user_id']): ?>
<form method="POST" style="display: inline;">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="user_id" value="<?= $user['user_id'] ?>">
<button type="submit" class="btn btn-sm btn-danger" data-confirm="Delete this admin user?">
<i class="fas fa-trash"></i>
</button>
</form>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- User Modal -->
<div class="modal-overlay" id="userModal">
<div class="modal">
<div class="modal-header">
<h3 class="modal-title" id="userModalTitle">Add Admin User</h3>
<button type="button" class="modal-close" onclick="Modal.close('userModal')">&times;</button>
</div>
<form method="POST" id="userForm">
<div class="modal-body">
<input type="hidden" name="action" id="userAction" value="create">
<input type="hidden" name="user_id" id="userId">
<div class="form-group">
<label class="form-label">Name *</label>
<input type="text" name="name" id="userName" class="form-input" required>
</div>
<div class="form-group">
<label class="form-label">Email *</label>
<input type="email" name="email" id="userEmail" class="form-input" required>
</div>
<div class="form-group">
<label class="form-label">Password <span id="passwordRequired">*</span></label>
<input type="password" name="password" id="userPassword" class="form-input">
<small class="text-muted" id="passwordHint">Leave blank to keep current password</small>
</div>
<div class="form-group">
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="is_master" id="userMaster">
Master Admin (full access)
</label>
</div>
<div id="permissionsSection">
<h4 style="margin-bottom: 0.75rem; font-size: 0.9rem;">Permissions</h4>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem;">
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="perm_dashboard" id="permDashboard" checked> Dashboard
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="perm_pos" id="permPos" checked> POS
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="perm_products" id="permProducts" checked> Products
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="perm_orders" id="permOrders" checked> Orders
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="perm_customers" id="permCustomers" checked> Customers
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="perm_settings" id="permSettings"> Settings
</label>
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
<input type="checkbox" name="perm_admin" id="permAdmin"> Admin Users
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="Modal.close('userModal')">Cancel</button>
<button type="submit" class="btn btn-primary" id="userSubmitBtn">Add User</button>
</div>
</form>
</div>
</div>
<script>
document.getElementById('userMaster').addEventListener('change', function() {
document.getElementById('permissionsSection').style.display = this.checked ? 'none' : 'block';
});
function openUserModal(user = null) {
const isEdit = !!user;
document.getElementById('userModalTitle').textContent = isEdit ? 'Edit Admin User' : 'Add Admin User';
document.getElementById('userSubmitBtn').textContent = isEdit ? 'Update User' : 'Add User';
document.getElementById('userAction').value = isEdit ? 'update' : 'create';
document.getElementById('userId').value = isEdit ? user.user_id : '';
document.getElementById('userName').value = isEdit ? user.name : '';
document.getElementById('userEmail').value = isEdit ? user.email : '';
document.getElementById('userPassword').value = '';
document.getElementById('userMaster').checked = isEdit ? user.is_master : false;
document.getElementById('passwordRequired').style.display = isEdit ? 'none' : 'inline';
document.getElementById('passwordHint').style.display = isEdit ? 'block' : 'none';
document.getElementById('userPassword').required = !isEdit;
if (isEdit) {
const perms = JSON.parse(user.permissions || '{}');
document.getElementById('permDashboard').checked = perms.dashboard ?? true;
document.getElementById('permPos').checked = perms.pos ?? true;
document.getElementById('permProducts').checked = perms.products ?? true;
document.getElementById('permOrders').checked = perms.orders ?? true;
document.getElementById('permCustomers').checked = perms.customers ?? true;
document.getElementById('permSettings').checked = perms.settings_payment ?? false;
document.getElementById('permAdmin').checked = perms.admin_management ?? false;
}
document.getElementById('permissionsSection').style.display =
document.getElementById('userMaster').checked ? 'none' : 'block';
Modal.open('userModal');
}
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>