288 lines
15 KiB
PHP
288 lines
15 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . '/queue_bootstrap.php';
|
|
qh_boot();
|
|
qh_admin_handle_request(); // To handle language swaps etc. if needed
|
|
|
|
$pdo = db();
|
|
$error = '';
|
|
$success = '';
|
|
|
|
// Handle actions
|
|
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'create_user') {
|
|
$username = trim($_POST['username'] ?? '');
|
|
$password = $_POST['password'] ?? '';
|
|
$role = $_POST['role'] ?? 'admin';
|
|
|
|
if ($username === '' || $password === '') {
|
|
$error = qh_t('Username and password are required.', 'اسم المستخدم وكلمة المرور مطلوبان.');
|
|
} else {
|
|
try {
|
|
$hash = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt = $pdo->prepare("INSERT INTO users (username, password, role) VALUES (:username, :password, :role)");
|
|
$stmt->execute(['username' => $username, 'password' => $hash, 'role' => $role]);
|
|
$success = qh_t('User created successfully.', 'تم إنشاء المستخدم بنجاح.');
|
|
} catch (PDOException $e) {
|
|
if ($e->getCode() == 23000) {
|
|
$error = qh_t('Username already exists.', 'اسم المستخدم موجود مسبقاً.');
|
|
} else {
|
|
$error = qh_t('Failed to create user.', 'فشل في إنشاء المستخدم.');
|
|
}
|
|
}
|
|
}
|
|
} elseif ($action === 'update_user') {
|
|
$id = (int)($_POST['id'] ?? 0);
|
|
$username = trim($_POST['username'] ?? '');
|
|
$password = $_POST['password'] ?? '';
|
|
$role = $_POST['role'] ?? 'admin';
|
|
|
|
if ($id <= 0 || $username === '') {
|
|
$error = qh_t('Invalid user data.', 'بيانات المستخدم غير صالحة.');
|
|
} else {
|
|
try {
|
|
if ($password !== '') {
|
|
$hash = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt = $pdo->prepare("UPDATE users SET username = :username, password = :password, role = :role WHERE id = :id");
|
|
$stmt->execute(['username' => $username, 'password' => $hash, 'role' => $role, 'id' => $id]);
|
|
} else {
|
|
$stmt = $pdo->prepare("UPDATE users SET username = :username, role = :role WHERE id = :id");
|
|
$stmt->execute(['username' => $username, 'role' => $role, 'id' => $id]);
|
|
}
|
|
$success = qh_t('User updated successfully.', 'تم تحديث المستخدم بنجاح.');
|
|
} catch (PDOException $e) {
|
|
if ($e->getCode() == 23000) {
|
|
$error = qh_t('Username already exists.', 'اسم المستخدم موجود مسبقاً.');
|
|
} else {
|
|
$error = qh_t('Failed to update user.', 'فشل في تحديث المستخدم.');
|
|
}
|
|
}
|
|
}
|
|
} elseif ($action === 'delete_user') {
|
|
$id = (int)($_POST['id'] ?? 0);
|
|
|
|
// Prevent deleting the last user
|
|
$count = $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
|
if ($count <= 1) {
|
|
$error = qh_t('Cannot delete the last user in the system.', 'لا يمكن حذف آخر مستخدم في النظام.');
|
|
} elseif ($id > 0) {
|
|
$stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
|
|
$stmt->execute(['id' => $id]);
|
|
$success = qh_t('User deleted successfully.', 'تم حذف المستخدم بنجاح.');
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
$users = $pdo->query("SELECT id, username, role, created_at FROM users ORDER BY id ASC")->fetchAll();
|
|
} catch (PDOException $e) {
|
|
if (str_contains($e->getMessage(), "Unknown column 'role'")) {
|
|
$pdo->exec("ALTER TABLE users ADD COLUMN role VARCHAR(20) DEFAULT 'admin'");
|
|
$users = $pdo->query("SELECT id, username, role, created_at FROM users ORDER BY id ASC")->fetchAll();
|
|
} elseif ($e->getCode() == '42S02') {
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS users (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, role VARCHAR(20) DEFAULT 'admin', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
|
|
$users = [];
|
|
$error = qh_t('Users table was missing and has been created.', 'كان جدول المستخدمين مفقوداً وتم إنشاؤه.');
|
|
} else {
|
|
throw $e;
|
|
}
|
|
}
|
|
$stats = qh_admin_stats();
|
|
|
|
$roles = [
|
|
'admin' => qh_t('Admin', 'مدير'),
|
|
'reception' => qh_t('Reception', 'استقبال'),
|
|
'nursing' => qh_t('Nursing', 'تمريض'),
|
|
'doctor' => qh_t('Doctor', 'طبيب'),
|
|
];
|
|
|
|
qh_page_start(
|
|
'admin',
|
|
qh_t('System Users', 'مستخدمو النظام'),
|
|
qh_t('Manage system users and access.', 'إدارة مستخدمي النظام وصلاحيات الوصول.')
|
|
);
|
|
?>
|
|
<div class="container-fluid container-xxl px-3 px-lg-4">
|
|
<div class="admin-layout">
|
|
<aside class="admin-sidebar-column">
|
|
<?php qh_render_admin_sidebar('admin_users.php', $stats); ?>
|
|
</aside>
|
|
|
|
<div class="admin-content-stack">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h1 class="h3 mb-0 text-gray-800 fw-bold"><?= qh_h(qh_t('System Users', 'مستخدمو النظام')) ?></h1>
|
|
<p class="text-muted mb-0 mt-1"><?= qh_h(qh_t('Manage system administrators and staff access.', 'إدارة مديري النظام وصلاحيات وصول الموظفين.')) ?></p>
|
|
</div>
|
|
<button type="button" class="btn btn-primary d-flex align-items-center gap-2" data-bs-toggle="modal" data-bs-target="#createUserModal">
|
|
<svg viewBox="0 0 24 24" width="18" height="18" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
|
<?= qh_h(qh_t('Add User', 'إضافة مستخدم')) ?>
|
|
</button>
|
|
</div>
|
|
|
|
<?php if ($error !== ''): ?>
|
|
<div class="alert alert-danger" role="alert"><?= qh_h($error) ?></div>
|
|
<?php endif; ?>
|
|
<?php if ($success !== ''): ?>
|
|
<div class="alert alert-success" role="alert"><?= qh_h($success) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card shadow-sm border-0 mb-4">
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th scope="col" class="px-4 py-3">ID</th>
|
|
<th scope="col" class="px-4 py-3"><?= qh_h(qh_t('Username', 'اسم المستخدم')) ?></th>
|
|
<th scope="col" class="px-4 py-3"><?= qh_h(qh_t('Role / Permissions', 'الدور / الصلاحيات')) ?></th>
|
|
<th scope="col" class="px-4 py-3"><?= qh_h(qh_t('Created At', 'تاريخ الإنشاء')) ?></th>
|
|
<th scope="col" class="px-4 py-3 text-end"><?= qh_h(qh_t('Actions', 'الإجراءات')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($users as $user): ?>
|
|
<tr>
|
|
<td class="px-4 py-3 text-muted">#<?= qh_h((string)$user['id']) ?></td>
|
|
<td class="px-4 py-3 fw-medium text-gray-900"><?= qh_h($user['username']) ?></td>
|
|
<td class="px-4 py-3">
|
|
<span class="badge bg-secondary"><?= qh_h($roles[$user['role']] ?? $user['role']) ?></span>
|
|
</td>
|
|
<td class="px-4 py-3 text-muted"><?= qh_h($user['created_at']) ?></td>
|
|
<td class="px-4 py-3 text-end">
|
|
<button type="button" class="btn btn-sm btn-outline-secondary me-2"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#editUserModal"
|
|
data-id="<?= qh_h((string)$user['id']) ?>"
|
|
data-username="<?= qh_h($user['username']) ?>"
|
|
data-role="<?= qh_h($user['role'] ?? 'admin') ?>">
|
|
<?= qh_h(qh_t('Edit', 'تعديل')) ?>
|
|
</button>
|
|
<?php if (count($users) > 1): ?>
|
|
<form action="" method="POST" class="d-inline-block" onsubmit="return confirm('<?= qh_h(qh_t('Are you sure you want to delete this user?', 'هل أنت متأكد أنك تريد حذف هذا المستخدم؟')) ?>');">
|
|
<input type="hidden" name="action" value="delete_user">
|
|
<input type="hidden" name="id" value="<?= qh_h((string)$user['id']) ?>">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">
|
|
<?= qh_h(qh_t('Delete', 'حذف')) ?>
|
|
</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($users)): ?>
|
|
<tr>
|
|
<td colspan="5" class="px-4 py-4 text-center text-muted">
|
|
<?= qh_h(qh_t('No users found.', 'لا يوجد مستخدمين.')) ?>
|
|
</td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create User Modal -->
|
|
<div class="modal fade" id="createUserModal" tabindex="-1" aria-labelledby="createUserModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content border-0 shadow">
|
|
<form action="" method="POST">
|
|
<input type="hidden" name="action" value="create_user">
|
|
<div class="modal-header border-bottom-0 pb-0">
|
|
<h5 class="modal-title fw-bold" id="createUserModalLabel"><?= qh_h(qh_t('Add New User', 'إضافة مستخدم جديد')) ?></h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label class="form-label text-muted small fw-bold text-uppercase"><?= qh_h(qh_t('Username', 'اسم المستخدم')) ?></label>
|
|
<input type="text" name="username" class="form-control form-control-lg bg-light" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label text-muted small fw-bold text-uppercase"><?= qh_h(qh_t('Role / Permissions', 'الدور / الصلاحيات')) ?></label>
|
|
<select name="role" class="form-select form-select-lg bg-light" required>
|
|
<?php foreach ($roles as $key => $label): ?>
|
|
<option value="<?= qh_h($key) ?>"><?= qh_h($label) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label text-muted small fw-bold text-uppercase"><?= qh_h(qh_t('Password', 'كلمة المرور')) ?></label>
|
|
<input type="password" name="password" class="form-control form-control-lg bg-light" required>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer border-top-0 pt-0">
|
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><?= qh_h(qh_t('Cancel', 'إلغاء')) ?></button>
|
|
<button type="submit" class="btn btn-primary px-4"><?= qh_h(qh_t('Create User', 'إنشاء المستخدم')) ?></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Edit User Modal -->
|
|
<div class="modal fade" id="editUserModal" tabindex="-1" aria-labelledby="editUserModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content border-0 shadow">
|
|
<form action="" method="POST">
|
|
<input type="hidden" name="action" value="update_user">
|
|
<input type="hidden" name="id" id="editUserId" value="">
|
|
<div class="modal-header border-bottom-0 pb-0">
|
|
<h5 class="modal-title fw-bold" id="editUserModalLabel"><?= qh_h(qh_t('Edit User', 'تعديل المستخدم')) ?></h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label class="form-label text-muted small fw-bold text-uppercase"><?= qh_h(qh_t('Username', 'اسم المستخدم')) ?></label>
|
|
<input type="text" name="username" id="editUserUsername" class="form-control form-control-lg bg-light" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label text-muted small fw-bold text-uppercase"><?= qh_h(qh_t('Role / Permissions', 'الدور / الصلاحيات')) ?></label>
|
|
<select name="role" id="editUserRole" class="form-select form-select-lg bg-light" required>
|
|
<?php foreach ($roles as $key => $label): ?>
|
|
<option value="<?= qh_h($key) ?>"><?= qh_h($label) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label text-muted small fw-bold text-uppercase"><?= qh_h(qh_t('New Password (Optional)', 'كلمة مرور جديدة (اختياري)')) ?></label>
|
|
<input type="password" name="password" class="form-control form-control-lg bg-light" placeholder="<?= qh_h(qh_t('Leave blank to keep current password', 'اتركه فارغاً للاحتفاظ بكلمة المرور الحالية')) ?>">
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer border-top-0 pt-0">
|
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><?= qh_h(qh_t('Cancel', 'إلغاء')) ?></button>
|
|
<button type="submit" class="btn btn-primary px-4"><?= qh_h(qh_t('Save Changes', 'حفظ التغييرات')) ?></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const editModal = document.getElementById('editUserModal');
|
|
if (editModal) {
|
|
editModal.addEventListener('show.bs.modal', function (event) {
|
|
const button = event.relatedTarget;
|
|
const id = button.getAttribute('data-id');
|
|
const username = button.getAttribute('data-username');
|
|
const role = button.getAttribute('data-role');
|
|
|
|
editModal.querySelector('#editUserId').value = id;
|
|
editModal.querySelector('#editUserUsername').value = username;
|
|
|
|
const roleSelect = editModal.querySelector('#editUserRole');
|
|
if (roleSelect && role) {
|
|
roleSelect.value = role;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
<?php
|
|
qh_page_end();
|