767 lines
36 KiB
PHP
767 lines
36 KiB
PHP
<?php
|
|
session_start();
|
|
|
|
// Check if user is logged in and is admin
|
|
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'admin') {
|
|
header("Location: ../auth/login.php");
|
|
exit();
|
|
}
|
|
|
|
// Use absolute path with error checking
|
|
$db_path = __DIR__ . '/../includes/database.php';
|
|
if (!file_exists($db_path)) {
|
|
die("Database configuration file not found at: $db_path");
|
|
}
|
|
|
|
require_once $db_path;
|
|
|
|
// Check if $pdo is set
|
|
if (!isset($pdo)) {
|
|
die("Database connection failed. \$pdo variable not set.");
|
|
}
|
|
|
|
$title = "User Management";
|
|
|
|
// Try different paths for header.php
|
|
$header_paths = [
|
|
'header.php', // Same directory
|
|
__DIR__ . '/header.php', // Absolute path in admin
|
|
__DIR__ . '/../header.php', // Parent directory (attendance_system)
|
|
__DIR__ . '/../includes/header.php', // Includes directory
|
|
__DIR__ . '/../templates/header.php', // Templates directory
|
|
'C:/xampp/htdocs/attendance_system/header.php',
|
|
'C:/xampp/htdocs/attendance_system/admin/header.php'
|
|
];
|
|
|
|
$header_found = false;
|
|
foreach ($header_paths as $path) {
|
|
if (file_exists($path)) {
|
|
include $path;
|
|
$header_found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$header_found) {
|
|
// If header not found, create basic HTML structure
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title><?php echo $title; ?></title>
|
|
|
|
<!-- Bootstrap 5 -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<!-- Bootstrap Icons -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
|
|
<!-- DataTables -->
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/1.11.5/css/dataTables.bootstrap5.min.css">
|
|
|
|
<style>
|
|
body {
|
|
background-color: #f5f7fb;
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
margin: 0;
|
|
padding: 0;
|
|
font-size: 0.9rem;
|
|
}
|
|
.navbar {
|
|
background: #37502c;
|
|
}
|
|
.card {
|
|
border-radius: 10px;
|
|
box-shadow: 0 5px 15px rgba(0,0,0,0.08);
|
|
margin-bottom: 15px;
|
|
border: none;
|
|
}
|
|
.card-header {
|
|
background: linear-gradient(135deg, #205e03 0%, #9bdb34 100%);
|
|
color: white;
|
|
border-radius: 10px 10px 0 0;
|
|
border: none;
|
|
padding: 12px 15px;
|
|
}
|
|
.table {
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
|
margin-bottom: 0;
|
|
font-size: 0.85rem;
|
|
}
|
|
.table th {
|
|
font-size: 0.8rem;
|
|
padding: 8px 12px;
|
|
background-color: #f8f9fa;
|
|
border-bottom: 2px solid #dee2e6;
|
|
}
|
|
.table td {
|
|
padding: 6px 12px;
|
|
vertical-align: middle;
|
|
}
|
|
.table tbody tr:hover {
|
|
background-color: #f8f9fa;
|
|
}
|
|
.status-active {
|
|
background-color: #d4edda;
|
|
color: #155724;
|
|
padding: 3px 6px;
|
|
border-radius: 4px;
|
|
font-size: 0.8rem;
|
|
}
|
|
.status-inactive {
|
|
background-color: #f8d7da;
|
|
color: #721c24;
|
|
padding: 3px 6px;
|
|
border-radius: 4px;
|
|
font-size: 0.8rem;
|
|
}
|
|
.badge {
|
|
font-size: 0.75rem;
|
|
padding: 3px 6px;
|
|
}
|
|
.action-buttons .btn {
|
|
padding: 3px 6px;
|
|
font-size: 0.8rem;
|
|
margin: 0 2px;
|
|
}
|
|
.search-box {
|
|
position: relative;
|
|
}
|
|
.search-box i {
|
|
position: absolute;
|
|
left: 10px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #6c757d;
|
|
}
|
|
.search-box input {
|
|
padding-left: 35px;
|
|
font-size: 0.85rem;
|
|
height: 36px;
|
|
}
|
|
.form-control, .form-select {
|
|
font-size: 0.85rem;
|
|
padding: 6px 10px;
|
|
height: 36px;
|
|
}
|
|
.stat-card {
|
|
padding: 12px;
|
|
}
|
|
.stat-card h3 {
|
|
font-size: 1.5rem;
|
|
}
|
|
.stat-card h6 {
|
|
font-size: 0.8rem;
|
|
}
|
|
.stat-card i {
|
|
font-size: 1.8rem;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Simple Navigation -->
|
|
<nav class="navbar navbar-expand-lg navbar-dark">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand" href="#">
|
|
<i class="bi bi-qr-code-scan me-2"></i>AMS - User Management
|
|
</a>
|
|
<div class="d-flex align-items-center text-white">
|
|
<span class="me-3" style="font-size: 0.9rem;">
|
|
<i class="bi bi-person-circle me-1"></i>
|
|
<?php echo htmlspecialchars($_SESSION['full_name'] ?? 'User'); ?>
|
|
</span>
|
|
<a href="../auth/logout.php" class="btn btn-outline-light btn-sm" style="font-size: 0.8rem;">
|
|
<i class="bi bi-box-arrow-right"></i> Logout
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container-fluid mt-3">
|
|
<?php
|
|
}
|
|
?>
|
|
<!-- ================ START OF YOUR USER MANAGEMENT CONTENT ================ -->
|
|
|
|
<!-- Display messages -->
|
|
<?php if (isset($_SESSION['message'])): ?>
|
|
<?php $message_type = $_SESSION['message_type'] ?? 'success'; ?>
|
|
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show py-2" role="alert" style="font-size: 0.85rem;">
|
|
<?php echo $_SESSION['message']; ?>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
<?php
|
|
unset($_SESSION['message']);
|
|
unset($_SESSION['message_type']);
|
|
?>
|
|
<?php endif; ?>
|
|
|
|
<div class="content-wrapper">
|
|
<div class="container-fluid">
|
|
<div class="row mb-3">
|
|
<div class="col">
|
|
<div class="card">
|
|
<div class="card-header d-flex justify-content-between align-items-center py-2">
|
|
<h6 class="mb-0" style="font-size: 0.9rem;"><i class="bi bi-people-fill me-1"></i>User Management</h6>
|
|
<button class="btn btn-primary btn-sm py-1 px-2" data-bs-toggle="modal" data-bs-target="#addUserModal" style="font-size: 0.8rem;">
|
|
<i class="bi bi-person-plus me-1"></i> Add User
|
|
</button>
|
|
</div>
|
|
<div class="card-body p-3">
|
|
<!-- Search and Filter -->
|
|
<div class="row mb-2 g-2">
|
|
<div class="col-md-6">
|
|
<div class="search-box">
|
|
<i class="bi bi-search"></i>
|
|
<input type="text" class="form-control" id="searchInput" placeholder="Search users...">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<select class="form-select" id="roleFilter">
|
|
<option value="">All Roles</option>
|
|
<option value="admin">Admin</option>
|
|
<option value="teacher">Teacher</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<select class="form-select" id="statusFilter">
|
|
<option value="">All Status</option>
|
|
<option value="1">Active</option>
|
|
<option value="0">Inactive</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Users Table - COMPACT VERSION -->
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-sm" id="usersTable">
|
|
<thead>
|
|
<tr>
|
|
<th width="3%">#</th>
|
|
<th width="20%">Full Name</th>
|
|
<th width="18%">Email</th>
|
|
<th width="12%">Username</th>
|
|
<th width="10%">Role</th>
|
|
<th width="10%">Status</th>
|
|
<th width="12%">Created</th>
|
|
<th width="15%">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
try {
|
|
$query = "SELECT * FROM users ORDER BY created_at DESC";
|
|
$stmt = $pdo->query($query);
|
|
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$count = 1;
|
|
|
|
if (count($users) > 0):
|
|
foreach ($users as $user):
|
|
$status_class = $user['status'] ? 'status-active' : 'status-inactive';
|
|
$status_text = $user['status'] ? 'Active' : 'Inactive';
|
|
|
|
$role_badge = '';
|
|
switch($user['role']) {
|
|
case 'admin': $role_badge = 'danger'; break;
|
|
case 'teacher': $role_badge = 'success'; break;
|
|
default: $role_badge = 'secondary';
|
|
}
|
|
?>
|
|
<tr>
|
|
<td class="text-muted"><?php echo $count++; ?></td>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<div class="rounded-circle bg-light p-1 me-2">
|
|
<i class="bi bi-person text-dark" style="font-size: 0.8rem;"></i>
|
|
</div>
|
|
<div>
|
|
<div style="font-size: 0.85rem; font-weight: 500;"><?php echo htmlspecialchars($user['full_name']); ?></div>
|
|
<?php if ($user['id'] == $_SESSION['user_id']): ?>
|
|
<span class="badge bg-warning" style="font-size: 0.65rem;">You</span>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<small class="text-truncate d-inline-block" style="max-width: 150px;" title="<?php echo htmlspecialchars($user['email'] ?? 'N/A'); ?>">
|
|
<?php echo htmlspecialchars($user['email'] ?? 'N/A'); ?>
|
|
</small>
|
|
</td>
|
|
<td><code style="font-size: 0.8rem;"><?php echo htmlspecialchars($user['username']); ?></code></td>
|
|
<td>
|
|
<span class="badge bg-<?php echo $role_badge; ?>">
|
|
<?php echo ucfirst($user['role']); ?>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="<?php echo $status_class; ?>">
|
|
<?php echo $status_text; ?>
|
|
</span>
|
|
</td>
|
|
<td><small><?php echo date('m/d/Y', strtotime($user['created_at'])); ?></small></td>
|
|
<td>
|
|
<div class="d-flex">
|
|
<button class="btn btn-sm btn-outline-primary py-0 px-1"
|
|
onclick="editUser(<?php echo $user['id']; ?>)"
|
|
title="Edit User">
|
|
<i class="bi bi-pencil" style="font-size: 0.8rem;"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-<?php echo $user['status'] ? 'warning' : 'success'; ?> py-0 px-1 mx-1"
|
|
onclick="toggleStatus(<?php echo $user['id']; ?>, <?php echo $user['status']; ?>)"
|
|
title="<?php echo $user['status'] ? 'Deactivate' : 'Activate'; ?>">
|
|
<i class="bi bi-<?php echo $user['status'] ? 'x-circle' : 'check-circle'; ?>" style="font-size: 0.8rem;"></i>
|
|
</button>
|
|
<?php if ($user['id'] != $_SESSION['user_id']): ?>
|
|
<button class="btn btn-sm btn-outline-danger py-0 px-1"
|
|
onclick="deleteUser(<?php echo $user['id']; ?>, '<?php echo htmlspecialchars($user['full_name']); ?>')"
|
|
title="Delete User">
|
|
<i class="bi bi-trash" style="font-size: 0.8rem;"></i>
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
endforeach;
|
|
else:
|
|
?>
|
|
<tr>
|
|
<td colspan="8" class="text-center text-muted py-2">
|
|
<i class="bi bi-people me-1"></i> No users found.
|
|
</td>
|
|
</tr>
|
|
<?php
|
|
endif;
|
|
} catch (PDOException $e) {
|
|
?>
|
|
<tr>
|
|
<td colspan="8" class="text-center text-danger py-2">
|
|
<i class="bi bi-exclamation-triangle me-1"></i> Error loading users
|
|
</td>
|
|
</tr>
|
|
<?php } ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- User Stats - Compact Version -->
|
|
<div class="row g-2">
|
|
<div class="col-md-3">
|
|
<div class="card stat-card py-2">
|
|
<div class="card-body p-2">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h6 class="text-muted mb-1" style="font-size: 0.75rem;">Total Users</h6>
|
|
<h4 class="mb-0" style="font-size: 1.2rem;">
|
|
<?php
|
|
$query = "SELECT COUNT(*) as total FROM users";
|
|
$stmt = $pdo->query($query);
|
|
echo $stmt->fetch()['total'] ?? 0;
|
|
?>
|
|
</h4>
|
|
</div>
|
|
<i class="bi bi-people text-primary" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card stat-card py-2">
|
|
<div class="card-body p-2">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h6 class="text-muted mb-1" style="font-size: 0.75rem;">Active Users</h6>
|
|
<h4 class="mb-0" style="font-size: 1.2rem;">
|
|
<?php
|
|
$query = "SELECT COUNT(*) as active FROM users WHERE status = 1";
|
|
$stmt = $pdo->query($query);
|
|
echo $stmt->fetch()['active'] ?? 0;
|
|
?>
|
|
</h4>
|
|
</div>
|
|
<i class="bi bi-check-circle text-success" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card stat-card py-2">
|
|
<div class="card-body p-2">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h6 class="text-muted mb-1" style="font-size: 0.75rem;">Admins</h6>
|
|
<h4 class="mb-0" style="font-size: 1.2rem;">
|
|
<?php
|
|
$query = "SELECT COUNT(*) as admins FROM users WHERE role = 'admin'";
|
|
$stmt = $pdo->query($query);
|
|
echo $stmt->fetch()['admins'] ?? 0;
|
|
?>
|
|
</h4>
|
|
</div>
|
|
<i class="bi bi-shield-check text-danger" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card stat-card py-2">
|
|
<div class="card-body p-2">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div>
|
|
<h6 class="text-muted mb-1" style="font-size: 0.75rem;">Teachers</h6>
|
|
<h4 class="mb-0" style="font-size: 1.2rem;">
|
|
<?php
|
|
$query = "SELECT COUNT(*) as teachers FROM users WHERE role = 'teacher'";
|
|
$stmt = $pdo->query($query);
|
|
echo $stmt->fetch()['teachers'] ?? 0;
|
|
?>
|
|
</h4>
|
|
</div>
|
|
<i class="bi bi-person-badge text-info" style="font-size: 1.5rem;"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ================ MODALS SECTION ================ -->
|
|
|
|
<!-- Add User Modal -->
|
|
<div class="modal fade" id="addUserModal" tabindex="-1" aria-labelledby="addUserModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-md">
|
|
<div class="modal-content">
|
|
<div class="modal-header py-2">
|
|
<h6 class="modal-title mb-0" id="addUserModalLabel"><i class="bi bi-person-plus me-1"></i>Add New User</h6>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form action="process_user.php" method="POST" id="addUserForm">
|
|
<div class="modal-body p-3">
|
|
<input type="hidden" name="action" value="add">
|
|
|
|
<div class="row g-2">
|
|
<div class="col-md-6 mb-2">
|
|
<label for="full_name" class="form-label" style="font-size: 0.85rem;">Full Name <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control form-control-sm" id="full_name" name="full_name" required>
|
|
</div>
|
|
<div class="col-md-6 mb-2">
|
|
<label for="username" class="form-label" style="font-size: 0.85rem;">Username <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control form-control-sm" id="username" name="username" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label for="email" class="form-label" style="font-size: 0.85rem;">Email Address</label>
|
|
<input type="email" class="form-control form-control-sm" id="email" name="email">
|
|
</div>
|
|
|
|
<div class="row g-2">
|
|
<div class="col-md-6 mb-2">
|
|
<label for="password" class="form-label" style="font-size: 0.85rem;">Password <span class="text-danger">*</span></label>
|
|
<input type="password" class="form-control form-control-sm" id="password" name="password" required>
|
|
</div>
|
|
<div class="col-md-6 mb-2">
|
|
<label for="confirm_password" class="form-label" style="font-size: 0.85rem;">Confirm Password <span class="text-danger">*</span></label>
|
|
<input type="password" class="form-control form-control-sm" id="confirm_password" name="confirm_password" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-2">
|
|
<div class="col-md-6 mb-2">
|
|
<label for="role" class="form-label" style="font-size: 0.85rem;">Role <span class="text-danger">*</span></label>
|
|
<select class="form-select form-select-sm" id="role" name="role" required>
|
|
<option value="">Select Role</option>
|
|
<option value="admin">Admin</option>
|
|
<option value="teacher">Teacher</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6 mb-2">
|
|
<label for="status" class="form-label" style="font-size: 0.85rem;">Status</label>
|
|
<select class="form-select form-select-sm" id="status" name="status">
|
|
<option value="1">Active</option>
|
|
<option value="0">Inactive</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer py-2">
|
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-primary btn-sm">Add 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 modal-md">
|
|
<div class="modal-content">
|
|
<div class="modal-header py-2">
|
|
<h6 class="modal-title mb-0" id="editUserModalLabel"><i class="bi bi-pencil me-1"></i>Edit User</h6>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form action="process_user.php" method="POST" id="editUserForm">
|
|
<div class="modal-body p-3">
|
|
<input type="hidden" name="action" value="edit">
|
|
<input type="hidden" id="edit_user_id" name="user_id">
|
|
|
|
<div class="row g-2">
|
|
<div class="col-md-6 mb-2">
|
|
<label for="edit_full_name" class="form-label" style="font-size: 0.85rem;">Full Name <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control form-control-sm" id="edit_full_name" name="full_name" required>
|
|
</div>
|
|
<div class="col-md-6 mb-2">
|
|
<label for="edit_username" class="form-label" style="font-size: 0.85rem;">Username <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control form-control-sm" id="edit_username" name="username" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label for="edit_email" class="form-label" style="font-size: 0.85rem;">Email Address</label>
|
|
<input type="email" class="form-control form-control-sm" id="edit_email" name="email">
|
|
</div>
|
|
|
|
<div class="row g-2">
|
|
<div class="col-md-6 mb-2">
|
|
<label for="edit_password" class="form-label" style="font-size: 0.85rem;">New Password (leave blank)</label>
|
|
<input type="password" class="form-control form-control-sm" id="edit_password" name="password">
|
|
</div>
|
|
<div class="col-md-6 mb-2">
|
|
<label for="edit_confirm_password" class="form-label" style="font-size: 0.85rem;">Confirm New Password</label>
|
|
<input type="password" class="form-control form-control-sm" id="edit_confirm_password" name="confirm_password">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-2">
|
|
<div class="col-md-6 mb-2">
|
|
<label for="edit_role" class="form-label" style="font-size: 0.85rem;">Role <span class="text-danger">*</span></label>
|
|
<select class="form-select form-select-sm" id="edit_role" name="role" required>
|
|
<option value="">Select Role</option>
|
|
<option value="admin">Admin</option>
|
|
<option value="teacher">Teacher</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6 mb-2">
|
|
<label for="edit_status" class="form-label" style="font-size: 0.85rem;">Status</label>
|
|
<select class="form-select form-select-sm" id="edit_status" name="status">
|
|
<option value="1">Active</option>
|
|
<option value="0">Inactive</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer py-2">
|
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="submit" class="btn btn-primary btn-sm">Update User</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Delete Confirmation Modal -->
|
|
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-sm">
|
|
<div class="modal-content">
|
|
<div class="modal-header bg-danger text-white py-2">
|
|
<h6 class="modal-title mb-0" id="deleteModalLabel"><i class="bi bi-exclamation-triangle me-1"></i>Confirm Delete</h6>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body p-3">
|
|
<p class="mb-2" style="font-size: 0.85rem;">Delete user: <strong id="deleteUserName"></strong>?</p>
|
|
<p class="text-danger mb-0" style="font-size: 0.8rem;"><i class="bi bi-exclamation-circle me-1"></i>Cannot be undone.</p>
|
|
</div>
|
|
<div class="modal-footer py-2">
|
|
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-danger btn-sm" id="confirmDelete">Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ================ JAVASCRIPT SECTION ================ -->
|
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
|
|
<script src="https://cdn.datatables.net/1.11.5/js/dataTables.bootstrap5.min.js"></script>
|
|
|
|
<script>
|
|
// Table filtering and search - COMPACT VERSION
|
|
$(document).ready(function() {
|
|
const table = $('#usersTable').DataTable({
|
|
pageLength: 15, // More rows per page
|
|
lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]],
|
|
responsive: true,
|
|
dom: '<"row"<"col-sm-12"fr>>rt<"row"<"col-sm-6"i><"col-sm-6"p>>',
|
|
language: {
|
|
search: "_INPUT_",
|
|
searchPlaceholder: "Search...",
|
|
lengthMenu: "Show _MENU_ entries",
|
|
info: "Showing _START_ to _END_ of _TOTAL_ users",
|
|
paginate: {
|
|
first: "First",
|
|
last: "Last",
|
|
next: "→",
|
|
previous: "←"
|
|
}
|
|
},
|
|
columnDefs: [
|
|
{ orderable: false, targets: [7] } // Make actions column not sortable
|
|
]
|
|
});
|
|
|
|
$('#searchInput').on('keyup', function() {
|
|
table.search(this.value).draw();
|
|
});
|
|
|
|
$('#roleFilter').on('change', function() {
|
|
table.column(4).search(this.value).draw();
|
|
});
|
|
|
|
$('#statusFilter').on('change', function() {
|
|
table.column(5).search(this.value).draw();
|
|
});
|
|
});
|
|
|
|
// Edit User Function
|
|
function editUser(userId) {
|
|
fetch(`get_user.php?id=${userId}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
const user = data.user;
|
|
document.getElementById('edit_user_id').value = user.id;
|
|
document.getElementById('edit_full_name').value = user.full_name;
|
|
document.getElementById('edit_username').value = user.username;
|
|
document.getElementById('edit_email').value = user.email || '';
|
|
document.getElementById('edit_role').value = user.role;
|
|
document.getElementById('edit_status').value = user.status;
|
|
|
|
const editModal = new bootstrap.Modal(document.getElementById('editUserModal'));
|
|
editModal.show();
|
|
} else {
|
|
alert('Error loading user data: ' + data.message);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Error loading user data');
|
|
});
|
|
}
|
|
|
|
// Toggle User Status
|
|
function toggleStatus(userId, currentStatus) {
|
|
if (confirm(`Are you sure you want to ${currentStatus ? 'deactivate' : 'activate'} this user?`)) {
|
|
const formData = new FormData();
|
|
formData.append('action', 'toggle_status');
|
|
formData.append('user_id', userId);
|
|
|
|
fetch('process_user.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert('Error: ' + data.message);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Error updating user status');
|
|
});
|
|
}
|
|
}
|
|
|
|
// Delete User Function
|
|
let userToDelete = null;
|
|
let userNameToDelete = '';
|
|
|
|
function deleteUser(userId, userName) {
|
|
userToDelete = userId;
|
|
userNameToDelete = userName;
|
|
document.getElementById('deleteUserName').textContent = userName;
|
|
const deleteModal = new bootstrap.Modal(document.getElementById('deleteModal'));
|
|
deleteModal.show();
|
|
}
|
|
|
|
// Confirm Delete
|
|
document.getElementById('confirmDelete').addEventListener('click', function() {
|
|
if (userToDelete) {
|
|
const formData = new FormData();
|
|
formData.append('action', 'delete');
|
|
formData.append('user_id', userToDelete);
|
|
|
|
fetch('process_user.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert('Error: ' + data.message);
|
|
bootstrap.Modal.getInstance(document.getElementById('deleteModal')).hide();
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Error deleting user');
|
|
bootstrap.Modal.getInstance(document.getElementById('deleteModal')).hide();
|
|
});
|
|
}
|
|
});
|
|
|
|
// Form Validation
|
|
document.getElementById('addUserForm').addEventListener('submit', function(e) {
|
|
const password = document.getElementById('password').value;
|
|
const confirmPassword = document.getElementById('confirm_password').value;
|
|
|
|
if (password !== confirmPassword) {
|
|
e.preventDefault();
|
|
alert('Passwords do not match!');
|
|
return false;
|
|
}
|
|
|
|
if (password.length < 6) {
|
|
e.preventDefault();
|
|
alert('Password must be at least 6 characters long!');
|
|
return false;
|
|
}
|
|
});
|
|
|
|
document.getElementById('editUserForm').addEventListener('submit', function(e) {
|
|
const password = document.getElementById('edit_password').value;
|
|
const confirmPassword = document.getElementById('edit_confirm_password').value;
|
|
|
|
if (password !== confirmPassword) {
|
|
e.preventDefault();
|
|
alert('Passwords do not match!');
|
|
return false;
|
|
}
|
|
|
|
if (password && password.length < 6) {
|
|
e.preventDefault();
|
|
alert('Password must be at least 6 characters long!');
|
|
return false;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<?php
|
|
// Check if we need to close HTML tags (if no header was found)
|
|
if (!$header_found) {
|
|
echo '</div></body></html>';
|
|
}
|
|
?>
|