Employment attendance system
This commit is contained in:
parent
3b25d53f36
commit
894b41720e
157
add_employee.php
Normal file
157
add_employee.php
Normal 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
43
assets/css/custom.css
Normal 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
111
attendance_report.php
Normal 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
40
auth.php
Normal 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 {
|
||||||
|
}
|
||||||
|
?>
|
||||||
@ -15,3 +15,23 @@ function db() {
|
|||||||
}
|
}
|
||||||
return $pdo;
|
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();
|
||||||
|
|||||||
21
db/migrate_leave_requests.php
Normal file
21
db/migrate_leave_requests.php
Normal 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
22
delete_employee.php
Normal 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
79
edit_employee.php
Normal 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
46
get_leave_events.php
Normal 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
293
index.php
@ -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;
|
<?php
|
||||||
$now = date('Y-m-d H:i:s');
|
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">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>New Style</title>
|
<title>Dashboard - Employee Attendance System</title>
|
||||||
<?php
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
// Read project preview data from environment
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
<link rel="stylesheet" href="assets/css/custom.css">
|
||||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
?>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<?php if ($projectDescription): ?>
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||||
<!-- 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>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<div class="card">
|
<div class="d-flex">
|
||||||
<h1>Analyzing your requirements and generating your website…</h1>
|
<?php include 'sidebar.php'; ?>
|
||||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
|
||||||
<span class="sr-only">Loading…</span>
|
<div class="main-content flex-grow-1 p-4">
|
||||||
</div>
|
<div class="container-fluid">
|
||||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
<h1 class="h3 mb-0 text-gray-800">Dashboard</h1>
|
||||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
<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>
|
</div>
|
||||||
</main>
|
</div>
|
||||||
<footer>
|
|
||||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
|
||||||
</footer>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
230
leave_requests.php
Normal file
230
leave_requests.php
Normal 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
60
login.php
Normal 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
7
logout.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
$_SESSION = array();
|
||||||
|
session_destroy();
|
||||||
|
header("location: login.php");
|
||||||
|
exit;
|
||||||
|
?>
|
||||||
102
mark_attendance.php
Normal file
102
mark_attendance.php
Normal 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
70
profile.php
Normal 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
35
sidebar.php
Normal 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
119
submit_leave_request.php
Normal 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
42
update_leave_status.php
Normal 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
103
view_employees.php
Normal 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>
|
||||||
Loading…
x
Reference in New Issue
Block a user