/home/awneajlw/public_html/codestechvista.com/admin/users.php
<?php
session_start();
require_once '../config/database.php';
require_once '../includes/auth.php';
// Check if user is admin
if (!isset($_SESSION['user_id']) || $_SESSION['user_role'] !== 'admin') {
header('Location: ../login.php');
exit();
}
$database = new Database();
$db = $database->getConnection();
$success_message = '';
$error_message = '';
// Handle User Actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'delete_user') {
$user_id = $_POST['user_id'] ?? 0;
try {
$query = "DELETE FROM users WHERE id = ? AND role != 'admin'";
$stmt = $db->prepare($query);
$stmt->execute([$user_id]);
$success_message = "User deleted successfully!";
} catch (Exception $e) {
$error_message = "Error deleting user: " . $e->getMessage();
}
}
elseif ($action === 'add_user') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$password = $_POST['password'] ?? '';
$role = $_POST['role'] ?? 'user';
if (empty($name) || empty($email) || empty($password)) {
$error_message = "Name, email, and password are required!";
} else {
try {
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$query = "INSERT INTO users (name, email, phone, password, role) VALUES (?, ?, ?, ?, ?)";
$stmt = $db->prepare($query);
$stmt->execute([$name, $email, $phone, $hashed_password, $role]);
$success_message = "User added successfully!";
} catch (Exception $e) {
$error_message = "Error adding user: " . $e->getMessage();
}
}
}
elseif ($action === 'update_user') {
$user_id = $_POST['user_id'] ?? 0;
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$role = $_POST['role'] ?? 'user';
try {
$query = "UPDATE users SET name = ?, email = ?, phone = ?, role = ? WHERE id = ?";
$stmt = $db->prepare($query);
$stmt->execute([$name, $email, $phone, $role, $user_id]);
// Update password if provided
if (!empty($_POST['password'])) {
$hashed_password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$query = "UPDATE users SET password = ? WHERE id = ?";
$stmt = $db->prepare($query);
$stmt->execute([$hashed_password, $user_id]);
}
$success_message = "User updated successfully!";
} catch (Exception $e) {
$error_message = "Error updating user: " . $e->getMessage();
}
}
}
// Get all main users with their sub-users count
$query = "SELECT u.*,
(SELECT COUNT(*) FROM users WHERE parent_user_id = u.id AND user_type = 'sub') as sub_users_count
FROM users u
WHERE u.role IN ('user', 'shop_owner') AND (u.user_type IS NULL OR u.user_type = 'main')
ORDER BY u.created_at DESC";
$stmt = $db->prepare($query);
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Get all sub-users with their parent information
$query = "SELECT u.*, p.name as parent_name, p.email as parent_email
FROM users u
LEFT JOIN users p ON u.parent_user_id = p.id
WHERE u.user_type = 'sub'
ORDER BY u.created_at DESC";
$stmt = $db->prepare($query);
$stmt->execute();
$sub_users = $stmt->fetchAll(PDO::FETCH_ASSOC);
$page_title = "Users Management";
?>
<?php include 'includes/header.php'; ?>
<?php include 'includes/sidebar.php'; ?>
<style>
/* Enhanced Users Management Styling */
.action-btn {
padding: 8px 14px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 5px;
}
.btn-success-custom {
background: linear-gradient(135deg, #28a745, #20c997);
color: white;
}
.btn-success-custom:hover {
background: linear-gradient(135deg, #218838, #1aa179);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(40, 167, 69, 0.3);
}
.btn-danger-custom {
background: linear-gradient(135deg, #dc3545, #c82333);
color: white;
}
.btn-danger-custom:hover {
background: linear-gradient(135deg, #c82333, #bd2130);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(220, 53, 69, 0.3);
}
.badge-custom {
padding: 8px 16px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
display: inline-block;
}
/* Enhanced Dropdown Styling */
.dataTables_length {
margin-bottom: 20px;
}
.dataTables_length select {
padding: 8px 12px;
border: 2px solid #e2e8f0;
border-radius: 8px;
background: white;
font-size: 14px;
color: #4a5568;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.dataTables_length select:focus {
outline: none;
border-color: #169D53;
box-shadow: 0 0 0 3px rgba(22, 157, 83, 0.1);
transform: translateY(-1px);
}
.dataTables_length select:hover {
border-color: #169D53;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.dataTables_length label {
font-weight: 600;
color: #2d3748;
margin-right: 10px;
}
/* DataTables Wrapper Styling */
.dataTables_wrapper {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
border: 1px solid #e2e8f0;
}
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter {
margin-bottom: 20px;
}
.dataTables_wrapper .dataTables_filter input {
padding: 10px 15px;
border: 2px solid #e2e8f0;
border-radius: 8px;
background: white;
font-size: 14px;
color: #4a5568;
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.dataTables_wrapper .dataTables_filter input:focus {
outline: none;
border-color: #169D53;
box-shadow: 0 0 0 3px rgba(22, 157, 83, 0.1);
transform: translateY(-1px);
}
.dataTables_wrapper .dataTables_filter input:hover {
border-color: #169D53;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.dataTables_wrapper .dataTables_filter label {
font-weight: 600;
color: #2d3748;
margin-right: 10px;
}
/* Table Styling */
.table-custom {
border-collapse: separate;
border-spacing: 0;
width: 100%;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.table-custom thead th {
background: linear-gradient(135deg, #169D53, #128a43);
color: white;
padding: 15px 20px;
font-weight: 600;
font-size: 14px;
text-align: left;
border: none;
position: relative;
}
.table-custom thead th:first-child {
border-top-left-radius: 12px;
}
.table-custom thead th:last-child {
border-top-right-radius: 12px;
}
.table-custom tbody td {
padding: 15px 20px;
border-bottom: 1px solid #f1f5f9;
color: #4a5568;
font-size: 14px;
}
.table-custom tbody tr:hover {
background: #f8fafc;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0,0,0,0.05);
}
.table-custom tbody tr:last-child td:first-child {
border-bottom-left-radius: 12px;
}
.table-custom tbody tr:last-child td:last-child {
border-bottom-right-radius: 12px;
}
/* Pagination Styling */
.dataTables_paginate {
margin-top: 20px;
text-align: center;
}
.dataTables_paginate .paginate_button {
padding: 8px 12px;
margin: 0 2px;
border: 1px solid #e2e8f0;
border-radius: 6px;
background: white;
color: #4a5568;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-block;
}
.dataTables_paginate .paginate_button:hover {
background: #169D53;
color: white;
border-color: #169D53;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(22, 157, 83, 0.3);
}
.dataTables_paginate .paginate_button.current {
background: #169D53;
color: white;
border-color: #169D53;
font-weight: 600;
}
.dataTables_paginate .paginate_button.disabled {
opacity: 0.5;
cursor: not-allowed;
}
.dataTables_paginate .paginate_button.disabled:hover {
background: white;
color: #4a5568;
border-color: #e2e8f0;
transform: none;
box-shadow: none;
}
/* Info Styling */
.dataTables_info {
color: #6b7280;
font-size: 14px;
margin-top: 15px;
text-align: center;
}
/* Responsive Design */
@media (max-width: 768px) {
.dataTables_wrapper {
padding: 15px;
margin: 10px;
}
.dataTables_length,
.dataTables_filter {
margin-bottom: 15px;
}
.dataTables_length select,
.dataTables_filter input {
width: 100%;
margin-bottom: 10px;
}
.table-custom {
font-size: 12px;
}
.table-custom thead th,
.table-custom tbody td {
padding: 10px 8px;
}
.dataTables_paginate .paginate_button {
padding: 6px 8px;
font-size: 12px;
margin: 1px;
}
}
@media (max-width: 480px) {
.dataTables_wrapper {
padding: 10px;
margin: 5px;
}
.table-custom {
font-size: 11px;
}
.table-custom thead th,
.table-custom tbody td {
padding: 8px 5px;
}
.dataTables_paginate .paginate_button {
padding: 4px 6px;
font-size: 11px;
}
}
}
.badge-success {
background: linear-gradient(135deg, #d4edda, #c3e6cb);
color: #155724;
border: 1px solid #c3e6cb;
}
.badge-info {
background: linear-gradient(135deg, #d1ecf1, #bee5eb);
color: #0c5460;
border: 1px solid #bee5eb;
}
.badge-warning {
background: linear-gradient(135deg, #fff3cd, #ffeaa7);
color: #856404;
border: 1px solid #ffeaa7;
}
.table-custom tbody tr {
transition: all 0.3s ease;
}
.table-custom tbody tr:hover {
background: #f8f9fa;
transform: scale(1.01);
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.modal-custom .modal-header {
background: linear-gradient(135deg, #169D53 0%, #0d7a3f 100%);
color: white;
padding: 20px 25px;
}
.modal-custom .modal-title {
font-weight: 700;
font-size: 20px;
}
.modal-custom .btn-primary-custom {
background: linear-gradient(135deg, #169D53, #0d7a3f);
border: none;
padding: 12px 24px;
font-weight: 600;
}
.modal-custom .btn-primary-custom:hover {
background: linear-gradient(135deg, #128a43, #0a6331);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(22, 157, 83, 0.3);
}
.content-card {
border: 1px solid #e9ecef;
transition: all 0.3s ease;
}
.content-card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.stat-card {
border-left-width: 4px;
border-left-style: solid;
}
.stat-card:nth-child(1) {
border-left-color: #169D53;
}
.stat-card:nth-child(2) {
border-left-color: #28a745;
}
.stat-card:nth-child(3) {
border-left-color: #17a2b8;
}
.stat-card:nth-child(4) {
border-left-color: #ffc107;
}
.list-group-item {
border: none;
border-bottom: 1px solid #f0f0f0;
padding: 15px 0;
}
.list-group-item:last-child {
border-bottom: none;
}
/* DataTables Customization */
.dataTables_wrapper .dataTables_filter input {
border: 2px solid #169D53;
border-radius: 6px;
padding: 8px 12px;
}
.dataTables_wrapper .dataTables_filter input:focus {
outline: none;
box-shadow: 0 0 0 0.2rem rgba(22, 157, 83, 0.15);
}
.dataTables_wrapper .dataTables_length select {
border: 2px solid #169D53;
border-radius: 6px;
padding: 6px 10px;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current {
background: linear-gradient(135deg, #169D53, #0d7a3f) !important;
border-color: #169D53 !important;
color: white !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
background: #169D53 !important;
border-color: #169D53 !important;
color: white !important;
}
</style>
<div class="main-content">
<!-- Page Header -->
<div class="page-header">
<h1 class="page-title">
<i class="fas fa-users"></i> Users Management
</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="dashboard.php">Dashboard</a></li>
<li class="breadcrumb-item active">Users</li>
</ol>
</nav>
</div>
<!-- Alert Messages -->
<?php if ($success_message): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="fas fa-check-circle"></i> <?php echo htmlspecialchars($success_message); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="fas fa-exclamation-triangle"></i> <?php echo htmlspecialchars($error_message); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<!-- Main Users Table -->
<div class="content-card">
<div class="card-header-custom">
<h3 class="card-title-custom">
<i class="fas fa-user"></i> All Users (<?php echo count($users); ?>)
</h3>
<button class="btn-primary-custom" data-bs-toggle="modal" data-bs-target="#addUserModal">
<i class="fas fa-plus"></i> Add New User
</button>
</div>
<div class="table-responsive">
<table id="usersTable" class="table table-custom">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Role</th>
<th>Sub Users</th>
<th>Registered</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo $user['id']; ?></td>
<td><strong><?php echo htmlspecialchars($user['name']); ?></strong></td>
<td><?php echo htmlspecialchars($user['email']); ?></td>
<td><?php echo htmlspecialchars($user['phone']); ?></td>
<td>
<span class="badge-custom badge-<?php echo $user['role'] == 'shop_owner' ? 'info' : 'success'; ?>">
<?php echo ucfirst(str_replace('_', ' ', $user['role'])); ?>
</span>
<?php if ($user['user_type'] == 'sub'): ?>
<span class="badge-custom badge-warning ml-1">
Sub User
</span>
<?php else: ?>
<span class="badge-custom badge-primary ml-1">
Main User
</span>
<?php endif; ?>
</td>
<td>
<span class="badge-custom badge-warning">
<?php echo $user['sub_users_count']; ?> Sub Users
</span>
</td>
<td><?php echo date('M d, Y', strtotime($user['created_at'])); ?></td>
<td>
<div class="action-buttons">
<button class="action-btn btn-success-custom" onclick="editUser(<?php echo htmlspecialchars(json_encode($user)); ?>)">
<i class="fas fa-edit"></i>
</button>
<button class="action-btn btn-danger-custom" onclick="deleteUser(<?php echo $user['id']; ?>, '<?php echo htmlspecialchars($user['name']); ?>')">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- Sub Users Table -->
<div class="content-card mt-4">
<div class="card-header-custom">
<h3 class="card-title-custom">
<i class="fas fa-user-friends"></i> Sub Users (<?php echo count($sub_users); ?>)
</h3>
</div>
<?php if (empty($sub_users)): ?>
<div class="text-center py-5">
<i class="fas fa-users text-muted" style="font-size: 48px; opacity: 0.3;"></i>
<p class="text-muted mt-3">No sub users found</p>
</div>
<?php else: ?>
<div class="table-responsive">
<table id="subUsersTable" class="table table-custom">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Parent User</th>
<th>Status</th>
<th>Created</th>
</tr>
</thead>
<tbody>
<?php foreach ($sub_users as $sub_user): ?>
<tr>
<td><?php echo $sub_user['id']; ?></td>
<td><strong><?php echo htmlspecialchars($sub_user['name']); ?></strong></td>
<td><?php echo htmlspecialchars($sub_user['email']); ?></td>
<td><?php echo htmlspecialchars($sub_user['phone'] ?? 'N/A'); ?></td>
<td>
<span class="badge-custom badge-info">
<?php echo htmlspecialchars($sub_user['parent_name'] ?? 'N/A'); ?>
</span>
</td>
<td>
<span class="badge-custom badge-<?php echo $sub_user['user_type'] == 'sub' ? 'success' : 'warning'; ?>">
<?php echo ucfirst($sub_user['user_type'] ?? 'Main'); ?>
</span>
</td>
<td><?php echo date('M d, Y', strtotime($sub_user['created_at'])); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<!-- Add User Modal -->
<div class="modal fade modal-custom" id="addUserModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-user-plus"></i> Add New User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST">
<div class="modal-body">
<input type="hidden" name="action" value="add_user">
<div class="mb-3">
<label class="form-label">Name *</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Email *</label>
<input type="email" name="email" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Phone</label>
<input type="text" name="phone" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">Password *</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Role</label>
<select name="role" class="form-select">
<option value="user">User</option>
<option value="shop_owner">Shop Owner</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn-primary-custom">Add User</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit User Modal -->
<div class="modal fade modal-custom" id="editUserModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-user-edit"></i> Edit User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST" id="editUserForm">
<div class="modal-body">
<input type="hidden" name="action" value="update_user">
<input type="hidden" name="user_id" id="edit_user_id">
<div class="mb-3">
<label class="form-label">Name *</label>
<input type="text" name="name" id="edit_name" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Email *</label>
<input type="email" name="email" id="edit_email" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Phone</label>
<input type="text" name="phone" id="edit_phone" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">New Password (leave blank to keep current)</label>
<input type="password" name="password" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">Role</label>
<select name="role" id="edit_role" class="form-select">
<option value="user">User</option>
<option value="shop_owner">Shop Owner</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn-primary-custom">Update User</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete User Form -->
<form method="POST" id="deleteUserForm" style="display: none;">
<input type="hidden" name="action" value="delete_user">
<input type="hidden" name="user_id" id="delete_user_id">
</form>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- DataTables -->
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
<script>
$(document).ready(function() {
// Initialize Main Users DataTable
$('#usersTable').DataTable({
order: [[0, 'desc']],
pageLength: 25,
language: {
search: "Search users:"
}
});
// Initialize Sub Users DataTable (only if table exists)
if ($('#subUsersTable').length) {
$('#subUsersTable').DataTable({
order: [[0, 'desc']],
pageLength: 25,
language: {
search: "Search sub users:"
}
});
}
});
function editUser(user) {
document.getElementById('edit_user_id').value = user.id;
document.getElementById('edit_name').value = user.name;
document.getElementById('edit_email').value = user.email;
document.getElementById('edit_phone').value = user.phone || '';
document.getElementById('edit_role').value = user.role;
new bootstrap.Modal(document.getElementById('editUserModal')).show();
}
function deleteUser(userId, userName) {
if (confirm('Are you sure you want to delete user "' + userName + '"? This action cannot be undone.')) {
document.getElementById('delete_user_id').value = userId;
document.getElementById('deleteUserForm').submit();
}
}
// Initialize DataTables for both tables
$(document).ready(function() {
// Initialize main users table
$('#usersTable').DataTable({
"responsive": true,
"pageLength": 25,
"lengthMenu": [[10, 25, 50, 100], [10, 25, 50, 100]],
"order": [[0, "desc"]],
"language": {
"search": "Search users:",
"lengthMenu": "Show _MENU_ entries",
"info": "Showing _START_ to _END_ of _TOTAL_ entries",
"infoEmpty": "No entries found",
"infoFiltered": "(filtered from _MAX_ total entries)",
"paginate": {
"first": "First",
"last": "Last",
"next": "Next",
"previous": "Previous"
}
},
"dom": '<"row"<"col-sm-6"l><"col-sm-6"f>>rtip',
"columnDefs": [
{ "orderable": false, "targets": -1 } // Disable sorting on action column
]
});
// Initialize sub users table
$('#subUsersTable').DataTable({
"responsive": true,
"pageLength": 25,
"lengthMenu": [[10, 25, 50, 100], [10, 25, 50, 100]],
"order": [[0, "desc"]],
"language": {
"search": "Search sub users:",
"lengthMenu": "Show _MENU_ entries",
"info": "Showing _START_ to _END_ of _TOTAL_ entries",
"infoEmpty": "No entries found",
"infoFiltered": "(filtered from _MAX_ total entries)",
"paginate": {
"first": "First",
"last": "Last",
"next": "Next",
"previous": "Previous"
}
},
"dom": '<"row"<"col-sm-6"l><"col-sm-6"f>>rtip'
});
});
}
</script>
</body>
</html>