Employment attendance system

This commit is contained in:
Flatlogic Bot 2025-11-28 03:31:58 +00:00
parent 3b25d53f36
commit 894b41720e
19 changed files with 1458 additions and 142 deletions

157
add_employee.php Normal file
View File

@ -0,0 +1,157 @@
<?php
session_start();
require_once 'db/config.php';
// Check if user is logged in and is an Admin
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true || $_SESSION['role'] !== 'Admin') {
header('location: login.php');
exit;
}
$username = $password = $role = '';
$username_err = $password_err = $role_err = '';
$success_msg = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Validate username
if (empty(trim($_POST['username']))) {
$username_err = 'Please enter a username.';
} else {
// Check if username already exists
$sql = 'SELECT id FROM users WHERE username = :username';
if ($stmt = db()->prepare($sql)) {
$stmt->bindParam(':username', trim($_POST['username']), PDO::PARAM_STR);
if ($stmt->execute()) {
if ($stmt->rowCount() == 1) {
$username_err = 'This username is already taken.';
} else {
$username = trim($_POST['username']);
}
} else {
echo 'Oops! Something went wrong. Please try again later.';
}
unset($stmt);
}
}
// Validate password
if (empty(trim($_POST['password']))) {
$password_err = 'Please enter a password.';
} elseif (strlen(trim($_POST['password'])) < 6) {
$password_err = 'Password must have at least 6 characters.';
} else {
$password = trim($_POST['password']);
}
// Validate role
if (empty($_POST['role'])) {
$role_err = 'Please select a role.';
} else {
$role = $_POST['role'];
}
// Check input errors before inserting in database
if (empty($username_err) && empty($password_err) && empty($role_err)) {
$sql = 'INSERT INTO users (username, password, role) VALUES (:username, :password, :role)';
if ($stmt = db()->prepare($sql)) {
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->bindParam(':password', $hashed_password, PDO::PARAM_STR);
$stmt->bindParam(':role', $role, PDO::PARAM_STR);
// Hash password
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
if ($stmt->execute()) {
$success_msg = 'Employee added successfully!';
// Clear form fields
$username = $password = $role = '';
} else {
echo 'Oops! Something went wrong. Please try again later.';
}
unset($stmt);
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add Employee - Employee Attendance System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="sidebar">
<h4 class="mb-4 fw-bold">Attendance System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill me-2"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="#"><i class="bi bi-person-plus-fill me-2"></i> Add Employee</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-people-fill me-2"></i> Employees</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-calendar-check-fill me-2"></i> Attendance</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-file-earmark-bar-graph-fill me-2"></i> Reports</a>
</li>
<li class="nav-item mt-auto">
<a class="nav-link" href="logout.php"><i class="bi bi-box-arrow-left me-2"></i> Logout</a>
</li>
</ul>
</div>
<div class="main-content">
<div class="container-fluid">
<h1 class="mt-4">Add New Employee</h1>
<p class="lead">Fill out the form to add a new employee to the system.</p>
<?php if(!empty($success_msg)): ?>
<div class="alert alert-success"><?php echo $success_msg; ?></div>
<?php endif; ?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" class="mt-4 card p-4 bg-white border-0 shadow-sm">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" name="username" id="username" class="form-control <?php echo (!empty($username_err)) ? 'is-invalid' : ''; ?>" value="<?php echo $username; ?>">
<span class="invalid-feedback"><?php echo $username_err; ?></span>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" name="password" id="password" class="form-control <?php echo (!empty($password_err)) ? 'is-invalid' : ''; ?>">
<span class="invalid-feedback"><?php echo $password_err; ?></span>
</div>
<div class="mb-3">
<label for="role" class="form-label">Role</label>
<select name="role" id="role" class="form-select <?php echo (!empty($role_err)) ? 'is-invalid' : ''; ?>">
<option value="">Select a role...</option>
<option value="Admin" <?php if($role == 'Admin') echo 'selected'; ?>>Admin</option>
<option value="HR" <?php if($role == 'HR') echo 'selected'; ?>>HR</option>
<option value="Employee" <?php if($role == 'Employee') echo 'selected'; ?>>Employee</option>
<option value="Supervisor" <?php if($role == 'Supervisor') echo 'selected'; ?>>Supervisor</option>
</select>
<span class="invalid-feedback"><?php echo $role_err; ?></span>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary" style="background-color: #3B82F6;">Add Employee</button>
</div>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

43
assets/css/custom.css Normal file
View File

@ -0,0 +1,43 @@
body {
font-family: 'Inter', sans-serif;
background-color: #F3F4F6;
}
.login-body {
background-image: linear-gradient(to right, #3B82F6, #1E40AF);
}
.card-header {
border-bottom: 0;
}
.form-control:focus {
box-shadow: 0 0 0 0.25rem rgba(59, 130, 246, 0.25);
border-color: #3B82F6;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
bottom: 0;
width: 250px;
padding: 20px;
background-color: #1F2937;
color: #fff;
}
.sidebar .nav-link {
color: #D1D5DB;
font-weight: 500;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #fff;
background-color: #374151;
}
.main-content {
margin-left: 250px;
padding: 20px;
}

111
attendance_report.php Normal file
View File

@ -0,0 +1,111 @@
<?php
session_start();
if (!isset($_SESSION['user_id']) || !in_array($_SESSION['role'], ['Admin', 'HR'])) {
header('Location: login.php');
exit();
}
require_once 'db/config.php';
include 'sidebar.php';
// Fetch attendance data
$search_date = isset($_GET['search_date']) ? $_GET['search_date'] : '';
$search_name = isset($_GET['search_name']) ? $_GET['search_name'] : '';
$sql = "
SELECT a.id, e.name, a.status, a.date, a.check_in_time, a.check_out_time
FROM attendance a
JOIN employees e ON a.employee_id = e.id
";
$where_clauses = [];
$params = [];
if (!empty($search_date)) {
$where_clauses[] = "a.date = :date";
$params['date'] = $search_date;
}
if (!empty($search_name)) {
$where_clauses[] = "e.name LIKE :name";
$params['name'] = '%' . $search_name . '%';
}
if (!empty($where_clauses)) {
$sql .= " WHERE " . implode(' AND ', $where_clauses);
}
$stmt = db()->prepare($sql);
$stmt->execute($params);
$attendance_records = $stmt->fetchAll();
?>
<div class="container-fluid">
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">This is the Attendance Report Page</h1>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Filter by Date</h6>
</div>
<div class="card-body">
<form method="get" action="attendance_report.php">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="search_date">Select Date</label>
<input type="date" class="form-control" id="search_date" name="search_date" value="<?= htmlspecialchars($search_date) ?>">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="search_name">Employee Name</label>
<input type="text" class="form-control" id="search_name" name="search_name" placeholder="Enter employee name..." value="<?= isset($_GET['search_name']) ? htmlspecialchars($_GET['search_name']) : '' ?>">
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Search</button>
</form>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Attendance Records</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Employee Name</th>
<th>Status</th>
<th>Date</th>
<th>Check-in Time</th>
<th>Check-out Time</th>
</tr>
</thead>
<tbody>
<?php if (empty($attendance_records)): ?>
<tr>
<td colspan="5" class="text-center">No records found for this date.</td>
</tr>
<?php else: ?>
<?php foreach ($attendance_records as $record): ?>
<tr>
<td><?= htmlspecialchars($record['name']) ?></td>
<td><?= htmlspecialchars($record['status']) ?></td>
<td><?= htmlspecialchars($record['date']) ?></td>
<td><?= htmlspecialchars($record['check_in_time']) ?></td>
<td><?= htmlspecialchars($record['check_out_time']) ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php include 'footer.php'; ?>

40
auth.php Normal file
View File

@ -0,0 +1,40 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
require_once 'db/config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user) {
if (password_verify($password, $user['password'])) {
$_SESSION['loggedin'] = true;
$_SESSION['id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['role'] = $user['role'];
header("location: index.php");
exit;
} else {
$_SESSION['error'] = "Invalid username or password.";
header("location: login.php");
exit;
}
} else {
$_SESSION['error'] = "Invalid username or password.";
header("location: login.php");
exit;
}
} else {
}
?>

View File

@ -15,3 +15,23 @@ function db() {
}
return $pdo;
}
function init_db() {
$pdo = db();
$pdo->exec("CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role ENUM('Admin', 'HR', 'Employee', 'Supervisor') NOT NULL
);");
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute(['admin']);
if ($stmt->rowCount() == 0) {
$password = password_hash('password', PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (username, password, role) VALUES (?, ?, ?)");
$stmt->execute(['admin', $password, 'Admin']);
}
}
init_db();

View File

@ -0,0 +1,21 @@
<?php
require_once 'config.php';
try {
$pdo = db();
$sql = "CREATE TABLE IF NOT EXISTS leave_requests (
id INT AUTO_INCREMENT PRIMARY KEY,
employee_id INT NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
reason TEXT,
status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (employee_id) REFERENCES users(id) ON DELETE CASCADE
);";
$pdo->exec($sql);
echo "Table 'leave_requests' created successfully." . PHP_EOL;
} catch (PDOException $e) {
die("Error creating table: " . $e->getMessage());
}
?>

22
delete_employee.php Normal file
View File

@ -0,0 +1,22 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true || $_SESSION['role'] !== 'Admin') {
header('location: login.php');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id) {
header('location: view_employees.php');
exit;
}
$pdo = db();
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$id]);
header('location: view_employees.php');
exit;
?>

79
edit_employee.php Normal file
View File

@ -0,0 +1,79 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true || $_SESSION['role'] !== 'Admin') {
header('location: login.php');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id) {
header('location: view_employees.php');
exit;
}
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) {
die('User not found.');
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$role = $_POST['role'];
$updateStmt = $pdo->prepare("UPDATE users SET username = ?, role = ? WHERE id = ?");
$updateStmt->execute([$username, $role, $id]);
header('location: view_employees.php');
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Edit Employee - Employee Attendance System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<?php include 'sidebar.php'; ?>
<div class="main-content">
<div class="container-fluid">
<h1 class="mt-4">Edit Employee</h1>
<div class="card shadow-sm">
<div class="card-body">
<form action="edit_employee.php?id=<?php echo $id; ?>" method="post">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" value="<?php echo htmlspecialchars($user['username']); ?>" required>
</div>
<div class="mb-3">
<label for="role" class="form-label">Role</label>
<select class="form-select" id="role" name="role">
<option value="Employee" <?php echo ($user['role'] == 'Employee') ? 'selected' : ''; ?>>Employee</option>
<option value="Admin" <?php echo ($user['role'] == 'Admin') ? 'selected' : ''; ?>>Admin</option>
<option value="HR" <?php echo ($user['role'] == 'HR') ? 'selected' : ''; ?>>HR</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Update Employee</button>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

46
get_leave_events.php Normal file
View File

@ -0,0 +1,46 @@
<?php
header('Content-Type: application/json');
require_once 'db/config.php';
session_start();
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
echo json_encode([]);
exit;
}
if ($_SESSION['role'] !== 'Admin' && $_SESSION['role'] !== 'HR' && $_SESSION['role'] !== 'Employee') {
echo json_encode([]);
exit;
}
$events = [];
try {
$pdo = db();
$sql = "SELECT lr.start_date as start, lr.end_date as end, u.username as title FROM leave_requests lr JOIN users u ON lr.employee_id = u.id WHERE lr.status = 'approved'";
if ($_SESSION['role'] == 'Employee') {
$sql .= " AND lr.employee_id = :employee_id";
}
$stmt = $pdo->prepare($sql);
if ($_SESSION['role'] == 'Employee') {
$stmt->bindParam(':employee_id', $_SESSION['id'], PDO::PARAM_INT);
}
$stmt->execute();
$events = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Adjust end date for FullCalendar
foreach ($events as &$event) {
$event['end'] = date('Y-m-d', strtotime($event['end'] . ' +1 day'));
}
} catch (PDOException $e) {
// On error, return empty array
echo json_encode([]);
exit;
}
echo json_encode($events);
?>

293
index.php
View File

@ -1,150 +1,159 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
<?php
session_start();
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
header('location: login.php');
exit;
}
require_once 'db/config.php';
$pdo = db();
$today = date('Y-m-d');
// Fetch total employees
$stmt_total = $pdo->query('SELECT COUNT(*) FROM users');
$total_employees = $stmt_total->fetchColumn();
// Fetch attendance stats for today
$stmt_attendance = $pdo->prepare("SELECT status, COUNT(*) as count FROM attendance WHERE attendance_date = ? GROUP BY status");
$stmt_attendance->execute([$today]);
$attendance_stats = $stmt_attendance->fetchAll(PDO::FETCH_KEY_PAIR);
$on_time_today = $attendance_stats['Present'] ?? 0;
$late_today = $attendance_stats['Late'] ?? 0;
$absent_today = $attendance_stats['Absent'] ?? 0;
// Fetch pending leave requests for Admin/HR
$pending_leave_requests = 0;
if (in_array($_SESSION['role'], ['Admin', 'HR'])) {
$stmt_leave = $pdo->query("SELECT COUNT(*) FROM leave_requests WHERE status = 'pending'");
$pending_leave_requests = $stmt_leave->fetchColumn();
}
?>
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard - Employee Attendance System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
<div class="d-flex">
<?php include 'sidebar.php'; ?>
<div class="main-content flex-grow-1 p-4">
<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="h3 mb-0 text-gray-800">Dashboard</h1>
<p class="lead mb-0">Welcome, <strong><?php echo htmlspecialchars($_SESSION['username']); ?>!</strong></p>
</div>
<div class="row">
<!-- Total Employees Card -->
<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="bi bi-people-fill h2 text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- On Time Today Card -->
<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">On Time Today</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $on_time_today; ?></div>
</div>
<div class="col-auto">
<i class="bi bi-check-circle-fill h2 text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Late Today Card -->
<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">Late Today</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $late_today; ?></div>
</div>
<div class="col-auto">
<i class="bi bi-exclamation-triangle-fill h2 text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Absent Today Card -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-danger 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-danger text-uppercase mb-1">Absent Today</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $absent_today; ?></div>
</div>
<div class="col-auto">
<i class="bi bi-x-circle-fill h2 text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<?php if (in_array($_SESSION['role'], ['Admin', 'HR'])): ?>
<div class="row">
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<a href="leave_requests.php" class="text-decoration-none">
<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">Pending Leave Requests</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $pending_leave_requests; ?></div>
</div>
<div class="col-auto">
<i class="bi bi-calendar-plus-fill h2 text-gray-300"></i>
</div>
</div>
</div>
</a>
</div>
</div>
</div>
<?php endif; ?>
<p>From here you can manage employees, track attendance, and generate reports.</p>
</div>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

230
leave_requests.php Normal file
View File

@ -0,0 +1,230 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
header('location: login.php');
exit;
}
if ($_SESSION['role'] !== 'Admin' && $_SESSION['role'] !== 'HR' && $_SESSION['role'] !== 'Employee') {
header('location: index.php');
exit;
}
$requests = [];
try {
$pdo = db();
$sql = "SELECT lr.*, u.username FROM leave_requests lr JOIN users u ON lr.employee_id = u.id";
if ($_SESSION['role'] == 'Employee') {
$sql .= " WHERE lr.employee_id = :employee_id";
}
$sql .= " ORDER BY lr.created_at DESC";
$stmt = $pdo->prepare($sql);
if ($_SESSION['role'] == 'Employee') {
$stmt->bindParam(':employee_id', $_SESSION['id'], PDO::PARAM_INT);
}
$stmt->execute();
$requests = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
die("Could not fetch leave requests.");
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Leave Requests - Employee Attendance System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.css' rel='stylesheet' />
</head>
<body>
<?php include 'sidebar.php'; ?>
<div class="main-content">
<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center">
<h1 class="mt-4">Leave Requests</h1>
<div>
<a href="submit_leave_request.php" class="btn btn-primary">Submit New Request</a>
<button id="toggle-view" class="btn btn-secondary">Calendar View</button>
</div>
</div>
<p class="lead">Manage and view employee leave requests.</p>
<?php if ($_SESSION['role'] === 'Admin' || $_SESSION['role'] === 'HR'): ?>
<p class="text-muted">You are viewing all employee leave requests.</p>
<?php else: ?>
<p class="text-muted">You are viewing your own leave requests.</p>
<?php endif; ?> <div id="calendar-view" style="display: none;">
<div id="calendar"></div>
</div>
<div id="list-view">
<div class="card shadow-sm">
<div class="card-body">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th scope="col">Employee</th>
<th scope="col">Start Date</th>
<th scope="col">End Date</th>
<th scope="col">Reason</th>
<th scope="col">Status</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($requests)):
?>
<tr>
<td colspan="6" class="text-center">No leave requests found.</td>
</tr>
<?php else:
?>
<?php foreach ($requests as $request):
?>
<tr>
<td><?php echo htmlspecialchars($request['username']); ?></td>
<td><?php echo htmlspecialchars($request['start_date']); ?></td>
<td><?php echo htmlspecialchars($request['end_date']); ?></td>
<td><?php echo htmlspecialchars($request['reason']); ?></td>
<td>
<span class="badge bg-<?php echo $request['status'] == 'approved' ? 'success' : ($request['status'] == 'rejected' ? 'danger' : 'warning'); ?>">
<?php echo ucfirst($request['status']); ?>
</span>
</td>
<td>
<?php if (($_SESSION['role'] === 'Admin' || $_SESSION['role'] === 'HR') && $request['status'] === 'pending'): ?>
<a href="update_leave_status.php?id=<?php echo $request['id']; ?>&status=approved" class="btn btn-sm btn-outline-success">Approve</a>
<a href="update_leave_status.php?id=<?php echo $request['id']; ?>&status=rejected" class="btn btn-sm btn-outline-danger">Reject</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
events: 'get_leave_events.php',
height: 'auto'
});
var listView = document.getElementById('list-view');
var calendarView = document.getElementById('calendar-view');
var toggleButton = document.getElementById('toggle-view');
toggleButton.addEventListener('click', function() {
if (listView.style.display === 'none') {
listView.style.display = 'block';
calendarView.style.display = 'none';
toggleButton.textContent = 'Calendar View';
} else {
listView.style.display = 'none';
calendarView.style.display = 'block';
toggleButton.textContent = 'List View';
calendar.render();
}
});
});
</script>
</body>
</html>

60
login.php Normal file
View File

@ -0,0 +1,60 @@
<?php
session_start();
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
header('location: index.php');
exit;
}
$error = '';
if (isset($_SESSION['error']) && !empty($_SESSION['error'])) {
$error = $_SESSION['error'];
unset($_SESSION['error']);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - Employee Attendance System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body class="login-body">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-4">
<div class="card shadow-lg border-0 rounded-lg mt-5">
<div class="card-header bg-primary text-white text-center">
<h3 class="fw-bold my-4">Employee Attendance System</h3>
</div>
<div class="card-body p-4 p-sm-5">
<form action="auth.php" method="post">
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<div class="form-floating mb-3">
<input type="text" class="form-control" id="username" name="username" placeholder="Username" required>
<label for="username">Username</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control" id="password" name="password" placeholder="Password" required>
<label for="password">Password</label>
</div>
<div class="d-grid">
<button class="btn btn-primary btn-lg fw-bold" type="submit">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

7
logout.php Normal file
View File

@ -0,0 +1,7 @@
<?php
session_start();
$_SESSION = array();
session_destroy();
header("location: login.php");
exit;
?>

102
mark_attendance.php Normal file
View File

@ -0,0 +1,102 @@
<?php
require_once 'auth.php';
require_once 'db/config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$employee_id = $_POST['employee_id'];
$action = $_POST['action'];
$current_time = date('H:i:s');
$current_date = date('Y-m-d');
if ($action === 'check-in') {
$stmt = db()->prepare("SELECT id FROM attendance WHERE employee_id = ? AND date = ?");
$stmt->execute([$employee_id, $current_date]);
$attendance_record = $stmt->fetch();
if ($attendance_record) {
$stmt = db()->prepare("UPDATE attendance SET check_in_time = ?, status = 'Present' WHERE id = ?");
$stmt->execute([$current_time, $attendance_record['id']]);
} else {
$stmt = db()->prepare("INSERT INTO attendance (employee_id, date, status, check_in_time) VALUES (?, ?, 'Present', ?)");
$stmt->execute([$employee_id, $current_date, $current_time]);
}
} elseif ($action === 'check-out') {
$stmt = db()->prepare("UPDATE attendance SET check_out_time = ? WHERE employee_id = ? AND date = ?");
$stmt->execute([$current_time, $employee_id, $current_date]);
}
header('Location: mark_attendance.php');
exit();
}
// Only allow Admin and HR to access this page
if (!isset($_SESSION['user_role']) || ($_SESSION['user_role'] !== 'Admin' && $_SESSION['user_role'] !== 'HR')) {
header('Location: index.php');
exit();
}
$pdo = db();
$today = date('Y-m-d');
// Fetch all employees (users)
$stmt = $pdo->prepare('SELECT id, username, role FROM users ORDER BY username');
$stmt->execute();
$employees = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mark Attendance</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<div class="d-flex">
<?php include 'sidebar.php'; ?>
<div class="container-fluid main-content">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h1 class="h5 mb-0">Mark Daily Attendance</h1>
</div>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-light">
<tr>
<th>Employee Name</th>
<th>Role</th>
<th class="text-center">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($employees as $employee): ?>
<tr>
<td><?php echo htmlspecialchars($employee['username']); ?></td>
<td><?php echo htmlspecialchars($employee['role']); ?></td>
<td class="text-center">
<form action="mark_attendance.php" method="post" style="display: inline-block;">
<input type="hidden" name="employee_id" value="<?= $employee['id'] ?>">
<button type="submit" name="action" value="check-in" class="btn btn-success btn-sm">Check-in</button>
</form>
<form action="mark_attendance.php" method="post" style="display: inline-block;">
<input type="hidden" name="employee_id" value="<?= $employee['id'] ?>">
<button type="submit" name="action" value="check-out" class="btn btn-danger btn-sm">Check-out</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

70
profile.php Normal file
View File

@ -0,0 +1,70 @@
<?php
session_start();
if (!isset($_SESSION["role"])) {
header("location: login.php");
}
require 'db/config.php';
$username = $_SESSION["username"];
// Fetch user details
$stmt = db()->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
// Fetch user attendance
$stmt = db()->prepare("SELECT attendance_date, status FROM attendance WHERE user_id = ? ORDER BY attendance_date DESC");
$stmt->execute([$user['id']]);
$attendance_records = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html>
<head>
<title>Employee Profile</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/css/custom.css" rel="stylesheet">
</head>
<body>
<div class="d-flex">
<?php include 'sidebar.php'; ?>
<div class="content p-4">
<h1 class="mb-4">Employee Profile</h1>
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">Profile Details</h5>
<p><strong>Name:</strong> <?php echo htmlspecialchars($user['full_name']); ?></p>
<p><strong>Username:</strong> <?php echo htmlspecialchars($user['username']); ?></p>
<p><strong>Role:</strong> <?php echo htmlspecialchars($user['role']); ?></p>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">Attendance History</h5>
<table class="table table-striped">
<thead>
<tr>
<th>Date</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php foreach ($attendance_records as $record): ?>
<tr>
<td><?php echo htmlspecialchars($record['attendance_date']); ?></td>
<td><?php echo htmlspecialchars($record['status']); ?></td>
</tr>
<?php endforeach; ?>
<?php if (empty($attendance_records)): ?>
<tr>
<td colspan="2" class="text-center">No attendance records found.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>

35
sidebar.php Normal file
View File

@ -0,0 +1,35 @@
<div class="sidebar">
<h4 class="mb-4 fw-bold">Attendance System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="index.php"><i class="bi bi-grid-fill me-2"></i> Dashboard</a>
</li>
<?php if(isset($_SESSION['role']) && $_SESSION['role'] == 'Admin'): ?>
<li class="nav-item">
<a class="nav-link" href="add_employee.php"><i class="bi bi-person-plus-fill me-2"></i> Add Employee</a>
</li>
<li class="nav-item">
<a class="nav-link" href="view_employees.php"><i class="bi bi-people-fill me-2"></i> View Employees</a>
</li>
<?php endif; ?>
<?php if(isset($_SESSION['role']) && ($_SESSION['role'] == 'Admin' || $_SESSION['role'] == 'HR')):
?>
<li class="nav-item">
<a class="nav-link" href="mark_attendance.php"><i class="bi bi-calendar-check-fill me-2"></i> Mark Attendance</a>
</li>
<?php endif; ?>
<li class="nav-item">
<a class="nav-link" href="attendance_report.php"><i class="bi bi-file-earmark-bar-graph-fill me-2"></i> Attendance Report</a>
</li>
<li class="nav-item">
<a class="nav-link <?php echo basename($_SERVER['PHP_SELF']) == 'leave_requests.php' || basename($_SERVER['PHP_SELF']) == 'submit_leave_request.php' ? 'active' : ''; ?>" href="leave_requests.php"><i class="bi bi-calendar-plus-fill me-2"></i> Leave Requests</a>
</li>
<li class="nav-item">
<a class="nav-link" href="profile.php"><i class="bi bi-person-circle me-2"></i> Profile</a>
</li>
<li class="nav-item mt-auto">
<a class="nav-link" href="logout.php"><i class="bi bi-box-arrow-left me-2"></i> Logout</a>
</li>
</ul>
</div>

119
submit_leave_request.php Normal file
View File

@ -0,0 +1,119 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
header('location: login.php');
exit;
}
$start_date = $end_date = $reason = '';
$start_date_err = $end_date_err = $reason_err = '';
$success_msg = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Validate start date
if (empty(trim($_POST['start_date']))) {
$start_date_err = 'Please enter a start date.';
} else {
$start_date = trim($_POST['start_date']);
}
// Validate end date
if (empty(trim($_POST['end_date']))) {
$end_date_err = 'Please enter an end date.';
} else {
$end_date = trim($_POST['end_date']);
}
// Validate reason
if (empty(trim($_POST['reason']))) {
$reason_err = 'Please provide a reason.';
} else {
$reason = trim($_POST['reason']);
}
if (empty($start_date_err) && empty($end_date_err) && empty($reason_err)) {
$sql = 'INSERT INTO leave_requests (employee_id, start_date, end_date, reason) VALUES (:employee_id, :start_date, :end_date, :reason)';
if ($stmt = db()->prepare($sql)) {
$stmt->bindParam(':employee_id', $_SESSION['id'], PDO::PARAM_INT);
$stmt->bindParam(':start_date', $start_date, PDO::PARAM_STR);
$stmt->bindParam(':end_date', $end_date, PDO::PARAM_STR);
$stmt->bindParam(':reason', $reason, PDO::PARAM_STR);
if ($stmt->execute()) {
$success_msg = 'Leave request submitted successfully!';
// Send email notification to Admins and HR
require_once 'mail/MailService.php';
$sql_users = "SELECT username FROM users WHERE role = 'Admin' OR role = 'HR'";
$stmt_users = db()->query($sql_users);
$recipients = $stmt_users->fetchAll(PDO::FETCH_COLUMN);
if (!empty($recipients)) {
$subject = "New Leave Request Submitted";
$body = "A new leave request has been submitted by {$_SESSION['username']}.<br><br>"
. "<b>Start Date:</b> {$start_date}<br>"
. "<b>End Date:</b> {$end_date}<br>"
. "<b>Reason:</b> {$reason}<br><br>"
. "Please log in to the system to approve or reject this request.";
MailService::sendMail($recipients, $subject, $body, strip_tags($body));
}
$start_date = $end_date = $reason = '';
} else {
echo 'Oops! Something went wrong. Please try again later.';
}
unset($stmt);
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Submit Leave Request - Employee Attendance System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<?php include 'sidebar.php'; ?>
<div class="main-content">
<div class="container-fluid">
<h1 class="mt-4">Submit Leave Request</h1>
<p class="lead">Fill out the form to request time off.</p>
<?php if (!empty($success_msg)): ?>
<div class="alert alert-success"><?php echo $success_msg; ?></div>
<?php endif; ?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" class="mt-4 card p-4 bg-white border-0 shadow-sm">
<div class="mb-3">
<label for="start_date" class="form-label">Start Date</label>
<input type="date" name="start_date" id="start_date" class="form-control <?php echo (!empty($start_date_err)) ? 'is-invalid' : ''; ?>" value="<?php echo $start_date; ?>">
<span class="invalid-feedback"><?php echo $start_date_err; ?></span>
</div>
<div class="mb-3">
<label for="end_date" class="form-label">End Date</label>
<input type="date" name="end_date" id="end_date" class="form-control <?php echo (!empty($end_date_err)) ? 'is-invalid' : ''; ?>" value="<?php echo $end_date; ?>">
<span class="invalid-feedback"><?php echo $end_date_err; ?></span>
</div>
<div class="mb-3">
<label for="reason" class="form-label">Reason for Leave</label>
<textarea name="reason" id="reason" class="form-control <?php echo (!empty($reason_err)) ? 'is-invalid' : ''; ?>" rows="3"><?php echo $reason; ?></textarea>
<span class="invalid-feedback"><?php echo $reason_err; ?></span>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">Submit Request</button>
</div>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

42
update_leave_status.php Normal file
View File

@ -0,0 +1,42 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true || ($_SESSION['role'] !== 'Admin' && $_SESSION['role'] !== 'HR')) {
header('location: login.php');
exit;
}
if (isset($_GET['id']) && isset($_GET['status'])) {
$id = $_GET['id'];
$status = $_GET['status'];
if ($status === 'approved' || $status === 'rejected') {
$sql = "UPDATE leave_requests SET status = :status WHERE id = :id";
if ($stmt = db()->prepare($sql)) {
$stmt->bindParam(':status', $status, PDO::PARAM_STR);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
if ($stmt->execute()) {
// Send email notification to the employee
require_once 'mail/MailService.php';
$sql_request = "SELECT lr.start_date, lr.end_date, u.username FROM leave_requests lr JOIN users u ON lr.employee_id = u.id WHERE lr.id = :id";
$stmt_request = db()->prepare($sql_request);
$stmt_request->bindParam(':id', $id, PDO::PARAM_INT);
$stmt_request->execute();
$request_data = $stmt_request->fetch(PDO::FETCH_ASSOC);
if ($request_data) {
$to = $request_data['username'];
$subject = "Your Leave Request has been " . ucfirst($status);
$body = "Your leave request from {$request_data['start_date']} to {$request_data['end_date']} has been <b>{$status}</b>.<br><br>"
. "Log in to the system for more details.";
MailService::sendMail($to, $subject, $body, strip_tags($body));
}
}
}
}
}
header('location: leave_requests.php');
exit;
?>

103
view_employees.php Normal file
View File

@ -0,0 +1,103 @@
<?php
session_start();
require_once 'db/config.php';
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true || $_SESSION['role'] !== 'Admin') {
header('location: login.php');
exit;
}
$users = [];
try {
$pdo = db();
$stmt = $pdo->query("SELECT id, username, role FROM users ORDER BY id DESC");
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// For a real app, you'd want to log this error
die("Could not connect to the database or fetch users.");
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>View Employees - Employee Attendance System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="sidebar">
<h4 class="mb-4 fw-bold">Attendance System</h4>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-grid-fill me-2"></i> Dashboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="add_employee.php"><i class="bi bi-person-plus-fill me-2"></i> Add Employee</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="view_employees.php"><i class="bi bi-people-fill me-2"></i> View Employees</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-calendar-check-fill me-2"></i> Attendance</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><i class="bi bi-file-earmark-bar-graph-fill me-2"></i> Reports</a>
</li>
<li class="nav-item mt-auto">
<a class="nav-link" href="logout.php"><i class="bi bi-box-arrow-left me-2"></i> Logout</a>
</li>
</ul>
</div>
<div class="main-content">
<div class="container-fluid">
<h1 class="mt-4">View Employees</h1>
<p class="lead">A list of all users in the system.</p>
<div class="card shadow-sm">
<div class="card-body">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th scope="col">ID</th>
<th scope="col">Username</th>
<th scope="col">Role</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($users)): ?>
<tr>
<td colspan="4" class="text-center">No users found.</td>
</tr>
<?php else: ?>
<?php foreach ($users as $user): ?>
<tr>
<th scope="row"><?php echo htmlspecialchars($user['id']); ?></th>
<td><?php echo htmlspecialchars($user['username']); ?></td>
<td><?php echo htmlspecialchars($user['role']); ?></td>
<td>
<a href="edit_employee.php?id=<?php echo $user['id']; ?>" class="btn btn-sm btn-outline-primary"><i class="bi bi-pencil-square"></i></a>
<a href="delete_employee.php?id=<?php echo $user['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure you want to delete this employee?');"><i class="bi bi-trash"></i></a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>