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: appraisals.php

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

Size: 21.66 KB

Permissions: 0666

<?php
require __DIR__ . '/../includes/helpers.php';
require_admin();
ensure_appraisal_tables();
ensure_employees_table();

$pdo   = db();
$flash = flash();
$admin = current_admin();
$errors = [];

$view    = $_GET['view'] ?? 'cycles';
$cycleId = isset($_GET['cycle']) ? (int)$_GET['cycle'] : 0;

// --- POST ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!verify_csrf($_POST['csrf_token'] ?? '')) {
        redirect_with_message('appraisals.php', 'Session expired.', 'error');
    }
    $action = $_POST['action'] ?? '';

    // Create / update cycle
    if ($action === 'save_cycle') {
        $id     = (int)($_POST['id'] ?? 0);
        $title  = sanitize_text($_POST['title'] ?? '');
        $type   = sanitize_text($_POST['type']  ?? 'annual');
        $year   = (int)($_POST['year'] ?? date('Y'));
        $from   = sanitize_text($_POST['from_date'] ?? '');
        $to     = sanitize_text($_POST['to_date']   ?? '');
        if (!$title) $errors[] = 'Title is required.';
        if (!$from || !$to) $errors[] = 'Review period dates are required.';
        if (empty($errors)) {
            if ($id) {
                $pdo->prepare('UPDATE appraisal_cycles SET title=?,type=?,year=?,from_date=?,to_date=?,updated_at=NOW() WHERE id=?')
                    ->execute([$title, $type, $year, $from, $to, $id]);
            } else {
                $pdo->prepare('INSERT INTO appraisal_cycles (title,type,year,from_date,to_date,created_by) VALUES (?,?,?,?,?,?)')
                    ->execute([$title, $type, $year, $from, $to, $admin['id'] ?? null]);
            }
            redirect_with_message('appraisals.php', $id ? 'Cycle updated.' : 'Cycle created.');
        }
    }

    // Open / close cycle
    if ($action === 'set_status') {
        $id     = (int)($_POST['cycle_id']  ?? 0);
        $status = in_array($_POST['status'] ?? '', ['draft','open','closed']) ? $_POST['status'] : 'draft';
        if ($id) {
            $pdo->prepare('UPDATE appraisal_cycles SET status=?,updated_at=NOW() WHERE id=?')->execute([$status, $id]);
        }
        redirect_with_message('appraisals.php?view=employees&cycle='.$id, 'Status updated.');
    }

    // Save/update appraisal for an employee
    if ($action === 'save_appraisal') {
        $cid     = (int)($_POST['cycle_id']   ?? 0);
        $eid     = (int)($_POST['employee_id'] ?? 0);
        $aid     = (int)($_POST['appraisal_id'] ?? 0);
        $selfR   = min(5, max(1, (int)($_POST['self_rating']    ?? 0)));
        $mgrR    = min(5, max(1, (int)($_POST['manager_rating'] ?? 0)));
        $selfC   = sanitize_text($_POST['self_comments']    ?? '');
        $mgrC    = sanitize_text($_POST['manager_comments'] ?? '');
        if ($cid && $eid) {
            if ($aid) {
                $pdo->prepare(
                    'UPDATE appraisals SET self_rating=?,self_comments=?,manager_rating=?,manager_comments=?,updated_at=NOW() WHERE id=?'
                )->execute([$selfR, $selfC ?: null, $mgrR, $mgrC ?: null, $aid]);
            } else {
                $pdo->prepare(
                    'INSERT INTO appraisals (cycle_id,employee_id,self_rating,self_comments,manager_rating,manager_comments) VALUES (?,?,?,?,?,?)'
                )->execute([$cid, $eid, $selfR, $selfC ?: null, $mgrR, $mgrC ?: null]);
            }
        }
        redirect_with_message('appraisals.php?view=employees&cycle='.$cid, 'Appraisal saved.');
    }

    // Delete cycle
    if ($action === 'delete_cycle') {
        $id = (int)($_POST['cycle_id'] ?? 0);
        if ($id) {
            $pdo->prepare('DELETE FROM appraisals WHERE cycle_id=?')->execute([$id]);
            $pdo->prepare('DELETE FROM appraisal_cycles WHERE id=? AND status=\'draft\'')->execute([$id]);
        }
        redirect_with_message('appraisals.php', 'Cycle deleted.');
    }
}

// --- Load data ---
$cycles = $pdo->query('SELECT ac.*, (SELECT COUNT(*) FROM appraisals WHERE cycle_id=ac.id) AS appraisal_count FROM appraisal_cycles ac ORDER BY ac.year DESC, ac.id DESC')->fetchAll();

$cycle      = null;
$empRecords = [];
if ($cycleId) {
    $cycle = $pdo->prepare('SELECT * FROM appraisal_cycles WHERE id=? LIMIT 1');
    $cycle->execute([$cycleId]);
    $cycle = $cycle->fetch() ?: null;

    if ($cycle) {
        $stmt = $pdo->prepare(
            'SELECT e.id AS emp_id, e.first_name, e.last_name, e.department, e.designation,
                    a.id AS appraisal_id, a.self_rating, a.self_comments, a.manager_rating, a.manager_comments
             FROM employees e
             LEFT JOIN appraisals a ON a.employee_id = e.id AND a.cycle_id = ?
             WHERE e.deleted_at IS NULL AND e.employee_status = \'active\'
             ORDER BY e.department, e.first_name'
        );
        $stmt->execute([$cycleId]);
        $empRecords = $stmt->fetchAll();
    }
}

$editCycle = null;
if (isset($_GET['edit'])) {
    $ec = $pdo->prepare('SELECT * FROM appraisal_cycles WHERE id=? LIMIT 1');
    $ec->execute([(int)$_GET['edit']]);
    $editCycle = $ec->fetch() ?: null;
}

function e(string $v): string { return htmlspecialchars($v, ENT_QUOTES, 'UTF-8'); }
$ratingLabel = fn($r) => [
    '',
    '<i class="fas fa-star" style="color:gold;"></i>',
    '<i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i>',
    '<i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i>',
    '<i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i>',
    '<i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i><i class="fas fa-star" style="color:gold;"></i>'
][max(0,min(5,(int)$r))] ?? '';
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Appraisals &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">
    <style>
        .cycle-card { border:1px solid #e5e7eb; border-radius:10px; padding:16px 20px; margin-bottom:12px; display:flex; justify-content:space-between; align-items:center; }
        .status-badge { display:inline-block; padding:2px 10px; border-radius:999px; font-size:.72rem; font-weight:700; }
        .stars { letter-spacing:-1px; font-size:1rem; }
        .modal-overlay { display:none; position:fixed; inset:0; background:rgba(0,0,0,.4); z-index:999; align-items:center; justify-content:center; }
        .modal-overlay.open { display:flex; }
    </style>
</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">Appraisals</h1>
                    <div class="breadcrumb-nav"><span>Manage performance review cycles.</span></div>
                </div>
            </div>
            <div class="top-bar-right">
                <a href="dashboard.php" class="badge">Dashboard</a>
                <a href="logout.php" class="badge">Logout</a>
            </div>
        </div>
        <div class="dashboard-container">

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

    <?php foreach ($errors as $err): ?>
        <div class="alert alert-error"><?php echo e($err); ?></div>
    <?php endforeach; ?>

    <!-- ===== CYCLES VIEW ===== -->
    <?php if ($view === 'cycles'): ?>

    <div class="card" style="margin-bottom:16px;">
        <h4 style="margin:0 0 14px; font-size:.85rem; text-transform:uppercase; letter-spacing:.04em; color:#6b7280;">
            <?php echo $editCycle ? 'Edit Cycle' : 'New Appraisal Cycle'; ?>
        </h4>
        <form method="POST">
            <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
            <input type="hidden" name="action" value="save_cycle" />
            <?php if ($editCycle): ?>
                <input type="hidden" name="id" value="<?php echo (int)$editCycle['id']; ?>" />
            <?php endif; ?>
            <div style="display:grid; grid-template-columns:2fr 1fr 1fr 1fr 1fr; gap:12px; align-items:end;">
                <div class="form-group" style="margin:0;">
                    <label>Cycle Title</label>
                    <input type="text" name="title" class="form-control" required
                           value="<?php echo e($editCycle ? $editCycle['title'] : 'Annual Review '.date('Y')); ?>" />
                </div>
                <div class="form-group" style="margin:0;">
                    <label>Type</label>
                    <select name="type" class="form-control">
                        <?php foreach (['annual','h1','h2','quarterly'] as $t): ?>
                        <option value="<?php echo $t; ?>" <?php echo ($editCycle && $editCycle['type']===$t) ? 'selected' : ''; ?>><?php echo ucfirst($t); ?></option>
                        <?php endforeach; ?>
                    </select>
                </div>
                <div class="form-group" style="margin:0;">
                    <label>Year</label>
                    <input type="number" name="year" class="form-control" min="2020" max="2099"
                           value="<?php echo $editCycle ? (int)$editCycle['year'] : date('Y'); ?>" />
                </div>
                <div class="form-group" style="margin:0;">
                    <label>From Date</label>
                    <input type="date" name="from_date" class="form-control" required
                           value="<?php echo e($editCycle ? $editCycle['from_date'] : ''); ?>" />
                </div>
                <div class="form-group" style="margin:0;">
                    <label>To Date</label>
                    <input type="date" name="to_date" class="form-control" required
                           value="<?php echo e($editCycle ? $editCycle['to_date'] : ''); ?>" />
                </div>
            </div>
            <button type="submit" class="btn btn-primary" style="margin-top:12px;">
                <?php echo $editCycle ? 'Update Cycle' : 'Create Cycle'; ?>
            </button>
            <?php if ($editCycle): ?>
                <a href="appraisals.php" style="margin-left:10px; font-size:.85rem; color:#6b7280;">Cancel</a>
            <?php endif; ?>
        </form>
    </div>

    <?php if (empty($cycles)): ?>
        <div class="card" style="text-align:center; padding:40px; color:#6b7280;">No appraisal cycles created yet.</div>
    <?php else: ?>
        <?php foreach ($cycles as $cyc):
            $statusColor = ['draft'=>'#fef3c7;color:#92400e','open'=>'#d1fae5;color:#065f46','closed'=>'#f3f4f6;color:#374151'][$cyc['status']] ?? '#f3f4f6;color:#374151';
        ?>
        <div class="cycle-card">
            <div>
                <div style="font-weight:700; font-size:.95rem;"><?php echo e($cyc['title']); ?></div>
                <div style="font-size:.78rem; color:#6b7280; margin-top:3px;">
                    <?php echo ucfirst($cyc['type']); ?> &bull; <?php echo $cyc['year']; ?> &bull;
                    <?php echo date('d M', strtotime($cyc['from_date'])); ?> รขโ‚ฌโ€œ <?php echo date('d M Y', strtotime($cyc['to_date'])); ?>
                    &bull; <?php echo (int)$cyc['appraisal_count']; ?> appraisals
                </div>
            </div>
            <div style="display:flex; align-items:center; gap:10px;">
                <span class="status-badge" style="background:<?php echo $statusColor; ?>;">
                    <?php echo ucfirst($cyc['status']); ?>
                </span>
                <a class="badge" href="appraisals.php?view=employees&cycle=<?php echo (int)$cyc['id']; ?>">
                    <?php echo $cyc['status']==='closed' ? 'Results' : 'Manage'; ?>
                </a>
                <a href="appraisals.php?edit=<?php echo (int)$cyc['id']; ?>" style="font-size:.82rem; color:#6b7280;">Edit</a>
                <?php if ($cyc['status'] === 'draft'): ?>
                <form method="POST" style="display:inline;" onsubmit="return confirm('Delete this cycle?');">
                    <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
                    <input type="hidden" name="action" value="delete_cycle" />
                    <input type="hidden" name="cycle_id" value="<?php echo (int)$cyc['id']; ?>" />
                    <button type="submit" style="background:none; border:none; color:#ef4444; cursor:pointer; font-size:.82rem;">Delete</button>
                </form>
                <?php endif; ?>
            </div>
        </div>
        <?php endforeach; ?>
    <?php endif; ?>

    <!-- ===== EMPLOYEES VIEW ===== -->
    <?php elseif ($view === 'employees' && $cycle): ?>

    <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:16px;">
        <div>
            <h2 style="margin:0; font-size:1.05rem;"><?php echo e($cycle['title']); ?></h2>
            <div style="font-size:.8rem; color:#6b7280;">
                <?php echo date('d M Y', strtotime($cycle['from_date'])); ?> รขโ‚ฌโ€œ <?php echo date('d M Y', strtotime($cycle['to_date'])); ?>
            </div>
        </div>
        <div style="display:flex; gap:8px;">
            <?php if ($cycle['status'] === 'draft'): ?>
            <form method="POST" style="display:inline;">
                <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
                <input type="hidden" name="action" value="set_status" />
                <input type="hidden" name="cycle_id" value="<?php echo (int)$cycle['id']; ?>" />
                <input type="hidden" name="status" value="open" />
                <button type="submit" style="background:#2563eb; color:#fff; border:none; padding:6px 14px; border-radius:6px; cursor:pointer; font-size:.82rem;">Open Cycle</button>
            </form>
            <?php elseif ($cycle['status'] === 'open'): ?>
            <form method="POST" style="display:inline;" onsubmit="return confirm('Close cycle? Employees will no longer be able to submit self-assessments.');">
                <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
                <input type="hidden" name="action" value="set_status" />
                <input type="hidden" name="cycle_id" value="<?php echo (int)$cycle['id']; ?>" />
                <input type="hidden" name="status" value="closed" />
                <button type="submit" style="background:#6b7280; color:#fff; border:none; padding:6px 14px; border-radius:6px; cursor:pointer; font-size:.82rem;">Close Cycle</button>
            </form>
            <?php endif; ?>
        </div>
    </div>

    <?php if (empty($empRecords)): ?>
        <div class="card" style="text-align:center; padding:40px; color:#6b7280;">No active employees found.</div>
    <?php else: ?>
    <div class="card" style="overflow-x:auto;">
        <table style="width:100%; border-collapse:collapse; font-size:.82rem;">
            <thead>
                <tr style="background:#f9fafb;">
                    <th style="padding:9px 12px; border-bottom:1px solid #e5e7eb; text-align:left;">Employee</th>
                    <th style="padding:9px 12px; border-bottom:1px solid #e5e7eb; text-align:left;">Dept</th>
                    <th style="padding:9px 12px; border-bottom:1px solid #e5e7eb; text-align:center;">Self Rating</th>
                    <th style="padding:9px 12px; border-bottom:1px solid #e5e7eb; text-align:center;">Manager Rating</th>
                    <th style="padding:9px 12px; border-bottom:1px solid #e5e7eb; text-align:center;">Action</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($empRecords as $er): ?>
                <tr>
                    <td style="padding:8px 12px; border-bottom:1px solid #f3f4f6; font-weight:600;"><?php echo e($er['first_name'].' '.$er['last_name']); ?></td>
                    <td style="padding:8px 12px; border-bottom:1px solid #f3f4f6; color:#6b7280;"><?php echo e($er['department']); ?></td>
                    <td style="padding:8px 12px; border-bottom:1px solid #f3f4f6; text-align:center;">
                        <?php echo $er['self_rating'] ? '<span class="stars">'.$ratingLabel($er['self_rating']).'</span> ('.$er['self_rating'].')' : '<span style="color:#d1d5db;">โ€”</span>'; ?>
                    </td>
                    <td style="padding:8px 12px; border-bottom:1px solid #f3f4f6; text-align:center;">
                        <?php echo $er['manager_rating'] ? '<span class="stars">'.$ratingLabel($er['manager_rating']).'</span> ('.$er['manager_rating'].')' : '<span style="color:#d1d5db;">โ€”</span>'; ?>
                    </td>
                    <td style="padding:8px 12px; border-bottom:1px solid #f3f4f6; text-align:center;">
                        <?php if ($cycle['status'] !== 'closed'): ?>
                        <button type="button" onclick="openAppraisalModal(<?php echo htmlspecialchars(json_encode($er), ENT_QUOTES); ?>, <?php echo (int)$cycle['id']; ?>)"
                                style="background:none; border:none; color:#2563eb; cursor:pointer; font-size:.82rem;">
                            <?php echo $er['appraisal_id'] ? 'Edit' : 'Rate'; ?>
                        </button>
                        <?php else: ?>
                            <span style="color:#9ca3af; font-size:.78rem;">Closed</span>
                        <?php endif; ?>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    <?php endif; ?>
    <?php endif; ?>
</div>

<!-- Appraisal modal -->
<div id="appraisal-modal" class="modal-overlay">
    <div style="background:#fff; border-radius:12px; padding:28px; width:440px; max-width:95vw;">
        <h3 id="modal-emp-name" style="margin:0 0 18px; font-size:1rem;"></h3>
        <form method="POST" action="appraisals.php?view=employees&cycle=<?php echo $cycleId; ?>">
            <input type="hidden" name="csrf_token" value="<?php echo e(csrf_token()); ?>" />
            <input type="hidden" name="action" value="save_appraisal" />
            <input type="hidden" name="cycle_id" id="modal-cycle-id" />
            <input type="hidden" name="employee_id" id="modal-emp-id" />
            <input type="hidden" name="appraisal_id" id="modal-appraisal-id" />

            <div style="display:grid; grid-template-columns:1fr 1fr; gap:12px;">
                <div class="form-group">
                    <label>Self Rating (1รขโ‚ฌโ€œ5)</label>
                    <select name="self_rating" id="modal-self-rating" class="form-control">
                        <?php for ($i=1;$i<=5;$i++): ?><option value="<?php echo $i; ?>"><?php echo $i; ?></option><?php endfor; ?>
                    </select>
                </div>
                <div class="form-group">
                    <label>Manager Rating (1รขโ‚ฌโ€œ5)</label>
                    <select name="manager_rating" id="modal-mgr-rating" class="form-control">
                        <?php for ($i=1;$i<=5;$i++): ?><option value="<?php echo $i; ?>"><?php echo $i; ?></option><?php endfor; ?>
                    </select>
                </div>
            </div>
            <div class="form-group">
                <label>Self Comments</label>
                <textarea name="self_comments" id="modal-self-comments" class="form-control" rows="2"></textarea>
            </div>
            <div class="form-group">
                <label>Manager Comments</label>
                <textarea name="manager_comments" id="modal-mgr-comments" class="form-control" rows="2"></textarea>
            </div>
            <div style="display:flex; gap:10px;">
                <button type="submit" class="btn btn-primary" style="flex:1;">Save</button>
                <button type="button" onclick="document.getElementById('appraisal-modal').classList.remove('open')"
                        style="flex:1; background:#f3f4f6; border:1px solid #e5e7eb; border-radius:6px; cursor:pointer;">Cancel</button>
            </div>
        </form>
    </div>
</div>
<script>
function openAppraisalModal(emp, cycleId) {
    document.getElementById('modal-emp-name').textContent = emp.first_name + ' ' + emp.last_name;
    document.getElementById('modal-cycle-id').value      = cycleId;
    document.getElementById('modal-emp-id').value        = emp.emp_id;
    document.getElementById('modal-appraisal-id').value  = emp.appraisal_id || '';
    document.getElementById('modal-self-rating').value   = emp.self_rating    || 3;
    document.getElementById('modal-mgr-rating').value    = emp.manager_rating || 3;
    document.getElementById('modal-self-comments').value  = emp.self_comments    || '';
    document.getElementById('modal-mgr-comments').value   = emp.manager_comments || '';
    document.getElementById('appraisal-modal').classList.add('open');
}
document.getElementById('appraisal-modal').addEventListener('click', function(e) {
    if (e.target === this) this.classList.remove('open');
});
</script>
        </div>
    </div>
</div>
</body>
</html>




โ† Back to Directory Edit File ๐Ÿ”’ Chmod

WP File Manager