Persiapan hosting: config DB, perbaikan role, fix redirect

This commit is contained in:
Athallah Ghathfan Aqila
2026-06-13 13:56:43 +07:00
parent e3d7750f11
commit 46e999a9d0
9 changed files with 255 additions and 26 deletions
+3
View File
@@ -25,3 +25,6 @@ desktop.ini
# Temp test files # Temp test files
uas/test_*.php uas/test_*.php
# Konfigurasi database (berisi kredensial — jangan di-push)
config.php
+193
View File
@@ -0,0 +1,193 @@
-- ================================================================
-- DATABASE: db_webgis (versi hosting — tanpa CREATE DATABASE/USE)
-- WebGIS SIG B - Tugas + UAS
-- Athallah Ghathfan Aqila | D1041231060 | Untan
-- Import file ini ke database yang sudah dibuat di InfinityFree
-- ================================================================
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ================================================================
-- BAGIAN TUGAS
-- ================================================================
CREATE TABLE IF NOT EXISTS spbu (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(255) NOT NULL,
nomor VARCHAR(50),
status_24jam ENUM('Ya','Tidak') DEFAULT 'Tidak',
lat DECIMAL(10,7) NOT NULL,
lng DECIMAL(10,7) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS jalan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_jalan VARCHAR(255) NOT NULL,
status_jalan ENUM('Nasional','Provinsi','Kabupaten') DEFAULT 'Kabupaten',
panjang_m DECIMAL(10,2),
geojson TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS persil (
id INT AUTO_INCREMENT PRIMARY KEY,
nomor_persil VARCHAR(100) NOT NULL,
status_milik ENUM('SHM','HGB','HGU','HP') DEFAULT 'SHM',
luas_m2 DECIMAL(12,2),
geojson TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS masjid (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_masjid VARCHAR(255) NOT NULL,
pic VARCHAR(100),
alamat TEXT,
radius_m INT DEFAULT 300,
lat DECIMAL(10,7) NOT NULL,
lng DECIMAL(10,7) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS kemiskinan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_kk VARCHAR(255) NOT NULL,
jumlah_kk INT DEFAULT 1,
alamat TEXT,
lat DECIMAL(10,7) NOT NULL,
lng DECIMAL(10,7) NOT NULL,
pkh TINYINT(1) NOT NULL DEFAULT 0,
bpnt TINYINT(1) NOT NULL DEFAULT 0,
blt TINYINT(1) NOT NULL DEFAULT 0,
foto VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS wilayah (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(255) NOT NULL,
tipe ENUM('RT','RW','Kelurahan','Kecamatan') DEFAULT 'RT',
geojson TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- ================================================================
-- BAGIAN UAS
-- ================================================================
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
nama VARCHAR(100),
role ENUM('admin','operator') DEFAULT 'operator',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS rumah_ibadah (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(255) NOT NULL,
jenis ENUM('Masjid','Musholla','Gereja Protestan','Gereja Katolik','Pura','Vihara','Klenteng','Lainnya') DEFAULT 'Masjid',
kontak VARCHAR(100),
alamat TEXT,
lat DECIMAL(10,7) NOT NULL,
lng DECIMAL(10,7) NOT NULL,
radius INT DEFAULT 300,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS penduduk_miskin (
id INT AUTO_INCREMENT PRIMARY KEY,
kk_nama VARCHAR(255) NOT NULL,
nik VARCHAR(20),
alamat TEXT,
kecamatan VARCHAR(100),
kelurahan VARCHAR(100),
lat DECIMAL(10,7) NOT NULL,
lng DECIMAL(10,7) NOT NULL,
jumlah_anggota INT DEFAULT 1,
rumah_ibadah_id INT,
jarak_meter DECIMAL(10,2),
status_bantuan ENUM('belum_dibantu','sudah_dibantu','menunggu_verifikasi') DEFAULT 'belum_dibantu',
jenis_bantuan VARCHAR(255),
tanggal_bantuan DATE,
bukti_file VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (rumah_ibadah_id) REFERENCES rumah_ibadah(id) ON DELETE SET NULL
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS anggota_keluarga (
id INT AUTO_INCREMENT PRIMARY KEY,
penduduk_id INT NOT NULL,
nama VARCHAR(255) NOT NULL,
hubungan VARCHAR(50),
umur INT,
pekerjaan VARCHAR(100),
keterangan TEXT,
FOREIGN KEY (penduduk_id) REFERENCES penduduk_miskin(id) ON DELETE CASCADE
) ENGINE=InnoDB;
-- ================================================================
-- DATA SAMPLE - TUGAS
-- ================================================================
INSERT IGNORE INTO spbu (nama, nomor, status_24jam, lat, lng) VALUES
('SPBU Gajahmada', '64.771.01', 'Ya', -0.0208, 109.3284),
('SPBU Ahmad Yani', '64.771.02', 'Ya', -0.0342, 109.3401),
('SPBU Tanjungpura', '64.771.03', 'Tidak', -0.0156, 109.3512),
('SPBU Sultan Hamid II', '64.771.04', 'Ya', -0.0470, 109.3350);
INSERT IGNORE INTO masjid (nama_masjid, pic, alamat, radius_m, lat, lng) VALUES
('Masjid Raya Mujahidin', 'H. Ahmad Fauzi', 'Jl. Gajahmada, Pontianak Selatan', 450, -0.0261, 109.3256),
('Masjid Al-Muhajirin', 'Ustadz Mahmud', 'Jl. Sutoyo, Pontianak Kota', 300, -0.0189, 109.3478),
('Masjid Nurul Huda', 'Ustadz Fahmi', 'Jl. Ahmad Yani, Pontianak Timur', 350, -0.0387, 109.3398),
('Masjid Jami Sultan', 'H. Ridwan', 'Jl. Tanjungpura, Pontianak Barat', 400, -0.0142, 109.3332);
INSERT IGNORE INTO kemiskinan (nama_kk, jumlah_kk, alamat, lat, lng, pkh, bpnt, blt) VALUES
('Ahmad Suryana', 4, 'Jl. Gajahmada Gg. 3', -0.0278, 109.3267, 1, 1, 0),
('Siti Rohana', 3, 'Jl. Sutoyo No. 8', -0.0201, 109.3461, 0, 1, 1),
('Budi Santoso', 5, 'Jl. Ahmad Yani No. 32', -0.0355, 109.3412, 1, 0, 0),
('Dewi Rahayu', 2, 'Jl. Tanjungpura No. 7', -0.0412, 109.3389, 0, 0, 1),
('Hendra Kusuma', 6, 'Jl. Imam Bonjol No. 21', -0.0167, 109.3502, 1, 1, 1),
('Ratna Wulandari', 3, 'Jl. Gusti Situt No. 5', -0.0301, 109.3220, 1, 0, 1),
('Suparman', 7, 'Jl. Pak Kasih No. 12', -0.0243, 109.3310, 0, 1, 0);
-- ================================================================
-- DATA SAMPLE - UAS
-- password = 'admin123'
-- ================================================================
INSERT IGNORE INTO users (username, password, nama, role) VALUES
('admin', '$2y$10$Ep64LS7KEQc2jKMu.AsH.O2wKF9ku4C8Cz0z4RHahgmYbz0vMr0/.', 'Administrator', 'admin'),
('operator', '$2y$10$Ep64LS7KEQc2jKMu.AsH.O2wKF9ku4C8Cz0z4RHahgmYbz0vMr0/.', 'Operator Lapangan', 'operator');
INSERT IGNORE INTO rumah_ibadah (id, nama, jenis, kontak, alamat, lat, lng, radius) VALUES
(1, 'Masjid Raya Mujahidin', 'Masjid', '0561-123456', 'Jl. Ahmad Yani, Pontianak', -0.0262, 109.3429, 500),
(2, 'Gereja Katedral Santo Yosef', 'Gereja Katolik', '0561-234567', 'Jl. Pattimura, Pontianak', -0.0312, 109.3301, 400),
(3, 'Vihara Bodhisattva Karaniya Metta', 'Vihara', '0561-345678', 'Jl. Tanjungpura, Pontianak', -0.0355, 109.3344, 350),
(4, 'Pura Agung Nusantara', 'Pura', '0561-456789', 'Jl. Gajah Mada, Pontianak', -0.0409, 109.3221, 400),
(5, 'Musholla Al-Ikhlas', 'Musholla', NULL, 'Jl. Kom Yos Sudarso, Pontianak', -0.0195, 109.3553, 250);
INSERT IGNORE INTO penduduk_miskin (id, kk_nama, nik, alamat, lat, lng, rumah_ibadah_id, jarak_meter, status_bantuan, jenis_bantuan, tanggal_bantuan) VALUES
(1, 'Ahmad Subandi', '6171011234560001', 'Gg. Melati No.3', -0.0290, 109.3410, 1, 312.5, 'sudah_dibantu', 'PKH', '2024-03-01'),
(2, 'Siti Rahayu', '6171021234560002', 'Jl. Budi Utomo Gg.5', -0.0278, 109.3450, 1, 245.0, 'belum_dibantu', NULL, NULL),
(3, 'Budi Santoso', '6171031234560003', 'Jl. Gusti Hamzah', -0.0320, 109.3290, 2, 198.3, 'menunggu_verifikasi', NULL, NULL),
(4, 'Maria Yuliana', '6171041234560004', 'Jl. Purnama Gg.2', -0.0350, 109.3320, 3, 267.1, 'sudah_dibantu', 'BPNT + PKH', '2024-01-15'),
(5, 'Wati Sari', '6171051234560005', 'Jl. Kom Yos Sudarso', -0.0188, 109.3561, 5, 89.4, 'belum_dibantu', NULL, NULL);
INSERT IGNORE INTO anggota_keluarga (penduduk_id, nama, hubungan, umur, pekerjaan) VALUES
(1, 'Ahmad Subandi', 'Kepala Keluarga', 45, 'Buruh Harian'),
(1, 'Dewi Subandi', 'Istri', 40, 'Ibu Rumah Tangga'),
(1, 'Rizki Subandi', 'Anak', 18, 'Pelajar'),
(2, 'Siti Rahayu', 'Kepala Keluarga', 38, 'Pedagang Kecil'),
(2, 'Putri Rahayu', 'Anak', 12, 'Pelajar'),
(3, 'Budi Santoso', 'Kepala Keluarga', 52, 'Tidak Bekerja'),
(3, 'Sari Santoso', 'Istri', 48, 'Buruh Cuci'),
(4, 'Maria Yuliana', 'Kepala Keluarga', 41, 'Pedagang'),
(5, 'Wati Sari', 'Kepala Keluarga', 33, 'Buruh');
SET FOREIGN_KEY_CHECKS = 1;
+23
View File
@@ -0,0 +1,23 @@
<?php
$host = 'ifuntanhub.dev';
$port = 33060;
$user = 'mysql';
$pass = '6PRtFLPtC2yBZyKyxuuitJWUtII078Kp6O0SEFhnGUTVcJX40K4HvUHtI8utyVFp';
$name = 'db_webgis';
$conn = new mysqli($host, $user, $pass, $name, $port);
if ($conn->connect_error) {
die("Koneksi gagal: " . $conn->connect_error . "\n");
}
echo "Koneksi berhasil!\n";
$sql = file_get_contents(__DIR__ . '/uas/db_webgis.sql');
if ($conn->multi_query($sql)) {
do {
$conn->store_result();
} while ($conn->next_result());
echo "Import selesai!\n";
} else {
echo "Error: " . $conn->error . "\n";
}
$conn->close();
+9 -5
View File
@@ -1,9 +1,13 @@
<?php <?php
$host = getenv('DB_HOST') ?: '127.0.0.1'; if (!defined('DB_HOST')) {
$user = getenv('DB_USER') ?: 'root'; $cfg = __DIR__ . '/config.php';
$pass = getenv('DB_PASS') ?: ''; if (file_exists($cfg)) require_once $cfg;
$name = getenv('DB_NAME') ?: 'db_webgis'; }
$port = (int)(getenv('DB_PORT') ?: 3306); $host = defined('DB_HOST') ? DB_HOST : (getenv('DB_HOST') ?: '127.0.0.1');
$user = defined('DB_USER') ? DB_USER : (getenv('DB_USER') ?: 'root');
$pass = defined('DB_PASS') ? DB_PASS : (getenv('DB_PASS') ?: '');
$name = defined('DB_NAME') ? DB_NAME : (getenv('DB_NAME') ?: 'db_webgis');
$port = defined('DB_PORT') ? (int)DB_PORT : (int)(getenv('DB_PORT') ?: 3306);
$conn = mysqli_connect($host, $user, $pass, $name, $port); $conn = mysqli_connect($host, $user, $pass, $name, $port);
if (!$conn) { if (!$conn) {
die(json_encode(['status' => 'error', 'message' => 'Koneksi database gagal: ' . mysqli_connect_error()])); die(json_encode(['status' => 'error', 'message' => 'Koneksi database gagal: ' . mysqli_connect_error()]));
+3 -3
View File
@@ -9,7 +9,7 @@ $action = $_POST['action'] ?? $_GET['action'] ?? 'list';
// ── LIST ──────────────────────────────────────────────────────── // ── LIST ────────────────────────────────────────────────────────
if ($action === 'list') { if ($action === 'list') {
$rows = mysqli_fetch_all( $rows = mysqli_fetch_all(
mysqli_query($conn, "SELECT id, username, nama, created_at FROM users ORDER BY nama"), mysqli_query($conn, "SELECT id, username, nama, role, created_at FROM users ORDER BY nama"),
MYSQLI_ASSOC MYSQLI_ASSOC
); );
echo json_encode(['status' => 'success', 'data' => $rows]); echo json_encode(['status' => 'success', 'data' => $rows]);
@@ -27,7 +27,7 @@ if ($action === 'add') {
exit; exit;
} }
$role = in_array($_POST['role'] ?? '', ['admin','superadmin']) ? $_POST['role'] : 'admin'; $role = in_array($_POST['role'] ?? '', ['admin','operator']) ? $_POST['role'] : 'operator';
$hash = password_hash($password, PASSWORD_DEFAULT); $hash = password_hash($password, PASSWORD_DEFAULT);
$st = mysqli_prepare($conn, "INSERT INTO users (username, password, nama, role) VALUES (?,?,?,?)"); $st = mysqli_prepare($conn, "INSERT INTO users (username, password, nama, role) VALUES (?,?,?,?)");
mysqli_stmt_bind_param($st, 'ssss', $username, $hash, $nama, $role); mysqli_stmt_bind_param($st, 'ssss', $username, $hash, $nama, $role);
@@ -46,7 +46,7 @@ if ($action === 'update') {
$id = (int)($_POST['id'] ?? 0); $id = (int)($_POST['id'] ?? 0);
$nama = trim($_POST['nama'] ?? ''); $nama = trim($_POST['nama'] ?? '');
$pass = $_POST['password'] ?? ''; $pass = $_POST['password'] ?? '';
$role = in_array($_POST['role'] ?? '', ['admin','superadmin']) ? $_POST['role'] : 'admin'; $role = in_array($_POST['role'] ?? '', ['admin','operator']) ? $_POST['role'] : 'operator';
if ($id <= 0 || !$nama) { if ($id <= 0 || !$nama) {
echo json_encode(['status' => 'error', 'message' => 'Data tidak valid']); echo json_encode(['status' => 'error', 'message' => 'Data tidak valid']);
+4 -4
View File
@@ -8,22 +8,22 @@ function requireLogin() {
echo json_encode(['status' => 'error', 'message' => 'Sesi habis, silakan login kembali.']); echo json_encode(['status' => 'error', 'message' => 'Sesi habis, silakan login kembali.']);
exit; exit;
} }
header('Location: /uas/login.php'); header('Location: login.php');
exit; exit;
} }
} }
function requireSuperAdmin() { function requireSuperAdmin() {
requireLogin(); requireLogin();
if ($_SESSION['user']['role'] !== 'superadmin') { if ($_SESSION['user']['role'] !== 'admin') {
http_response_code(403); http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Akses ditolak. Hanya superadmin.']); echo json_encode(['status' => 'error', 'message' => 'Akses ditolak. Hanya admin.']);
exit; exit;
} }
} }
function isSuperAdmin() { function isSuperAdmin() {
return ($_SESSION['user']['role'] ?? '') === 'superadmin'; return ($_SESSION['user']['role'] ?? '') === 'admin';
} }
function currentUser() { function currentUser() {
+13 -7
View File
@@ -1,10 +1,14 @@
<?php <?php
if (isset($conn)) return; if (isset($conn)) return;
$host = getenv('DB_HOST') ?: '127.0.0.1'; if (!defined('DB_HOST')) {
$user = getenv('DB_USER') ?: 'root'; $cfg = dirname(__DIR__) . '/config.php';
$pass = getenv('DB_PASS') ?: ''; if (file_exists($cfg)) require_once $cfg;
$name = getenv('DB_NAME') ?: 'db_webgis'; }
$port = (int)(getenv('DB_PORT') ?: 3306); $host = defined('DB_HOST') ? DB_HOST : (getenv('DB_HOST') ?: '127.0.0.1');
$user = defined('DB_USER') ? DB_USER : (getenv('DB_USER') ?: 'root');
$pass = defined('DB_PASS') ? DB_PASS : (getenv('DB_PASS') ?: '');
$name = defined('DB_NAME') ? DB_NAME : (getenv('DB_NAME') ?: 'db_webgis');
$port = defined('DB_PORT') ? (int)DB_PORT : (int)(getenv('DB_PORT') ?: 3306);
$conn = mysqli_init(); $conn = mysqli_init();
mysqli_options($conn, MYSQLI_OPT_CONNECT_TIMEOUT, 5); mysqli_options($conn, MYSQLI_OPT_CONNECT_TIMEOUT, 5);
$ok = @mysqli_real_connect($conn, $host, $user, $pass, $name, $port); $ok = @mysqli_real_connect($conn, $host, $user, $pass, $name, $port);
@@ -23,7 +27,7 @@ if (!isset($GLOBALS[$setup_flag])) {
username VARCHAR(50) UNIQUE NOT NULL, username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL,
nama VARCHAR(100), nama VARCHAR(100),
role ENUM('superadmin','admin','operator') DEFAULT 'operator', role ENUM('admin','operator') DEFAULT 'operator',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)"); )");
$conn->query("CREATE TABLE IF NOT EXISTS rumah_ibadah ( $conn->query("CREATE TABLE IF NOT EXISTS rumah_ibadah (
@@ -55,10 +59,12 @@ if (!isset($GLOBALS[$setup_flag])) {
hubungan VARCHAR(50), umur INT, pekerjaan VARCHAR(100), keterangan TEXT, hubungan VARCHAR(50), umur INT, pekerjaan VARCHAR(100), keterangan TEXT,
FOREIGN KEY (penduduk_id) REFERENCES penduduk_miskin(id) ON DELETE CASCADE FOREIGN KEY (penduduk_id) REFERENCES penduduk_miskin(id) ON DELETE CASCADE
)"); )");
$conn->query("UPDATE users SET role='admin' WHERE role='superadmin'");
$conn->query("ALTER TABLE users MODIFY COLUMN role ENUM('admin','operator') DEFAULT 'operator'");
$count = $conn->query("SELECT COUNT(*) FROM users")->fetch_row()[0]; $count = $conn->query("SELECT COUNT(*) FROM users")->fetch_row()[0];
if ($count == 0) { if ($count == 0) {
$hash = '$2y$10$Ep64LS7KEQc2jKMu.AsH.O2wKF9ku4C8Cz0z4RHahgmYbz0vMr0/.'; $hash = '$2y$10$Ep64LS7KEQc2jKMu.AsH.O2wKF9ku4C8Cz0z4RHahgmYbz0vMr0/.';
$conn->query("INSERT INTO users (username,password,nama,role) VALUES ('admin','$hash','Administrator','superadmin')"); $conn->query("INSERT INTO users (username,password,nama,role) VALUES ('admin','$hash','Administrator','admin')");
$conn->query("INSERT INTO users (username,password,nama,role) VALUES ('operator','$hash','Operator Lapangan','operator')"); $conn->query("INSERT INTO users (username,password,nama,role) VALUES ('operator','$hash','Operator Lapangan','operator')");
} }
$conn->query("INSERT IGNORE INTO rumah_ibadah (id,nama,jenis,kontak,alamat,lat,lng,radius) VALUES $conn->query("INSERT IGNORE INTO rumah_ibadah (id,nama,jenis,kontak,alamat,lat,lng,radius) VALUES
+1 -1
View File
@@ -127,7 +127,7 @@ input::placeholder{color:#94a3b8}
<p class="hint">Default: <span>admin</span> / <span>admin123</span></p> <p class="hint">Default: <span>admin</span> / <span>admin123</span></p>
<div style="text-align:center;margin-top:20px;padding-top:20px;border-top:1px solid #1e293b"> <div style="text-align:center;margin-top:20px;padding-top:20px;border-top:1px solid #1e293b">
<a href="/index.php" style="color:#475569;font-size:12px;text-decoration:none;display:inline-flex;align-items:center;gap:6px;transition:.15s" onmouseover="this.style.color='#94a3b8'" onmouseout="this.style.color='#475569'"> <a href="../index.php" style="color:#475569;font-size:12px;text-decoration:none;display:inline-flex;align-items:center;gap:6px;transition:.15s" onmouseover="this.style.color='#94a3b8'" onmouseout="this.style.color='#475569'">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg> <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
Kembali ke Portal Kembali ke Portal
</a> </a>
+6 -6
View File
@@ -41,8 +41,8 @@ tbody tr:hover td{background:rgba(255,255,255,.02)}
.u-name{font-weight:600;font-size:13px} .u-name{font-weight:600;font-size:13px}
.u-un{font-size:11px;color:var(--muted);margin-top:2px;font-family:monospace} .u-un{font-size:11px;color:var(--muted);margin-top:2px;font-family:monospace}
.badge{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:600} .badge{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:600}
.badge-superadmin{background:rgba(99,102,241,.2);color:#a5b4fc} .badge-admin{background:rgba(99,102,241,.2);color:#a5b4fc}
.badge-admin{background:rgba(100,116,139,.2);color:#94a3b8} .badge-operator{background:rgba(100,116,139,.2);color:#94a3b8}
.me-tag{display:inline-flex;align-items:center;gap:4px;font-size:10px;background:rgba(245,158,11,.15);color:#fbbf24;padding:2px 8px;border-radius:8px;margin-left:8px;font-weight:600} .me-tag{display:inline-flex;align-items:center;gap:4px;font-size:10px;background:rgba(245,158,11,.15);color:#fbbf24;padding:2px 8px;border-radius:8px;margin-left:8px;font-weight:600}
.btn-sm{display:inline-flex;align-items:center;gap:5px;padding:6px 12px;border-radius:8px;font-size:12px;font-weight:500;cursor:pointer;font-family:inherit;transition:var(--trans);border:none} .btn-sm{display:inline-flex;align-items:center;gap:5px;padding:6px 12px;border-radius:8px;font-size:12px;font-weight:500;cursor:pointer;font-family:inherit;transition:var(--trans);border:none}
.btn-edit{background:rgba(59,130,246,.1);color:var(--blue);border:1px solid rgba(59,130,246,.2)} .btn-edit{background:rgba(59,130,246,.1);color:var(--blue);border:1px solid rgba(59,130,246,.2)}
@@ -100,7 +100,7 @@ tbody tr:hover td{background:rgba(255,255,255,.02)}
</div> </div>
<?php if (!$isSuperAdmin): ?> <?php if (!$isSuperAdmin): ?>
<div class="no-access"><i class="fas fa-lock" style="margin-right:8px"></i>Hanya superadmin yang dapat mengelola pengguna. Role kamu: <strong><?= $user['role'] ?></strong></div> <div class="no-access"><i class="fas fa-lock" style="margin-right:8px"></i>Hanya admin yang dapat mengelola pengguna. Role kamu: <strong><?= $user['role'] ?></strong></div>
<?php endif; ?> <?php endif; ?>
<div class="card"> <div class="card">
@@ -146,7 +146,7 @@ tbody tr:hover td{background:rgba(255,255,255,.02)}
<label>Role <span class="req">*</span></label> <label>Role <span class="req">*</span></label>
<select id="f-role"> <select id="f-role">
<option value="admin">Admin</option> <option value="admin">Admin</option>
<option value="superadmin">Superadmin</option> <option value="operator">Operator</option>
</select> </select>
</div> </div>
</div> </div>
@@ -229,8 +229,8 @@ function renderUsers(rows) {
const isMe = parseInt(u.id) === MY_ID; const isMe = parseInt(u.id) === MY_ID;
const color = avatarColor(u.nama || u.username); const color = avatarColor(u.nama || u.username);
const init = (u.nama || u.username || '?')[0].toUpperCase(); const init = (u.nama || u.username || '?')[0].toUpperCase();
const roleC = u.role === 'superadmin' ? 'badge-superadmin' : 'badge-admin'; const roleC = u.role === 'admin' ? 'badge-admin' : 'badge-operator';
const roleI = u.role === 'superadmin' ? 'shield-alt' : 'user'; const roleI = u.role === 'admin' ? 'shield-alt' : 'user';
const acols = IS_SUPER ? ` const acols = IS_SUPER ? `
<td style="text-align:right;white-space:nowrap"> <td style="text-align:right;white-space:nowrap">
<button class="btn-sm btn-edit" onclick='openEdit(${JSON.stringify(u)})'> <button class="btn-sm btn-edit" onclick='openEdit(${JSON.stringify(u)})'>