206 lines
9.4 KiB
PHP
206 lines
9.4 KiB
PHP
<?php $pdo = $db; ?>
|
|
<?php
|
|
if (!is_admin()) {
|
|
// Only admins for now, or roles with permission
|
|
// header('Location: index.php'); exit;
|
|
}
|
|
|
|
// Fetch Stats
|
|
$total_employees = $pdo->query("SELECT COUNT(*) FROM employees")->fetchColumn();
|
|
$present_today = $pdo->query("SELECT COUNT(DISTINCT employee_id) FROM attendance_logs WHERE date = CURDATE() AND status IN ('Present', 'Late')")->fetchColumn();
|
|
$on_leave_today = $pdo->query("SELECT COUNT(*) FROM leave_requests WHERE CURDATE() BETWEEN start_date AND end_date AND status = 'Approved'")->fetchColumn();
|
|
$pending_leaves = $pdo->query("SELECT COUNT(*) FROM leave_requests WHERE status = 'Pending'")->fetchColumn();
|
|
|
|
// Recent Attendance
|
|
$recent_attendance = $pdo->query("
|
|
SELECT a.*, e.name_en, e.name_ar
|
|
FROM attendance_logs a
|
|
JOIN employees e ON a.employee_id = e.id
|
|
ORDER BY a.created_at DESC
|
|
LIMIT 5
|
|
")->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
?>
|
|
|
|
<div class="container-fluid">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1 class="h3 mb-0 text-gray-800">HR Dashboard</h1>
|
|
<div>
|
|
<a href="employees.php" class="btn btn-sm btn-primary shadow-sm"><i class="fas fa-users fa-sm text-white-50"></i> Employees</a>
|
|
<a href="hr_attendance.php" class="btn btn-sm btn-info shadow-sm"><i class="fas fa-clock fa-sm text-white-50"></i> Attendance</a>
|
|
<a href="hr_leaves.php" class="btn btn-sm btn-warning shadow-sm"><i class="fas fa-calendar-minus fa-sm text-white-50"></i> Leave Requests</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stats Rows -->
|
|
<div class="row">
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-primary shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Total Employees</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $total_employees; ?></div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fas fa-users fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-success shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Present Today</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $present_today; ?></div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fas fa-user-check fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-info shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">On Leave Today</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $on_leave_today; ?></div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fas fa-plane-departure fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-3 col-md-6 mb-4">
|
|
<div class="card border-left-warning shadow h-100 py-2">
|
|
<div class="card-body">
|
|
<div class="row no-gutters align-items-center">
|
|
<div class="col mr-2">
|
|
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Pending Requests</div>
|
|
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $pending_leaves; ?></div>
|
|
</div>
|
|
<div class="col-auto">
|
|
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Recent Attendance -->
|
|
<div class="col-lg-6 mb-4">
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">Recent Attendance Logs</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered" width="100%" cellspacing="0">
|
|
<thead>
|
|
<tr>
|
|
<th>Employee</th>
|
|
<th>Status</th>
|
|
<th>Time</th>
|
|
<th>Source</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($recent_attendance as $log): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($log['name_en']); ?></td>
|
|
<td>
|
|
<span class="badge badge-<?php
|
|
echo $log['status'] == 'Present' ? 'success' :
|
|
($log['status'] == 'Late' ? 'warning' : 'danger');
|
|
?>">
|
|
<?php echo $log['status']; ?>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
In: <?php echo $log['check_in'] ? date('H:i', strtotime($log['check_in'])) : '-'; ?><br>
|
|
Out: <?php echo $log['check_out'] ? date('H:i', strtotime($log['check_out'])) : '-'; ?>
|
|
</td>
|
|
<td><?php echo htmlspecialchars($log['source']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if(empty($recent_attendance)): ?>
|
|
<tr><td colspan="4" class="text-center">No logs today</td></tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Biometric Simulator -->
|
|
<div class="col-lg-6 mb-4">
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-info">Simulate Biometric Device Push</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<p>Use this form to test biometric integration. In a real scenario, the device POSTs to <code>/api/biometric_push.php</code>.</p>
|
|
<form id="biometricSimForm">
|
|
<div class="form-group">
|
|
<label>Employee ID</label>
|
|
<input type="number" class="form-control" name="employee_id" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Type</label>
|
|
<select class="form-control" name="type">
|
|
<option value="check_in">Check In</option>
|
|
<option value="check_out">Check Out</option>
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-block">Simulate Push</button>
|
|
</form>
|
|
<div id="simResult" class="mt-3"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.getElementById('biometricSimForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
const formData = new FormData(this);
|
|
const data = {
|
|
api_key: 'test_key', // You would configure this per device
|
|
employee_id: formData.get('employee_id'),
|
|
type: formData.get('type'),
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
|
|
fetch('api/biometric_push.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data)
|
|
})
|
|
.then(r => r.json())
|
|
.then(d => {
|
|
const resDiv = document.getElementById('simResult');
|
|
if(d.success) {
|
|
resDiv.innerHTML = '<div class="alert alert-success">Success: ' + d.message + '</div>';
|
|
setTimeout(() => location.reload(), 1500);
|
|
} else {
|
|
resDiv.innerHTML = '<div class="alert alert-danger">Error: ' + (d.error || 'Unknown') + '</div>';
|
|
}
|
|
});
|
|
});
|
|
</script>
|