|
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/dashboard.php
Size: 35.29 KB
Permissions: 0666
<?php
require __DIR__ . '/../includes/helpers.php';
require_admin();
ensure_employees_table();
ensure_designations_table();
try { ensure_notifications_table(); } catch (Throwable $e) { error_log('Notifications table init failed: ' . $e->getMessage()); }
$admin = current_admin();
$roleLabel = (($admin['role'] ?? '') === 'super') ? 'Super Admin' : 'Admin';
$flash = flash();
$q = isset($_GET['q']) ? sanitize_text($_GET['q']) : '';
$cardFilter = isset($_GET['card']) ? sanitize_text($_GET['card']) : '';
$statusOptions = ['Active', 'Left', 'Terminated', 'Absconded / Defaulted', 'All'];
$status = isset($_GET['status']) ? sanitize_text($_GET['status']) : 'Active';
if (!in_array($status, $statusOptions, true)) {
$status = 'Active';
}
$departments = is_super_admin() ? list_departments() : allowed_departments_for_admin();
$departmentFilter = isset($_GET['department']) ? sanitize_text($_GET['department']) : '';
if ($departmentFilter !== '' && !in_array($departmentFilter, $departments, true)) {
$departmentFilter = '';
}
$designationRows = list_designations(true);
$designationOptions = array_map(fn($row) => ['id' => (int) $row['id'], 'name' => $row['name']], $designationRows);
$designationIds = array_column($designationOptions, 'id');
$designationFilter = isset($_GET['designation']) ? (int) $_GET['designation'] : 0;
if ($designationFilter && !in_array($designationFilter, $designationIds, true)) {
$designationFilter = 0;
}
$pdo = db();
$sql = 'SELECT e.*, d.name AS designation_name, d.status AS designation_status FROM employees e LEFT JOIN designations d ON e.designation_id = d.id';
$where = ['e.deleted_at IS NULL'];
$params = [];
$statusColumn = 'employee_status';
if ($status !== 'All') {
$where[] = "e.{$statusColumn} = :status";
$params[':status'] = $status;
}
apply_department_filter($where, $params, 'e');
if ($departmentFilter !== '') {
$where[] = 'e.department = :department';
$params[':department'] = $departmentFilter;
}
if ($designationFilter) {
$where[] = 'e.designation_id = :designation_id';
$params[':designation_id'] = $designationFilter;
}
if ($cardFilter !== '') {
$where[] = 'e.card_number LIKE :card';
$params[':card'] = "%{$cardFilter}%";
}
if ($q !== '') {
$where[] = '(e.first_name LIKE :q_fn OR e.last_name LIKE :q_ln OR e.email LIKE :q_em OR e.phone LIKE :q_ph OR e.card_number LIKE :q_card)';
$params[':q_fn'] = "%{$q}%";
$params[':q_ln'] = "%{$q}%";
$params[':q_em'] = "%{$q}%";
$params[':q_ph'] = "%{$q}%";
$params[':q_card'] = "%{$q}%";
}
if (!empty($where)) {
$sql .= ' WHERE ' . implode(' AND ', $where);
}
$sql .= ' ORDER BY e.created_at DESC';
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$employees = $stmt->fetchAll();
$total = count($employees);
$latest = $employees[0] ?? null;
// Helper to count pending documents for an employee
$pendingCountFor = function (array $emp): int {
// Uses shared helper that understands Aadhaar JSON format and file existence
return count(pending_documents_for_employee($emp));
};
$statusClasses = [
'Active' => 'status-active',
'Left' => 'status-left',
'Terminated' => 'status-terminated',
'Absconded / Defaulted' => 'status-absconded',
];
$exportParams = array_filter([
'q' => $q,
'status' => $status,
'department' => $departmentFilter,
'designation' => $designationFilter ?: null,
'card' => $cardFilter ?: null,
], fn($value) => $value !== '' && $value !== null && $value !== 'All');
$exportUrl = 'export.php' . (!empty($exportParams) ? ('?' . http_build_query($exportParams)) : '');
// Get metrics for KPI cards
$pendingApprovalsCount = (int)$pdo->query("SELECT COUNT(*) FROM employees WHERE approval_status='pending' AND deleted_at IS NULL")->fetchColumn();
$activeEmployeeCount = (int)$pdo->query("SELECT COUNT(*) FROM employees WHERE employee_status='Active' AND deleted_at IS NULL")->fetchColumn();
// Get on-leave count (handle if leaves table doesn't exist)
$onLeaveCount = 0;
try {
$onLeaveCount = (int)$pdo->query("SELECT COUNT(*) FROM leaves WHERE status='approved' AND DATE(start_date) <= CURDATE() AND DATE(end_date) >= CURDATE() AND deleted_at IS NULL")->fetchColumn();
} catch (Exception $e) {
// Leaves table doesn't exist yet - set to 0
$onLeaveCount = 0;
}
// Get unread notifications count
$unreadNotificationsCount = get_unread_notification_count($admin['id']);
// Get recent activity
$recentActivity = $pdo->query("
SELECT
'new_employee' as type,
CONCAT(first_name, ' ', last_name) as title,
created_at as timestamp
FROM employees
WHERE deleted_at IS NULL
ORDER BY created_at DESC
LIMIT 5
")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Admin Dashboard - HRMS</title>
<link rel="stylesheet" href="../assets/css/style.css" />
<link rel="stylesheet" href="../assets/css/polish.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script src="../assets/js/app.js"></script>
</head>
<body class="dashboard-layout">
<div class="app-wrapper">
<?php require '_sidebar.php'; ?>
<!-- MAIN CONTENT -->
<div class="main-content">
<!-- Top Bar -->
<div class="top-bar">
<div class="top-bar-left">
<button class="sidebar-toggle" id="sidebarToggle" aria-label="Toggle sidebar"><i class="fas fa-bars"></i></button>
<div>
<h1 class="page-title">Dashboard</h1>
<div class="breadcrumb-nav">
<span>Welcome back,</span>
<span><?php echo htmlspecialchars($admin['username'] ?? 'Admin', ENT_QUOTES, 'UTF-8'); ?></span>
</div>
</div>
</div>
<div class="top-bar-right">
<button class="notification-bell" title="Notifications"><i class="fas fa-bell"></i>
<?php if ($unreadNotificationsCount > 0): ?>
<span class="notification-badge"><?php echo $unreadNotificationsCount; ?></span>
<?php endif; ?>
</button>
<div class="user-menu">
<div class="user-avatar"><?php echo strtoupper(substr($admin['username'] ?? 'A', 0, 1)); ?></div>
<div class="user-name"><?php echo htmlspecialchars($admin['username'] ?? 'Admin', ENT_QUOTES, 'UTF-8'); ?></div>
</div>
<a href="logout.php" style="color: #cbd5e1; text-decoration: none; padding: 8px 12px; border-radius: 6px; transition: background 0.15s; font-size: 13px; font-weight: 600;" title="Logout">Logout</a>
</div>
</div>
<!-- Dashboard Content -->
<div class="dashboard-container">
<?php if ($flash): ?>
<div class="alert <?php echo $flash['type'] === 'error' ? 'alert-error' : 'alert-success'; ?>" style="margin-bottom: 24px;">
<?php echo htmlspecialchars($flash['message'], ENT_QUOTES, 'UTF-8'); ?>
</div>
<?php endif; ?>
<!-- KPI Cards -->
<div class="kpi-grid">
<div class="kpi-card">
<div class="kpi-header">
<div class="kpi-title">Total Employees</div>
<div class="kpi-icon"><i class="fas fa-users"></i></div>
</div>
<div class="kpi-value"><?php echo $activeEmployeeCount; ?></div>
<div class="kpi-change positive">Active</div>
</div>
<div class="kpi-card">
<div class="kpi-header">
<div class="kpi-title">Pending Approvals</div>
<div class="kpi-icon"><i class="fas fa-check-circle"></i></div>
</div>
<div class="kpi-value"><?php echo $pendingApprovalsCount; ?></div>
<div class="kpi-change <?php echo $pendingApprovalsCount > 0 ? 'negative' : 'positive'; ?>">
<?php echo $pendingApprovalsCount > 0 ? 'Action needed' : 'All clear'; ?>
</div>
</div>
<div class="kpi-card">
<div class="kpi-header">
<div class="kpi-title">On Leave Today</div>
<div class="kpi-icon"><i class="fas fa-umbrella"></i></div>
</div>
<div class="kpi-value"><?php echo $onLeaveCount; ?></div>
<div class="kpi-change">This week</div>
</div>
<div class="kpi-card">
<div class="kpi-header">
<div class="kpi-title">Total Submissions</div>
<div class="kpi-icon"><i class="fas fa-file-alt"></i></div>
</div>
<div class="kpi-value"><?php echo $total; ?></div>
<div class="kpi-change">All time</div>
</div>
</div>
<!-- Announcements Marquee -->
<?php
$announcements = get_marquee_announcements(null, 10);
if (!empty($announcements)):
?>
<div class="announcements-marquee">
<div class="announcements-marquee-inner">
<?php foreach ($announcements as $announcement): ?>
<div class="announcements-marquee-item">
<a href="announcements.php?id=<?php echo (int)$announcement['id']; ?>" title="<?php echo htmlspecialchars($announcement['title'], ENT_QUOTES, 'UTF-8'); ?>">
<?php echo htmlspecialchars(substr($announcement['title'], 0, 60), ENT_QUOTES, 'UTF-8'); ?>
<?php if (strlen($announcement['title']) > 60): ?>...<?php endif; ?>
</a>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<!-- Quick Actions -->
<div class="quick-actions">
<a href="../onboarding.php" class="action-btn">
<div class="action-icon"><i class="fas fa-plus"></i></div>
<div>New Entry</div>
</a>
<a href="attendance.php" class="action-btn">
<div class="action-icon"><i class="fas fa-check"></i></div>
<div>Mark Attendance</div>
</a>
<a href="payroll.php" class="action-btn">
<div class="action-icon"><i class="fas fa-rupee-sign"></i></div>
<div>Run Payroll</div>
</a>
<a href="announcements.php" class="action-btn">
<div class="action-icon"><i class="fas fa-exclamation-circle"></i></div>
<div>Post Notice</div>
</a>
<a href="<?php echo htmlspecialchars($exportUrl, ENT_QUOTES, 'UTF-8'); ?>" class="action-btn">
<div class="action-icon"><i class="fas fa-download"></i></div>
<div>Export Data</div>
</a>
</div>
<!-- Main Dashboard Grid -->
<div class="dashboard-grid">
<!-- Charts/Analytics Column -->
<div>
<div class="chart-card">
<div class="chart-header">Employee Distribution by Department</div>
<div class="chart-container">
<canvas id="departmentChart"></canvas>
</div>
</div>
</div>
<!-- Activity Feed -->
<div class="sidebar-activity">
<div class="chart-header">Recent Activity</div>
<?php if (empty($recentActivity)): ?>
<div style="text-align: center; color: #6b7280; padding: 20px; font-size: 12px;">
No recent activity
</div>
<?php else: ?>
<?php foreach ($recentActivity as $activity): ?>
<div class="activity-item">
<div class="activity-icon"><i class="fas fa-user-plus"></i></div>
<div class="activity-text">
<div class="activity-title"><?php echo htmlspecialchars($activity['title'], ENT_QUOTES, 'UTF-8'); ?> joined</div>
<div class="activity-time"><?php echo date('M d, H:i', strtotime($activity['timestamp'])); ?></div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<!-- Employee Records Table -->
<div class="chart-card" style="margin-top: 32px;">
<div class="chart-header" style="margin-bottom: 20px;">Employee Records</div>
<!-- Table Controls -->
<div class="table-controls" style="margin-bottom: 16px;">
<input type="text" class="table-search" placeholder="Search..." />
<input type="text" id="cardFilter" class="table-filter-select" placeholder="Filter by Card Number" style="width: 140px;" value="<?php echo htmlspecialchars($cardFilter, ENT_QUOTES, 'UTF-8'); ?>" />
<?php if (!empty($departments)): ?>
<select class="table-filter-select" title="Filter by Department" onchange="updateFilters('department', this.value)">
<option value="">All Departments</option>
<?php foreach ($departments as $dept): ?>
<option value="<?php echo htmlspecialchars($dept, ENT_QUOTES, 'UTF-8'); ?>" <?php echo $departmentFilter === $dept ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($dept, ENT_QUOTES, 'UTF-8'); ?>
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<select class="table-filter-select" title="Filter by Status" onchange="updateFilters('status', this.value)">
<option value="">All Status</option>
<?php foreach ($statusOptions as $opt): ?>
<option value="<?php echo htmlspecialchars($opt, ENT_QUOTES, 'UTF-8'); ?>" <?php echo $status === $opt ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($opt, ENT_QUOTES, 'UTF-8'); ?>
</option>
<?php endforeach; ?>
</select>
<?php if (!empty($designationOptions)): ?>
<select class="table-filter-select" title="Filter by Designation" onchange="updateFilters('designation', this.value)">
<option value="">All Designations</option>
<?php foreach ($designationOptions as $desig): ?>
<option value="<?php echo $desig['id']; ?>" <?php echo $designationFilter == $desig['id'] ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($desig['name'], ENT_QUOTES, 'UTF-8'); ?>
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<select class="table-rows-select" title="Rows per page">
<option value="10">10 rows</option>
<option value="25">25 rows</option>
<option value="50">50 rows</option>
</select>
<button type="button" class="table-filter-select" title="Reset Filters" onclick="window.location.href='dashboard.php'" style="cursor: pointer; padding: 6px 12px; background: #6b7280; border: none; color: white; border-radius: 4px; font-size: 13px; font-weight: 500; transition: background 0.2s;">
<i class="fas fa-redo-alt"></i> Reset
</button>
<button type="button" id="bulkImportBtn" class="table-filter-select" title="Bulk Import" style="cursor: pointer; padding: 6px 12px; background: #1e3a5f; border: none; color: white; border-radius: 4px; font-size: 13px; font-weight: 500; transition: background 0.2s; margin-left:8px;">
<i class="fas fa-file-upload"></i> Bulk Import
</button>
</div>
<!-- Bulk Actions Toolbar -->
<form method="post" action="delete.php" id="bulkDeleteForm">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<!-- Selected IDs are injected here by JS before submission -->
</form>
<div class="bulk-actions-bar">
<span class="bulk-selection-info">0 rows selected</span>
<button id="bulkImportBtn" class="bulk-action-btn" style="background: #1e3a5f; border-color: #1e3a5f;" type="button"><i class="fas fa-file-upload"></i> Bulk Import</button>
<button class="bulk-action-btn" style="background: #10b981; border-color: #10b981;" onclick="alert('Export feature coming soon');"><i class="fas fa-check"></i> Export Selected</button>
<button class="bulk-action-btn" id="bulkDeleteBtn" style="background: #ef4444; border-color: #ef4444;" type="button"><i class="fas fa-trash"></i> Delete Selected</button>
</div>
<div class="table-wrapper">
<table class="table" id="employeeTable">
<thead>
<tr>
<th style="width: 40px; text-align: center;"><input type="checkbox" class="row-select-checkbox" title="Select all" /></th>
<th class="cell-nowrap">Full Name</th>
<th class="cell-nowrap">Date of Joining</th>
<th>Contact Number</th>
<th class="cell-nowrap">Emergency Contact</th>
<th>Card Number</th>
<th>Department</th>
<th>Designation</th>
<th class="cell-nowrap col-status">Status</th>
<th class="cell-nowrap">Pending Docs</th>
<th class="col-docs">Docs</th>
<th class="col-actions">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($employees)): ?>
<tr><td colspan="11" style="text-align: center; color: #9ca3af; padding: 32px;">No records found.</td></tr>
<?php else: ?>
<?php foreach ($employees as $emp): ?>
<?php $pendingCount = $pendingCountFor($emp); ?>
<tr>
<td style="width: 40px; text-align: center;"><input type="checkbox" class="row-select-checkbox" value="<?php echo $emp['id']; ?>" /></td>
<td class="cell-nowrap">
<?php
$hasPhoto = (bool) resolve_upload_path($emp['photo_path'] ?? null);
$photoUrl = $hasPhoto
? 'download.php?id=' . $emp['id'] . '&type=photo&mode=inline'
: 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2240%22 height=%2240%22 viewBox=%220 0 80 80%22%3E%3Crect width=%2280%22 height=%2280%22 rx=%2240%22 fill=%22%23e5e7eb%22/%3E%3Cpath fill=%22%239ca3af%22 d=%22M40 12a14 14 0 1 1 0 28 14 14 0 0 1 0-28Zm0 32c11.046 0 20 6.268 20 14v6H20v-6c0-7.732 8.954-14 20-14Z%22/%3E%3C/svg%3E';
?>
<span class="avatar-wrap">
<img src="<?php echo htmlspecialchars($photoUrl, ENT_QUOTES, 'UTF-8'); ?>" loading="lazy" alt="Photo" class="avatar-thumb" width="40" height="40" />
<span>
<span class="name-line"><?php echo htmlspecialchars($emp['first_name'], ENT_QUOTES, 'UTF-8'); ?></span>
<span class="subtext">Father: <?php echo htmlspecialchars($emp['last_name'], ENT_QUOTES, 'UTF-8'); ?></span>
</span>
</span>
</td>
<td class="cell-nowrap"><?php echo htmlspecialchars($emp['date_of_joining'] ?? '', ENT_QUOTES, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($emp['phone'], ENT_QUOTES, 'UTF-8'); ?></td>
<td class="cell-nowrap">
<div><?php echo htmlspecialchars($emp['emergency_contact_name'] ?? '', ENT_QUOTES, 'UTF-8'); ?></div>
<span class="subtext"><?php echo htmlspecialchars($emp['emergency_contact_number'] ?? '', ENT_QUOTES, 'UTF-8'); ?><?php echo !empty($emp['emergency_contact_relation']) ? ' • ' . htmlspecialchars($emp['emergency_contact_relation'], ENT_QUOTES, 'UTF-8') : ''; ?></span>
</td>
<td><?php echo htmlspecialchars($emp['card_number'] ?? '', ENT_QUOTES, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($emp['department'] ?? '', ENT_QUOTES, 'UTF-8'); ?></td>
<?php $designationName = $emp['designation_name'] ?? null; ?>
<td>
<?php echo $designationName ? htmlspecialchars($designationName, ENT_QUOTES, 'UTF-8') : '—'; ?>
</td>
<?php $statusLabel = $emp['employee_status'] ?? 'Active'; ?>
<?php $statusClass = $statusClasses[$statusLabel] ?? 'status-active'; ?>
<td class="cell-nowrap">
<span class="badge status-badge <?php echo $statusClass; ?>"><?php echo htmlspecialchars($statusLabel, ENT_QUOTES, 'UTF-8'); ?></span>
</td>
<td class="cell-nowrap">
<?php if ($pendingCount === 0): ?>
<span class="badge">0</span>
<?php else: ?>
<span class="badge" style="background:#f59e0b;color:#1f2937;"><?php echo $pendingCount; ?></span>
<?php endif; ?>
</td>
<td class="col-docs" style="text-align:center;">
<div class="doc-menu">
<span class="doc-menu-toggle" title="Documents" aria-label="Documents"><i class="fas fa-file"></i></span>
<div class="doc-menu-list">
<a href="download.php?id=<?php echo $emp['id']; ?>&type=aadhaar">Aadhaar</a>
<a href="download.php?id=<?php echo $emp['id']; ?>&type=pan">PAN</a>
<a href="download.php?id=<?php echo $emp['id']; ?>&type=qualification">Graduation</a>
<a href="download.php?id=<?php echo $emp['id']; ?>&type=tenth_marksheet">10th Marksheet</a>
<a href="download.php?id=<?php echo $emp['id']; ?>&type=twelfth_marksheet">12th Marksheet</a>
<a href="download.php?id=<?php echo $emp['id']; ?>&type=bank_proof">Bank Proof</a>
<a href="download.php?id=<?php echo $emp['id']; ?>&type=photo">Photo</a>
</div>
</div>
</td>
<td class="col-actions">
<div class="row-actions">
<div class="action-menu">
<button type="button" class="action-toggle"><i class="fas fa-ellipsis-v"></i></button>
<div class="action-menu-list">
<a href="view.php?id=<?php echo $emp['id']; ?>">View</a>
<a href="edit.php?id=<?php echo $emp['id']; ?>">Edit</a>
<form method="post" action="delete.php" onsubmit="return confirm('Move this record to Trash?');" style="margin:0;">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<input type="hidden" name="id" value="<?php echo $emp['id']; ?>" />
<button type="submit">Move to Trash</button>
</form>
</div>
</div>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Pagination Controls -->
<div class="table-pagination" style="margin-top: 16px;"></div>
</div>
</div>
</div>
</div>
<div class="sidebar-overlay" id="sidebarOverlay"></div>
<!-- Bulk Import Modal (centered overlay, dark theme) -->
<div id="bulkImportModal" class="modal" style="position:fixed; inset:0; z-index:1100; display:none; align-items:center; justify-content:center; background:rgba(2,6,23,0.6);">
<div class="modal-content" style="width:100%; max-width:720px; margin:0 20px; background: rgba(30,41,59,0.95); padding:22px; border-radius:10px; box-shadow:0 12px 30px rgba(2,6,23,0.6); border:1px solid rgba(59,130,246,0.12); color: #cbd5e1;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
<h3 style="margin:0; color: #e5e7eb;">Bulk Import Employees</h3>
<button id="bulkImportClose" aria-label="Close import dialog" style="background:none;border:none;font-size:20px;cursor:pointer;color:#e5e7eb;">×</button>
</div>
<p style="color:#93c5fd; margin:0 0 12px 0;">Download the sample CSV to see the required columns, then upload your filled file.</p>
<div style="display:flex; flex-wrap:wrap; gap:12px; align-items:center; margin-top:6px;">
<a href="../assets/sample_employee_import.csv" class="button" download style="display:inline-block;padding:10px 14px;background:#2563eb;color:#fff;border-radius:8px;text-decoration:none;">Download sample file</a>
<form id="bulkImportForm" action="import.php" method="post" enctype="multipart/form-data" style="display:flex; gap:8px; align-items:center;">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>" />
<label for="import_file" style="background:transparent; color:#cbd5e1; padding:8px 10px; border-radius:6px; border:1px solid rgba(59,130,246,0.12); cursor:pointer;">Choose file</label>
<input id="import_file" type="file" name="import_file" accept=".csv" required style="display:none;" />
<button type="submit" class="button" style="padding:10px 14px;background:#10b981;color:#052e19;border-radius:8px;border:none;cursor:pointer;">Upload file</button>
</form>
</div>
<div style="margin-top:16px;color:#9ca3af;font-size:13px;">Accepted format: CSV. First row must be column headers. See sample for required columns.</div>
</div>
</div>
<script>
// Sidebar Toggle
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');
});
// Department Chart
const ctx = document.getElementById('departmentChart');
if (ctx) {
const deptData = {};
document.querySelectorAll('.table tbody tr').forEach(row => {
const deptCell = row.cells[6]; // Department column (after checkbox, name, joining, phone, emergency, card)
if (deptCell) {
const dept = deptCell.textContent.trim();
if (dept && dept !== 'Department') {
deptData[dept] = (deptData[dept] || 0) + 1;
}
}
});
new Chart(ctx, {
type: 'bar',
data: {
labels: Object.keys(deptData),
datasets: [{
label: 'Employees',
data: Object.values(deptData),
backgroundColor: 'rgba(37, 99, 235, 0.6)',
borderColor: 'rgba(37, 99, 235, 1)',
borderRadius: 8,
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true,
grid: { color: 'rgba(255,255,255,0.1)' },
ticks: { color: '#9ca3af' }
},
x: {
grid: { display: false },
ticks: { color: '#9ca3af' }
}
}
}
});
}
// Initialize ProfessionalTable for employee records
if (document.getElementById('employeeTable')) {
window.currentTable = new ProfessionalTable('employeeTable', {
sortable: true,
filterable: true,
paginated: true,
selectable: true,
rowsPerPage: [10, 25, 50]
});
// Setup search input
const searchInput = document.querySelector('.table-search');
if (searchInput) {
searchInput.addEventListener('input', (e) => {
if (window.currentTable) {
window.currentTable.filter(e.target.value);
}
});
}
// Setup card number filter
const cardFilterInput = document.getElementById('cardFilter');
if (cardFilterInput) {
cardFilterInput.addEventListener('input', (e) => {
// Debounce the filter update
clearTimeout(cardFilterInput._timeout);
cardFilterInput._timeout = setTimeout(() => {
updateFilters('card', e.target.value);
}, 300);
});
}
// Setup rows per page selector
const rowsSelect = document.querySelector('.table-rows-select');
if (rowsSelect) {
rowsSelect.addEventListener('change', (e) => {
if (window.currentTable) {
window.currentTable.setRowsPerPage(parseInt(e.target.value));
}
});
}
}
// Function to handle filter changes
function updateFilters(filterType, filterValue) {
const url = new URL(window.location);
const params = new URLSearchParams(url.search);
if (filterValue === '') {
params.delete(filterType);
} else {
params.set(filterType, filterValue);
}
window.location.href = url.pathname + (params.toString() ? '?' + params.toString() : '');
}
// Bulk Import modal handling
const bulkImportBtn = document.getElementById('bulkImportBtn');
const bulkImportModal = document.getElementById('bulkImportModal');
const bulkImportClose = document.getElementById('bulkImportClose');
if (bulkImportBtn && bulkImportModal) {
bulkImportBtn.addEventListener('click', () => { bulkImportModal.style.display = 'flex'; });
}
if (bulkImportClose && bulkImportModal) {
bulkImportClose.addEventListener('click', () => { bulkImportModal.style.display = 'none'; });
}
// Close modal on overlay click
window.addEventListener('click', (e) => {
if (e.target === bulkImportModal) bulkImportModal.style.display = 'none';
});
// Bulk Delete
document.getElementById('bulkDeleteBtn')?.addEventListener('click', function () {
const checked = Array.from(document.querySelectorAll('#employeeTable .row-select-checkbox:checked'))
.map(cb => cb.value)
.filter(v => v && v !== 'on'); // exclude header checkbox
if (checked.length === 0) {
alert('Please select at least one record to delete.');
return;
}
if (!confirm('Move ' + checked.length + ' selected record(s) to Trash?')) {
return;
}
const form = document.getElementById('bulkDeleteForm');
// Remove any previously injected hidden inputs
form.querySelectorAll('input[name="ids[]"]').forEach(el => el.remove());
checked.forEach(id => {
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'ids[]';
input.value = id;
form.appendChild(input);
});
form.submit();
});
</script>
</body>
</html>