399 lines
12 KiB
PHP
399 lines
12 KiB
PHP
<?php
|
|
require_once 'auth.php';
|
|
requireLogin();
|
|
requireRole('admin');
|
|
|
|
$conn = new mysqli("localhost", "root", "", "webgis");
|
|
$error = '';
|
|
$success = '';
|
|
|
|
// --- TAMBAH USER ---
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'tambah') {
|
|
$nama = trim($_POST['nama']);
|
|
$username = trim($_POST['username']);
|
|
$password = trim($_POST['password']);
|
|
$role = $_POST['role'];
|
|
|
|
if (!$nama || !$username || !$password || !in_array($role, ['admin', 'operator'])) {
|
|
$error = "Semua field wajib diisi dengan benar.";
|
|
} else {
|
|
// Cek apakah username sudah ada
|
|
$cek = $conn->prepare("SELECT id FROM users WHERE username = ?");
|
|
$cek->bind_param("s", $username);
|
|
$cek->execute();
|
|
$cek->store_result();
|
|
|
|
if ($cek->num_rows > 0) {
|
|
$error = "Username <b>$username</b> sudah digunakan.";
|
|
} else {
|
|
$hash = password_hash($password, PASSWORD_DEFAULT);
|
|
$stmt = $conn->prepare("INSERT INTO users (nama, username, password, role) VALUES (?, ?, ?, ?)");
|
|
$stmt->bind_param("ssss", $nama, $username, $hash, $role);
|
|
if ($stmt->execute()) {
|
|
$success = "User <b>$username</b> berhasil ditambahkan.";
|
|
} else {
|
|
$error = "Gagal menyimpan user: " . $stmt->error;
|
|
}
|
|
$stmt->close();
|
|
}
|
|
$cek->close();
|
|
}
|
|
}
|
|
|
|
// --- HAPUS USER ---
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'hapus') {
|
|
$id = (int) $_POST['id'];
|
|
|
|
// Tidak boleh hapus diri sendiri
|
|
if ($id === (int) $_SESSION['user']) {
|
|
$error = "Tidak bisa menghapus akun yang sedang aktif.";
|
|
} else {
|
|
$stmt = $conn->prepare("DELETE FROM users WHERE id = ?");
|
|
$stmt->bind_param("i", $id);
|
|
if ($stmt->execute()) {
|
|
$success = "User berhasil dihapus.";
|
|
} else {
|
|
$error = "Gagal menghapus user.";
|
|
}
|
|
$stmt->close();
|
|
}
|
|
}
|
|
|
|
// --- AMBIL SEMUA USER ---
|
|
$users = $conn->query("SELECT id, nama, username, role, created_at FROM users ORDER BY created_at DESC");
|
|
$conn->close();
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Kelola User - Sistem Pemetaan</title>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
|
|
body {
|
|
font-family: 'Segoe UI', sans-serif;
|
|
background: #f0f4f8;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
/* NAVBAR */
|
|
.navbar {
|
|
background: #1B2A4A;
|
|
color: white;
|
|
padding: 14px 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.navbar h1 {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.navbar a {
|
|
color: white;
|
|
text-decoration: none;
|
|
font-size: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
opacity: 0.85;
|
|
transition: opacity 0.2s;
|
|
}
|
|
|
|
.navbar a:hover { opacity: 1; }
|
|
|
|
/* CONTAINER */
|
|
.container {
|
|
max-width: 900px;
|
|
margin: 32px auto;
|
|
padding: 0 20px;
|
|
display: grid;
|
|
grid-template-columns: 1fr 320px;
|
|
gap: 24px;
|
|
align-items: start;
|
|
}
|
|
|
|
/* CARD */
|
|
.card {
|
|
background: white;
|
|
border-radius: 12px;
|
|
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.card-header {
|
|
background: #1B2A4A;
|
|
color: white;
|
|
padding: 16px 20px;
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.card-body { padding: 20px; }
|
|
|
|
/* ALERT */
|
|
.alert {
|
|
padding: 12px 16px;
|
|
border-radius: 8px;
|
|
font-size: 13px;
|
|
margin-bottom: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.alert-success { background: #eafaf1; color: #1e8449; }
|
|
.alert-error { background: #fdecea; color: #c0392b; }
|
|
|
|
/* TABEL */
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: 14px;
|
|
}
|
|
|
|
thead th {
|
|
background: #f0f4f8;
|
|
color: #555;
|
|
font-weight: 600;
|
|
padding: 10px 14px;
|
|
text-align: left;
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
tbody tr {
|
|
border-bottom: 1px solid #f0f4f8;
|
|
transition: background 0.15s;
|
|
}
|
|
|
|
tbody tr:hover { background: #fafbfc; }
|
|
|
|
tbody td {
|
|
padding: 12px 14px;
|
|
color: #333;
|
|
}
|
|
|
|
.badge {
|
|
display: inline-block;
|
|
padding: 3px 10px;
|
|
border-radius: 20px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.badge-admin { background: #1B2A4A; color: white; }
|
|
.badge-operator { background: #e8f4fd; color: #2471a3; }
|
|
|
|
.badge-me {
|
|
font-size: 10px;
|
|
background: #eafaf1;
|
|
color: #1e8449;
|
|
padding: 2px 6px;
|
|
border-radius: 10px;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
.btn-hapus {
|
|
background: none;
|
|
border: none;
|
|
color: #e74c3c;
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
padding: 4px 8px;
|
|
border-radius: 6px;
|
|
transition: background 0.15s;
|
|
}
|
|
|
|
.btn-hapus:hover { background: #fdecea; }
|
|
.btn-hapus:disabled { opacity: 0.3; cursor: not-allowed; }
|
|
|
|
/* FORM */
|
|
.form-group { margin-bottom: 14px; }
|
|
|
|
.form-group label {
|
|
display: block;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
color: #555;
|
|
margin-bottom: 5px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.4px;
|
|
}
|
|
|
|
.form-group input,
|
|
.form-group select {
|
|
width: 100%;
|
|
padding: 9px 12px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 8px;
|
|
font-size: 14px;
|
|
outline: none;
|
|
transition: border-color 0.2s;
|
|
}
|
|
|
|
.form-group input:focus,
|
|
.form-group select:focus {
|
|
border-color: #1B2A4A;
|
|
}
|
|
|
|
.btn-submit {
|
|
width: 100%;
|
|
padding: 11px;
|
|
background: #1B2A4A;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: background 0.2s;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.btn-submit:hover { background: #253d6e; }
|
|
|
|
@media (max-width: 680px) {
|
|
.container { grid-template-columns: 1fr; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<nav class="navbar">
|
|
<h1><i class="fa-solid fa-users-gear"></i> Kelola User</h1>
|
|
<a href="index.php">
|
|
<i class="fa-solid fa-map-location-dot"></i> Kembali ke Peta
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="container">
|
|
|
|
<!-- TABEL DAFTAR USER -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<i class="fa-solid fa-list"></i> Daftar User
|
|
</div>
|
|
<div class="card-body">
|
|
|
|
<?php if ($error): ?>
|
|
<div class="alert alert-error">
|
|
<i class="fa-solid fa-circle-exclamation"></i>
|
|
<?= $error ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($success): ?>
|
|
<div class="alert alert-success">
|
|
<i class="fa-solid fa-circle-check"></i>
|
|
<?= $success ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>Nama</th>
|
|
<th>Username</th>
|
|
<th>Role</th>
|
|
<th>Dibuat</th>
|
|
<th>Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php $no = 1; while ($u = $users->fetch_assoc()): ?>
|
|
<tr>
|
|
<td><?= $no++ ?></td>
|
|
<td>
|
|
<?= htmlspecialchars($u['nama']) ?>
|
|
<?php if ($u['id'] == $_SESSION['user']): ?>
|
|
<span class="badge-me">Anda</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($u['username']) ?></td>
|
|
<td>
|
|
<span class="badge badge-<?= $u['role'] ?>">
|
|
<?= ucfirst($u['role']) ?>
|
|
</span>
|
|
</td>
|
|
<td><?= date('d M Y', strtotime($u['created_at'])) ?></td>
|
|
<td>
|
|
<form method="POST" onsubmit="return konfirmasiHapus(this)">
|
|
<input type="hidden" name="action" value="hapus">
|
|
<input type="hidden" name="id" value="<?= $u['id'] ?>">
|
|
<button type="submit" class="btn-hapus"
|
|
<?= $u['id'] == $_SESSION['user'] ? 'disabled title="Tidak bisa hapus akun sendiri"' : '' ?>>
|
|
<i class="fa-solid fa-trash"></i> Hapus
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endwhile; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FORM TAMBAH USER -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<i class="fa-solid fa-user-plus"></i> Tambah User Baru
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="POST">
|
|
<input type="hidden" name="action" value="tambah">
|
|
|
|
<div class="form-group">
|
|
<label>Nama Lengkap</label>
|
|
<input type="text" name="nama" placeholder="Contoh: Budi Santoso" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Username</label>
|
|
<input type="text" name="username" placeholder="Contoh: budi123" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Password</label>
|
|
<input type="password" name="password" placeholder="Min. 6 karakter" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Role</label>
|
|
<select name="role">
|
|
<option value="operator">Operator</option>
|
|
<option value="admin">Admin</option>
|
|
</select>
|
|
</div>
|
|
|
|
<button type="submit" class="btn-submit">
|
|
<i class="fa-solid fa-user-plus"></i> Tambah User
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
function konfirmasiHapus(form) {
|
|
return confirm("Yakin ingin menghapus user ini?");
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|