|
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/document_requests.php
Size: 15.79 KB
Permissions: 0666
<?php
require __DIR__ . '/../includes/helpers.php';
require_admin();
ensure_employees_table();
ensure_document_requests_table();
$roleLabel = 'Admin';
$flash = flash();
$pdo = db();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || !verify_csrf($_POST['csrf_token'])) {
redirect_with_message('document_requests.php', 'Invalid session token.', 'error');
}
$action = $_POST['action'] ?? 'create';
if ($action === 'cancel') {
$id = (int) ($_POST['id'] ?? 0);
if ($id <= 0) {
redirect_with_message('document_requests.php', 'Invalid request selection.', 'error');
}
$stmt = $pdo->prepare('SELECT status FROM document_requests WHERE id = ? LIMIT 1');
$stmt->execute([$id]);
$row = $stmt->fetch();
if (!$row) {
redirect_with_message('document_requests.php', 'Request not found.', 'error');
}
if ($row['status'] !== 'pending') {
redirect_with_message('document_requests.php', 'Only pending requests can be cancelled.', 'error');
}
update_document_request_status($id, 'cancelled');
redirect_with_message('document_requests.php', 'Request cancelled.');
}
$employeeId = (int) ($_POST['employee_id'] ?? 0);
$docs = (array) ($_POST['docs'] ?? []);
$note = sanitize_text($_POST['note'] ?? '');
if ($employeeId <= 0) {
redirect_with_message('document_requests.php', 'Select a valid employee.', 'error');
}
$deptCheck = $pdo->prepare('SELECT department FROM employees WHERE id = ? LIMIT 1');
$deptCheck->execute([$employeeId]);
$deptRow = $deptCheck->fetch();
if (!$deptRow) {
redirect_with_message('document_requests.php', 'Employee not found.', 'error');
}
enforce_department_access(['department' => $deptRow['department'] ?? '']);
try {
$request = create_document_request($employeeId, $docs, $note !== '' ? $note : null);
redirect_with_message('document_requests.php', 'Request created. Share code: ' . $request['request_code']);
} catch (Throwable $e) {
redirect_with_message('document_requests.php', $e->getMessage(), 'error');
}
}
$where = [];
$params = [];
apply_department_filter($where, $params, 'e');
$sql = 'SELECT dr.*, e.first_name, e.last_name, e.phone, e.email, e.department FROM document_requests dr JOIN employees e ON dr.employee_id = e.id';
if (!empty($where)) {
$sql .= ' WHERE ' . implode(' AND ', $where);
}
$sql .= ' ORDER BY dr.created_at DESC';
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$requests = $stmt->fetchAll();
$empSql = 'SELECT e.id, e.first_name, e.last_name, e.phone, e.email, e.department, e.aadhaar_path, e.pan_path, e.qualification_path, e.tenth_marksheet_path, e.twelfth_marksheet_path, e.bank_proof_path, e.photo_path FROM employees e WHERE e.deleted_at IS NULL';
$empParams = [];
$empWhere = [];
apply_department_filter($empWhere, $empParams);
if (!empty($empWhere)) {
$empSql .= ' AND ' . implode(' AND ', $empWhere);
}
$empSql .= ' ORDER BY e.created_at DESC';
$empStmt = $pdo->prepare($empSql);
$empStmt->execute($empParams);
$pendingEmployees = [];
foreach ($empStmt->fetchAll() as $emp) {
$pending = pending_documents_for_employee($emp);
if (!empty($pending)) {
$emp['pending_docs'] = $pending;
$pendingEmployees[] = $emp;
}
}
$documentOptions = [
'aadhaar_front' => 'Aadhaar Front',
'aadhaar_back' => 'Aadhaar Back',
'pan' => 'PAN Document',
'qualification' => 'Graduation',
'tenth_marksheet' => '10th Marksheet',
'twelfth_marksheet' => '12th Marksheet',
'bank_proof' => 'Bank Proof',
'photo' => 'Passport Photo',
];
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document Requests</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">Document Requests</h1>
<div class="breadcrumb-nav">
<span>View and manage document requests</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">
<div class="brand">
<div class="brand-title">
<h1 style="margin:0;">Document Requests</h1>
<p class="helper" style="margin:2px 0 0 0;">Create and track pending upload requests.</p>
</div>
</div>
<div class="actions">
<a class="badge" href="dashboard.php">Dashboard</a>
<a class="badge" href="../onboarding.php">New Entry</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" style="margin-bottom:20px;">
<h3 style="margin-top:0;">Create Request</h3>
<form method="post" action="document_requests.php" style="display:grid; gap:12px; max-width:520px;">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<div>
<label for="employee_id">Employee ID</label>
<input id="employee_id" name="employee_id" type="number" min="1" required />
<p class="helper">Use the ID from the dashboard row.</p>
</div>
<div>
<label>Documents to request</label>
<div style="display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:8px 14px;">
<?php foreach ($documentOptions as $key => $label): ?>
<label class="doc-checkbox" style="display:flex; align-items:center; gap:8px;">
<input type="checkbox" name="docs[]" value="<?php echo htmlspecialchars($key, ENT_QUOTES, 'UTF-8'); ?>" />
<span><?php echo htmlspecialchars($label, ENT_QUOTES, 'UTF-8'); ?></span>
</label>
<?php endforeach; ?>
</div>
<p class="helper">Select at least one document.</p>
</div>
<div>
<label for="note">Admin note (optional)</label>
<input id="note" name="note" type="text" maxlength="255" placeholder="Example: Missing PAN" />
</div>
<div style="display:flex; justify-content:flex-end; gap:10px;">
<button type="submit">Create Request</button>
</div>
</form>
</div>
<div class="card" style="margin-bottom:20px;">
<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; margin-bottom:10px;">
<h3 style="margin:0;">Employees With Pending Documents</h3>
<span class="helper">Click "Use ID" to fill the form above.</span>
</div>
<div class="table-wrapper">
<table class="table">
<thead>
<tr>
<th>Employee</th>
<th>Pending Docs</th>
<th class="cell-nowrap">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($pendingEmployees)): ?>
<tr><td colspan="3">No pending documents detected.</td></tr>
<?php else: ?>
<?php foreach ($pendingEmployees as $emp): ?>
<tr>
<td>
<div><?php echo htmlspecialchars($emp['first_name'] . ' ' . $emp['last_name'], ENT_QUOTES, 'UTF-8'); ?> (ID: <?php echo (int) $emp['id']; ?>)</div>
<div class="subtext"><?php echo htmlspecialchars($emp['phone'], ENT_QUOTES, 'UTF-8'); ?> รขโฌยข <?php echo htmlspecialchars($emp['email'], ENT_QUOTES, 'UTF-8'); ?></div>
</td>
<td>
<div class="subtext" style="display:flex; flex-wrap:wrap; gap:6px 10px;">
<?php foreach ($emp['pending_docs'] as $doc): ?>
<span class="badge" style="background:#fef9c3; color:#92400e;"><?php echo htmlspecialchars($doc, ENT_QUOTES, 'UTF-8'); ?></span>
<?php endforeach; ?>
</div>
</td>
<td class="cell-nowrap">
<button type="button" class="button-ghost" data-fill-employee="<?php echo (int) $emp['id']; ?>">Use ID</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<div class="card">
<div style="display:flex; justify-content:space-between; align-items:center; gap:12px; margin-bottom:10px;">
<h3 style="margin:0;">All Requests</h3>
<span class="helper">Newest first</span>
</div>
<div class="table-wrapper">
<table class="table">
<thead>
<tr>
<th class="cell-nowrap">Code</th>
<th>Employee</th>
<th>Requested Docs</th>
<th>Status</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($requests)): ?>
<tr><td colspan="6">No requests yet.</td></tr>
<?php else: ?>
<?php foreach ($requests as $req): ?>
<?php $docs = json_decode($req['requested_docs'] ?? '[]', true) ?: []; ?>
<tr>
<td class="cell-nowrap"><strong><?php echo htmlspecialchars($req['request_code'], ENT_QUOTES, 'UTF-8'); ?></strong></td>
<td>
<div><?php echo htmlspecialchars($req['first_name'] . ' ' . $req['last_name'], ENT_QUOTES, 'UTF-8'); ?> (ID: <?php echo (int) $req['employee_id']; ?>)</div>
<div class="subtext"><?php echo htmlspecialchars($req['phone'], ENT_QUOTES, 'UTF-8'); ?> รขโฌยข <?php echo htmlspecialchars($req['email'], ENT_QUOTES, 'UTF-8'); ?></div>
</td>
<td>
<?php if (empty($docs)): ?>
<span class="subtext">None</span>
<?php else: ?>
<div class="subtext" style="display:flex; flex-wrap:wrap; gap:6px 10px;">
<?php foreach ($docs as $doc): ?>
<span class="badge" style="background:#eef2ff; color:#1e3a8a;"><?php echo htmlspecialchars($documentOptions[$doc] ?? $doc, ENT_QUOTES, 'UTF-8'); ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (!empty($req['admin_note'])): ?>
<div class="helper">Note: <?php echo htmlspecialchars($req['admin_note'], ENT_QUOTES, 'UTF-8'); ?></div>
<?php endif; ?>
</td>
<td class="cell-nowrap">
<?php if ($req['status'] === 'pending'): ?>
<span class="badge" style="background:#fef9c3; color:#92400e;">Pending</span>
<?php elseif ($req['status'] === 'completed'): ?>
<span class="badge" style="background:#dcfce7; color:#166534;">Completed</span>
<?php else: ?>
<span class="badge" style="background:#fee2e2; color:#991b1b;">Cancelled</span>
<?php endif; ?>
</td>
<td class="cell-nowrap"><?php echo htmlspecialchars($req['created_at'], ENT_QUOTES, 'UTF-8'); ?></td>
<td class="cell-nowrap">
<?php if ($req['status'] === 'pending'): ?>
<form method="post" action="document_requests.php" style="display:inline;" onsubmit="return confirm('Cancel this request?');">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<input type="hidden" name="action" value="cancel" />
<input type="hidden" name="id" value="<?php echo (int) $req['id']; ?>" />
<button type="submit" class="button-ghost">Cancel</button>
</form>
<?php else: ?>
<span class="subtext">โ</span>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</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>
<script>
(function() {
const fillerButtons = document.querySelectorAll('[data-fill-employee]');
const employeeField = document.getElementById('employee_id');
if (!employeeField) return;
fillerButtons.forEach((btn) => {
btn.addEventListener('click', () => {
employeeField.value = btn.getAttribute('data-fill-employee');
employeeField.focus();
window.scrollTo({ top: 0, behavior: 'smooth' });
});
});
})();
</script>
</body>
</html>