0% found this document useful (0 votes)
12 views83 pages

Source-Code File PHP

The document contains PHP code for a system that manages user authentication and database connections for a job promotion decision support system. It includes classes for database configuration, session management, and functions for executing SQL queries, handling user login, and managing session data. The main login page is designed to validate user credentials and redirect them based on their roles after successful login.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views83 pages

Source-Code File PHP

The document contains PHP code for a system that manages user authentication and database connections for a job promotion decision support system. It includes classes for database configuration, session management, and functions for executing SQL queries, handling user login, and managing session data. The main login page is designed to validate user credentials and redirect them based on their roles after successful login.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 83

//source-code file: /config/database.

php :
<?php
// Konfigurasi Database PDO untuk SPK Promosi Jabatan
class Database {
private static $instance = null;
private $host = 'localhost';
private $db_name = 'spk_promosi_jabatan';
private $username = 'root';
private $password = '';
private $conn; public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function getConnection() {
$this->conn = null;
try {
$dsn = "mysql:host=" . $this->host . ";dbname=" . $this->db_name .
";charset=utf8mb4";
$this->conn = new PDO($dsn, $this->username, $this->password);
// Set PDO options
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,
PDO::FETCH_ASSOC);
$this->conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $e) {
echo "Connection Error: " . $e->getMessage();
die();
}
return $this->conn;
}
// Method untuk test koneksi
public function testConnection() {
try {
$pdo = $this->getConnection();
if ($pdo) {
return true;
}
} catch (Exception $e) {
return false;
}
return false;
}
}
// Inisialisasi koneksi global
$database = new Database();
$pdo = $database->getConnection();
// Function helper untuk execute query
function executeQuery($pdo, $sql, $params = []) {
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
} catch (PDOException $e) {
error_log("Database Error: " . $e->getMessage());
return false;
}
}
// Function helper untuk fetch single row
function fetchRow($pdo, $sql, $params = []) {
$stmt = executeQuery($pdo, $sql, $params);
return $stmt ? $stmt->fetch() : false;
}
// Function helper untuk fetch multiple rows
function fetchAll($pdo, $sql, $params = []) {
$stmt = executeQuery($pdo, $sql, $params);
return $stmt ? $stmt->fetchAll() : false;
}
// Function helper untuk insert dan return last insert id
function insertAndGetId($pdo, $sql, $params = []) {
$stmt = executeQuery($pdo, $sql, $params);
return $stmt ? $pdo->lastInsertId() : false;
}?>

//source-code file: /config/session.php :


<?php
// Start session jika belum
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
class SessionManager {
// Fungsi untuk login user
public static function login($userData) {
$_SESSION['user_id'] = $userData['idUser'];
$_SESSION['username'] = $userData['username'];
$_SESSION['role'] = $userData['role'];
$_SESSION['status'] = $userData['status'];
$_SESSION['login_time'] = time();
// Set data tambahan berdasarkan role
if ($userData['role'] == 'Admin') {
$_SESSION['nama'] = $userData['namaAdmin'];
$_SESSION['noHP'] = $userData['noHP'];
} elseif ($userData['role'] == 'Manager') {
$_SESSION['nama'] = $userData['namaManager'];
$_SESSION['noHP'] = $userData['noHP'];
} elseif ($userData['role'] == 'Karyawan') {
$_SESSION['nama'] = $userData['namaKaryawan'];
$_SESSION['noHP'] = $userData['noHP'];
$_SESSION['karyawan_id'] = $userData['idKaryawan'];
}
return true;
}
// Fungsi untuk logout
public static function logout() {
session_unset();
session_destroy();
return true;
}
// Cek apakah user sudah login
public static function isLoggedIn() {
return isset($_SESSION['user_id']) && isset($_SESSION['role']);
}
// Get user data
public static function getUserData() {
if (self::isLoggedIn()) {
return [
'user_id' => $_SESSION['user_id'],
'username' => $_SESSION['username'],
'role' => $_SESSION['role'],
'nama' => $_SESSION['nama'] ?? '',
'noHP' => $_SESSION['noHP'] ?? '',
'karyawan_id' => $_SESSION['karyawan_id'] ?? null
];
}
return false;
}
// Get user role
public static function getRole() {
return $_SESSION['role'] ?? null;
}
// Get user ID
public static function getUserId() {
return $_SESSION['user_id'] ?? null;
}
// Cek authorization berdasarkan role
public static function checkRole($allowedRoles) {
if (!self::isLoggedIn()) {
return false;
}
$userRole = self::getRole();
if (is_string($allowedRoles)) {
return $userRole === $allowedRoles;
}
if (is_array($allowedRoles)) {
return in_array($userRole, $allowedRoles);
}
return false;
}
// Redirect jika tidak ada akses
public static function requireRole($allowedRoles, $redirectUrl =
'../index.php') {
if (!self::checkRole($allowedRoles)) {
header("Location: $redirectUrl");
exit();
}
}
// Redirect ke dashboard sesuai role
public static function redirectToDashboard() {
$role = self::getRole();
switch ($role) {
case 'Admin':
header("Location: dashboard/admin/index.php");
break;
case 'Manager':
header("Location: dashboard/manager/index.php");
break;
case 'Karyawan':
header("Location: dashboard/karyawan/index.php");
break;
default:
header("Location: index.php");
}
exit();
}
// Set flash message
public static function setFlash($type, $message) {
$_SESSION['flash'][$type] = $message;
}
// Get dan hapus flash message
public static function getFlash($type) {
if (isset($_SESSION['flash'][$type])) {
$message = $_SESSION['flash'][$type];
unset($_SESSION['flash'][$type]);
return $message;
}
return null;
}
// Cek session timeout (30 menit)
public static function checkTimeout($timeout = 1800) {
if (isset($_SESSION['login_time'])) {
if (time() - $_SESSION['login_time'] > $timeout) {
self::logout();
return false;
}
// Update login time
$_SESSION['login_time'] = time();
}
return true;
}
// Generate CSRF token
public static function generateCSRF() {
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
// Verify CSRF token
public static function verifyCSRF($token) {
return isset($_SESSION['csrf_token']) &&
hash_equals($_SESSION['csrf_token'], $token);
}
}
// Auto check timeout pada setiap page load
if (SessionManager::isLoggedIn()) {
if (!SessionManager::checkTimeout()) {
header("Location: index.php?timeout=1");
exit();
}
}?>

//source-code file: index.php (halaman login) :


<?php
// index.php - Landing Page / Login
require_once 'config/database.php';
require_once 'config/session.php';
// Redirect jika sudah login
if (SessionManager::isLoggedIn()) {
SessionManager::redirectToDashboard();
}
// Handle login form submission
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['login'])) {
$username = trim($_POST['username']);
$password = $_POST['password'];
if (empty($username) || empty($password)) {
$error = "Username dan password harus diisi!";
} else {
// Query untuk mendapatkan data user dengan join ke tabel detail
$sql = "SELECT u.*,
CASE
WHEN u.role = 'Admin' THEN a.namaAdmin
WHEN u.role = 'Manager' THEN m.namaManager
WHEN u.role = 'Karyawan' THEN k.namaKaryawan
END as nama,
CASE
WHEN u.role = 'Admin' THEN a.noHP
WHEN u.role = 'Manager' THEN m.noHP
WHEN u.role = 'Karyawan' THEN k.noHP
END as noHP,
k.idKaryawan
FROM users u
LEFT JOIN admin a ON u.idUser = a.idUser
LEFT JOIN managerfbs m ON u.idUser = m.idUser
LEFT JOIN karyawanfbs k ON u.idUser = k.idUser
WHERE u.username = ? AND u.status = 'Aktif'";
$user = fetchRow($pdo, $sql, [$username]);
if ($user && password_verify($password, $user['password'])) {
// Login berhasil
$userData = [
'idUser' => $user['idUser'],
'username' => $user['username'],
'role' => $user['role'],
'status' => $user['status']
];
// Tambahkan data spesifik role
if ($user['role'] == 'Admin') {
$userData['namaAdmin'] = $user['nama'];
$userData['noHP'] = $user['noHP'];
} elseif ($user['role'] == 'Manager') {
$userData['namaManager'] = $user['nama'];
$userData['noHP'] = $user['noHP'];
} elseif ($user['role'] == 'Karyawan') {
$userData['namaKaryawan'] = $user['nama'];
$userData['noHP'] = $user['noHP'];
$userData['idKaryawan'] = $user['idKaryawan'];
}
SessionManager::login($userData);
SessionManager::redirectToDashboard();
} else {
$error = "Username atau password salah!";
}
}
}
// Handle timeout message
$timeout_message = '';
if (isset($_GET['timeout'])) {
$timeout_message = "Sesi Anda telah berakhir. Silakan login kembali.";
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SPK Promosi Jabatan - Hotel Le Polonia</title>
<!-- Bootstrap 5 CSS -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet">
<!-- Font Awesome -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/
all.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="assets/css/custom.css" rel="stylesheet">
<style>
</style>
</head>
<body>
<div class="login-wrapper">
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-12">
<div class="login-container">
<div class="row g-0">
<!-- Logo Section -->
<div class="col-md-6">
<div class="logo-section">
<i class="fas fa-hotel logo-icon"></i>
<h2 class="fw-bold mb-3">Hotel Le Polonia</h2>
<h4 class="mb-4">Sistem Pendukung
Keputusan</h4>
<p class="lead text-center">Promosi Jabatan
Karyawan Departemen FBS</p>
<div class="mt-4">
<small class="text-light opacity-75">
Menggunakan Metode Simple Additive
Weighting (SAW)
</small>
</div>
</div>
</div>
<!-- Login Form Section -->
<div class="col-md-6">
<div class="form-section">
<h3 class="form-title">Login Sistem</h3>
<?php if (isset($error)): ?>
<div class="alert alert-danger alert-
dismissible fade show" role="alert">
<i class="fas fa-exclamation-triangle
me-2"></i>
<?= htmlspecialchars($error) ?>
<button type="button" class="btn-close"
data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<?php if ($timeout_message): ?>
<div class="alert alert-warning alert-
dismissible fade show" role="alert">
<i class="fas fa-clock me-2"></i>
<?=
htmlspecialchars($timeout_message) ?>
<button type="button" class="btn-close"
data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>
<form method="POST" action="">
<div class="form-group">
<label for="username" class="form-
label">Username</label>
<div class="input-wrapper">
<input type="text" class="form-
control"
id="username"
name="username"
placeholder="Masukkan
username Anda"
value="<?=
isset($_POST['username']) ? htmlspecialchars($_POST['username']) : '' ?>"
required>
</div>
</div>
<div class="form-group">
<label for="password" class="form-
label">Password</label>
<div class="input-wrapper">
<div class="password-wrapper">
<input type="password"
class="form-control"
id="password"
name="password"
placeholder="Masukkan
password Anda"
required>
<span class="password-toggle"
onclick="togglePassword()">
<i class="fas fa-eye"
id="toggleIcon"></i>
</span>
</div>
</div>
</div>
<div class="form-group">
<button type="submit" name="login"
class="btn btn-login">
<i class="fas fa-sign-in-alt me-
2"></i>
Masuk Sistem
</button>
</div>
</form>
<div class="footer-links">
<small class="text-muted">
Belum punya akun?
<a href="auth/register.php">Daftar di
sini</a>
</small>
</div>
<div class="security-badge">
<i class="fas fa-shield-alt me-2"></i>
<small>Sistem Keamanan Terjamin</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap 5 JS -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js">
</script>
<script>
// Toggle password visibility
function togglePassword() {
const passwordInput = document.getElementById('password');
const toggleIcon = document.getElementById('toggleIcon');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
toggleIcon.classList.remove('fa-eye');
toggleIcon.classList.add('fa-eye-slash');
} else {
passwordInput.type = 'password';
toggleIcon.classList.remove('fa-eye-slash');
toggleIcon.classList.add('fa-eye');
}
}
// Auto dismiss alerts after 5 seconds
setTimeout(function() {
const alerts = document.querySelectorAll('.alert');
alerts.forEach(function(alert) {
const bsAlert = new bootstrap.Alert(alert);
bsAlert.close();
});
}, 5000);
// Add focus animations
document.querySelectorAll('.form-control').forEach(function(input) {
input.addEventListener('focus', function() {
this.parentElement.classList.add('focused');
});
input.addEventListener('blur', function() {
this.parentElement.classList.remove('focused');
});
});
</script>
</body>
</html>

//source-code file: /auth/login.php :


<?php
// auth/login.php - Process Login
require_once '../config/database.php';
require_once '../config/session.php';

// Redirect jika sudah login


if (SessionManager::isLoggedIn()) {
SessionManager::redirectToDashboard();
}

$response = ['success' => false, 'message' => ''];


if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Verify CSRF token if available
if (isset($_POST['csrf_token']) && !
SessionManager::verifyCSRF($_POST['csrf_token'])) {
$response['message'] = 'Token keamanan tidak valid!';
echo json_encode($response);
exit;
}

$username = trim($_POST['username'] ?? '');


$password = $_POST['password'] ?? '';

// Validasi input
if (empty($username) || empty($password)) {
$response['message'] = 'Username dan password harus diisi!';
} else {
try {
// Query untuk mendapatkan data user dengan join ke tabel detail
$sql = "SELECT u.*,
CASE
WHEN u.role = 'Admin' THEN a.namaAdmin
WHEN u.role = 'Manager' THEN m.namaManager
WHEN u.role = 'Karyawan' THEN k.namaKaryawan
END as nama,
CASE
WHEN u.role = 'Admin' THEN a.noHP
WHEN u.role = 'Manager' THEN m.noHP
WHEN u.role = 'Karyawan' THEN k.noHP
END as noHP,
k.idKaryawan
FROM users u
LEFT JOIN admin a ON u.idUser = a.idUser AND u.role = 'Admin'
LEFT JOIN managerfbs m ON u.idUser = m.idUser AND u.role =
'Manager'
LEFT JOIN karyawanfbs k ON u.idUser = k.idUser AND u.role =
'Karyawan'
WHERE u.username = ? AND u.status = 'Aktif'";

$user = fetchRow($pdo, $sql, [$username]);

if ($user && password_verify($password, $user['password'])) {


// Cek status khusus untuk karyawan
if ($user['role'] == 'Karyawan') {
$sqlKaryawan = "SELECT statusKerja FROM karyawanfbs WHERE
idUser = ?";
$karyawan = fetchRow($pdo, $sqlKaryawan, [$user['idUser']]);

if ($karyawan && $karyawan['statusKerja'] != 'Aktif') {


$response['message'] = 'Akun karyawan tidak dalam status
aktif!';
echo json_encode($response);
exit;
}
}

// Prepare user data for session


$userData = [
'idUser' => $user['idUser'],
'username' => $user['username'],
'role' => $user['role'],
'status' => $user['status']
];

// Tambahkan data spesifik role


if ($user['role'] == 'Admin') {
$userData['namaAdmin'] = $user['nama'];
$userData['noHP'] = $user['noHP'];
} elseif ($user['role'] == 'Manager') {
$userData['namaManager'] = $user['nama'];
$userData['noHP'] = $user['noHP'];
} elseif ($user['role'] == 'Karyawan') {
$userData['namaKaryawan'] = $user['nama'];
$userData['noHP'] = $user['noHP'];
$userData['idKaryawan'] = $user['idKaryawan'];
}

// Login berhasil
if (SessionManager::login($userData)) {
// Log activity
if (function_exists('SPKHelper::logActivity')) {
SPKHelper::logActivity($pdo, $user['idUser'], 'LOGIN',
'User berhasil login');
}

$response['success'] = true;
$response['message'] = 'Login berhasil!';

// set redirect berdasarkan role


switch ($user['role']) {
case 'Admin' || 'manager':
$response['redirect'] = '../dashboard/admin/index.php';
break;
case 'Manager':
$response['redirect'] =
'../dashboard/manager/index.php';
break;
case 'Karyawan':
$response['redirect'] =
'../dashboard/karyawan/index.php';
break;
default:
$response['redirect'] = '../index.php';
}
} else {
$response['message'] = 'Gagal membuat sesi login!';
}
} else {
$response['message'] = 'Username atau password salah!';

// log login gagal


if (function_exists('SPKHelper::logActivity')) {
SPKHelper::logActivity($pdo, 0, 'LOGIN_FAILED', "Failed login
attempt for username: $username");
}
}
} catch (Exception $e) {
$response['message'] = 'Terjadi kesalahan sistem. Silakan coba lagi.';
error_log("Login Error: " . $e->getMessage());
}
}
}

// return respon dengan format JSON untuk AJAX


if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
header('Content-Type: application/json');
echo json_encode($response);
exit;
}

// arahkan kembali ke halaman login dengan pesan


if ($response['success']) {
header("Location: " . $response['redirect']);
} else {
SessionManager::setFlash('error', $response['message']);
header("Location: ../index.php");
}
exit;
?>

//source-code file: /auth/register.php :


<?php
require_once '../config/database.php';
require_once '../config/session.php';
require_once '../includes/functions.php';
// Redirect jika sudah login
if (SessionManager::isLoggedIn()) {
SessionManager::redirectToDashboard();
}
$errors = [];
$success = '';
// menangani registrasi form
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['register'])) {
// verifikasi token CSRF
if (!SessionManager::verifyCSRF($_POST['csrf_token'] ?? '')) {
$errors[] = 'Token keamanan tidak valid!';
} else {
// Validasi input
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
$confirm_password = $_POST['confirm_password'] ?? '';
$role = $_POST['role'] ?? 'Karyawan';
$nama = trim($_POST['nama'] ?? '');
$noHP = trim($_POST['noHP'] ?? '');
// Validasi data umum
if (empty($username)) $errors[] = 'Username harus diisi!';
if (empty($password)) $errors[] = 'Password harus diisi!';
if (empty($confirm_password)) $errors[] = 'Konfirmasi password harus
diisi!';
if (empty($nama)) $errors[] = 'Nama harus diisi!';
if ($password != $confirm_password) {
$errors[] = 'Password dan konfirmasi password tidak sama!';
}
if (strlen($password) < 6) {
$errors[] = 'Password minimal 6 karakter!';
}
// Validasi khusus untuk karyawan
if ($role == 'Karyawan') {
$jenisKelamin = $_POST['jenisKelamin'] ?? '';
$tanggalLahir = $_POST['tanggalLahir'] ?? '';
$pendidikan = $_POST['pendidikan'] ?? '';
$Alamat = $_POST['Alamat'] ?? '';
$jabatan = $_POST['jabatan'] ?? '';
$tanggalMasuk = $_POST['tanggalMasuk'] ?? '';
$statusKerja = $_POST['statusKerja'] ?? 'Aktif';

if (empty($jenisKelamin)) $errors[] = 'Jenis kelamin harus dipilih!';


if (empty($tanggalLahir)) $errors[] = 'Tanggal lahir harus diisi!';
if (empty($jabatan)) $errors[] = 'Jabatan harus dipilih!';
if (empty($tanggalMasuk)) $errors[] = 'Tanggal masuk harus diisi!';
}
// Cek username sudah ada atau belum
if (empty($errors)) {
$sqlCheck = "SELECT idUser FROM users WHERE username = ?";
$existingUser = fetchRow($pdo, $sqlCheck, [$username]);

if ($existingUser) {
$errors[] = 'Username sudah digunakan!';
}
}
// Proses registrasi jika tidak ada error
if (empty($errors)) {
try {
$pdo->beginTransaction();
// Hash password
$hashedPassword = SPKHelper::hashPassword($password);
// Insert ke tabel users
$sqlUser = "INSERT INTO users (username, password, role, status)
VALUES (?, ?, ?, 'Aktif')";
$userId = insertAndGetId($pdo, $sqlUser, [$username,
$hashedPassword, $role]);

if ($userId) {
// Insert ke tabel detail berdasarkan role
if ($role == 'Admin') {
$sqlDetail = "INSERT INTO admin (idUser, namaAdmin, noHP)
VALUES (?, ?, ?)";
executeQuery($pdo, $sqlDetail, [$userId, $nama, $noHP]);
} elseif ($role == 'Manager') {
$sqlDetail = "INSERT INTO managerfbs (idUser, namaManager,
noHP) VALUES (?, ?, ?)";
executeQuery($pdo, $sqlDetail, [$userId, $nama, $noHP]);
} elseif ($role == 'Karyawan') {
$sqlDetail = "INSERT INTO karyawanfbs (idUser,
namaKaryawan, jenisKelamin, tanggalLahir, noHP, jabatan, pendidikan, Alamat,
tanggalMasuk, statusKerja)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
executeQuery($pdo, $sqlDetail, [
$userId, $nama, $jenisKelamin, $tanggalLahir,
$noHP, $jabatan, $pendidikan, $Alamat, $tanggalMasuk,
$statusKerja
]);
}

$pdo->commit();
$success = 'Registrasi berhasil! Silakan login dengan akun yang
telah dibuat.';

// membersihkan data POST untuk menghindari pengiriman ulang


$_POST = [];
} else {
$pdo->rollback();
$errors[] = 'Gagal membuat akun. Silakan coba lagi.';
}
} catch (Exception $e) {
$pdo->rollback();
$errors[] = 'Terjadi kesalahan sistem. Silakan coba lagi.';
error_log("Registration Error: " . $e->getMessage());
}
}
}
}
?>

<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registrasi - SPK Promosi Jabatan</title>

<!-- Bootstrap 5 CSS -->


<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet">
<!-- Font Awesome -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/
all.min.css" rel="stylesheet">

<link rel="stylesheet" href="../assets/css/custom.css">


</head>
<body>
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8 col-xl-7">
<div class="register-container p-5">
<div class="text-center mb-4">
<i class="fas fa-user-plus fa-3x text-primary mb-3"></i>
<h2 class="fw-bold">Registrasi Akun</h2>
<p class="text-muted">Buat akun baru untuk mengakses
sistem</p>
</div>

<?php if (!empty($errors)): ?>


<div class="alert alert-danger alert-dismissible fade show"
role="alert">
<i class="fas fa-exclamation-triangle me-2"></i>
<ul class="mb-0">
<?php foreach ($errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
<button type="button" class="btn-close" data-bs-
dismiss="alert"></button>
</div>
<?php endif; ?>

<?php if ($success): ?>


<div class="alert alert-success alert-dismissible fade
show" role="alert">
<i class="fas fa-check-circle me-2"></i>
<?= htmlspecialchars($success) ?>
<button type="button" class="btn-close" data-bs-
dismiss="alert"></button>
</div>
<?php endif; ?>

<form method="POST" action="" id="registerForm">


<input type="hidden" name="csrf_token" value="<?=
SessionManager::generateCSRF() ?>">

<div class="row">
<div class="col-md-6 mb-3">
<label for="username" class="form-label fw-
semibold">
<i class="fas fa-user me-2"></i>Username
</label>
<input type="text" class="form-control"
id="username" name="username"
placeholder="Masukkan username"
value="<?=
htmlspecialchars($_POST['username'] ?? '') ?>" required>
</div>

<div class="col-md-6 mb-3">


<label for="role" class="form-label fw-semibold">
<i class="fas fa-user-tag me-2"></i>Role
</label>
<select class="form-select" id="role" name="role"
onchange="toggleKaryawanFields()" required>
<option value="">Pilih Role</option>
<option value="Karyawan" <?= ($_POST['role'] ??
'') == 'Karyawan' ? 'selected' : '' ?>>Karyawan</option>
<option value="Manager" <?= ($_POST['role'] ??
'') == 'Manager' ? 'selected' : '' ?>>Manager</option>
<option value="Admin" <?= ($_POST['role'] ??
'') == 'Admin' ? 'selected' : '' ?>>Admin</option>
</select>
</div>
</div>

<div class="row">
<div class="col-md-6 mb-3">
<label for="password" class="form-label fw-
semibold">
<i class="fas fa-lock me-2"></i>Password
</label>
<div class="input-group">
<input type="password" class="form-control"
id="password" name="password"
placeholder="Masukkan password"
required>
<span class="input-group-text password-toggle"
onclick="togglePassword('password')">
<i class="fas fa-eye"
id="password-eye"></i>
</span>
</div>
</div>

<div class="col-md-6 mb-3">


<label for="confirm_password" class="form-label fw-
semibold">
<i class="fas fa-lock me-2"></i>Konfirmasi
Password
</label>
<div class="input-group">
<input type="password" class="form-control"
id="confirm_password" name="confirm_password"
placeholder="Konfirmasi password"
required>
<span class="input-group-text password-toggle"
onclick="togglePassword('confirm_password')">
<i class="fas fa-eye" id="confirm_password-
eye"></i>
</span>
</div>
</div>
</div>

<div class="row">
<div class="col-md-6 mb-3">
<label for="nama" class="form-label fw-semibold">
<i class="fas fa-id-card me-2"></i>Nama Lengkap
</label>
<input type="text" class="form-control" id="nama"
name="nama"
placeholder="Masukkan nama lengkap"
value="<?=
htmlspecialchars($_POST['nama'] ?? '') ?>" required>
</div>

<div class="col-md-6 mb-3">


<label for="noHP" class="form-label fw-semibold">
<i class="fas fa-phone me-2"></i>No. HP
</label>
<input type="tel" class="form-control" id="noHP"
name="noHP"
placeholder="Masukkan nomor HP"
value="<?=
htmlspecialchars($_POST['noHP'] ?? '') ?>">
</div>
<div class="text-center mt-3">
<p class="mb-0">Sudah punya akun?
<a href="login.php" class="btn-link fw-
semibold">Login di sini</a>
</p>
</div>
</div>

<!-- Fields khusus untuk Karyawan -->


<div id="karyawan-fields" class="karyawan-fields">
<hr class="my-4">
<h5 class="text-primary mb-3">
<i class="fas fa-user-tie me-2"></i>Data Karyawan
</h5>

<div class="row">
<div class="col-md-6 mb-3">
<label for="jenisKelamin" class="form-label fw-
semibold">
<i class="fas fa-venus-mars me-2"></i>Jenis
Kelamin
</label>
<select class="form-select" id="jenisKelamin"
name="jenisKelamin">
<option value="">Pilih Jenis
Kelamin</option>
<option value="Laki-laki" <?=
($_POST['jenisKelamin'] ?? '') == 'Laki-laki' ? 'selected' : ''
?>>Laki-laki</option>
<option value="Perempuan" <?=
($_POST['jenisKelamin'] ?? '') == 'Perempuan' ? 'selected' : ''
?>>Perempuan</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="Alamat" class="form-label fw-semibold">
<i class="fas fa-id-card me-2"></i>Alamat
</label>
<input type="text" class="form-control" id="Alamat"
name="Alamat"
placeholder="Masukkan Alamat"
value="<?= htmlspecialchars($_POST['Alamat']
?? '') ?>" required>
</div>

<div class="col-md-6 mb-3">


<label for="tanggalLahir" class="form-label fw-
semibold">
<i class="fas fa-calendar me-2"></i>Tanggal
Lahir
</label>
<input type="date" class="form-control"
id="tanggalLahir" name="tanggalLahir"
value="<?=
htmlspecialchars($_POST['tanggalLahir'] ?? '') ?>">
</div>
</div>

<div class="row">
<div class="col-md-6 mb-3">
<label for="jabatan" class="form-label fw-
semibold">
<i class="fas fa-briefcase
me-2"></i>Jabatan
</label>
<select class="form-select" id="jabatan"
name="jabatan">
<option value="">Pilih Jabatan</option>
<option value="Waiter" <?=
($_POST['jabatan'] ?? '') == 'Waiter' ? 'selected' : '' ?>>Waiter</option>
<option value="Waitress" <?=
($_POST['jabatan'] ?? '') == 'Waitress' ? 'selected' : '' ?>>Waitress</option>
<option value="Captain" <?=
($_POST['jabatan'] ?? '') == 'Captain' ? 'selected' : '' ?>>Captain</option>
<option value="Assistant Restauran Manager"
<?= ($_POST['jabatan'] ?? '') == 'Assistant Restauran Manager' ? 'selected' : '' ?
>>Assistant Restauran Manager</option>
</select>
</div>

<div class="row">
<div class="col-md-6 mb-3">
<label for="pendidikan" class="form-label fw-
semibold">
<i class="fas fa-briefcase
me-2"></i>pendidikan
</label>
<select class="form-select" id="pendidikan"
name="pendidikan">
<option value="">Pilih pendidikan</option>
<option value="SMK/SMA" <?=
($_POST['pendidikan'] ?? '') == 'SMK/SMA' ? 'selected' : '' ?>>SMK/SMA</option>
<option value="Diploma 1" <?=
($_POST['pendidikan'] ?? '') == 'Diploma 1' ? 'selected' : '' ?>>Diploma 1</option>
<option value="Diploma 3" <?=
($_POST['pendidikan'] ?? '') == 'Diploma 3' ? 'selected' : '' ?>>Diploma 3</option>
<option value="Strata 1" <?=
($_POST['pendidikan'] ?? '') == 'Strata 1' ? 'selected' : '' ?>>Strata 1</option>
<option value="Strata 2" <?=
($_POST['pendidikan'] ?? '') == 'Strata 2' ? 'selected' : '' ?>>Strata 2</option>
</select>
</div>

<div class="col-md-6 mb-3">


<label for="tanggalMasuk" class="form-label fw-
semibold">
<i class="fas fa-calendar-plus
me-2"></i>Tanggal Masuk
</label>
<input type="date" class="form-control"
id="tanggalMasuk" name="tanggalMasuk"
value="<?=
htmlspecialchars($_POST['tanggalMasuk'] ?? '') ?>">
</div>
</div>

<div class="row">
<div class="col-md-6 mb-3">
<label for="statusKerja" class="form-label fw-
semibold">
<i class="fas fa-user-check
me-2"></i>Status Kerja
</label>
<select class="form-select" id="statusKerja"
name="statusKerja">
<option value="Aktif" <?=
($_POST['statusKerja'] ?? 'Aktif') == 'Aktif' ? 'selected' : '' ?>>Aktif</option>
<option value="Cuti" <?=
($_POST['statusKerja'] ?? '') == 'Cuti' ? 'selected' : '' ?>>Cuti</option>
<option value="Non-Aktif" <?=
($_POST['statusKerja'] ?? '') == 'Non-Aktif' ? 'selected' : ''
?>>Non-Aktif</option>
</select>
</div>
</div>
</div>

<div class="d-grid gap-2 mt-4">


<button type="submit" name="register" class="btn btn-
primary btn-register">
<i class="fas fa-user-plus me-2"></i>Daftar
Sekarang
</button>
</div>

<div class="text-center mt-3">


<p class="mb-0">Sudah punya akun?
<a href="login.php" class="btn-link fw-
semibold">Login di sini</a>
</p>
</div>
</form>
</div>
</div>
</div>
</div>

<!-- Bootstrap 5 JS -->


<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js">
</script>

<script>
// fungsi untuk hide/show password
function togglePassword(fieldId) {
const field = document.getElementById(fieldId);
const eye = document.getElementById(fieldId + '-eye');

if (field.type === 'password') {


field.type = 'text';
eye.classList.remove('fa-eye');
eye.classList.add('fa-eye-slash');
} else {
field.type = 'password';
eye.classList.remove('fa-eye-slash');
eye.classList.add('fa-eye');
}
}

// fungsi untuk toggle fields khusus karyawan


function toggleKaryawanFields() {
const role = document.getElementById('role').value;
const karyawanFields = document.getElementById('karyawan-fields');

if (role === 'Karyawan') {


karyawanFields.style.display = 'block';
//atribut yang diperlukan untuk karyawan
document.getElementById('jenisKelamin').required = true;
document.getElementById('tanggalLahir').required = true;
document.getElementById('jabatan').required = true;
document.getElementById('tanggalMasuk').required = true;
} else {
karyawanFields.style.display = 'none';
// hapus atribut yang diperlukan
document.getElementById('jenisKelamin').required = false;
document.getElementById('tanggalLahir').required = false;
document.getElementById('jabatan').required = false;
document.getElementById('tanggalMasuk').required = false;
}
}

// inisialisasi tampilan karyawan fields


document.addEventListener('DOMContentLoaded', function() {
toggleKaryawanFields();

// set maks date untuk tanggal lahir dan tanggal masuk


// agar tidak bisa memilih tanggal di masa depan
const today = new Date().toISOString().split('T')[0];
document.getElementById('tanggalLahir').max = today;
document.getElementById('tanggalMasuk').max = today;
});

// Form validation
document.getElementById('registerForm').addEventListener('submit',
function(e) {
const password = document.getElementById('password').value;
const confirmPassword =
document.getElementById('confirm_password').value;

if (password !== confirmPassword) {


e.preventDefault();
alert('Password dan konfirmasi password tidak sama!');
return false;
}

if (password.length < 6) {
e.preventDefault();
alert('Password minimal 6 karakter!');
return false;
}
});
</script>
</body>
</html>

//source-code file: /includes/header.php :


<?php
// Tentukan base path berdasarkan lokasi file saat ini
$currentPath = $_SERVER['PHP_SELF'];
$basePath = '';
// Jika di dalam folder dashboard/admin, base path adalah ../../
if (strpos($currentPath, '/dashboard/admin/') !== false) {
$basePath = '../../';
} elseif (strpos($currentPath, '/dashboard/manager/') !== false) {
$basePath = '../../';
} elseif (strpos($currentPath, '/dashboard/karyawan/') !== false) {
$basePath = '../../';
}
// Tentukan apakah ini halaman login atau register
$isLoginPage = (strpos($currentPath, 'login.php') !== false);
$isRegisterPage = (strpos($currentPath, 'register.php') !== false ||
strpos($currentPath, 'registrasi.php') !== false);
$bodyClass = '';
if ($isLoginPage) {
$bodyClass = 'login-page';
} elseif ($isRegisterPage) {
$bodyClass = 'register-page';
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Aplikasi SPK FBS</title>
<!-- Bootstrap CSS -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet">
<!-- Font Awesome -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/
all.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="<?= $basePath ?>assets/css/custom.css" rel="stylesheet">
</head>
<body<?= !empty($bodyClass) ? ' class="' . $bodyClass . '"' : '' ?>>
<?php if (!$isLoginPage && !$isRegisterPage): ?>
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="<?= $basePath ?>index.php">
<img src="<?= $basePath ?>assets/img/logo.jpg" alt="Logo"
height="30" class="d-inline-block align-text-top me-2">
SPK Promosi Jabatan Departemen FBS <i><b>Le-Polonia </b></i> Hotel
Medan
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<a>
<i class="fas fa-user me-1"></i>
<?= isset($_SESSION['nama']) ?
htmlspecialchars($_SESSION['nama']) : 'User' ?> |
</a>
<a href="<?= $basePath ?>auth/logout.php">
<i class="fas fa-sign-out-alt me-1" style="color:
black;"></i> Logout
</a>
</ul>
</div>
</div>
</nav>
<?php endif; ?>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js">
</script>

//source-code file: /includes/sidebar.php :


<?php
// Tentukan current page untuk active menu
$currentPage = basename($_SERVER['PHP_SELF']);
// Cek apakah ini halaman login atau register
$currentPath = $_SERVER['PHP_SELF'];
$isLoginPage = (strpos($currentPath, 'login.php') !== false);
$isRegisterPage = (strpos($currentPath, 'register.php') !== false ||
strpos($currentPath, 'registrasi.php') !== false);
// Jangan tampilkan sidebar untuk halaman login dan register
if (!$isLoginPage && !$isRegisterPage):
?>
<div class="d-flex">
<nav id="sidebar" class="bg-light border-end shadow-sm">
<div class="p-3">
<h6 class="text-muted text-uppercase fw-bold mb-3">Menu <?=
ucfirst($_SESSION['role']) ?></h6>
</div>
<div class="list-group list-group-flush">
<?php if($_SESSION['role'] === 'Admin'): ?>
<a href="index.php" class="list-group-item list-group-item-action
<?= $currentPage == 'index.php' ? 'active' : '' ?>">
<i class="fas fa-tachometer-alt me-2"></i> Dashboard Admin
</a>
<a href="users.php" class="list-group-item list-group-item-action
<?= $currentPage == 'users.php' ? 'active' : '' ?>">
<i class="fas fa-users me-2"></i> Pengguna
</a>

<a href="kriteria.php" class="list-group-item list-group-item-


action <?= $currentPage == 'kriteria.php' ? 'active' : '' ?>">
<i class="fas fa-list me-2"></i> Kriteria
</a>
<a href="subkriteria.php" class="list-group-item list-group-item-
action <?= $currentPage == 'subkriteria.php' ? 'active' : '' ?>">
<i class="fas fa-list-ul me-2"></i> Subkriteria
</a>
<a href="penilaian.php" class="list-group-item list-group-item-
action <?= $currentPage == 'penilaian.php' ? 'active' : '' ?>">
<i class="fas fa-star me-2"></i> Penilaian
</a>
<a href="analisis.php" class="list-group-item list-group-item-
action <?= $currentPage == 'analisis.php' ? 'active' : '' ?>">
<i class="fas fa-chart-line me-2"></i> Analisis
</a>

<?php elseif($_SESSION['role'] === 'Manager'): ?>


<a href="index.php" class="list-group-item list-group-item-action
<?= $currentPage == 'index.php' ? 'active' : '' ?>">
<i class="fas fa-tachometer-alt me-2"></i> Dashboard Manager
</a>
<a href="karyawan.php" class="list-group-item list-group-item-
action <?= $currentPage == 'karyawan.php' ? 'active' : '' ?>">
<i class="fas fa-users me-2"></i> Karyawan
</a>
<a href="kriteria.php" class="list-group-item list-
group-item-action <?= $currentPage == 'kriteria.php' ? 'active' : '' ?>">
<i class="fas fa-list me-2"></i> Kriteria
</a>
<a href="subkriteria.php" class="list-group-item list-group-item-
action <?= $currentPage == 'subkriteria.php' ? 'active' : '' ?>">
<i class="fas fa-list-ul me-2"></i> Subkriteria
</a>
<a href="penilaian.php" class="list-group-item list-group-item-
action <?= $currentPage == 'penilaian.php' ? 'active' : '' ?>">
<i class="fas fa-star me-2"></i> Penilaian
</a>
<a href="analisis.php" class="list-group-item list-group-item-
action <?= $currentPage == 'analisis.php' ? 'active' : '' ?>">
<i class="fas fa-chart-line me-2"></i> Analisis
</a>
<?php else: ?>
<a href="index.php" class="list-group-item list-group-item-action
<?= $currentPage == 'index.php' ? 'active' : '' ?>">
<i class="fas fa-tachometer-alt me-2"></i> Dashboard Karyawan
</a>
<a href="profil.php" class="list-group-item list-group-item-action
<?= $currentPage == 'profil.php' ? 'active' : '' ?>">
<i class="fas fa-user me-2"></i> Profil
</a>
<a href="riwayat.php" class="list-group-item list-group-item-action
<?= $currentPage == 'riwayat.php' ? 'active' : '' ?>">
<i class="fas fa-history me-2"></i> Riwayat hasil perangkingan
</a>
<?php endif; ?>
</div>
</nav>
<?php endif; ?>

//source-code file: /includes/footer.php :


<?php
// Cek apakah ini halaman login atau register
$currentPath = $_SERVER['PHP_SELF'];
$isLoginPage = (strpos($currentPath, 'login.php') !== false);
$isRegisterPage = (strpos($currentPath, 'register.php') !== false ||
strpos($currentPath, 'registrasi.php') !== false);

// Tutup div flex container jika bukan halaman login/register


if (!$isLoginPage && !$isRegisterPage):
?>
</div> <!-- End of d-flex from sidebar -->
<?php endif; ?>

<!-- Footer -->


<?php if (!$isLoginPage && !$isRegisterPage): ?>
<footer class="bg-light mt-auto py-3">
<div class="container-fluid">
<div class="row">
<div class="col-12 text-center">
<small class="text-muted">
&copy; <?= date('Y') ?> Hotel Le Polonia - SPK Promosi
Jabatan FBS
</small>
</div>
</div>
</div>
</footer>
<?php endif; ?>

<!-- Bootstrap JS Bundle -->


<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js">
</script>
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- Custom JS -->
<script src="<?= isset($basePath) ? $basePath : '../../'
?>assets/js/custom.js"></script>
</body>
</html>

//source-code file: /dashboard/admin/index.php :<?php


// Start session terlebih dahulu
require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../includes/functions.php';

// Pastikan hanya Admin yang dapat mengakses


SessionManager::requireRole('Admin' );

// Ambil data sesi pengguna


$user = SessionManager::getUserData();

// Query untuk statistik dinamis dengan nama tabel yang benar


$db = Database::getInstance()->getConnection();

try {
// Gunakan nama tabel yang sesuai dengan database Anda
$totalPengguna = $db->query("SELECT COUNT(*) FROM users WHERE status =
'Aktif'")->fetchColumn();
$totalKriteria = $db->query("SELECT COUNT(*) FROM kriteria WHERE status =
'Aktif'")->fetchColumn();
$totalKaryawan = $db->query("SELECT COUNT(*) FROM karyawanfbs WHERE statusKerja
= 'Aktif'")->fetchColumn();
$totalAnalisis = $db->query("SELECT COUNT(*) FROM hasilspk")->fetchColumn();
} catch (Exception $e) {
// Jika terjadi error, set nilai default
$totalPengguna = 0;
$totalKriteria = 0;
$totalKaryawan = 0;
$totalAnalisis = 0;
}
?>

<?php include __DIR__ . '/../../includes/header.php'; ?>


<?php include __DIR__ . '/../../includes/sidebar.php'; ?>

<main class="content">
<div class="container-fluid p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="mb-0">Dashboard Admin</h1>
<div class="text-muted">
<i class="fas fa-calendar-alt me-1"></i>
<?= date('d F Y') ?>
</div>
</div>

<div class="card mb-4">


<div class="card-body">
<h5 class="card-title">
<i class="fas fa-user-shield me-2 text-primary"></i>
Selamat datang, <?= htmlspecialchars($user['nama']); ?>!
</h5>
<p class="card-text">Anda memiliki akses penuh untuk mengelola
sistem SPK promosi jabatan karyawan departemen FBS.</p>
</div>
</div>

<!-- Widget Statistik -->


<div class="row mb-4">
<div class="col-lg-3 col-md-6 mb-3">
<div class="card text-white bg-primary h-100">
<div class="card-body d-flex justify-content-between align-
items-center">
<div>
<h5 class="card-title mb-1 text-white">Total
Pengguna</h5>
<p class="card-text display-6 mb-0 text-white fw-
bold"><?= $totalPengguna ?></p>
</div>
<i class="fas fa-users fa-2x" style="opacity: 0.75; color:
rgba(255,255,255,0.75);"></i>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card text-white bg-success h-100">
<div class="card-body d-flex justify-content-between align-
items-center">
<div>
<h5 class="card-title mb-1 text-white">Total
Kriteria</h5>
<p class="card-text display-6 mb-0 text-white fw-
bold"><?= $totalKriteria ?></p>
</div>
<i class="fas fa-list fa-2x" style="opacity: 0.75; color:
rgba(255,255,255,0.75);"></i>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card text-white bg-warning h-100">
<div class="card-body d-flex justify-content-between align-
items-center">
<div>
<h5 class="card-title mb-1 text-white">Total
Karyawan</h5>
<p class="card-text display-6 mb-0 text-white fw-
bold"><?= $totalKaryawan ?></p>
</div>
<i class="fas fa-user-tie fa-2x" style="opacity: 0.75;
color: rgba(255,255,255,0.75);"></i>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card text-white bg-info h-100">
<div class="card-body d-flex justify-content-between align-
items-center">
<div>
<h5 class="card-title mb-1 text-white">Total
Analisis</h5>
<p class="card-text display-6 mb-0 text-white fw-
bold"><?= $totalAnalisis ?></p>
</div>
<i class="fas fa-chart-line fa-2x" style="opacity: 0.75;
color: rgba(255,255,255,0.75);"></i>
</div>
</div>
</div>
</div>

<!-- Grafik Statistik -->


<div class="row mb-4">
<div class="col-md-6 mb-3">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-chart-bar me-2"></i>
Grafik Batang
</h5>
</div>
<div class="card-body">
<canvas id="barChart" height="300"></canvas>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-chart-pie me-2"></i>
Grafik Pie
</h5>
</div>
<div class="card-body">
<canvas id="pieChart" height="300"></canvas>
</div>
</div>
</div>
</div>

<!-- Quick Actions -->


<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-bolt me-2"></i>
Aksi Cepat
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-lg-3 col-md-6 mb-3">
<a href="users.php" class="btn btn-outline-primary w-100">
<i class="fas fa-users me-2"></i>
Kelola Pengguna
</a>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<a href="kriteria.php" class="btn btn-outline-success w-
100">
<i class="fas fa-list me-2"></i>
Kelola Kriteria
</a>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<a href="analisis.php" class="btn btn-outline-warning w-
100">
<i class="fas fa-chart-line me-2"></i>
Analisis SPK
</a>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<a href="laporan.php" class="btn btn-outline-info w-100">
<i class="fas fa-file-alt me-2"></i>
Lihat Laporan
</a>
</div>
</div>
</div>
</div>
</div>
</main>

<script>
// Render Charts
document.addEventListener('DOMContentLoaded', function() {
// Bar Chart
const barCtx = document.getElementById('barChart').getContext('2d');
new Chart(barCtx, {
type: 'bar',
data: {
labels: ['Pengguna', 'Kriteria', 'Karyawan', 'Analisis'],
datasets: [{
label: 'Jumlah',
data: [<?= $totalPengguna ?>, <?= $totalKriteria ?>, <?=
$totalKaryawan ?>, <?= $totalAnalisis ?>],
backgroundColor: [
'rgba(13, 110, 253, 0.8)',
'rgba(25, 135, 84, 0.8)',
'rgba(255, 193, 7, 0.8)',
'rgba(13, 202, 240, 0.8)'
],
borderColor: [
'rgba(13, 110, 253, 1)',
'rgba(25, 135, 84, 1)',
'rgba(255, 193, 7, 1)',
'rgba(13, 202, 240, 1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
}
});

// Pie Chart
const pieCtx = document.getElementById('pieChart').getContext('2d');
new Chart(pieCtx, {
type: 'pie',
data: {
labels: ['Pengguna', 'Kriteria', 'Karyawan', 'Analisis'],
datasets: [{
data: [<?= $totalPengguna ?>, <?= $totalKriteria ?>, <?=
$totalKaryawan ?>, <?= $totalAnalisis ?>],
backgroundColor: [
'rgba(13, 110, 253, 0.8)',
'rgba(25, 135, 84, 0.8)',
'rgba(255, 193, 7, 0.8)',
'rgba(13, 202, 240, 0.8)'
],
borderColor: '#fff',
borderWidth: 2
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
});
</script>

<?php include __DIR__ . '/../../includes/footer.php'; ?>

//source-code file: /dashboard/admin/kriteia.php :


<?php
require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../includes/functions.php';

SessionManager::requireRole('Admin');
$db = Database::getInstance()->getConnection();

// Menangani berbagai aksi CRUD


$action = $_GET['action'] ?? 'list';
$id = $_GET['id'] ?? null;
$message = '';
$messageType = '';

// CRUD Operations
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
if (isset($_POST['create_kriteria'])) {
// CREATE KRITERIA
$namaKriteria = $_POST['namaKriteria'];
$bobot = $_POST['bobot'];
$jenisKriteria = $_POST['jenisKriteria'];
$status = $_POST['status'];

// Validasi total bobot tidak melebihi 1.00


$stmt = $db->prepare("SELECT SUM(bobot) as totalBobot FROM kriteria
WHERE status = 'Aktif' AND idKriteria != ?");
$stmt->execute([0]); // 0 karena ini create baru
$totalBobot = $stmt->fetch(PDO::FETCH_ASSOC)['totalBobot'] ?? 0;

if (($totalBobot + $bobot) > 1.00) {


throw new Exception("Total bobot kriteria tidak boleh melebihi
1.00. Sisa bobot yang tersedia: " . (1.00 - $totalBobot));
}

// Insert ke tabel kriteria


$stmt = $db->prepare("INSERT INTO kriteria (namaKriteria, bobot,
jenisKriteria, status, created_at) VALUES (?, ?, ?, ?, NOW())");
$stmt->execute([$namaKriteria, $bobot, $jenisKriteria, $status]);

$message = "Kriteria berhasil ditambahkan!";


$messageType = "success";

} elseif (isset($_POST['update_kriteria'])) {
// UPDATE KRITERIA
$kriteriaId = $_POST['kriteria_id'];
$namaKriteria = $_POST['namaKriteria'];
$bobot = $_POST['bobot'];
$jenisKriteria = $_POST['jenisKriteria'];
$status = $_POST['status'];

// Validasi total bobot tidak melebihi 1.00 (kecuali kriteria yang


sedang di-update)
$stmt = $db->prepare("SELECT SUM(bobot) as totalBobot FROM kriteria
WHERE status = 'Aktif' AND idKriteria != ?");
$stmt->execute([$kriteriaId]);
$totalBobot = $stmt->fetch(PDO::FETCH_ASSOC)['totalBobot'] ?? 0;

if (($totalBobot + $bobot) > 1.00) {


throw new Exception("Total bobot kriteria tidak boleh melebihi
1.00. Sisa bobot yang tersedia: " . (1.00 - $totalBobot));
}

// Update tabel kriteria


$stmt = $db->prepare("UPDATE kriteria SET namaKriteria = ?, bobot = ?,
jenisKriteria = ?, status = ? WHERE idKriteria = ?");
$stmt->execute([$namaKriteria, $bobot, $jenisKriteria, $status,
$kriteriaId]);
$message = "Kriteria berhasil diupdate!";
$messageType = "success";

} elseif (isset($_POST['delete_kriteria'])) {
// DELETE KRITERIA
$kriteriaId = $_POST['kriteria_id'];

// Cek apakah kriteria sudah digunakan dalam penilaian


$stmt = $db->prepare("SELECT COUNT(*) as jumlah FROM penilaiankaryawan
WHERE idKriteria = ?");
$stmt->execute([$kriteriaId]);
$jumlahPenilaian = $stmt->fetch(PDO::FETCH_ASSOC)['jumlah'];

if ($jumlahPenilaian > 0) {
throw new Exception("Kriteria tidak dapat dihapus karena sudah
digunakan dalam " . $jumlahPenilaian . " penilaian karyawan.");
}

// Hapus sub kriteria terlebih dahulu


$db->prepare("DELETE FROM subkriteria WHERE idKriteria = ?")-
>execute([$kriteriaId]);

// Hapus kriteria
$stmt = $db->prepare("DELETE FROM kriteria WHERE idKriteria = ?");
$stmt->execute([$kriteriaId]);

$message = "Kriteria berhasil dihapus!";


$messageType = "success";
}
} catch (Exception $e) {
$message = "Error: " . $e->getMessage();
$messageType = "danger";
}
}

// Ambil data kriteria untuk edit jika diperlukan


$editKriteria = null;
if ($action === 'edit' && $id) {
$stmt = $db->prepare("SELECT * FROM kriteria WHERE idKriteria = ?");
$stmt->execute([$id]);
$editKriteria = $stmt->fetch(PDO::FETCH_ASSOC);
}

// Ambil semua data kriteria untuk tampilan list


$kriteria = $db->query("SELECT k.*,
(SELECT COUNT(*) FROM subkriteria s WHERE
s.idKriteria = k.idKriteria) as jumlahSubKriteria,
(SELECT COUNT(*) FROM penilaiankaryawan p WHERE
p.idKriteria = k.idKriteria) as jumlahPenilaian
FROM kriteria k
ORDER BY k.bobot DESC")->fetchAll(PDO::FETCH_ASSOC);

// Hitung total bobot kriteria aktif


$totalBobotAktif = $db->query("SELECT SUM(bobot) as total FROM kriteria WHERE
status = 'Aktif'")->fetch(PDO::FETCH_ASSOC)['total'] ?? 0;
?>

<?php include __DIR__ . '/../../includes/header.php'; ?>


<?php include __DIR__ . '/../../includes/sidebar.php'; ?>
<main class="content p-4">
<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1><i class="fas fa-chart-line me-2"></i>Kelola Kriteria SPK</h1>
<div>
<?php if ($action !== 'create' && $action !== 'edit'): ?>
<a href="?action=create" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Tambah Kriteria
</a>
<?php endif; ?>
<?php if ($action === 'create' || $action === 'edit'): ?>
<a href="?" class="btn btn-secondary">
<i class="fas fa-arrow-left me-1"></i>Kembali
</a>
<?php endif; ?>
</div>
</div>

<!-- Alert Total Bobot -->


<?php if ($action === 'list'): ?>
<div class="alert alert-<?= $totalBobotAktif == 1.00 ? 'success' :
($totalBobotAktif < 1.00 ? 'warning' : 'danger') ?>" role="alert">
<i class="fas fa-info-circle me-2"></i>
<strong>Total Bobot Kriteria Aktif: <?= number_format($totalBobotAktif,
2) ?></strong>
<?php if ($totalBobotAktif == 1.00): ?>
- Bobot sudah seimbang dan siap digunakan untuk analisis SPK.
<?php elseif ($totalBobotAktif < 1.00): ?>
- Masih tersisa <?= number_format(1.00 - $totalBobotAktif, 2) ?>
bobot yang dapat dialokasikan.
<?php else: ?>
- Total bobot melebihi 1.00! Silakan sesuaikan bobot kriteria.
<?php endif; ?>
</div>
<?php endif; ?>

<!-- Alert Messages -->


<?php if ($message): ?>
<div class="alert alert-<?= $messageType ?> alert-dismissible fade show"
role="alert">
<?= $message ?>
<button type="button" class="btn-close"
data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>

<?php if ($action === 'create' || $action === 'edit'): ?>


<!-- FORM CREATE/EDIT -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-<?= $action === 'create' ? 'plus' : 'edit' ?>
me-2"></i>
<?= $action === 'create' ? 'Tambah' : 'Edit' ?> Kriteria
</h5>
</div>
<div class="card-body">
<form method="POST">
<?php if ($action === 'edit'): ?>
<input type="hidden" name="kriteria_id" value="<?=
$editKriteria['idKriteria'] ?>">
<?php endif; ?>

<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Nama Kriteria *</label>
<input type="text" class="form-control"
name="namaKriteria"
value="<?=
htmlspecialchars($editKriteria['namaKriteria'] ?? '') ?>"
placeholder="Contoh: Masa Kerja, Kemampuan
Komunikasi" required>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Bobot Kriteria *</label>
<div class="input-group">
<input type="number" class="form-control"
name="bobot"
value="<?= $editKriteria['bobot'] ??
'' ?>"
step="0.01" min="0.01" max="1.00"
placeholder="0.00" required>
<span class="input-group-text">
<small>Max: 1.00</small>
</span>
</div>
<small class="form-text text-muted">
Total bobot semua kriteria aktif harus = 1.00
<?php if ($action === 'create'): ?>
(Sisa: <?= number_format(1.00 -
$totalBobotAktif, 2) ?>)
<?php endif; ?>
</small>
</div>
</div>
</div>

<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Jenis Kriteria *</label>
<select class="form-select" name="jenisKriteria"
required>
<option value="">Pilih Jenis Kriteria</option>
<option value="Benefit" <?=
($editKriteria['jenisKriteria'] ?? '') === 'Benefit' ? 'selected' : '' ?>>
Benefit (Semakin tinggi semakin baik)
</option>
<option value="Cost" <?=
($editKriteria['jenisKriteria'] ?? '') === 'Cost' ? 'selected' : '' ?>>
Cost (Semakin rendah semakin baik)
</option>
</select>
<small class="form-text text-muted">
<strong>Benefit:</strong> Nilai tinggi lebih
diinginkan (misal: Pengalaman kerja)<br>
<strong>Cost:</strong> Nilai rendah lebih
diinginkan (misal: Jumlah pelanggaran)
</small>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Status *</label>
<select class="form-select" name="status" required>
<option value="Aktif" <?=
($editKriteria['status'] ?? 'Aktif') === 'Aktif' ? 'selected' : ''
?>>Aktif</option>
<option value="Non-Aktif" <?=
($editKriteria['status'] ?? '') === 'Non-Aktif' ? 'selected' : ''
?>>Non-Aktif</option>
</select>
<small class="form-text text-muted">
Hanya kriteria dengan status "Aktif" yang akan
digunakan dalam perhitungan SPK
</small>
</div>
</div>
</div>

<div class="mt-4">
<button type="submit" name="<?= $action === 'create' ?
'create_kriteria' : 'update_kriteria' ?>"
class="btn btn-<?= $action === 'create' ? 'primary'
: 'warning' ?>">
<i class="fas fa-save me-1"></i>
<?= $action === 'create' ? 'Simpan' : 'Update' ?>
</button>
<a href="?" class="btn btn-secondary ms-2">
<i class="fas fa-times me-1"></i>Batal
</a>
</div>
</form>
</div>
</div>

<?php else: ?>


<!-- TABEL LIST KRITERIA -->
<div class="card">
<div class="card-header">
<h5 class="mb-0"><i class="fas fa-list me-2"></i>Daftar Kriteria
SPK</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped table-bordered"
id="kriteriaTable">
<thead class="table-dark">
<tr>
<th width="5%">#</th>
<th>Nama Kriteria</th>
<th width="10%">Bobot</th>
<th width="10%">Jenis</th>
<th width="8%">Status</th>
<th width="12%">Sub Kriteria</th>
<th width="12%">Penilaian</th>
<th width="12%">Tanggal</th>
<th width="15%">Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach($kriteria as $index => $item): ?>
<tr>
<td><?= $index + 1 ?></td>
<td>
<strong><?=
htmlspecialchars($item['namaKriteria']) ?></strong>
<?php if ($item['status'] === 'Aktif'): ?>
<span class="badge bg-success ms-
2">Aktif</span>
<?php endif; ?>
</td>
<td>
<span class="badge bg-primary fs-6">
<?= number_format($item['bobot'], 2) ?>
</span>
</td>
<td>
<span class="badge bg-<?=
$item['jenisKriteria'] === 'Benefit' ? 'success' : 'warning' ?>">
<?= $item['jenisKriteria'] ?>
</span>
</td>
<td>
<span class="badge bg-<?= $item['status'] ===
'Aktif' ? 'success' : 'secondary' ?>">
<?= $item['status'] ?>
</span>
</td>
<td>
<span class="badge bg-info">
<?= $item['jumlahSubKriteria'] ?> Sub
</span>
<?php if ($item['jumlahSubKriteria'] > 0): ?>
<a href="../admin/subkriteria.php?
kriteria=<?= $item['idKriteria'] ?>"
class="btn btn-sm btn-outline-info ms-1"
title="Kelola Sub Kriteria">
<i class="fas fa-list"></i>
</a>
<?php endif; ?>
</td>
<td>
<?php if ($item['jumlahPenilaian'] > 0): ?>
<span class="badge bg-warning">
<?= $item['jumlahPenilaian'] ?> Data
</span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td><?= date('d/m/Y',
strtotime($item['created_at'])) ?></td>
<td>
<div class="btn-group" role="group">
<a href="?action=edit&id=<?=
$item['idKriteria'] ?>"
class="btn btn-sm btn-warning"
title="Edit">
<i class="fas fa-edit"></i>
</a>
<a href="../admin/subkriteria.php?
kriteria=<?= $item['idKriteria'] ?>"
class="btn btn-sm btn-info" title="Sub
Kriteria">
<i class="fas fa-list"></i>
</a>
<button type="button" class="btn btn-sm
btn-danger"
onclick="deleteKriteria(<?=
$item['idKriteria'] ?>, '<?= htmlspecialchars($item['namaKriteria']) ?>', <?=
$item['jumlahPenilaian'] ?>)"
title="Hapus"
<?= $item['jumlahPenilaian'] > 0 ?
'disabled' : '' ?>>
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
</div>
</main>

<!-- Modal Konfirmasi Hapus -->


<div class="modal fade" id="deleteModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Konfirmasi Hapus</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Apakah Anda yakin ingin menghapus kriteria <strong
id="deleteKriteriaName"></strong>?</p>
<div id="deleteWarning" class="alert alert-warning" style="display:
none;">
<i class="fas fa-exclamation-triangle me-2"></i>
Kriteria ini sudah digunakan dalam <span
id="jumlahPenilaianText"></span> penilaian dan tidak dapat dihapus!
</div>
<p class="text-danger"><small>Tindakan ini akan menghapus semua sub
kriteria yang terkait dan tidak dapat dibatalkan!</small></p>
</div>
<div class="modal-footer">
<form method="POST" id="deleteForm">
<input type="hidden" name="kriteria_id" id="deleteKriteriaId">
<button type="button" class="btn btn-secondary" data-bs-
dismiss="modal">Batal</button>
<button type="submit" name="delete_kriteria" class="btn btn-
danger" id="confirmDeleteBtn">Hapus</button>
</form>
</div>
</div>
</div>
</div>

<script>
// Delete kriteria function
function deleteKriteria(kriteriaId, kriteriaName, jumlahPenilaian) {
document.getElementById('deleteKriteriaId').value = kriteriaId;
document.getElementById('deleteKriteriaName').textContent = kriteriaName;

const deleteWarning = document.getElementById('deleteWarning');


const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');

if (jumlahPenilaian > 0) {
deleteWarning.style.display = 'block';
document.getElementById('jumlahPenilaianText').textContent =
jumlahPenilaian + ' penilaian';
confirmDeleteBtn.disabled = true;
confirmDeleteBtn.textContent = 'Tidak Dapat Dihapus';
} else {
deleteWarning.style.display = 'none';
confirmDeleteBtn.disabled = false;
confirmDeleteBtn.textContent = 'Hapus';
}

new bootstrap.Modal(document.getElementById('deleteModal')).show();
}

// Initialize DataTable if available


$(document).ready(function() {
if ($.fn.DataTable) {
$('#kriteriaTable').DataTable({
"language": {
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/Indonesian.json"
},
"pageLength": 10,
"order": [[2, "desc"]], // Sort by bobot descending
"columnDefs": [
{ "orderable": false, "targets": [8] } // Disable sorting on Action
column
]
});
}
});

// Form validation for bobot


document.addEventListener('DOMContentLoaded', function() {
const bobotInput = document.querySelector('input[name="bobot"]');
if (bobotInput) {
bobotInput.addEventListener('input', function() {
const value = parseFloat(this.value);
if (value > 1.00) {
this.setCustomValidity('Bobot tidak boleh lebih dari 1.00');
} else if (value <= 0) {
this.setCustomValidity('Bobot harus lebih dari 0');
} else {
this.setCustomValidity('');
}
});
}
});
</script>

<?php include __DIR__ . '/../../includes/footer.php'; ?>

//source-code file: /dashboard/admin/subkriteria.php :


<?php
require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../includes/functions.php';

SessionManager::requireRole('Admin');
$db = Database::getInstance()->getConnection();

// Menangani berbagai aksi CRUD


$action = $_GET['action'] ?? 'list';
$id = $_GET['id'] ?? null;
$kriteriaId = $_GET['kriteria'] ?? null;
$message = '';
$messageType = '';

// Ambil data kriteria yang dipilih


$selectedKriteria = null;
if ($kriteriaId) {
$stmt = $db->prepare("SELECT * FROM kriteria WHERE idKriteria = ?");
$stmt->execute([$kriteriaId]);
$selectedKriteria = $stmt->fetch(PDO::FETCH_ASSOC);
}

// CRUD Operations
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
if (isset($_POST['create_subkriteria'])) {
// CREATE SUBKRITERIA
$idKriteria = $_POST['idKriteria'];
$namaSubKriteria = $_POST['namaSubKriteria'];
$nilaiSkor = $_POST['nilaiSkor'];
$deskripsi = $_POST['deskripsi'];

// Validasi bahwa nilai skor belum digunakan untuk kriteria yang sama
$stmt = $db->prepare("SELECT COUNT(*) as jumlah FROM subkriteria WHERE
idKriteria = ? AND nilaiSkor = ?");
$stmt->execute([$idKriteria, $nilaiSkor]);
$jumlahSkorSama = $stmt->fetch(PDO::FETCH_ASSOC)['jumlah'];

if ($jumlahSkorSama > 0) {
throw new Exception("Nilai skor $nilaiSkor sudah digunakan untuk
kriteria ini. Silakan pilih nilai skor yang berbeda.");
}
// Insert ke tabel subkriteria
$stmt = $db->prepare("INSERT INTO subkriteria (idKriteria,
namaSubKriteria, nilaiSkor, deskripsi) VALUES (?, ?, ?, ?)");
$stmt->execute([$idKriteria, $namaSubKriteria, $nilaiSkor,
$deskripsi]);

$message = "Sub kriteria berhasil ditambahkan!";


$messageType = "success";

} elseif (isset($_POST['update_subkriteria'])) {
// UPDATE SUBKRITERIA
$subKriteriaId = $_POST['subkriteria_id'];
$idKriteria = $_POST['idKriteria'];
$namaSubKriteria = $_POST['namaSubKriteria'];
$nilaiSkor = $_POST['nilaiSkor'];
$deskripsi = $_POST['deskripsi'];

// Validasi bahwa nilai skor belum digunakan untuk kriteria yang sama
(kecuali yang sedang di-update)
$stmt = $db->prepare("SELECT COUNT(*) as jumlah FROM subkriteria WHERE
idKriteria = ? AND nilaiSkor = ? AND idSubKriteria != ?");
$stmt->execute([$idKriteria, $nilaiSkor, $subKriteriaId]);
$jumlahSkorSama = $stmt->fetch(PDO::FETCH_ASSOC)['jumlah'];

if ($jumlahSkorSama > 0) {
throw new Exception("Nilai skor $nilaiSkor sudah digunakan untuk
kriteria ini. Silakan pilih nilai skor yang berbeda.");
}

// Update tabel subkriteria


$stmt = $db->prepare("UPDATE subkriteria SET idKriteria = ?,
namaSubKriteria = ?, nilaiSkor = ?, deskripsi = ? WHERE idSubKriteria = ?");
$stmt->execute([$idKriteria, $namaSubKriteria, $nilaiSkor, $deskripsi,
$subKriteriaId]);

$message = "Sub kriteria berhasil diupdate!";


$messageType = "success";

} elseif (isset($_POST['delete_subkriteria'])) {
// DELETE SUBKRITERIA
$subKriteriaId = $_POST['subkriteria_id'];

// Cek apakah sub kriteria sudah digunakan dalam penilaian


$stmt = $db->prepare("SELECT COUNT(*) as jumlah FROM penilaiankaryawan
WHERE idSubKriteria = ?");
$stmt->execute([$subKriteriaId]);
$jumlahPenilaian = $stmt->fetch(PDO::FETCH_ASSOC)['jumlah'];

if ($jumlahPenilaian > 0) {
throw new Exception("Sub kriteria tidak dapat dihapus karena sudah
digunakan dalam " . $jumlahPenilaian . " penilaian karyawan.");
}

// Hapus sub kriteria


$stmt = $db->prepare("DELETE FROM subkriteria WHERE idSubKriteria
= ?");
$stmt->execute([$subKriteriaId]);
$message = "Sub kriteria berhasil dihapus!";
$messageType = "success";
}
} catch (Exception $e) {
$message = "Error: " . $e->getMessage();
$messageType = "danger";
}
}

// Ambil data sub kriteria untuk edit jika diperlukan


$editSubKriteria = null;
if ($action === 'edit' && $id) {
$stmt = $db->prepare("SELECT s.*, k.namaKriteria FROM subkriteria s
INNER JOIN kriteria k ON s.idKriteria = k.idKriteria
WHERE s.idSubKriteria = ?");
$stmt->execute([$id]);
$editSubKriteria = $stmt->fetch(PDO::FETCH_ASSOC);
if ($editSubKriteria) {
$kriteriaId = $editSubKriteria['idKriteria'];
$selectedKriteria = ['idKriteria' => $editSubKriteria['idKriteria'],
'namaKriteria' => $editSubKriteria['namaKriteria']];
}
}

// Ambil semua data kriteria untuk dropdown


$kriteriaList = $db->query("SELECT idKriteria, namaKriteria, status FROM kriteria
ORDER BY namaKriteria")->fetchAll(PDO::FETCH_ASSOC);

// Ambil data sub kriteria berdasarkan kriteria yang dipilih atau semua jika tidak
ada filter
$subKriteriaQuery = "SELECT s.*, k.namaKriteria, k.status as statusKriteria,
(SELECT COUNT(*) FROM penilaiankaryawan p WHERE
p.idSubKriteria = s.idSubKriteria) as jumlahPenilaian
FROM subkriteria s
INNER JOIN kriteria k ON s.idKriteria = k.idKriteria";

if ($kriteriaId) {
$subKriteriaQuery .= " WHERE s.idKriteria = ?";
$stmt = $db->prepare($subKriteriaQuery . " ORDER BY s.nilaiSkor ASC");
$stmt->execute([$kriteriaId]);
} else {
$stmt = $db->prepare($subKriteriaQuery . " ORDER BY k.namaKriteria, s.nilaiSkor
ASC");
$stmt->execute();
}
$subKriteria = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Hitung statistik sub kriteria jika ada kriteria yang dipilih


$statistik = null;
if ($kriteriaId) {
$stmt = $db->prepare("SELECT
COUNT(*) as totalSubKriteria,
MIN(nilaiSkor) as minSkor,
MAX(nilaiSkor) as maxSkor,
AVG(nilaiSkor) as avgSkor
FROM subkriteria WHERE idKriteria = ?");
$stmt->execute([$kriteriaId]);
$statistik = $stmt->fetch(PDO::FETCH_ASSOC);
}
?>

<?php include __DIR__ . '/../../includes/header.php'; ?>


<?php include __DIR__ . '/../../includes/sidebar.php'; ?>

<main class="content p-4">


<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>
<i class="fas fa-sitemap me-2"></i>Kelola Sub Kriteria SPK
<?php if ($selectedKriteria): ?>
<small class="text-muted">- <?=
htmlspecialchars($selectedKriteria['namaKriteria']) ?></small>
<?php endif; ?>
</h1>
<div>
<?php if ($action !== 'create' && $action !== 'edit'): ?>
<a href="?action=create<?= $kriteriaId ? '&kriteria=' . $kriteriaId
: '' ?>" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Tambah Sub Kriteria
</a>
<?php endif; ?>
<?php if ($action === 'create' || $action === 'edit'): ?>
<a href="?<?= $kriteriaId ? 'kriteria=' . $kriteriaId : '' ?>"
class="btn btn-secondary">
<i class="fas fa-arrow-left me-1"></i>Kembali
</a>
<?php endif; ?>
<a href="kriteria.php" class="btn btn-outline-secondary">
<i class="fas fa-chart-line me-1"></i>Kelola Kriteria
</a>
</div>
</div>

<!-- Filter Kriteria -->


<?php if ($action === 'list'): ?>
<div class="card mb-4">
<div class="card-body">
<div class="row align-items-end">
<div class="col-md-6">
<label class="form-label">Filter berdasarkan
Kriteria:</label>
<select class="form-select" id="filterKriteria"
onchange="filterByKriteria()">
<option value="">-- Semua Kriteria --</option>
<?php foreach($kriteriaList as $kriteria): ?>
<option value="<?= $kriteria['idKriteria'] ?>"
<?= $kriteriaId == $kriteria['idKriteria'] ?
'selected' : '' ?>>
<?= htmlspecialchars($kriteria['namaKriteria']) ?>
<?php if ($kriteria['status'] === 'Non-Aktif'): ?>
(Non-Aktif)
<?php endif; ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<?php if ($selectedKriteria && $statistik): ?>
<div class="row">
<div class="col-6">
<small class="text-muted">Total Sub
Kriteria:</small>
<div class="h5 mb-0"><?=
$statistik['totalSubKriteria'] ?></div>
</div>
<div class="col-6">
<small class="text-muted">Range Skor:</small>
<div class="h5 mb-0"><?= $statistik['minSkor'] ?> -
<?= $statistik['maxSkor'] ?></div>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php endif; ?>

<!-- Alert Messages -->


<?php if ($message): ?>
<div class="alert alert-<?= $messageType ?> alert-dismissible fade show"
role="alert">
<?= $message ?>
<button type="button" class="btn-close"
data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>

<?php if ($action === 'create' || $action === 'edit'): ?>


<!-- FORM CREATE/EDIT -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-<?= $action === 'create' ? 'plus' : 'edit' ?>
me-2"></i>
<?= $action === 'create' ? 'Tambah' : 'Edit' ?> Sub Kriteria
</h5>
</div>
<div class="card-body">
<form method="POST">
<?php if ($action === 'edit'): ?>
<input type="hidden" name="subkriteria_id" value="<?=
$editSubKriteria['idSubKriteria'] ?>">
<?php endif; ?>

<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Kriteria Induk *</label>
<select class="form-select" name="idKriteria"
required>
<option value="">Pilih Kriteria</option>
<?php foreach($kriteriaList as $kriteria): ?>
<option value="<?= $kriteria['idKriteria'] ?>"
<?= ($editSubKriteria['idKriteria'] ??
$kriteriaId) == $kriteria['idKriteria'] ? 'selected' : '' ?>>
<?=
htmlspecialchars($kriteria['namaKriteria']) ?>
<?php if ($kriteria['status'] === 'Non-
Aktif'): ?>
(Non-Aktif)
<?php endif; ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Nilai Skor *</label>
<input type="number" class="form-control"
name="nilaiSkor"
value="<?= $editSubKriteria['nilaiSkor'] ??
'' ?>"
min="1" max="10"
placeholder="1-10" required>
<small class="form-text text-muted">
Nilai skor harus unik untuk setiap kriteria
(rentang 1-10)
</small>
</div>
</div>
</div>

<div class="mb-3">
<label class="form-label">Nama Sub Kriteria *</label>
<input type="text" class="form-control"
name="namaSubKriteria"
value="<?=
htmlspecialchars($editSubKriteria['namaSubKriteria'] ?? '') ?>"
placeholder="Contoh: Sangat Baik, Baik, Cukup,
Kurang" required>
</div>

<div class="mb-3">
<label class="form-label">Deskripsi</label>
<textarea class="form-control" name="deskripsi" rows="3"
placeholder="Deskripsi detail mengenai sub
kriteria ini..."><?= htmlspecialchars($editSubKriteria['deskripsi'] ?? '')
?></textarea>
<small class="form-text text-muted">
Berikan penjelasan yang jelas agar memudahkan proses
penilaian
</small>
</div>

<div class="mt-4">
<button type="submit" name="<?= $action === 'create' ?
'create_subkriteria' : 'update_subkriteria' ?>"
class="btn btn-<?= $action === 'create' ? 'primary'
: 'warning' ?>">
<i class="fas fa-save me-1"></i>
<?= $action === 'create' ? 'Simpan' : 'Update' ?>
</button>
<a href="?<?= $kriteriaId ? 'kriteria=' . $kriteriaId :
'' ?>" class="btn btn-secondary ms-2">
<i class="fas fa-times me-1"></i>Batal
</a>
</div>
</form>
</div>
</div>

<?php else: ?>


<!-- TABEL LIST SUB KRITERIA -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-list me-2"></i>Daftar Sub Kriteria SPK
<?php if ($selectedKriteria): ?>
<span class="badge bg-primary ms-2"><?= count($subKriteria)
?> item</span>
<?php endif; ?>
</h5>
</div>
<div class="card-body">
<?php if (empty($subKriteria)): ?>
<div class="text-center py-5">
<i class="fas fa-inbox fa-3x text-muted mb-3"></i>
<h5 class="text-muted">Belum ada data sub kriteria</h5>
<p class="text-muted">
<?php if ($kriteriaId): ?>
Belum ada sub kriteria untuk kriteria "<?=
htmlspecialchars($selectedKriteria['namaKriteria']) ?>"
<?php else: ?>
Silakan tambah sub kriteria terlebih dahulu atau pilih
kriteria untuk melihat data
<?php endif; ?>
</p>
<a href="?action=create<?= $kriteriaId ? '&kriteria=' .
$kriteriaId : '' ?>" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Tambah Sub Kriteria
</a>
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-striped table-bordered"
id="subKriteriaTable">
<thead class="table-dark">
<tr>
<th width="5%">#</th>
<?php if (!$kriteriaId): ?>
<th>Kriteria</th>
<?php endif; ?>
<th>Nama Sub Kriteria</th>
<th width="10%">Skor</th>
<th>Deskripsi</th>
<th width="10%">Penilaian</th>
<th width="15%">Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach($subKriteria as $index => $item): ?>
<tr>
<td><?= $index + 1 ?></td>
<?php if (!$kriteriaId): ?>
<td>
<strong><?=
htmlspecialchars($item['namaKriteria']) ?></strong>
<?php if ($item['statusKriteria'] === 'Non-
Aktif'): ?>
<span class="badge bg-secondary ms-1">Non-
Aktif</span>
<?php endif; ?>
</td>
<?php endif; ?>
<td>
<strong><?=
htmlspecialchars($item['namaSubKriteria']) ?></strong>
</td>
<td>
<span class="badge bg-primary fs-6">
<?= $item['nilaiSkor'] ?>
</span>
</td>
<td>
<?php if ($item['deskripsi']): ?>
<span title="<?=
htmlspecialchars($item['deskripsi']) ?>">
<?=
htmlspecialchars(substr($item['deskripsi'], 0, 50)) ?>
<?= strlen($item['deskripsi']) > 50 ?
'...' : '' ?>
</span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td>
<?php if ($item['jumlahPenilaian'] > 0): ?>
<span class="badge bg-warning">
<?= $item['jumlahPenilaian'] ?> Data
</span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td>
<div class="btn-group" role="group">
<a href="?action=edit&id=<?=
$item['idSubKriteria'] ?>"
class="btn btn-sm btn-warning"
title="Edit">
<i class="fas fa-edit"></i>
</a>
<button type="button" class="btn btn-sm
btn-danger"
onclick="deleteSubKriteria(<?=
$item['idSubKriteria'] ?>, '<?= htmlspecialchars($item['namaSubKriteria']) ?>', <?=
$item['jumlahPenilaian'] ?>)"
title="Hapus"
<?= $item['jumlahPenilaian'] > 0 ?
'disabled' : '' ?>>
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
</main>

<!-- Modal Konfirmasi Hapus -->


<div class="modal fade" id="deleteModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Konfirmasi Hapus</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Apakah Anda yakin ingin menghapus sub kriteria <strong
id="deleteSubKriteriaName"></strong>?</p>
<div id="deleteWarning" class="alert alert-warning" style="display:
none;">
<i class="fas fa-exclamation-triangle me-2"></i>
Sub kriteria ini sudah digunakan dalam <span
id="jumlahPenilaianText"></span> penilaian dan tidak dapat dihapus!
</div>
<p class="text-danger"><small>Tindakan ini tidak dapat dibatalkan!
</small></p>
</div>
<div class="modal-footer">
<form method="POST" id="deleteForm">
<input type="hidden" name="subkriteria_id"
id="deleteSubKriteriaId">
<button type="button" class="btn btn-secondary" data-bs-
dismiss="modal">Batal</button>
<button type="submit" name="delete_subkriteria" class="btn btn-
danger" id="confirmDeleteBtn">Hapus</button>
</form>
</div>
</div>
</div>
</div>

<script>
// Filter by kriteria function
function filterByKriteria() {
const kriteriaId = document.getElementById('filterKriteria').value;
if (kriteriaId) {
window.location.href = '?kriteria=' + kriteriaId;
} else {
window.location.href = '?';
}
}

// Delete sub kriteria function


function deleteSubKriteria(subKriteriaId, subKriteriaName, jumlahPenilaian) {
document.getElementById('deleteSubKriteriaId').value = subKriteriaId;
document.getElementById('deleteSubKriteriaName').textContent = subKriteriaName;

const deleteWarning = document.getElementById('deleteWarning');


const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');

if (jumlahPenilaian > 0) {
deleteWarning.style.display = 'block';
document.getElementById('jumlahPenilaianText').textContent =
jumlahPenilaian + ' penilaian';
confirmDeleteBtn.disabled = true;
confirmDeleteBtn.textContent = 'Tidak Dapat Dihapus';
} else {
deleteWarning.style.display = 'none';
confirmDeleteBtn.disabled = false;
confirmDeleteBtn.textContent = 'Hapus';
}

new bootstrap.Modal(document.getElementById('deleteModal')).show();
}

// Initialize DataTable if available


$(document).ready(function() {
if ($.fn.DataTable) {
$('#subKriteriaTable').DataTable({
"language": {
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/Indonesian.json"
},
"pageLength": 10,
"order": [[<?= !$kriteriaId ? '2' : '1' ?>, "asc"]], // Sort by nama
sub kriteria ascending
"columnDefs": [
{ "orderable": false, "targets": [-1] } // Disable sorting on
Action column
]
});
}
});

// Form validation for nilai skor


document.addEventListener('DOMContentLoaded', function() {
const skorInput = document.querySelector('input[name="nilaiSkor"]');
if (skorInput) {
skorInput.addEventListener('input', function() {
const value = parseInt(this.value);
if (value > 10) {
this.setCustomValidity('Nilai skor tidak boleh lebih dari 10');
} else if (value < 1) {
this.setCustomValidity('Nilai skor harus minimal 1');
} else {
this.setCustomValidity('');
}
});
}
});
</script>
<?php include __DIR__ . '/../../includes/footer.php'; ?>

//source-code file: /dashboard/admin/users.php : <?php


require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../includes/functions.php';

SessionManager::requireRole('Admin');
$db = Database::getInstance()->getConnection();

// Menangani berbagai aksi CRUD


$action = $_GET['action'] ?? 'list';
$id = $_GET['id'] ?? null;
$message = '';
$messageType = '';

// CRUD Operations
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
if (isset($_POST['create_user'])) {
// CREATE USER
$username = $_POST['username'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$role = $_POST['role'];
$status = $_POST['status'];

// Insert ke tabel users


$stmt = $db->prepare("INSERT INTO users (username, password, role,
status, created_at, updated_at) VALUES (?, ?, ?, ?, NOW(), NOW())");
$stmt->execute([$username, $password, $role, $status]);
$userId = $db->lastInsertId();

// Insert ke tabel role-specific berdasarkan role


switch ($role) {
case 'Admin':
$stmt = $db->prepare("INSERT INTO admin (idUser, namaAdmin,
noHP) VALUES (?, ?, ?)");
$stmt->execute([$userId, $_POST['nama'], $_POST['noHP'] ??
null]);
break;
case 'Manager':
$stmt = $db->prepare("INSERT INTO managerfbs (idUser,
namaManager, noHP) VALUES (?, ?, ?)");
$stmt->execute([$userId, $_POST['nama'], $_POST['noHP'] ??
null]);
break;
case 'Karyawan':
// Perbaiki query INSERT - pastikan jumlah kolom sesuai dengan
nilai
$stmt = $db->prepare("INSERT INTO karyawanfbs (idUser,
namaKaryawan, jenisKelamin, tanggalLahir, noHP, jabatan, pendidikan, tanggalMasuk,
Alamat, statusKerja) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([
$userId,
$_POST['nama'],
$_POST['jenisKelamin'] ?? 'Laki-laki',
$_POST['tanggalLahir'] ?? null,
$_POST['noHP'] ?? null,
$_POST['jabatan'] ?? 'Waiter', // Ambil hanya 1 nilai
$_POST['pendidikan'] ?? 'SMK/SMA', // Ambil hanya 1 nilai
$_POST['tanggalMasuk'] ?? date('Y-m-d'),
$_POST['Alamat'] ?? null, // Tambahkan null check
$_POST['statusKerja'] ?? 'Aktif'
]);
break;
}

$message = "User berhasil ditambahkan!";


$messageType = "success";

} elseif (isset($_POST['update_user'])) {
// UPDATE USER
$userId = $_POST['user_id'];
$username = $_POST['username'];
$role = $_POST['role'];
$status = $_POST['status'];

// Update tabel users


if (!empty($_POST['password'])) {
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
$stmt = $db->prepare("UPDATE users SET username = ?, password = ?,
role = ?, status = ?, updated_at = NOW() WHERE idUser = ?");
$stmt->execute([$username, $password, $role, $status, $userId]);
} else {
$stmt = $db->prepare("UPDATE users SET username = ?, role = ?,
status = ?, updated_at = NOW() WHERE idUser = ?");
$stmt->execute([$username, $role, $status, $userId]);
}

// Update tabel role-specific


switch ($role) {
case 'Admin':
$stmt = $db->prepare("UPDATE admin SET namaAdmin = ?, noHP = ?
WHERE idUser = ?");
$stmt->execute([$_POST['nama'], $_POST['noHP'] ?? null,
$userId]);
break;
case 'Manager':
$stmt = $db->prepare("UPDATE managerfbs SET namaManager = ?,
noHP = ? WHERE idUser = ?");
$stmt->execute([$_POST['nama'], $_POST['noHP'] ?? null,
$userId]);
break;
case 'Karyawan':
// Sesuaikan dengan struktur tabel karyawanfbs yang sebenarnya
$stmt = $db->prepare("UPDATE karyawanfbs SET namaKaryawan = ?,
jenisKelamin = ?, tanggalLahir = ?, noHP = ?, jabatan = ?, pendidikan = ?,
tanggalMasuk = ?, Alamat = ?, statusKerja = ? WHERE idUser = ?");
$stmt->execute([
$_POST['nama'],
$_POST['jenisKelamin'] ?? 'Laki-laki',
$_POST['tanggalLahir'] ?? null,
$_POST['noHP'] ?? null,
$_POST['jabatan'] ?? 'Waiter', // Ambil dari form, bukan
hardcoded
$_POST['pendidikan'] ?? 'SMK/SMA',
$_POST['tanggalMasuk'] ?? date('Y-m-d'),
$_POST['Alamat'] ?? null,
$_POST['statusKerja'] ?? 'Aktif',
$userId
]);
break;
}

$message = "User berhasil diupdate!";


$messageType = "success";

} elseif (isset($_POST['delete_user'])) {
// DELETE USER
$userId = $_POST['user_id'];

// Hapus dari tabel role-specific terlebih dahulu


$db->prepare("DELETE FROM admin WHERE idUser = ?")->execute([$userId]);
$db->prepare("DELETE FROM managerfbs WHERE idUser = ?")-
>execute([$userId]);
$db->prepare("DELETE FROM karyawanfbs WHERE idUser = ?")-
>execute([$userId]);

// Hapus dari tabel users


$stmt = $db->prepare("DELETE FROM users WHERE idUser = ?");
$stmt->execute([$userId]);

$message = "User berhasil dihapus!";


$messageType = "success";
}
} catch (Exception $e) {
$message = "Error: " . $e->getMessage();
$messageType = "danger";
}
}

// Ambil data user untuk edit jika diperlukan


$editUser = null;
if ($action === 'edit' && $id) {
$stmt = $db->prepare("SELECT u.*,
a.namaAdmin, a.noHP as adminHP,
m.namaManager, m.noHP as managerHP,
k.namaKaryawan, k.jenisKelamin, k.tanggalLahir, k.noHP
as karyawanHP,
k.jabatan, k.pendidikan, k.tanggalMasuk, k.Alamat,
k.statusKerja as karyawanStatus
FROM users u
LEFT JOIN admin a ON u.idUser = a.idUser
LEFT JOIN managerfbs m ON u.idUser = m.idUser
LEFT JOIN karyawanfbs k ON u.idUser = k.idUser
WHERE u.idUser = ?");
$stmt->execute([$id]);
$editUser = $stmt->fetch(PDO::FETCH_ASSOC);
}

// Ambil semua data users untuk tampilan list


$users = $db->query("SELECT u.idUser, u.username, u.role, u.status, u.created_at,
u.updated_at,
a.namaAdmin, a.noHP as adminHP,
m.namaManager, m.noHP as managerHP,
k.namaKaryawan, k.jenisKelamin, k.tanggalLahir, k.noHP
as karyawanHP,
k.jabatan, k.pendidikan, k.tanggalMasuk, k.Alamat,
k.statusKerja as karyawanStatus
FROM users u
LEFT JOIN admin a ON u.idUser = a.idUser
LEFT JOIN managerfbs m ON u.idUser = m.idUser
LEFT JOIN karyawanfbs k ON u.idUser = k.idUser
ORDER BY u.username")->fetchAll(PDO::FETCH_ASSOC);
?>

<?php include __DIR__ . '/../../includes/header.php'; ?>


<?php include __DIR__ . '/../../includes/sidebar.php'; ?>

<main class="content p-4">


<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1><i class="fas fa-users me-2"></i>Kelola Pengguna</h1>
<div>
<?php if ($action !== 'create' && $action !== 'edit'): ?>
<a href="?action=create" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Tambah Pengguna
</a>
<?php endif; ?>
<?php if ($action === 'create' || $action === 'edit'): ?>
<a href="?" class="btn btn-secondary">
<i class="fas fa-arrow-left me-1"></i>Kembali
</a>
<?php endif; ?>
</div>
</div>

<!-- Alert Messages -->


<?php if ($message): ?>
<div class="alert alert-<?= $messageType ?> alert-dismissible fade show"
role="alert">
<?= $message ?>
<button type="button" class="btn-close"
data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>

<?php if ($action === 'create' || $action === 'edit'): ?>


<!-- FORM CREATE/EDIT -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-<?= $action === 'create' ? 'plus' : 'edit' ?>
me-2"></i>
<?= $action === 'create' ? 'Tambah' : 'Edit' ?> Pengguna
</h5>
</div>
<div class="card-body">
<form method="POST">
<?php if ($action === 'edit'): ?>
<input type="hidden" name="user_id" value="<?=
$editUser['idUser'] ?>">
<?php endif; ?>

<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Username *</label>
<input type="text" class="form-control"
name="username"
value="<?= $editUser['username'] ?? '' ?>"
required>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Password <?= $action ===
'edit' ? '(kosongkan jika tidak diubah)' : '*' ?></label>
<input type="password" class="form-control"
name="password"
<?= $action === 'create' ? 'required' : '' ?
>>
</div>
</div>
</div>

<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Role *</label>
<select class="form-select" name="role" required
onchange="toggleRoleFields(this.value)">
<option value="">Pilih Role</option>
<option value="Admin" <?= ($editUser['role'] ??
'') === 'Admin' ? 'selected' : '' ?>>Admin</option>
<option value="Manager" <?=
($editUser['role'] ?? '') === 'Manager' ? 'selected' : '' ?>>Manager</option>
<option value="Karyawan" <?= ($editUser['role']
?? '') === 'Karyawan' ? 'selected' : '' ?>>Karyawan</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Status *</label>
<select class="form-select" name="status" required>
<option value="Aktif" <?=
($editUser['status'] ?? '') === 'Aktif' ? 'selected' : '' ?>>Aktif</option>
<option value="Non-Aktif" <?=
($editUser['status'] ?? '') === 'Non-Aktif' ? 'selected' : '' ?>>Non-Aktif</option>
</select>
</div>
</div>
</div>

<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Nama *</label>
<input type="text" class="form-control" name="nama"

value="<?= $editUser['namaAdmin'] ??
$editUser['namaManager'] ?? $editUser['namaKaryawan'] ?? '' ?>" required>
</div>
</div>
<div class="col-md-6" id="noHP-field">
<div class="mb-3">
<label class="form-label">No. HP</label>
<input type="text" class="form-control" name="noHP"

value="<?= $editUser['adminHP'] ??
$editUser['managerHP'] ?? $editUser['karyawanHP'] ?? '' ?>">
</div>
</div>
</div>

<!-- Fields khusus untuk Karyawan -->


<div id="karyawan-fields" style="display: none;">
<hr>
<h6><i class="fas fa-user-tie me-2"></i>Informasi
Karyawan</h6>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Jenis Kelamin</label>
<select class="form-select"
name="jenisKelamin">
<option value="Laki-laki" <?=
($editUser['jenisKelamin'] ?? '') === 'Laki-laki' ? 'selected' : ''
?>>Laki-laki</option>
<option value="Perempuan" <?=
($editUser['jenisKelamin'] ?? '') === 'Perempuan' ? 'selected' : ''
?>>Perempuan</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Tanggal Lahir</label>
<input type="date" class="form-control"
name="tanggalLahir"
value="<?= $editUser['tanggalLahir'] ??
'' ?>">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Jabatan</label>
<select class="form-select" name="jabatan">
<option value="Waiter" <?=
($editUser['jabatan'] ?? '') === 'Waiter' ? 'selected' : '' ?>>Waiter</option>
<option value="Waitress" <?=
($editUser['jabatan'] ?? '') === 'Waitress' ? 'selected' : '' ?>>Waitress</option>
<option value="Captain" <?=
($editUser['jabatan'] ?? '') === 'Captain' ? 'selected' : '' ?>>Captain</option>
<option value="Assistant Restaurant
Manager" <?= ($editUser['jabatan'] ?? '') === 'Assistant Restaurant Manager' ?
'selected' : '' ?>>Assistant Restaurant Manager</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Tanggal Masuk
Kerja</label>
<input type="date" class="form-control"
name="tanggalMasuk"
value="<?= $editUser['tanggalMasuk'] ??
date('Y-m-d') ?>">
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Pendidikan</label>
<select class="form-select" name="pendidikan">
<option value="SMK/SMA" <?=
($editUser['pendidikan'] ?? '') === 'SMK/SMA' ? 'selected' : '' ?>>SMK/SMA</option>
<option value="Diploma 1" <?=
($editUser['pendidikan'] ?? '') === 'Diploma 1' ? 'selected' : '' ?>>Diploma
1</option>
<option value="Diploma 3" <?=
($editUser['pendidikan'] ?? '') === 'Diploma 3' ? 'selected' : '' ?>>Diploma
3</option>
<option value="Strata 1" <?=
($editUser['pendidikan'] ?? '') === 'Strata 1' ? 'selected' : '' ?>>Strata
1</option>
<option value="Strata 2" <?=
($editUser['pendidikan'] ?? '') === 'Strata 2' ? 'selected' : '' ?>>Strata
2</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Alamat *</label>
<textarea class="form-control" name="Alamat"
rows="2" required><?= $editUser['Alamat'] ?? '' ?></textarea>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Status Kerja</label>
<select class="form-select" name="statusKerja">
<option value="Aktif" <?=
($editUser['karyawanStatus'] ?? '') === 'Aktif' ? 'selected' : '' ?>>Aktif</option>
<option value="Cuti" <?=
($editUser['karyawanStatus'] ?? '') === 'Cuti' ? 'selected' : '' ?>>Cuti</option>
<option value="Non-Aktif" <?=
($editUser['karyawanStatus'] ?? '') === 'Non-Aktif' ? 'selected' : '' ?>>Non-
Aktif</option>
</select>
</div>
</div>
</div>
</div>
<div class="mt-4">
<button type="submit" name="<?= $action === 'create' ?
'create_user' : 'update_user' ?>"
class="btn btn-<?= $action === 'create' ? 'primary'
: 'warning' ?>">
<i class="fas fa-save me-1"></i>
<?= $action === 'create' ? 'Simpan' : 'Update' ?>
</button>
<a href="?" class="btn btn-secondary ms-2">
<i class="fas fa-times me-1"></i>Batal
</a>
</div>
</form>
</div>
</div>

<?php else: ?>


<!-- TABEL LIST USERS -->
<div class="card">
<div class="card-header">
<h5 class="mb-0"><i class="fas fa-list me-2"></i>Daftar
Pengguna</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped table-bordered"
id="usersTable">
<thead class="table-dark">
<tr>
<th width="5%">#</th>
<th>Username</th>
<th>Nama</th>
<th>Role</th>
<th>Status</th>
<th>Info Tambahan</th>
<th>Tanggal Dibuat</th>
<th width="15%">Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach($users as $index => $user): ?>
<tr>
<td><?= $index + 1 ?></td>
<td><?= htmlspecialchars($user['username']) ?></td>
<td><?= htmlspecialchars($user['namaAdmin'] ??
$user['namaManager'] ?? $user['namaKaryawan'] ?? '-') ?></td>
<td>
<span class="badge bg-<?= $user['role'] ===
'Admin' ? 'danger' : ($user['role'] === 'Manager' ? 'warning' : 'info') ?>">
<?= htmlspecialchars($user['role']) ?>
</span>
</td>
<td>
<span class="badge bg-<?= $user['status'] ===
'Aktif' ? 'success' : 'secondary' ?>">
<?= htmlspecialchars($user['status']) ?>
</span>
</td>
<td>
<?php if ($user['role'] === 'Karyawan'): ?>
<small>
<?= $user['jenisKelamin'] ? 'JK: ' .
$user['jenisKelamin'] : '' ?>
<?= $user['jabatan'] ? ', Jabatan: ' .
$user['jabatan'] : '' ?>
<?= $user['tanggalMasuk'] ? ', Masuk: '
. date('d/m/Y', strtotime($user['tanggalMasuk'])) : '' ?>
</small>
<?php else: ?>
<small><?= $user['adminHP'] ??
$user['managerHP'] ?? $user['karyawanHP'] ?? '-' ?></small>
<?php endif; ?>
</td>
<td><?= date('d/m/Y',
strtotime($user['created_at'])) ?></td>
<td>
<div class="btn-group" role="group">
<a href="?action=edit&id=<?=
$user['idUser'] ?>"
class="btn btn-sm btn-warning"
title="Edit">
<i class="fas fa-edit"></i>
</a>
<button type="button" class="btn btn-sm
btn-danger"
onclick="deleteUser(<?=
$user['idUser'] ?>, '<?= htmlspecialchars($user['username']) ?>')"
title="Hapus">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
</div>
</main>

<!-- Modal Konfirmasi Hapus -->


<div class="modal fade" id="deleteModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Konfirmasi Hapus</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Apakah Anda yakin ingin menghapus pengguna <strong
id="deleteUsername"></strong>?</p>
<p class="text-danger"><small>Tindakan ini tidak dapat dibatalkan!
</small></p>
</div>
<div class="modal-footer">
<form method="POST" id="deleteForm">
<input type="hidden" name="user_id" id="deleteUserId">
<button type="button" class="btn btn-secondary" data-bs-
dismiss="modal">Batal</button>
<button type="submit" name="delete_user" class="btn btn-
danger">Hapus</button>
</form>
</div>
</div>
</div>
</div>

<script>
// Toggle role-specific fields
function toggleRoleFields(role) {
const karyawanFields = document.getElementById('karyawan-fields');
const noHPField = document.getElementById('noHP-field');

if (role === 'Karyawan') {


karyawanFields.style.display = 'block';
noHPField.style.display = 'block'; // Karyawan juga punya noHP
} else {
karyawanFields.style.display = 'none';
noHPField.style.display = 'block';
}
}

// Initialize role fields on page load


document.addEventListener('DOMContentLoaded', function() {
const roleSelect = document.querySelector('select[name="role"]');
if (roleSelect && roleSelect.value) {
toggleRoleFields(roleSelect.value);
}
});

// Delete user function


function deleteUser(userId, username) {
document.getElementById('deleteUserId').value = userId;
document.getElementById('deleteUsername').textContent = username;
new bootstrap.Modal(document.getElementById('deleteModal')).show();
}

// Initialize DataTable if available


$(document).ready(function() {
if ($.fn.DataTable) {
$('#usersTable').DataTable({
"language": {
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/Indonesian.json"
},
"pageLength": 10,
"order": [[1, "asc"]]
});
}
});
</script>

<?php include __DIR__ . '/../../includes/footer.php'; ?>


//source-code file: /dashboard/admin/penilaian.php :
<?php
require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../includes/functions.php';

SessionManager::requireRole('Admin');
$db = Database::getInstance()->getConnection();

// Menangani berbagai aksi CRUD


$action = $_GET['action'] ?? 'list';
$id = $_GET['id'] ?? null;
$message = '';
$messageType = '';

// CRUD Operations
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
if (isset($_POST['create_penilaian'])) {
// CREATE PENILAIAN
$idKaryawan = $_POST['idKaryawan'];
$tanggalPenilaian = $_POST['tanggalPenilaian'];
$catatan = $_POST['catatan'] ?? '';
$idPenilai = $_SESSION['user_id'];

// Validasi: cek apakah sudah ada penilaian untuk karyawan ini pada
tanggal yang sama
$stmt = $db->prepare("SELECT COUNT(*) as jumlah FROM penilaiankaryawan
WHERE idKaryawan = ? AND tanggalPenilaian = ?");
$stmt->execute([$idKaryawan, $tanggalPenilaian]);
$existingCount = $stmt->fetch(PDO::FETCH_ASSOC)['jumlah'];

if ($existingCount > 0) {
throw new Exception("Penilaian untuk karyawan ini pada tanggal
tersebut sudah ada. Silakan edit penilaian yang sudah ada atau pilih tanggal
lain.");
}

$db->beginTransaction();

// Simpan penilaian untuk setiap kriteria


$kriteria = $_POST['kriteria'] ?? [];
$insertedCount = 0;

foreach ($kriteria as $idKriteria => $idSubKriteria) {


if (!empty($idSubKriteria)) {
$stmt = $db->prepare("INSERT INTO penilaiankaryawan
(idKaryawan, idKriteria, idSubKriteria,
tanggalPenilaian, idPenilai, catatan)
VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$idKaryawan, $idKriteria, $idSubKriteria,
$tanggalPenilaian, $idPenilai, $catatan]);
$insertedCount++;
}
}

if ($insertedCount == 0) {
throw new Exception("Tidak ada kriteria yang dinilai. Minimal satu
kriteria harus diisi.");
}

$db->commit();
$message = "Penilaian berhasil disimpan untuk {$insertedCount}
kriteria!";
$messageType = "success";

// Log activity
SPKHelper::logActivity($db, $_SESSION['user_id'], 'CREATE_PENILAIAN',
"Menambah penilaian karyawan ID: {$idKaryawan}
untuk {$insertedCount} kriteria");

} elseif (isset($_POST['update_penilaian'])) {
// UPDATE PENILAIAN
$idKaryawan = $_POST['idKaryawan'];
$tanggalPenilaian = $_POST['tanggalPenilaian'];
$catatan = $_POST['catatan'] ?? '';
$idPenilai = $_SESSION['user_id'];

$db->beginTransaction();

// Hapus penilaian lama untuk karyawan dan tanggal ini


$stmt = $db->prepare("DELETE FROM penilaiankaryawan
WHERE idKaryawan = ? AND tanggalPenilaian = ?");
$stmt->execute([$idKaryawan, $tanggalPenilaian]);

// Simpan penilaian baru


$kriteria = $_POST['kriteria'] ?? [];
$insertedCount = 0;

foreach ($kriteria as $idKriteria => $idSubKriteria) {


if (!empty($idSubKriteria)) {
$stmt = $db->prepare("INSERT INTO penilaiankaryawan
(idKaryawan, idKriteria, idSubKriteria,
tanggalPenilaian, idPenilai, catatan)
VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$idKaryawan, $idKriteria, $idSubKriteria,
$tanggalPenilaian, $idPenilai, $catatan]);
$insertedCount++;
}
}

if ($insertedCount == 0) {
throw new Exception("Tidak ada kriteria yang dinilai. Minimal satu
kriteria harus diisi.");
}

$db->commit();
$message = "Penilaian berhasil diupdate untuk {$insertedCount}
kriteria!";
$messageType = "success";

} elseif (isset($_POST['delete_penilaian'])) {
// DELETE PENILAIAN
$idKaryawan = $_POST['idKaryawan'];
$tanggalPenilaian = $_POST['tanggalPenilaian'];

$stmt = $db->prepare("DELETE FROM penilaiankaryawan


WHERE idKaryawan = ? AND tanggalPenilaian = ?");
$stmt->execute([$idKaryawan, $tanggalPenilaian]);

$deletedCount = $stmt->rowCount();
$message = "Penilaian berhasil dihapus ({$deletedCount} kriteria)!";
$messageType = "success";
}
} catch (Exception $e) {
if ($db->inTransaction()) {
$db->rollback();
}
$message = "Error: " . $e->getMessage();
$messageType = "danger";
}
}

// Ambil data untuk form


$karyawanAktif = $db->query("SELECT idKaryawan, namaKaryawan, jabatan
FROM karyawanfbs WHERE statusKerja = 'Aktif'
ORDER BY namaKaryawan")->fetchAll(PDO::FETCH_ASSOC);

$kriteriaAktif = $db->query("SELECT idKriteria, namaKriteria, bobot, jenisKriteria


FROM kriteria WHERE status = 'Aktif'
ORDER BY bobot DESC")->fetchAll(PDO::FETCH_ASSOC);

// Ambil data penilaian untuk edit jika diperlukan


$editPenilaian = null;
$editSubKriteria = [];
if ($action === 'edit' && isset($_GET['karyawan']) && isset($_GET['tanggal'])) {
$idKaryawan = $_GET['karyawan'];
$tanggalPenilaian = $_GET['tanggal'];

$stmt = $db->prepare("SELECT p.*, k.namaKaryawan, kr.namaKriteria,


sk.namaSubKriteria
FROM penilaiankaryawan p
JOIN karyawanfbs k ON p.idKaryawan = k.idKaryawan
JOIN kriteria kr ON p.idKriteria = kr.idKriteria
JOIN subkriteria sk ON p.idSubKriteria = sk.idSubKriteria
WHERE p.idKaryawan = ? AND p.tanggalPenilaian = ?");
$stmt->execute([$idKaryawan, $tanggalPenilaian]);
$editPenilaian = $stmt->fetchAll(PDO::FETCH_ASSOC);

if ($editPenilaian) {
foreach ($editPenilaian as $penilaian) {
$editSubKriteria[$penilaian['idKriteria']] =
$penilaian['idSubKriteria'];
}
}
}

// Ambil semua data penilaian untuk tampilan list dengan pagination


$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
$limit = 10;
$offset = ($page - 1) * $limit;

$searchQuery = $_GET['search'] ?? '';


$whereClause = '';
$params = [];

if ($searchQuery) {
$whereClause = "WHERE k.namaKaryawan LIKE ? OR k.jabatan LIKE ?";
$params = ["%{$searchQuery}%", "%{$searchQuery}%"];
}

// Count total records


$countSql = "SELECT COUNT(DISTINCT CONCAT(p.idKaryawan, '-', p.tanggalPenilaian))
as total
FROM penilaiankaryawan p
JOIN karyawanfbs k ON p.idKaryawan = k.idKaryawan
{$whereClause}";
$totalStmt = $db->prepare($countSql);
$totalStmt->execute($params);
$totalRecords = $totalStmt->fetch(PDO::FETCH_ASSOC)['total'];

// Get paginated data


$sql = "SELECT p.idKaryawan, p.tanggalPenilaian, k.namaKaryawan, k.jabatan,
COUNT(p.idKriteria) as jumlahKriteria,
AVG(sk.nilaiSkor) as rataRataSkor,
MAX(p.tanggalPenilaian) as tanggalTerakhir,
p.idPenilai
FROM penilaiankaryawan p
JOIN karyawanfbs k ON p.idKaryawan = k.idKaryawan
JOIN subkriteria sk ON p.idSubKriteria = sk.idSubKriteria
{$whereClause}
GROUP BY p.idKaryawan, p.tanggalPenilaian
ORDER BY p.tanggalPenilaian DESC, k.namaKaryawan
LIMIT {$limit} OFFSET {$offset}";

$penilaianList = $db->prepare($sql);
$penilaianList->execute($params);
$penilaianList = $penilaianList->fetchAll(PDO::FETCH_ASSOC);

// Generate pagination menggunakan SPKHelper


$pagination = SPKHelper::paginate($page, $totalRecords, $limit);

// Build base URL dengan parameter search


$baseUrl = '?';
$urlParams = [];
if ($searchQuery) {
$urlParams[] = 'search=' . urlencode($searchQuery);
}
$baseUrl .= implode('&', $urlParams);
?>

<?php include __DIR__ . '/../../includes/header.php'; ?>


<?php include __DIR__ . '/../../includes/sidebar.php'; ?>

<main class="content p-4">


<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1><i class="fas fa-clipboard-check me-2"></i>Kelola Penilaian
Karyawan</h1>
<div>
<?php if ($action !== 'create' && $action !== 'edit'): ?>
<a href="?action=create" class="btn btn-primary">
<i class="fas fa-plus me-1"></i>Tambah Penilaian
</a>
<?php endif; ?>
<?php if ($action === 'create' || $action === 'edit'): ?>
<a href="?" class="btn btn-secondary">
<i class="fas fa-arrow-left me-1"></i>Kembali
</a>
<?php endif; ?>
</div>
</div>

<!-- Alert Messages -->


<?php if ($message): ?>
<div class="alert alert-<?= $messageType ?> alert-dismissible fade show"
role="alert">
<?= $message ?>
<button type="button" class="btn-close"
data-bs-dismiss="alert"></button>
</div>
<?php endif; ?>

<?php if (empty($kriteriaAktif)): ?>


<div class="alert alert-warning" role="alert">
<i class="fas fa-exclamation-triangle me-2"></i>
<strong>Perhatian!</strong> Belum ada kriteria aktif. Silakan <a
href="kriteria.php">kelola kriteria</a> terlebih dahulu.
</div>
<?php endif; ?>

<?php if ($action === 'create' || $action === 'edit'): ?>


<!-- FORM CREATE/EDIT -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-<?= $action === 'create' ? 'plus' : 'edit' ?>
me-2"></i>
<?= $action === 'create' ? 'Tambah' : 'Edit' ?> Penilaian
Karyawan
</h5>
</div>
<div class="card-body">
<form method="POST" id="penilaianForm">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Pilih Karyawan *</label>
<select class="form-select" name="idKaryawan"
id="karyawanSelect" required
<?= $action === 'edit' ? 'disabled' : '' ?
>>
<option value="">Pilih Karyawan</option>
<?php foreach($karyawanAktif as $karyawan): ?>
<option value="<?= $karyawan['idKaryawan'] ?>"
<?= ($editPenilaian &&
$editPenilaian[0]['idKaryawan'] == $karyawan['idKaryawan']) ? 'selected' : '' ?>
data-jabatan="<?=
htmlspecialchars($karyawan['jabatan']) ?>">
<?=
htmlspecialchars($karyawan['namaKaryawan']) ?> - <?=
htmlspecialchars($karyawan['jabatan']) ?>
</option>
<?php endforeach; ?>
</select>
<?php if ($action === 'edit'): ?>
<input type="hidden" name="idKaryawan" value="<?=
$editPenilaian[0]['idKaryawan'] ?>">
<?php endif; ?>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Tanggal Penilaian
*</label>
<input type="date" class="form-control"
name="tanggalPenilaian"
value="<?= $editPenilaian ?
$editPenilaian[0]['tanggalPenilaian'] : date('Y-m-d') ?>"
max="<?= date('Y-m-d') ?>" required
<?= $action === 'edit' ? 'readonly' : '' ?>>
</div>
</div>
</div>

<!-- Info Karyawan Terpilih -->


<div id="karyawanInfo" class="alert alert-info" style="display:
none;">
<h6><i class="fas fa-user me-2"></i>Informasi Karyawan</h6>
<div class="row">
<div class="col-md-12">
<strong>Nama:</strong> <span
id="infoNama"></span><br>
<strong>Jabatan:</strong> <span
id="infoJabatan"></span>
</div>
</div>
</div>

<!-- Kriteria Penilaian -->


<div class="card mt-4">
<div class="card-header">
<h6 class="mb-0"><i class="fas fa-star
me-2"></i>Kriteria Penilaian</h6>
</div>
<div class="card-body">
<?php foreach($kriteriaAktif as $kriteria): ?>
<div class="mb-4 kriteria-section">
<div class="row align-items-center">
<div class="col-md-4">
<h6 class="mb-2">
<?=
htmlspecialchars($kriteria['namaKriteria']) ?>
<span class="badge bg-primary ms-
2">Bobot: <?= $kriteria['bobot'] ?></span>
</h6>
<small class="text-muted">
Jenis: <?= $kriteria['jenisKriteria'] ?
>
</small>
</div>
<div class="col-md-8">
<select class="form-select subkriteria-
select"
name="kriteria[<?=
$kriteria['idKriteria'] ?>]"
data-kriteria="<?=
$kriteria['idKriteria'] ?>"
required>
<option value="">Pilih Sub
Kriteria</option>
</select>
<div class="form-text">Pilih sub kriteria
yang sesuai dengan penilaian</div>
</div>
</div>
<hr class="my-3">
</div>
<?php endforeach; ?>
</div>
</div>

<!-- Preview Perhitungan -->


<div id="previewSection" class="card mt-4" style="display:
none;">
<div class="card-header">
<h6 class="mb-0"><i class="fas fa-calculator
me-2"></i>Preview Perhitungan</h6>
</div>
<div class="card-body">
<div id="previewContent">
<!-- Preview akan dimuat via AJAX -->
</div>
</div>
</div>

<div class="mb-3">
<label class="form-label">Catatan (Opsional)</label>
<textarea class="form-control" name="catatan" rows="3"
placeholder="Tambahkan catatan atau keterangan
tambahan..."><?= $editPenilaian ? htmlspecialchars($editPenilaian[0]['catatan']) :
'' ?></textarea>
</div>

<div class="mt-4">
<button type="button" id="previewBtn" class="btn btn-info
me-2">
<i class="fas fa-eye me-1"></i>Preview Perhitungan
</button>
<button type="submit" name="<?= $action === 'create' ?
'create_penilaian' : 'update_penilaian' ?>"
class="btn btn-<?= $action === 'create' ? 'primary'
: 'warning' ?>">
<i class="fas fa-save me-1"></i>
<?= $action === 'create' ? 'Simpan' : 'Update' ?>
</button>
<a href="?" class="btn btn-secondary ms-2">
<i class="fas fa-times me-1"></i>Batal
</a>
</div>
</form>
</div>
</div>
<?php else: ?>
<!-- SEARCH & FILTER -->
<div class="card mb-4">
<div class="card-body">
<form method="GET" class="row g-3">
<div class="col-md-6">
<input type="text" class="form-control" name="search"
value="<?= htmlspecialchars($searchQuery) ?>"
placeholder="Cari berdasarkan nama karyawan atau
jabatan...">
</div>
<div class="col-md-3">
<button type="submit" class="btn btn-primary">
<i class="fas fa-search me-1"></i>Cari
</button>
<a href="?" class="btn btn-secondary">Reset</a>
</div>
</form>
</div>
</div>

<!-- TABEL LIST PENILAIAN -->


<div class="card">
<div class="card-header">
<h5 class="mb-0"><i class="fas fa-list me-2"></i>Daftar Penilaian
Karyawan</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead class="table-dark">
<tr>
<th width="5%">#</th>
<th>Nama Karyawan</th>
<th>Jabatan</th>
<th width="12%">Tanggal</th>
<th width="10%">Kriteria</th>
<th width="10%">Rata-rata</th>
<th>Penilai</th>
<th width="15%">Aksi</th>
</tr>
</thead>
<tbody>
<?php if (empty($penilaianList)): ?>
<tr>
<td colspan="9" class="text-center text-muted">
<i class="fas fa-inbox fa-2x mb-2"></i><br>
Belum ada data penilaian
</td>
</tr>
<?php else: ?>
<?php foreach($penilaianList as $index => $item): ?>
<tr>
<td><?= $offset + $index + 1 ?></td>
<td>
<strong><?=
htmlspecialchars($item['namaKaryawan']) ?></strong>
</td>
<td><?= htmlspecialchars($item['jabatan']) ?></td>
<td><?= date('d/m/Y',
strtotime($item['tanggalPenilaian'])) ?></td>
<td>
<span class="badge bg-info">
<?= $item['jumlahKriteria'] ?>/<?=
count($kriteriaAktif) ?>
</span>
</td>
<td>
<span class="badge bg-<?= $item['rataRataSkor']
>= 3 ? 'success' : ($item['rataRataSkor'] >= 2 ? 'warning' : 'danger') ?>">
<?= number_format($item['rataRataSkor'], 2)
?>
</span>
</td>
<td><?= htmlspecialchars($item['idPenilai'])
?></td>
<td>
<div class="btn-group" role="group">
<a href="?action=edit&karyawan=<?=
$item['idKaryawan'] ?>&tanggal=<?= $item['tanggalPenilaian'] ?>"
class="btn btn-sm btn-warning"
title="Edit">
<i class="fas fa-edit"></i>
</a>
<button type="button" class="btn btn-sm
btn-info"
onclick="viewDetail(<?=
$item['idKaryawan'] ?>, '<?= $item['tanggalPenilaian'] ?>')"
title="Detail">
<i class="fas fa-eye"></i>
</button>
<button type="button" class="btn btn-sm
btn-danger"
onclick="deletePenilaian(<?=
$item['idKaryawan'] ?>, '<?= $item['tanggalPenilaian'] ?>', '<?=
htmlspecialchars($item['namaKaryawan']) ?>')"
title="Hapus">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>

<!-- Pagination -->


<?php if ($pagination['total_pages'] > 1): ?>
<div class="mt-3">
<?= SPKHelper::generatePaginationHTML($pagination,
$baseUrl) ?>

<!-- Info pagination -->


<div class="text-center mt-2">
<small class="text-muted">
Menampilkan <?= min($pagination['offset'] + 1,
$totalRecords) ?> - <?= min($pagination['offset'] + $limit, $totalRecords) ?>
dari <?= $totalRecords ?> data (Halaman <?=
$pagination['current_page'] ?> dari <?= $pagination['total_pages'] ?>)
</small>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
</main>

<!-- Modal Detail Penilaian -->


<div class="modal fade" id="detailModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Detail Penilaian</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="detailContent">
<!-- Detail akan dimuat via AJAX -->
</div>
</div>
</div>
</div>

<!-- Modal Konfirmasi Hapus -->


<div class="modal fade" id="deleteModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Konfirmasi Hapus</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Apakah Anda yakin ingin menghapus penilaian untuk <strong
id="deleteKaryawanName"></strong> pada tanggal <strong
id="deleteTanggal"></strong>?</p>
<p class="text-danger"><small>Tindakan ini tidak dapat dibatalkan!
</small></p>
</div>
<div class="modal-footer">
<form method="POST" id="deleteForm">
<input type="hidden" name="idKaryawan" id="deleteKaryawanId">
<input type="hidden" name="tanggalPenilaian"
id="deleteTanggalPenilaian">
<button type="button" class="btn btn-secondary" data-bs-
dismiss="modal">Batal</button>
<button type="submit" name="delete_penilaian" class="btn btn-
danger">Hapus</button>
</form>
</div>
</div>
</div>
</div>

<script>
// Function to view detail penilaian
function viewDetail(idKaryawan, tanggalPenilaian) {
const modal = new bootstrap.Modal(document.getElementById('detailModal'));
const content = document.getElementById('detailContent');

content.innerHTML = `
<div class="text-center p-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="mt-2">Mengambil detail penilaian...</p>
</div>
`;

fetch(`../../ajax/get_detail_penilaian.php?idKaryawan=${idKaryawan}&tanggal=$
{tanggalPenilaian}`)
.then(response => response.json())
.then(data => {
if (!data.success) {
content.innerHTML = `<div class="alert alert-danger">Gagal memuat
detail penilaian.</div>`;
return;
}

let html = `
<h6>Nama Karyawan: ${data.karyawan.namaKaryawan}</h6>
<p><strong>Jabatan:</strong> ${data.karyawan.jabatan}<br>
<strong>Tanggal Penilaian:</strong> ${data.tanggal}</p>
<table class="table table-sm table-bordered">

<thead><tr><th>Kriteria</th><th>Subkriteria</th><th>Skor</th></tr></thead><tbody>
`;

data.penilaian.forEach(row => {
html += `<tr><td>${row.namaKriteria}</td><td>$
{row.namaSubKriteria}</td><td>${row.nilaiSkor}</td></tr>`;
});

html += `</tbody></table>`;

if (data.catatan) {
html += `<p><strong>Catatan:</strong> ${data.catatan}</p>`;
}

content.innerHTML = html;
})
.catch(err => {
console.error(err);
content.innerHTML = `<div class="alert alert-danger">Terjadi kesalahan
saat mengambil data.</div>`;
});

modal.show();
}
// Function to delete penilaian
function deletePenilaian(idKaryawan, tanggalPenilaian, namaKaryawan) {
const modal = new bootstrap.Modal(document.getElementById('deleteModal'));

document.getElementById('deleteKaryawanName').textContent = namaKaryawan;
document.getElementById('deleteTanggal').textContent = new
Date(tanggalPenilaian).toLocaleDateString('id-ID');
document.getElementById('deleteKaryawanId').value = idKaryawan;
document.getElementById('deleteTanggalPenilaian').value = tanggalPenilaian;

modal.show();
}

// Load sub kriteria when page loads (for edit mode)


<?php if ($action === 'edit' && $editPenilaian): ?>
document.addEventListener('DOMContentLoaded', function() {
// Set karyawan info
const karyawanSelect = document.getElementById('karyawanSelect');
const selectedOption = karyawanSelect.options[karyawanSelect.selectedIndex];
if (selectedOption) {
showKaryawanInfo(selectedOption);
}

// Load sub kriteria for edit


<?php foreach($editSubKriteria as $kriteriaId => $subKriteriaId): ?>
loadSubKriteria(<?= $kriteriaId ?>, <?= $subKriteriaId ?>);
<?php endforeach; ?>
});
<?php endif; ?>

// Handle karyawan selection


document.getElementById('karyawanSelect')?.addEventListener('change', function() {
if (this.value) {
showKaryawanInfo(this.options[this.selectedIndex]);
// Load all sub kriteria
document.querySelectorAll('.subkriteria-select').forEach(select => {
const kriteriaId = select.dataset.kriteria;
loadSubKriteria(kriteriaId);
});
} else {
document.getElementById('karyawanInfo').style.display = 'none';
}
});

function showKaryawanInfo(option) {
document.getElementById('infoNama').textContent = option.text.split(' - ')[0];
document.getElementById('infoJabatan').textContent = option.dataset.jabatan;
document.getElementById('karyawanInfo').style.display = 'block';
}

function loadSubKriteria(kriteriaId, selectedId = null) {


const select = document.querySelector(`select[data-kriteria="${kriteriaId}"]`);
if (!select) return;

fetch(`../../ajax/get_subkriteria.php?idKriteria=${kriteriaId}`)
.then(resp => resp.json())
.then(json => {
if (!json.success) throw new Error(json.error || 'Gagal mengambil
data');
select.innerHTML = '<option value="">Pilih Sub Kriteria</option>';
json.data.forEach(sub => {
const option = new Option(
`${sub.namaSubKriteria} (Skor: ${sub.nilaiSkor})`,
sub.idSubKriteria
);
if (selectedId && sub.idSubKriteria == selectedId) {
option.selected = true;
}
select.appendChild(option);
});
})
.catch(error => {
console.error('Error loading sub kriteria:', error);
select.innerHTML = '<option value="">Error loading data</option>';
});
}

// Preview calculation
document.getElementById('previewBtn')?.addEventListener('click', function() {
const form = document.getElementById('penilaianForm');
if (!form.checkValidity()) {
form.reportValidity();
return;
}

const previewSection = document.getElementById('previewSection');


const previewContent = document.getElementById('previewContent');
previewContent.innerHTML = `
<div class="text-center p-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="mt-2">Menghitung preview...</p>
</div>`;
previewSection.style.display = 'block';

fetch('../../ajax/perhitungan_saw.php', {
method: 'POST',
body: new FormData(form),
})
.then(response => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
})
.then(json => {
if (!json.success) {
throw new Error(json.error || 'Gagal menghitung');
}

// *** Mulai render hasil ke HTML ***


const d = json.data;
let html = `
<h6>Hasil Perhitungan (${d.metode})</h6>
<p><strong>${d.karyawan.namaKaryawan}</strong><br>
Tanggal: ${d.tanggal_penilaian}<br>
Periode: ${d.periode}</p>

<table class="table table-sm">


<thead>
<tr>
<th>Kriteria</th>
<th>Sub-kriteria</th>
<th>Skor</th>
<th>Normalisasi</th>
<th>Bobot</th>
<th>Skor Terbobot</th>
</tr>
</thead>
<tbody>`;
for (const id in d.detail_penilaian) {
const det = d.detail_penilaian[id];
const norm = d.perhitungan.normalisasi[id];
html += `
<tr>
<td>${det.namaKriteria}</td>
<td>${det.namaSubKriteria}</td>
<td>${det.nilaiSkor}</td>
<td>${norm.normalisasi}</td>
<td>${norm.bobot}</td>
<td>${norm.skor_terbobot}</td>
</tr>`;
}
html += `</tbody></table>
<p>
<strong>Total Bobot:</strong> ${d.perhitungan.total_bobot}<br>
<strong>Total Skor:</strong> ${d.perhitungan.total_skor}<br>
<strong>Skor Final:</strong> ${d.perhitungan.skor_final}%<br>
<strong>Status:</strong> ${d.perhitungan.status_kelayakan}
</p>`;
previewContent.innerHTML = html;
})
.catch(err => {
console.error('Preview error:', err);
previewContent.innerHTML = `
<div class="alert alert-danger">
<strong>Error:</strong> ${err.message}
</div>`;
});
});
</script>

//source-code file: /dashboard/admin/analisis.php :


<?php
require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../includes/functions.php';

SessionManager::requireRole('Admin');
$db = Database::getInstance()->getConnection();

$message = '';
$messageType = '';
$hasilAnalisis = [];
$periode = $_GET['periode'] ?? date('Y-m');
$action = $_GET['action'] ?? 'view';

// Handle form submission untuk trigger analisis


if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['trigger_analisis'])) {
try {
$periodeAnalisis = $_POST['periode'];
$idAnalisis = $_SESSION['user_id'];

$db->beginTransaction();

// Hapus hasil analisis lama untuk periode yang sama


$stmtDelete = $db->prepare("DELETE FROM hasilspk WHERE periode = ?");
$stmtDelete->execute([$periodeAnalisis]);

// Ambil semua penilaian dalam periode tersebut


$stmtPenilaian = $db->prepare("
SELECT DISTINCT p.idKaryawan, k.namaKaryawan, k.jabatan
FROM penilaiankaryawan p
JOIN karyawanfbs k ON p.idKaryawan = k.idKaryawan
WHERE DATE_FORMAT(p.tanggalPenilaian, '%Y-%m') = ?
AND k.statusKerja = 'Aktif'
");
$stmtPenilaian->execute([$periodeAnalisis]);
$karyawanList = $stmtPenilaian->fetchAll(PDO::FETCH_ASSOC);

if (empty($karyawanList)) {
throw new Exception("Tidak ada penilaian ditemukan untuk periode
$periodeAnalisis");
}

// Ambil kriteria aktif


$stmtKriteria = $db->prepare("SELECT idKriteria, namaKriteria, bobot,
jenisKriteria
FROM kriteria WHERE status = 'Aktif'");
$stmtKriteria->execute();
$kriteriaList = $stmtKriteria->fetchAll(PDO::FETCH_ASSOC);

if (empty($kriteriaList)) {
throw new Exception("Tidak ada kriteria aktif");
}

// Hitung nilai min/max untuk normalisasi


$nilaiMinMax = [];
foreach ($kriteriaList as $kriteria) {
$stmtMinMax = $db->prepare("
SELECT MAX(sk.nilaiSkor) as nilai_max, MIN(sk.nilaiSkor) as
nilai_min
FROM penilaiankaryawan p
JOIN subkriteria sk ON p.idSubKriteria = sk.idSubKriteria
WHERE p.idKriteria = ? AND DATE_FORMAT(p.tanggalPenilaian, '%Y-%m')
= ?
");
$stmtMinMax->execute([$kriteria['idKriteria'], $periodeAnalisis]);
$minMax = $stmtMinMax->fetch(PDO::FETCH_ASSOC);

$nilaiMinMax[$kriteria['idKriteria']] = [
'max' => $minMax['nilai_max'] ?? 1,
'min' => $minMax['nilai_min'] ?? 1,
'bobot' => $kriteria['bobot'],
'jenis' => $kriteria['jenisKriteria']
];
}

// Hitung skor SAW untuk setiap karyawan


$hasilSAW = [];
foreach ($karyawanList as $karyawan) {
$idKaryawan = $karyawan['idKaryawan'];

// Ambil penilaian terbaru untuk karyawan ini dalam periode


$stmtNilai = $db->prepare("
SELECT p.idKriteria, sk.nilaiSkor, p.tanggalPenilaian
FROM penilaiankaryawan p
JOIN subkriteria sk ON p.idSubKriteria = sk.idSubKriteria
WHERE p.idKaryawan = ? AND DATE_FORMAT(p.tanggalPenilaian, '%Y-%m')
= ?
ORDER BY p.tanggalPenilaian DESC
");
$stmtNilai->execute([$idKaryawan, $periodeAnalisis]);
$nilaiKaryawan = $stmtNilai->fetchAll(PDO::FETCH_ASSOC);

// Ambil nilai terbaru per kriteria


$nilaiPerKriteria = [];
foreach ($nilaiKaryawan as $nilai) {
if (!isset($nilaiPerKriteria[$nilai['idKriteria']])) {
$nilaiPerKriteria[$nilai['idKriteria']] = $nilai['nilaiSkor'];
}
}

// Hitung skor SAW


$totalSkor = 0;
$totalBobot = 0;
$validKriteria = 0;

foreach ($kriteriaList as $kriteria) {


$idKriteria = $kriteria['idKriteria'];

if (isset($nilaiPerKriteria[$idKriteria])) {
$nilai = $nilaiPerKriteria[$idKriteria];
$bobot = $kriteria['bobot'];
$jenis = $kriteria['jenisKriteria'];
$max = $nilaiMinMax[$idKriteria]['max'];
$min = $nilaiMinMax[$idKriteria]['min'];

// Normalisasi
if ($jenis === 'Benefit') {
$normalisasi = $max > 0 ? $nilai / $max : 0;
} else {
$normalisasi = $nilai > 0 ? $min / $nilai : 0;
}

$skorTerbobot = $normalisasi * $bobot;


$totalSkor += $skorTerbobot;
$totalBobot += $bobot;
$validKriteria++;
}
}

// Hanya proses jika semua kriteria dinilai


if ($validKriteria == count($kriteriaList)) {
$skorFinal = $totalBobot > 0 ? $totalSkor / $totalBobot : 0;

$hasilSAW[] = [
'idKaryawan' => $idKaryawan,
'namaKaryawan' => $karyawan['namaKaryawan'],
'jabatan' => $karyawan['jabatan'],
'totalSkor' => $skorFinal
];
}
}

// Urutkan berdasarkan skor (descending) dan tentukan ranking


usort($hasilSAW, function($a, $b) {
return $b['totalSkor'] <=> $a['totalSkor'];
});

// Simpan hasil ke database


$threshold = 0.75; // 75% dari skor maksimal
foreach ($hasilSAW as $index => $hasil) {
$ranking = $index + 1;
$statusPromosi = $hasil['totalSkor'] >= $threshold ? 'Layak' : 'Tidak
Layak';

$stmtInsert = $db->prepare("
INSERT INTO hasilspk (idKaryawan, totalSkor, ranking,
statusPromosi,
tanggalAnalisis, idAnalisis, periode)
VALUES (?, ?, ?, ?, CURDATE(), ?, ?)
");
$stmtInsert->execute([
$hasil['idKaryawan'],
$hasil['totalSkor'],
$ranking,
$statusPromosi,
$idAnalisis,
$periodeAnalisis
]);
}

$db->commit();

$message = "Analisis SPK berhasil! Diproses " . count($hasilSAW) . "


karyawan untuk periode $periodeAnalisis";
$messageType = "success";
$periode = $periodeAnalisis;

// Log activity
SPKHelper::logActivity($db, $idAnalisis, 'RUN_SPK_ANALYSIS',
"Menjalankan analisis SPK untuk periode
$periodeAnalisis");

} catch (Exception $e) {


if ($db->inTransaction()) {
$db->rollBack();
}
$message = "Error: " . $e->getMessage();
$messageType = "error";
}
}

// Ambil hasil analisis untuk ditampilkan


try {
$stmtHasil = $db->prepare("
SELECT h.*, k.namaKaryawan, k.jabatan
FROM hasilspk h
JOIN karyawanfbs k ON h.idKaryawan = k.idKaryawan
WHERE h.periode = ?
ORDER BY h.ranking ASC
");
$stmtHasil->execute([$periode]);
$hasilAnalisis = $stmtHasil->fetchAll(PDO::FETCH_ASSOC);

// Ambil statistik
$stmtStats = $db->prepare("
SELECT
COUNT(*) as total_karyawan,
COUNT(CASE WHEN statusPromosi = 'Layak' THEN 1 END) as layak_promosi,
AVG(totalSkor) as rata_rata_skor,
MAX(totalSkor) as skor_tertinggi,
MIN(totalSkor) as skor_terendah
FROM hasilspk
WHERE periode = ?
");
$stmtStats->execute([$periode]);
$statistik = $stmtStats->fetch(PDO::FETCH_ASSOC);

} catch (Exception $e) {


$message = "Error mengambil data: " . $e->getMessage();
$messageType = "error";
}

// Handle export to PDF/Excel


if ($action === 'export' && !empty($hasilAnalisis)) {
$format = $_GET['format'] ?? 'pdf';

if ($format === 'pdf') {


// Pastikan file TCPDF sudah ada dan path benar
$tcpdfPath = __DIR__ . '/../../includes/tcpdf/tcpdf.php';
if (!file_exists($tcpdfPath)) {
die('TCPDF library file not found. Please check the path and make sure
TCPDF is installed.');
}
require_once $tcpdfPath;

if (!class_exists('TCPDF')) {
die('TCPDF class not found after require. Please check your TCPDF
installation.');
}

$pdf = new \TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);


$pdf->SetCreator('SPK Promosi Karyawan');
$pdf->SetAuthor('Admin');
$pdf->SetTitle('Hasil Analisis SPK - ' . $periode);

$pdf->AddPage();
$pdf->SetFont('helvetica', 'B', 16);
$pdf->Cell(0, 10, 'Hasil Analisis SPK Promosi Karyawan', 0, 1, 'C');
$pdf->Cell(0, 10, 'Periode: ' . date('F Y', strtotime($periode . '-01')),
0, 1, 'C');
$pdf->Ln(10);

// Table header
$pdf->SetFont('helvetica', 'B', 10);
$pdf->Cell(10, 8, 'No', 1, 0, 'C');
$pdf->Cell(50, 8, 'Nama Karyawan', 1, 0, 'C');
$pdf->Cell(30, 8, 'Jabatan', 1, 0, 'C');
$pdf->Cell(25, 8, 'Skor', 1, 0, 'C');
$pdf->Cell(20, 8, 'Ranking', 1, 0, 'C');
$pdf->Cell(30, 8, 'Status', 1, 1, 'C');

// Table content
$pdf->SetFont('helvetica', '', 9);
foreach ($hasilAnalisis as $hasil) {
$pdf->Cell(10, 8, $hasil['ranking'], 1, 0, 'C');
$pdf->Cell(50, 8, $hasil['namaKaryawan'], 1, 0, 'L');
$pdf->Cell(30, 8, $hasil['jabatan'], 1, 0, 'L');
$pdf->Cell(25, 8, number_format($hasil['totalSkor'], 3), 1, 0, 'C');
$pdf->Cell(20, 8, $hasil['ranking'], 1, 0, 'C');
$pdf->Cell(30, 8, $hasil['statusPromosi'], 1, 1, 'C');
}

$pdf->Output('hasil_analisis_spk_' . $periode . '.pdf', 'D');


exit;

} elseif ($format === 'excel') {


header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="hasil_analisis_spk_' .
$periode . '.xls"');

echo "<table border='1'>";


echo "<tr><th colspan='6'>Hasil Analisis SPK Promosi Karyawan - Periode:
" . date('F Y', strtotime($periode . '-01')) . "</th></tr>";
echo "<tr><th>No</th><th>Nama
Karyawan</th><th>Jabatan</th><th>Skor</th><th>Ranking</th><th>Status
Promosi</th></tr>";

foreach ($hasilAnalisis as $hasil) {


echo "<tr>";
echo "<td>" . $hasil['ranking'] . "</td>";
echo "<td>" . $hasil['namaKaryawan'] . "</td>";
echo "<td>" . $hasil['jabatan'] . "</td>";
echo "<td>" . number_format($hasil['totalSkor'], 3) . "</td>";
echo "<td>" . $hasil['ranking'] . "</td>";
echo "<td>" . $hasil['statusPromosi'] . "</td>";
echo "</tr>";
}
echo "</table>";
exit;
}
}

$pageTitle = "Analisis SPK";


require_once __DIR__ . '/../../includes/header.php';
?>

<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-
center">
<h5 class="mb-0">
<i class="fas fa-chart-line me-2"></i>Analisis SPK Promosi
Karyawan
</h5>
<div class="btn-group">
<button type="button" class="btn btn-primary btn-sm" data-
bs-toggle="modal" data-bs-target="#modalTriggerAnalisis">
<i class="fas fa-play me-1"></i>Jalankan Analisis
</button>
<a href="index.php" class="btn btn-secondary">
<i class="fas fa-arrow-left me-1"></i>Kembali
</a>
<?php if (!empty($hasilAnalisis)): ?>
<div class="btn-group">
<button type="button" class="btn btn-success btn-sm
dropdown-toggle"
data-bs-toggle="dropdown"
aria-expanded="false"
id="exportDropdown">
<i class="fas fa-download me-1"></i>Export
</button>
<ul class="dropdown-menu" aria-
labelledby="exportDropdown">
<li>
<a class="dropdown-item export-link"
href="?action=export&format=pdf&periode=<?=
urlencode($periode) ?>"
data-format="pdf">
<i class="fas fa-file-pdf me-1 text-
danger"></i>Export PDF
</a>
</li>
<li>
<a class="dropdown-item export-link"
href="?action=export&format=excel&periode=<?
= urlencode($periode) ?>"
data-format="excel">
<i class="fas fa-file-excel me-1 text-
success"></i>Export Excel
</a>
</li>
</ul>
</div>
<?php endif; ?>
</div>
</div>

<div class="card-body">
<?php if ($message): ?>
<div class="alert alert-<?= $messageType === 'success' ?
'success' : 'danger' ?> alert-dismissible fade show">
<?= htmlspecialchars($message) ?>
<button type="button" class="btn-close" data-bs-
dismiss="alert"></button>
</div>
<?php endif; ?>

<!-- Filter Periode -->


<div class="row mb-4">
<div class="col-md-4">
<label for="filterPeriode" class="form-label">Filter
Periode:</label>
<div class="input-group">
<input type="month" id="filterPeriode" class="form-
control" value="<?= $periode ?>">
<button class="btn btn-outline-secondary"
type="button" onclick="filterPeriode()">
<i class="fas fa-search"></i>
</button>
</div>
</div>
</div>

<?php if (!empty($hasilAnalisis)): ?>


<!-- Statistik -->
<div class="row mb-4">
<div class="col-md-2">
<div class="card bg-primary text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Total
Karyawan</h6>
<h4><?= $statistik['total_karyawan'] ??
0 ?></h4>
</div>
<i class="fas fa-users fa-2x"></i>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="card bg-success text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Layak
Promosi</h6>
<h4><?= $statistik['layak_promosi'] ??
0 ?></h4>
</div>
<i class="fas fa-thumbs-up fa-2x"></i>
</div>
</div>
</div>
</div>
<div class="col-md-2">
<div class="card bg-info text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Rata-rata
Skor</h6>
<h4><?=
number_format($statistik['rata_rata_skor'] ?? 0, 2) ?></h4>
</div>
<i class="fas fa-chart-bar fa-2x"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-warning text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Skor
Tertinggi</h6>
<h4><?=
number_format($statistik['skor_tertinggi'] ?? 0, 3) ?></h4>
</div>
<i class="fas fa-trophy fa-2x"></i>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-secondary text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Skor
Terendah</h6>
<h4><?=
number_format($statistik['skor_terendah'] ?? 0, 3) ?></h4>
</div>
<i class="fas fa-chart-line fa-2x"></i>
</div>
</div>
</div>
</div>
</div>

<!-- Tabel Hasil -->


<div class="table-responsive">
<table class="table table-striped table-hover"
id="tabelHasil">
<thead class="table-dark">
<tr>
<th>Ranking</th>
<th>Nama Karyawan</th>
<th>Jabatan</th>
<th>Total Skor</th>
<th>Status Promosi</th>
<th>Tanggal Analisis</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach ($hasilAnalisis as $hasil): ?>
<tr class="<?= $hasil['statusPromosi'] ===
'Layak' ? 'table-success' : '' ?>">
<td>
<span class="badge bg-primary fs-6">#<?=
$hasil['ranking'] ?></span>
</td>
<td>
<strong><?=
htmlspecialchars($hasil['namaKaryawan']) ?></strong>
</td>
<td><?= htmlspecialchars($hasil['jabatan']) ?
></td>
<td>
<span class="badge bg-info"><?=
number_format($hasil['totalSkor'], 3) ?></span>
</td>
<td>
<span class="badge bg-<?=
$hasil['statusPromosi'] === 'Layak' ? 'success' : 'danger' ?>">
<?= $hasil['statusPromosi'] ?>
</span>
</td>
<td><?= date('d/m/Y',
strtotime($hasil['tanggalAnalisis'])) ?></td>
<td>
<button class="btn btn-info btn-sm"
onclick="showDetail(<?= $hasil['idKaryawan'] ?>, '<?= $periode ?>')">
<i class="fas fa-eye"></i> Detail
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="text-center py-5">
<i class="fas fa-chart-line fa-3x text-muted mb-3"></i>
<h5 class="text-muted">Belum ada hasil analisis untuk
periode <?= date('F Y', strtotime($periode . '-01')) ?></h5>
<p class="text-muted">Klik tombol "Jalankan Analisis" untuk
memulai analisis SPK</p>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>

<!-- Modal Trigger Analisis -->


<div class="modal fade" id="modalTriggerAnalisis" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title">Jalankan Analisis SPK</h5>
<button type="button" class="btn-close" data-bs-
dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="alert alert-info">
<i class="fas fa-info-circle"></i>
Analisis akan memproses semua penilaian karyawan dalam
periode yang dipilih menggunakan metode SAW (Simple Additive Weighting).
</div>
<div class="mb-3">
<label for="periode" class="form-label">Pilih
Periode</label>
<input type="month" class="form-control" id="periode"
name="periode" value="<?= date('Y-m') ?>" required>
</div>
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle"></i>
<strong>Perhatian:</strong> Hasil analisis lama untuk
periode yang sama akan dihapus.
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-
dismiss="modal">Batal</button>
<button type="submit" name="trigger_analisis" class="btn btn-
primary">
<i class="fas fa-play me-1"></i>Jalankan Analisis
</button>

</div>
</form>
</div>
</div>
</div>

<!-- Modal Detail -->


<div class="modal fade" id="modalDetail" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Detail Perhitungan SPK</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="detailContent">
<!-- Content akan diload via AJAX -->
</div>
</div>
</div>
</div>

<script>

document.addEventListener('DOMContentLoaded', function() {
console.log('DOM loaded, initializing export functions...');

// Fix untuk dropdown export


const exportDropdown = document.getElementById('exportDropdown');
if (exportDropdown) {
console.log('Export dropdown found');

// Manual dropdown toggle


exportDropdown.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();

const dropdownMenu = this.nextElementSibling;


if (dropdownMenu) {
const isOpen = dropdownMenu.classList.contains('show');

// Close all other dropdowns first


document.querySelectorAll('.dropdown-menu.show').forEach(menu => {
menu.classList.remove('show');
});

// Toggle current dropdown


if (!isOpen) {
dropdownMenu.classList.add('show');
console.log('Dropdown opened');
} else {
dropdownMenu.classList.remove('show');
console.log('Dropdown closed');
}
}
});
}

// Handle export link clicks


const exportLinks = document.querySelectorAll('.export-link');
exportLinks.forEach(link => {
link.addEventListener('click', function(e) {
console.log('Export link clicked:', this.href);

// Show loading state


const originalText = this.innerHTML;
const format = this.getAttribute('data-format');

this.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>'


+ 'Mengunduh '
+ (format === 'pdf' ? 'PDF' : 'Excel')
+ '...';
this.style.pointerEvents = 'none';

// Create a temporary link to trigger download


const tempLink = document.createElement('a');
tempLink.href = this.href;
tempLink.target = '_blank';
tempLink.style.display = 'none';
document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);

// Reset tombol setelah delay


setTimeout(() => {
this.innerHTML = originalText;
this.style.pointerEvents = 'auto';

// Close dropdown
const dropdownMenu = this.closest('.dropdown-menu');
if (dropdownMenu) dropdownMenu.classList.remove('show');
}, 2000);
// Prevent default
e.preventDefault();
return false;
});
});
// Close dropdown when clicking outside
document.addEventListener('click', function(e) {
const dropdowns = document.querySelectorAll('.dropdown-menu.show');
dropdowns.forEach(dropdown => {
if (!dropdown.parentElement.contains(e.target)) {
dropdown.classList.remove('show');
}
});
});
});

function showDetail(idKaryawan, periode) {


const detailContent = document.getElementById('detailContent');
if (detailContent) {
detailContent.innerHTML = `<div class="text-center py-4">
<i class="fas fa-spinner fa-spin fa-2x text-primary mb-3"></i>
<p>Memuat detail penilaian...</p>
</div>`;
}

// Tampilkan modal
const modalElem = document.getElementById('modalDetail');
if (modalElem) {
const bsModal = new bootstrap.Modal(modalElem);
bsModal.show();
}

fetch('../../ajax/get_detail_penilaian.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `idKaryawan=${encodeURIComponent(idKaryawan)}&tanggal=$
{encodeURIComponent(periode)}`
})
.then(resp => {
if (!resp.ok) throw new Error(`HTTP error! status: ${resp.status}`);
return resp.json();
})
.then(data => {
if (!data.success) throw new Error(data.message);

// Awali HTML-nya
let html = `
<h5>Detail Penilaian: ${data.karyawan.namaKaryawan} ($
{data.karyawan.jabatan})</h5>
`;

if (data.isPeriode) {
html += `<p><strong>Periode:</strong> ${data.tanggalRaw} (menampilkan $
{data.daftarTanggal.length} tanggal)</p>`;
} else {
html += `<p><strong>Tanggal Penilaian:</strong>
${data.tanggalRaw}</p>`;
}

// Kita akan grouping berdasarkan setiap tanggal jika isPeriode = true


const groupedByTanggal = {};

data.penilaian.forEach(row => {
const tgl = row.tanggalPenilaian;
if (!groupedByTanggal[tgl]) groupedByTanggal[tgl] = [];
groupedByTanggal[tgl].push(row);
});

// Loop per tanggal


for (const tgl of Object.keys(groupedByTanggal)) {
html += `
<hr class="my-2">
<h6><i class="fas fa-calendar-alt me-1"></i> Tanggal: ${tgl}</h6>
<table class="table table-bordered table-sm mb-3">
<thead class="table-light">
<tr>
<th>Kriteria</th>
<th>Subkriteria</th>
<th>Skor</th>
<th>Bobot</th>
</tr>
</thead>
<tbody>
`;
groupedByTanggal[tgl].forEach(item => {
html += `
<tr>
<td>${item.namaKriteria}</td>
<td>${item.namaSubKriteria}</td>
<td>${item.nilaiSkor}</td>
<td>${item.bobot}</td>
</tr>`;
});
html += `</tbody></table>`;
}

if (data.catatan) {
html += `<p><strong>Catatan:</strong> ${data.catatan}</p>`;
}

detailContent.innerHTML = html;
})
.catch(err => {
console.error('Error loading detail:', err);
detailContent.innerHTML = `<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle me-2"></i>
Gagal memuat detail penilaian. Error: ${err.message}
</div>`;
});
}
// Filter periode function
function filterPeriode() {
const periode = document.getElementById('filterPeriode').value;
if (periode) {
console.log('Filtering by periode:', periode);
window.location.href = `analisis.php?periode=$
{encodeURIComponent(periode)}`;
}
}

// Initialize DataTable when jQuery is ready


$(document).ready(function() {
console.log('jQuery ready, initializing DataTable...');
if ($.fn.DataTable) {
$('#tabelHasil').DataTable({
"language": {
"url": "//cdn.datatables.net/plug-ins/1.11.5/i18n/id.json"
},
"order": [[ 0, "asc" ]], // Order by ranking
"pageLength": 10,
"responsive": true,
"columnDefs": [
{ "orderable": false, "targets": -1 } // Disable sorting on action
column
]
});
console.log('DataTable initialized');
}
});

// Handle form submission untuk analisis


document.addEventListener('DOMContentLoaded', function() {
const formAnalisis = document.querySelector('#modalTriggerAnalisis
form[method="POST"]');
if (formAnalisis) {
formAnalisis.addEventListener('submit', function(e) {
const submitBtn =
this.querySelector('button[name="trigger_analisis"]');
if (submitBtn) {
const originalText = submitBtn.innerHTML;

submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin


me-1"></i>Memproses Analisis...';
submitBtn.disabled = true;

// Show progress indication


const modalBody = this.closest('.modal-
content').querySelector('.modal-body');
const progressDiv = document.createElement('div');
progressDiv.innerHTML = `
<div class="alert alert-info mt-3">
<i class="fas fa-info-circle me-2"></i>
Sedang memproses analisis SAW, mohon tunggu...
</div>
`;
modalBody.appendChild(progressDiv);
}
});
}
});

// Debug function
function debugExport(format, periode) {
console.log('Debug export:', format, periode);
const url = `analisis.php?action=export&format=${format}&periode=${periode}`;
console.log('Export URL:', url);
window.open(url, '_blank');
}
</script>

<?php require_once __DIR__ . '/../../includes/footer.php'; ?>

You might also like