|
Server : LiteSpeed System : Linux terra.hostitbro.com 5.14.0-611.54.3.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 7 16:31:24 EDT 2026 x86_64 User : outerorb ( 1091) PHP Version : 8.1.34 Disable Function : mail Directory : /home2/outerorb/emp.outerorbittech.in/admin/ | |
|
Path: /home2/outerorb/emp.outerorbittech.in/admin/approvals.php
Size: 10.34 KB
Permissions: 0666
<?php
require __DIR__ . '/../includes/helpers.php';
require_admin();
ensure_employees_table();
ensure_employee_auth_table();
$roleLabel = 'Admin';
$flash = flash();
$pdo = db();
// Handle approve/reject POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || !verify_csrf($_POST['csrf_token'])) {
redirect_with_message('approvals.php', 'Session expired. Try again.', 'error');
}
$action = sanitize_text($_POST['action'] ?? '');
$id = isset($_POST['id']) ? (int) $_POST['id'] : 0;
if (!$id || !in_array($action, ['approve', 'reject'], true)) {
redirect_with_message('approvals.php', 'Invalid request.', 'error');
}
// Fetch employee to verify access
$emp = $pdo->prepare('SELECT id, first_name, last_name, phone, department FROM employees WHERE id = ? AND deleted_at IS NULL LIMIT 1');
$emp->execute([$id]);
$emp = $emp->fetch();
if (!$emp) {
redirect_with_message('approvals.php', 'Employee not found.', 'error');
}
enforce_department_access($emp);
if ($action === 'approve') {
// Set approval_status = approved
$pdo->prepare("UPDATE employees SET approval_status = 'approved' WHERE id = ?")->execute([$id]);
// Create login credentials: default password = phone number
$defaultPassword = $emp['phone'];
$hash = password_hash($defaultPassword, PASSWORD_DEFAULT);
$pdo->prepare(
'INSERT INTO employee_auth (employee_id, password_hash, must_change_password, is_active)
VALUES (?, ?, 1, 1)
ON DUPLICATE KEY UPDATE password_hash = VALUES(password_hash), must_change_password = 1, is_active = 1'
)->execute([$id, $hash]);
redirect_with_message(
'approvals.php',
htmlspecialchars($emp['first_name'] . ' ' . $emp['last_name'], ENT_QUOTES, 'UTF-8') .
' approved. Default login password is their phone number: ' . htmlspecialchars($emp['phone'], ENT_QUOTES, 'UTF-8') .
'. They must change it on first login.'
);
} else {
$pdo->prepare("UPDATE employees SET approval_status = 'rejected' WHERE id = ?")->execute([$id]);
redirect_with_message('approvals.php', htmlspecialchars($emp['first_name'] . ' ' . $emp['last_name'], ENT_QUOTES, 'UTF-8') . ' rejected.', 'error');
}
}
// Fetch pending employees (respect department filter for non-super admins)
$where = ["e.deleted_at IS NULL", "e.approval_status = 'pending'"];
$params = [];
apply_department_filter($where, $params, 'e');
$sql = 'SELECT e.id, e.first_name, e.last_name, e.phone, e.email, e.department, e.created_at,
d.name AS designation_name
FROM employees e
LEFT JOIN designations d ON d.id = e.designation_id
WHERE ' . implode(' AND ', $where) . '
ORDER BY e.created_at ASC';
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$pending = $stmt->fetchAll();
$admin = current_admin();
$roleLabel = (($admin['role'] ?? '') === 'super') ? 'Super Admin' : 'Admin';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pending Approvals</title>
<link rel="stylesheet" href="../assets/css/style.css?v=<?php echo filemtime(__DIR__ . '/../assets/css/style.css'); ?>" />
<link rel="stylesheet" href="../assets/css/polish.css?v=<?php echo filemtime(__DIR__ . '/../assets/css/polish.css'); ?>" />
</head>
<body class="dashboard-layout">
<div class="app-wrapper">
<?php require '_sidebar.php'; ?>
<div class="main-content">
<div class="top-bar">
<div class="top-bar-left">
<button class="sidebar-toggle" id="sidebarToggle" aria-label="Toggle sidebar">☰</button>
<div>
<h1 class="page-title">Pending Approvals</h1>
<div class="breadcrumb-nav">
<span>Review and activate employee registrations</span>
</div>
</div>
</div>
<div class="top-bar-right">
<a href="dashboard.php" style="color: #cbd5e1; text-decoration: none; padding: 8px 12px; border-radius: 6px; transition: background 0.15s; font-size: 13px; font-weight: 600;">← Dashboard</a>
</div>
</div>
<div class="dashboard-container" style="max-width: 1200px;">
<div class="container">
<div class="header" style="display: none;">
<div class="brand">
<div class="brand-title">
<h1 style="margin:0;">Pending Approvals</h1>
<p class="helper" style="margin:2px 0 0 0;">Review and activate employee self-registrations.</p>
<p class="helper" style="margin:4px 0 0 0;">Signed in as <?php echo htmlspecialchars($admin['username'] ?? 'Admin', ENT_QUOTES, 'UTF-8'); ?> (<?php echo htmlspecialchars($roleLabel, ENT_QUOTES, 'UTF-8'); ?>)</p>
</div>
</div>
<div class="actions">
<a class="badge" href="dashboard.php">Dashboard</a>
<a class="badge" href="logout.php">Logout</a>
</div>
</div>
<?php if ($flash): ?>
<div class="alert <?php echo $flash['type'] === 'error' ? 'alert-error' : 'alert-success'; ?>">
<?php echo htmlspecialchars($flash['message'], ENT_QUOTES, 'UTF-8'); ?>
</div>
<?php endif; ?>
<div class="card">
<?php if (empty($pending)): ?>
<p style="color:#6b7280; padding:20px 0;">No pending registrations. All self-submitted forms have been reviewed.</p>
<?php else: ?>
<p class="helper" style="margin-bottom:16px;">
<?php echo count($pending); ?> self-registration<?php echo count($pending) !== 1 ? 's' : ''; ?> awaiting review.
On approval the employee's default login password will be set to their phone number — they must change it on first login.
</p>
<div class="table-wrapper">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th>Department</th>
<th>Designation</th>
<th>Submitted</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($pending as $row): ?>
<tr>
<td class="cell-nowrap">
<a href="view.php?id=<?php echo $row['id']; ?>" style="font-weight:600;">
<?php echo htmlspecialchars($row['first_name'] . ' ' . $row['last_name'], ENT_QUOTES, 'UTF-8'); ?>
</a>
</td>
<td><?php echo htmlspecialchars($row['phone'], ENT_QUOTES, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($row['email'], ENT_QUOTES, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($row['department'], ENT_QUOTES, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($row['designation_name'] ?? '—', ENT_QUOTES, 'UTF-8'); ?></td>
<td class="cell-nowrap"><?php echo htmlspecialchars($row['created_at'], ENT_QUOTES, 'UTF-8'); ?></td>
<td class="cell-nowrap">
<div style="display:flex; gap:8px; flex-wrap:wrap;">
<form method="post" action="approvals.php" style="margin:0;">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<input type="hidden" name="id" value="<?php echo $row['id']; ?>" />
<input type="hidden" name="action" value="approve" />
<button type="submit" style="background:#16a34a; color:#fff; border:none; padding:6px 14px; border-radius:6px; cursor:pointer; font-size:.85rem;">
Approve
</button>
</form>
<form method="post" action="approvals.php" style="margin:0;"
onsubmit="return confirm('Reject this registration? The employee will not be able to log in.');">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<input type="hidden" name="id" value="<?php echo $row['id']; ?>" />
<input type="hidden" name="action" value="reject" />
<button type="submit" style="background:#dc2626; color:#fff; border:none; padding:6px 14px; border-radius:6px; cursor:pointer; font-size:.85rem;">
Reject
</button>
</form>
<a href="view.php?id=<?php echo $row['id']; ?>" class="badge">View</a>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sidebar-overlay" id="sidebarOverlay"></div>
<script>
const sidebar = document.getElementById('sidebar');
const sidebarToggle = document.getElementById('sidebarToggle');
const sidebarOverlay = document.getElementById('sidebarOverlay');
sidebarToggle?.addEventListener('click', () => {
sidebar.classList.toggle('open');
sidebarOverlay.classList.toggle('open');
});
sidebarOverlay?.addEventListener('click', () => {
sidebar.classList.remove('open');
sidebarOverlay.classList.remove('open');
});
</script>
</body>
</html>