Server : LiteSpeed
System : Linux terra.hostitbro.com 5.14.0-611.54.3.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 7 16:31:24 EDT 2026 x86_64
User : outerorb ( 1091)
PHP Version : 8.1.34
Disable Function : mail
Directory :  /home2/outerorb/emp.outerorbittech.in/admin/

📁 Create New:
⬆️ Upload File:
Current Dir [ Writable ] Root [ Writable ]


OR Upload from URL:
URL: Save as:

📄 File: leaves.php

Path: /home2/outerorb/emp.outerorbittech.in/admin/leaves.php

Size: 18.98 KB

Permissions: 0666

<?php
require __DIR__ . '/../includes/helpers.php';
require_admin();
ensure_leave_tables();
ensure_employees_table();
$roleLabel = 'Admin';$pdo   = db();
$flash = flash();
$admin = current_admin();
$year  = isset($_GET['year']) ? (int) $_GET['year'] : (int) date('Y');

// ---------- POST: approve / reject / add manual leave ----------
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!verify_csrf($_POST['csrf_token'] ?? '')) {
        redirect_with_message('leaves.php?year=' . $year, 'Session expired.', 'error');
    }
    $action = $_POST['action'] ?? '';
    $id     = (int) ($_POST['id'] ?? 0);

    if (in_array($action, ['approve', 'reject'], true) && $id) {
        $newStatus = $action === 'approve' ? 'approved' : 'rejected';
        $notes     = sanitize_text($_POST['admin_notes'] ?? '');

        $app = $pdo->prepare('SELECT * FROM leave_applications WHERE id = ? LIMIT 1');
        $app->execute([$id]);
        $app = $app->fetch();

        if ($app && $app['status'] === 'pending') {
            $pdo->prepare(
                'UPDATE leave_applications SET status=?, admin_notes=?, reviewed_by=?, reviewed_at=NOW(), updated_at=NOW() WHERE id=?'
            )->execute([$newStatus, $notes ?: null, $admin['id'] ?? null, $id]);

            // On approval: deduct from leave balance
            if ($newStatus === 'approved') {
                $yr = (int) date('Y', strtotime($app['from_date']));
                $pdo->prepare(
                    'INSERT INTO leave_balances (employee_id, leave_type_id, year, allocated_days, used_days)
                     VALUES (?, ?, ?,
                         (SELECT annual_days FROM leave_types WHERE id = ?),
                         ?)
                     ON DUPLICATE KEY UPDATE used_days = used_days + ?'
                )->execute([
                    $app['employee_id'], $app['leave_type_id'], $yr,
                    $app['leave_type_id'], $app['total_days'],
                    $app['total_days'],
                ]);

                // Auto-fill attendance_logs for leave days
                $start = new DateTime($app['from_date']);
                $end   = new DateTime($app['to_date']);
                ensure_attendance_tables();
                while ($start <= $end) {
                    $ds  = $start->format('Y-m-d');
                    $dow = (int) $start->format('N');
                    if ($dow <= 5) { // weekdays only
                        $pdo->prepare(
                            'INSERT INTO attendance_logs (employee_id, attend_date, status, marked_by)
                             VALUES (?,?,\'on_leave\',?)
                             ON DUPLICATE KEY UPDATE status=\'on_leave\', marked_by=VALUES(marked_by), updated_at=NOW()'
                        )->execute([$app['employee_id'], $ds, $admin['id'] ?? null]);
                    }
                    $start->modify('+1 day');
                }
            }
            redirect_with_message('leaves.php?year=' . $year, 'Leave application ' . $newStatus . '.');
        }
    }

    // Admin manually adds a leave application on behalf of an employee
    if ($action === 'add') {
        $empId       = (int) ($_POST['employee_id'] ?? 0);
        $ltId        = (int) ($_POST['leave_type_id'] ?? 0);
        $fromDate    = sanitize_text($_POST['from_date'] ?? '');
        $toDate      = sanitize_text($_POST['to_date'] ?? '');
        $reason      = sanitize_text($_POST['reason'] ?? '');
        $addStatus   = in_array($_POST['add_status'] ?? '', ['pending','approved','rejected']) ? $_POST['add_status'] : 'approved';

        if ($empId && $ltId && $fromDate && $toDate) {
            $emp = $pdo->prepare('SELECT department FROM employees WHERE id = ? LIMIT 1');
            $emp->execute([$empId]);
            $dept = ($emp->fetch())['department'] ?? null;
            $days = count_working_days($fromDate, $toDate, $dept);

            $pdo->prepare(
                'INSERT INTO leave_applications (employee_id, leave_type_id, from_date, to_date, total_days, reason, status, reviewed_by, reviewed_at)
                 VALUES (?,?,?,?,?,?,?,?,NOW())'
            )->execute([$empId, $ltId, $fromDate, $toDate, $days, $reason ?: null, $addStatus, $admin['id'] ?? null]);

            $newId = (int) $pdo->lastInsertId();

            if ($addStatus === 'approved') {
                $yr = (int) date('Y', strtotime($fromDate));
                $pdo->prepare(
                    'INSERT INTO leave_balances (employee_id, leave_type_id, year, allocated_days, used_days)
                     VALUES (?,?,?,(SELECT annual_days FROM leave_types WHERE id=?),?)
                     ON DUPLICATE KEY UPDATE used_days=used_days+?'
                )->execute([$empId, $ltId, $yr, $ltId, $days, $days]);

                ensure_attendance_tables();
                $s = new DateTime($fromDate); $e = new DateTime($toDate);
                while ($s <= $e) {
                    $ds  = $s->format('Y-m-d');
                    $dow = (int) $s->format('N');
                    if ($dow <= 5) {
                        $pdo->prepare(
                            'INSERT INTO attendance_logs (employee_id, attend_date, status, marked_by)
                             VALUES (?,?,\'on_leave\',?)
                             ON DUPLICATE KEY UPDATE status=\'on_leave\', updated_at=NOW()'
                        )->execute([$empId, $ds, $admin['id'] ?? null]);
                    }
                    $s->modify('+1 day');
                }
            }
            redirect_with_message('leaves.php?year=' . $year, 'Leave entry added.');
        }
    }
}

// ---------- Filters ----------
$statusFilter = sanitize_text($_GET['status'] ?? '');
$deptFilter   = sanitize_text($_GET['dept']   ?? '');

$where  = ['YEAR(la.from_date) = :year'];
$params = [':year' => $year];

if ($statusFilter !== '') {
    $where[]           = 'la.status = :status';
    $params[':status'] = $statusFilter;
}
if ($deptFilter !== '') {
    $where[]         = 'e.department = :dept';
    $params[':dept'] = $deptFilter;
}
$allowedDepts = allowed_departments_for_admin();
if (!empty($allowedDepts)) {
    $phs = [];
    foreach ($allowedDepts as $i => $d) { $k = ':d'.$i; $phs[] = $k; $params[$k] = $d; }
    $where[] = 'e.department IN (' . implode(',', $phs) . ')';
}

$sql = 'SELECT la.*, e.first_name, e.last_name, e.department, lt.name AS leave_type_name, lt.code
        FROM leave_applications la
        JOIN employees e ON e.id = la.employee_id
        JOIN leave_types lt ON lt.id = la.leave_type_id
        WHERE ' . implode(' AND ', $where) . '
        ORDER BY la.created_at DESC';
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$applications = $stmt->fetchAll();

$pendingCount = array_sum(array_map(fn($a) => $a['status'] === 'pending' ? 1 : 0, $applications));

// For add form
$allEmployees = $pdo->query("SELECT id, first_name, last_name, department FROM employees WHERE deleted_at IS NULL AND employee_status='active' ORDER BY first_name")->fetchAll();
$leaveTypes   = list_leave_types(true);
$departments  = list_departments();

function e(string $v): string { return htmlspecialchars($v, ENT_QUOTES, 'UTF-8'); }
$statusBadge = [
    'pending'   => 'background:#fef3c7; color:#92400e;',
    'approved'  => 'background:#d1fae5; color:#065f46;',
    'rejected'  => 'background:#fee2e2; color:#991b1b;',
    'cancelled' => 'background:#f3f4f6; color:#6b7280;',
];
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Leave Applications &mdash; HRMS</title>
    <link rel="stylesheet" href="../assets/css/style.css?v=<?php echo filemtime(__DIR__ . '/../assets/css/style.css'); ?>" />
    <link rel="stylesheet" href="../assets/css/polish.css?v=<?php echo filemtime(__DIR__ . '/../assets/css/polish.css'); ?>" />
</head>
<body class="dashboard-layout">
<div class="app-wrapper">
    <?php require '_sidebar.php'; ?>
    <div class="main-content">
        <div class="top-bar">
            <div class="top-bar-left">
                <button class="sidebar-toggle" id="sidebarToggle" aria-label="Toggle sidebar">☰</button>
                <div>
                    <h1 class="page-title">Leaves</h1>
                    <div class="breadcrumb-nav">
                        <span>Manage employee leaves</span>
                    </div>
                </div>
            </div>
            <div class="top-bar-right">
                <a href="dashboard.php" style="color: #cbd5e1; text-decoration: none; padding: 8px 12px; border-radius: 6px; transition: background 0.15s; font-size: 13px; font-weight: 600;">← Dashboard</a>
            </div>
        </div>
        <div class="dashboard-container" style="max-width: 1200px;">
<div class="container">
    <div class="header">
        <div class="brand">
            <div class="brand-title">
                <h1 style="margin:0;">Leave Applications</h1>
                <p class="helper" style="margin:2px 0 0;"><?php echo $pendingCount > 0 ? $pendingCount . ' pending approval' : 'All caught up'; ?></p>
            </div>
        </div>
        <div class="actions">
            <a class="badge" href="leave_types.php">Leave Types</a>
            <a class="badge" href="attendance.php">Attendance</a>
            <a class="badge" href="dashboard.php">Dashboard</a>
            <a class="badge" href="logout.php">Logout</a>
        </div>
    </div>

    <?php if ($flash): ?>
        <div class="alert <?php echo $flash['type'] === 'error' ? 'alert-error' : 'alert-success'; ?>">
            <?php echo e($flash['message']); ?>
        </div>
    <?php endif; ?>

    <!-- Add manual leave entry -->
    <details class="card" style="margin-bottom:20px;">
        <summary style="cursor:pointer; font-weight:700; padding:4px 0;">+ Add Leave Entry</summary>
        <form method="POST" style="margin-top:16px;">
            <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
            <input type="hidden" name="action" value="add" />
            <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(180px, 1fr)); gap:12px;">
                <div class="form-group" style="margin:0;">
                    <label>Employee *</label>
                    <select name="employee_id" class="form-control" required>
                        <option value="">Select employee</option>
                        <?php foreach ($allEmployees as $emp): ?>
                            <option value="<?php echo (int)$emp['id']; ?>"><?php echo e($emp['first_name'].' '.$emp['last_name'].' ('.$emp['department'].')'); ?></option>
                        <?php endforeach; ?>
                    </select>
                </div>
                <div class="form-group" style="margin:0;">
                    <label>Leave Type *</label>
                    <select name="leave_type_id" class="form-control" required>
                        <option value="">Select type</option>
                        <?php foreach ($leaveTypes as $lt): ?>
                            <option value="<?php echo (int)$lt['id']; ?>"><?php echo e($lt['name']); ?></option>
                        <?php endforeach; ?>
                    </select>
                </div>
                <div class="form-group" style="margin:0;">
                    <label>From *</label>
                    <input type="date" name="from_date" class="form-control" required />
                </div>
                <div class="form-group" style="margin:0;">
                    <label>To *</label>
                    <input type="date" name="to_date" class="form-control" required />
                </div>
                <div class="form-group" style="margin:0;">
                    <label>Status</label>
                    <select name="add_status" class="form-control">
                        <option value="approved">Approved</option>
                        <option value="pending">Pending</option>
                    </select>
                </div>
                <div class="form-group" style="margin:0;">
                    <label>Reason</label>
                    <input type="text" name="reason" class="form-control" placeholder="Optional" />
                </div>
            </div>
            <button type="submit" class="btn btn-primary" style="margin-top:14px;">Add Leave</button>
        </form>
    </details>

    <!-- Filters -->
    <div class="card" style="margin-bottom:16px; padding:12px 16px;">
        <form method="GET" style="display:flex; gap:10px; flex-wrap:wrap; align-items:center;">
            <select name="year" class="form-control" style="height:28px; font-size:.8rem; margin:0; width:auto;">
                <?php for ($y = date('Y') + 1; $y >= date('Y') - 3; $y--): ?>
                    <option value="<?php echo $y; ?>" <?php echo $y === $year ? 'selected' : ''; ?>><?php echo $y; ?></option>
                <?php endfor; ?>
            </select>
            <select name="status" class="form-control" style="height:28px; font-size:.8rem; margin:0; width:auto;">
                <option value="">All Statuses</option>
                <?php foreach (['pending','approved','rejected','cancelled'] as $s): ?>
                    <option value="<?php echo $s; ?>" <?php echo $statusFilter === $s ? 'selected' : ''; ?>><?php echo ucfirst($s); ?></option>
                <?php endforeach; ?>
            </select>
            <select name="dept" class="form-control" style="height:28px; font-size:.8rem; margin:0; width:auto;">
                <option value="">All Departments</option>
                <?php foreach ($departments as $dept): ?>
                    <option value="<?php echo e($dept['name']); ?>" <?php echo $deptFilter === $dept['name'] ? 'selected' : ''; ?>>
                        <?php echo e($dept['name']); ?>
                    </option>
                <?php endforeach; ?>
            </select>
            <button type="submit" class="btn btn-primary" style="height:28px; padding:0 14px; font-size:.8rem;">Filter</button>
        </form>
    </div>

    <div class="card">
        <?php if (empty($applications)): ?>
            <p style="color:#6b7280; text-align:center; padding:30px 0;">No leave applications found for the selected filters.</p>
        <?php else: ?>
        <table style="width:100%; border-collapse:collapse; font-size:.875rem;">
            <thead>
                <tr style="background:#f9fafb;">
                    <?php foreach (['Employee','Department','Leave Type','From','To','Days','Status','Reason','Actions'] as $h): ?>
                        <th style="padding:10px 12px; text-align:left; border-bottom:1px solid #e5e7eb; white-space:nowrap;"><?php echo $h; ?></th>
                    <?php endforeach; ?>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($applications as $app): ?>
                <tr>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6;">
                        <?php echo e($app['first_name'] . ' ' . $app['last_name']); ?>
                    </td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6; color:#6b7280;"><?php echo e($app['department']); ?></td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6;">
                        <?php echo e($app['leave_type_name']); ?> <code style="font-size:.75rem;"><?php echo e($app['code']); ?></code>
                    </td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6;"><?php echo date('d M', strtotime($app['from_date'])); ?></td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6;"><?php echo date('d M', strtotime($app['to_date'])); ?></td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6; text-align:center;"><?php echo $app['total_days']; ?></td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6;">
                        <span style="display:inline-block; padding:2px 8px; border-radius:999px; font-size:.75rem; font-weight:600; <?php echo $statusBadge[$app['status']] ?? ''; ?>">
                            <?php echo ucfirst($app['status']); ?>
                        </span>
                    </td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6; max-width:180px; color:#6b7280; font-size:.82rem;">
                        <?php echo $app['reason'] ? e($app['reason']) : '—'; ?>
                    </td>
                    <td style="padding:9px 12px; border-bottom:1px solid #f3f4f6; white-space:nowrap;">
                        <?php if ($app['status'] === 'pending'): ?>
                        <form method="POST" style="display:inline;">
                            <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
                            <input type="hidden" name="action" value="approve" />
                            <input type="hidden" name="id" value="<?php echo (int)$app['id']; ?>" />
                            <button type="submit" style="background:#d1fae5; border:none; color:#065f46; padding:3px 10px; border-radius:4px; cursor:pointer; font-size:.8rem;">Approve</button>
                        </form>
                        &nbsp;
                        <form method="POST" style="display:inline;" onsubmit="return confirm('Reject this leave?');">
                            <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
                            <input type="hidden" name="action" value="reject" />
                            <input type="hidden" name="id" value="<?php echo (int)$app['id']; ?>" />
                            <button type="submit" style="background:#fee2e2; border:none; color:#991b1b; padding:3px 10px; border-radius:4px; cursor:pointer; font-size:.8rem;">Reject</button>
                        </form>
                        <?php else: ?>
                            <span style="color:#9ca3af; font-size:.8rem;"><?php echo ucfirst($app['status']); ?></span>
                        <?php endif; ?>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        <?php endif; ?>
    </div>
</div>
        </div>
        </div>
    </div>
</div>

<div class="sidebar-overlay" id="sidebarOverlay"></div>

<script>
    const sidebar = document.getElementById('sidebar');
    const sidebarToggle = document.getElementById('sidebarToggle');
    const sidebarOverlay = document.getElementById('sidebarOverlay');

    sidebarToggle?.addEventListener('click', () => {
        sidebar.classList.toggle('open');
        sidebarOverlay.classList.toggle('open');
    });

    sidebarOverlay?.addEventListener('click', () => {
        sidebar.classList.remove('open');
        sidebarOverlay.classList.remove('open');
    });
</script>
</body>
</html>



← Back to Directory Edit File 🔒 Chmod

WP File Manager