From 6158f4b1a4d0786090fdcfde06016484e1a0eeb2 Mon Sep 17 00:00:00 2001 From: powji17 Date: Wed, 10 Jun 2026 17:39:36 +0700 Subject: [PATCH] menambahkan fitur edit data pengguna dan memperbarui landing page --- Pertemuan01/hapus_area.php | 18 - Pertemuan01/hapus_jalan.php | 38 -- Pertemuan01/index.html | 14 - Pertemuan01/load_area.php | 20 -- Pertemuan01/load_jalan.php | 18 - Pertemuan01/simpan_area.php | 33 -- Pertemuan01/simpan_jalan.php | 26 -- Pertemuan01/update_area.php | 31 -- Pertemuan01/update_jalan.php | 31 -- WebGISPovertyMapping/api/users/get_user.php | 19 + WebGISPovertyMapping/api/users/hapus_user.php | 28 ++ .../api/users/update_user.php | 55 +++ WebGISPovertyMapping/assets/css/style.css | 338 +++++++++++++----- WebGISPovertyMapping/index.php | 82 +++-- WebGISPovertyMapping/users.php | 251 ++++++++++--- index.php | 322 ++++++++++++++--- 16 files changed, 869 insertions(+), 455 deletions(-) delete mode 100644 Pertemuan01/hapus_area.php delete mode 100644 Pertemuan01/hapus_jalan.php delete mode 100644 Pertemuan01/load_area.php delete mode 100644 Pertemuan01/load_jalan.php delete mode 100644 Pertemuan01/simpan_area.php delete mode 100644 Pertemuan01/simpan_jalan.php delete mode 100644 Pertemuan01/update_area.php delete mode 100644 Pertemuan01/update_jalan.php create mode 100644 WebGISPovertyMapping/api/users/get_user.php create mode 100644 WebGISPovertyMapping/api/users/hapus_user.php create mode 100644 WebGISPovertyMapping/api/users/update_user.php diff --git a/Pertemuan01/hapus_area.php b/Pertemuan01/hapus_area.php deleted file mode 100644 index 819df19..0000000 --- a/Pertemuan01/hapus_area.php +++ /dev/null @@ -1,18 +0,0 @@ -prepare("DELETE FROM area_polygon WHERE id = ?"); - $stmt->bind_param("i", $id); - if ($stmt->execute()) { - echo json_encode(["status" => "success"]); - } else { - echo json_encode(["status" => "error", "message" => $stmt->error]); - } - $stmt->close(); -} -$conn->close(); -?> \ No newline at end of file diff --git a/Pertemuan01/hapus_jalan.php b/Pertemuan01/hapus_jalan.php deleted file mode 100644 index 175d531..0000000 --- a/Pertemuan01/hapus_jalan.php +++ /dev/null @@ -1,38 +0,0 @@ -connect_error) { - echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]); - exit; -} - -$data = json_decode(file_get_contents("php://input"), true); - -if ($data && isset($data['id'])) { - $id = $data['id']; - - // Hapus data dari tabel jalan_polyline berdasarkan ID - $stmt = $conn->prepare("DELETE FROM jalan_polyline WHERE id = ?"); - $stmt->bind_param("i", $id); - - if ($stmt->execute()) { - echo json_encode(["status" => "success", "message" => "Garis jalan berhasil dihapus"]); - } else { - echo json_encode(["status" => "error", "message" => "Gagal menghapus data: " . $stmt->error]); - } - - $stmt->close(); -} else { - echo json_encode(["status" => "error", "message" => "ID tidak valid"]); -} - -$conn->close(); -?> \ No newline at end of file diff --git a/Pertemuan01/index.html b/Pertemuan01/index.html index fa564f9..7bc731a 100644 --- a/Pertemuan01/index.html +++ b/Pertemuan01/index.html @@ -23,20 +23,6 @@ - - -
-
- -
diff --git a/Pertemuan01/load_area.php b/Pertemuan01/load_area.php deleted file mode 100644 index f583e4b..0000000 --- a/Pertemuan01/load_area.php +++ /dev/null @@ -1,20 +0,0 @@ -query($sql); -$data_area = array(); - -if ($result->num_rows > 0) { - while($row = $result->fetch_assoc()) { - // Mengubah string geojson dari database kembali menjadi Object JSON - // Ini wajib agar Leaflet.geoJSON() di Javascript bisa merendernya - $row['geojson'] = json_decode($row['geojson']); - $data_area[] = $row; - } -} - -echo json_encode($data_area); -$conn->close(); -?> \ No newline at end of file diff --git a/Pertemuan01/load_jalan.php b/Pertemuan01/load_jalan.php deleted file mode 100644 index 7455a87..0000000 --- a/Pertemuan01/load_jalan.php +++ /dev/null @@ -1,18 +0,0 @@ -query($sql); -$data_jalan = array(); - -if ($result->num_rows > 0) { - while($row = $result->fetch_assoc()) { - // Parse string geojson menjadi object agar mudah dibaca Javascript - $row['geojson'] = json_decode($row['geojson']); - $data_jalan[] = $row; - } -} -echo json_encode($data_jalan); -$conn->close(); -?> \ No newline at end of file diff --git a/Pertemuan01/simpan_area.php b/Pertemuan01/simpan_area.php deleted file mode 100644 index 566b5b0..0000000 --- a/Pertemuan01/simpan_area.php +++ /dev/null @@ -1,33 +0,0 @@ -prepare("INSERT INTO area_polygon (nama_kavling, status_kepemilikan, luas_m2, geojson) VALUES (?, ?, ?, ?)"); - - // Parameter: "ssds" berarti String, String, Double (Desimal), String - $stmt->bind_param("ssds", $nama_kavling, $status, $luas_m2, $geojson_string); - - if ($stmt->execute()) { - echo json_encode(["status" => "success", "id" => $stmt->insert_id]); - } else { - echo json_encode(["status" => "error", "message" => $stmt->error]); - } - $stmt->close(); -} else { - // Tambahkan pesan error jika data tidak lengkap - echo json_encode(["status" => "error", "message" => "Data area tidak lengkap"]); -} -$conn->close(); -?> \ No newline at end of file diff --git a/Pertemuan01/simpan_jalan.php b/Pertemuan01/simpan_jalan.php deleted file mode 100644 index 785c6b2..0000000 --- a/Pertemuan01/simpan_jalan.php +++ /dev/null @@ -1,26 +0,0 @@ -prepare("INSERT INTO jalan_polyline (nama_jalan, status, panjang_m, geojson) VALUES (?, ?, ?, ?)"); - $stmt->bind_param("ssds", $nama_jalan, $status, $panjang_m, $geojson_string); - - if ($stmt->execute()) { - echo json_encode(["status" => "success", "id" => $stmt->insert_id]); - } else { - echo json_encode(["status" => "error", "message" => $stmt->error]); - } - $stmt->close(); -} else { - echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]); -} -$conn->close(); -?> \ No newline at end of file diff --git a/Pertemuan01/update_area.php b/Pertemuan01/update_area.php deleted file mode 100644 index cf93d84..0000000 --- a/Pertemuan01/update_area.php +++ /dev/null @@ -1,31 +0,0 @@ -connect_error) { - echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]); - exit; -} - -$data = json_decode(file_get_contents("php://input"), true); - -if ($data && isset($data['id']) && isset($data['geojson'])) { - $id = $data['id']; - $luas_m2 = $data['luas_m2']; - $geojson_string = json_encode($data['geojson']); - - $stmt = $conn->prepare("UPDATE area_polygon SET luas_m2 = ?, geojson = ? WHERE id = ?"); - $stmt->bind_param("dsi", $luas_m2, $geojson_string, $id); - - if ($stmt->execute()) { - echo json_encode(["status" => "success"]); - } else { - echo json_encode(["status" => "error", "message" => $stmt->error]); - } - $stmt->close(); -} else { - echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]); -} -$conn->close(); -?> \ No newline at end of file diff --git a/Pertemuan01/update_jalan.php b/Pertemuan01/update_jalan.php deleted file mode 100644 index e36d3ff..0000000 --- a/Pertemuan01/update_jalan.php +++ /dev/null @@ -1,31 +0,0 @@ -connect_error) { - echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]); - exit; -} - -$data = json_decode(file_get_contents("php://input"), true); - -if ($data && isset($data['id']) && isset($data['geojson'])) { - $id = $data['id']; - $panjang_m = $data['panjang_m']; - $geojson_string = json_encode($data['geojson']); - - $stmt = $conn->prepare("UPDATE jalan_polyline SET panjang_m = ?, geojson = ? WHERE id = ?"); - $stmt->bind_param("dsi", $panjang_m, $geojson_string, $id); - - if ($stmt->execute()) { - echo json_encode(["status" => "success"]); - } else { - echo json_encode(["status" => "error", "message" => $stmt->error]); - } - $stmt->close(); -} else { - echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]); -} -$conn->close(); -?> \ No newline at end of file diff --git a/WebGISPovertyMapping/api/users/get_user.php b/WebGISPovertyMapping/api/users/get_user.php new file mode 100644 index 0000000..1a82274 --- /dev/null +++ b/WebGISPovertyMapping/api/users/get_user.php @@ -0,0 +1,19 @@ +prepare("SELECT id, nama, username, role FROM users WHERE id = ?"); +$stmt->bind_param("i", $id); +$stmt->execute(); +$result = $stmt->get_result(); +$data = $result->fetch_assoc(); + +echo $data ? json_encode($data) : json_encode(["status" => "error", "message" => "User tidak ditemukan"]); + +$stmt->close(); +$conn->close(); +?> \ No newline at end of file diff --git a/WebGISPovertyMapping/api/users/hapus_user.php b/WebGISPovertyMapping/api/users/hapus_user.php new file mode 100644 index 0000000..0181104 --- /dev/null +++ b/WebGISPovertyMapping/api/users/hapus_user.php @@ -0,0 +1,28 @@ + "error", "message" => "Tidak bisa menghapus akun sendiri"]); + exit; +} + +$stmt = $conn->prepare("DELETE FROM users WHERE id = ?"); +$stmt->bind_param("i", $id); + +if ($stmt->execute()) { + echo json_encode(["status" => "success"]); +} else { + echo json_encode(["status" => "error", "message" => $stmt->error]); +} + +$stmt->close(); +$conn->close(); +?> \ No newline at end of file diff --git a/WebGISPovertyMapping/api/users/update_user.php b/WebGISPovertyMapping/api/users/update_user.php new file mode 100644 index 0000000..1c2b289 --- /dev/null +++ b/WebGISPovertyMapping/api/users/update_user.php @@ -0,0 +1,55 @@ + "error", "message" => "Data tidak lengkap"]); + exit; +} + +$id = (int) $data['id']; +$nama = trim($data['nama']); +$username = trim($data['username']); +$role = $data['role']; + +if (!$nama || !$username || !in_array($role, ['admin', 'operator'])) { + echo json_encode(["status" => "error", "message" => "Data tidak valid"]); + exit; +} + +// Cek username sudah dipakai user lain +$cek = $conn->prepare("SELECT id FROM users WHERE username = ? AND id != ?"); +$cek->bind_param("si", $username, $id); +$cek->execute(); +$cek->store_result(); +if ($cek->num_rows > 0) { + echo json_encode(["status" => "error", "message" => "Username sudah digunakan user lain"]); + $cek->close(); + $conn->close(); + exit; +} +$cek->close(); + +// Update dengan atau tanpa password baru +if (!empty($data['password'])) { + $hash = password_hash($data['password'], PASSWORD_DEFAULT); + $stmt = $conn->prepare("UPDATE users SET nama=?, username=?, password=?, role=? WHERE id=?"); + $stmt->bind_param("ssssi", $nama, $username, $hash, $role, $id); +} else { + $stmt = $conn->prepare("UPDATE users SET nama=?, username=?, role=? WHERE id=?"); + $stmt->bind_param("sssi", $nama, $username, $role, $id); +} + +if ($stmt->execute()) { + echo json_encode(["status" => "success"]); +} else { + echo json_encode(["status" => "error", "message" => $stmt->error]); +} + +$stmt->close(); +$conn->close(); +?> \ No newline at end of file diff --git a/WebGISPovertyMapping/assets/css/style.css b/WebGISPovertyMapping/assets/css/style.css index b17bdfd..c89b3d7 100644 --- a/WebGISPovertyMapping/assets/css/style.css +++ b/WebGISPovertyMapping/assets/css/style.css @@ -1,83 +1,72 @@ +/* ===== RESET & BASE ===== */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + html, body { - height: 100vh; width: 100vw; margin: 0; padding: 0; - display: flex; font-family: Arial, sans-serif; overflow: hidden; -} - -#sidebar { - width: 280px; background-color: #f8f9fa; padding: 20px; - box-shadow: 2px 0 5px rgba(0,0,0,0.2); z-index: 1000; overflow-y: auto; -} - -#sidebar h3 { margin-top: 0; border-bottom: 2px solid #ddd; padding-bottom: 10px; } - -/* Styling Ikon Mode */ -.mode-selector { margin-bottom: 20px; } -.mode-buttons { + height: 100vh; + width: 100vw; + overflow: hidden; display: flex; - justify-content: center; - gap: 8px; - margin-bottom: 8px; -} -.mode-btn { - flex: 0 0 auto; /* tidak melebar penuh */ - width: 110px; - padding: 10px 8px; - text-align: center; -} -.mode-btn i { font-size: 24px; margin-bottom: 8px; display: block; } -.mode-btn:hover { background: #e9ecef; } - -/* Warna saat tombol mode aktif */ -.mode-btn.active[data-mode="point"] { border-color: #e74c3c; color: #e74c3c; background: #fadbd8; } -.mode-btn.active[data-mode="polyline"] { border-color: #3498db; color: #3498db; background: #d6eaf8; } -.mode-btn.active[data-mode="polygon"] { border-color: #2ecc71; color: #2ecc71; background: #d5f5e3; } -.mode-btn.active[data-mode="prasejahtera"] { border-color: #c0392b; color: #ffffff; background: #e74c3c; } -.mode-btn.active[data-mode="ibadah"] { border-color: #6c3483; color: #ffffff; background: #8e44ad; } -/* Styling tombol edit aktif */ -.mode-btn.active[data-mode="edit_jalan"] { background-color: #f1c40f !important; color: white !important; } -.mode-btn.active[data-mode="edit_kavling"] { background-color: #27ae60 !important; color: white !important; } - -/* Styling Input & Action Buttons */ -.action-buttons { - display: none; background: #fff; padding: 15px; - border-radius: 8px; border: 1px solid #ddd; margin-top: 10px; margin-bottom: 20px; + font-family: 'Segoe UI', Arial, sans-serif; } -.action-buttons input, .action-buttons select { - width: 100%; margin-bottom: 15px; padding: 8px; box-sizing: border-box; - border: 1px solid #ccc; border-radius: 4px; +/* ===== SIDEBAR ===== */ +#sidebar { + width: 280px; + min-width: 280px; + background: white; + display: flex; + flex-direction: column; + padding: 0; + box-shadow: 2px 0 12px rgba(0,0,0,0.10); + z-index: 1000; + overflow-y: auto; } -.action-buttons button { - width: 100%; padding: 10px; margin-bottom: 8px; cursor: pointer; - border-radius: 5px; font-weight: bold; +/* Header sidebar */ +.sidebar-header { + background: #1B2A4A; + color: white; + padding: 18px 20px; + font-size: 16px; + font-weight: 700; + display: flex; + align-items: center; + gap: 10px; + letter-spacing: 0.3px; + flex-shrink: 0; } -.btn-success { background-color: #2ecc71; color: white; border: none; } -.btn-danger { background-color: #e74c3c; color: white; border: none; } - -#map-container { flex: 1; position: relative; } -#map { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } +.sidebar-body { + padding: 16px; + display: flex; + flex-direction: column; + gap: 10px; + flex: 1; +} +/* ===== USER INFO ===== */ .user-info { display: flex; flex-direction: column; align-items: center; - padding: 12px; + padding: 16px 12px; background: #f0f4f8; - border-radius: 8px; - margin-bottom: 12px; - gap: 4px; + border-radius: 10px; + gap: 6px; } .user-info i { - font-size: 28px; + font-size: 32px; color: #1B2A4A; } .user-info span { - font-weight: 600; - font-size: 14px; + font-weight: 700; + font-size: 15px; color: #1B2A4A; } @@ -85,52 +74,219 @@ html, body { font-size: 11px; background: #1B2A4A; color: white; - padding: 2px 8px; + padding: 3px 10px; border-radius: 20px; text-transform: uppercase; + letter-spacing: 0.5px; } +/* ===== DIVIDER ===== */ +.sidebar-divider { + height: 1px; + background: #e8edf2; + margin: 2px 0; +} + +/* ===== LABEL SECTION ===== */ +.sidebar-label { + font-size: 11px; + font-weight: 700; + color: #aab4c0; + text-transform: uppercase; + letter-spacing: 0.8px; + padding: 0 2px; +} + +/* ===== TOMBOL MODE (Prasejahtera & Rumah Ibadah) ===== */ +.mode-buttons { + display: flex; + gap: 8px; + justify-content: center; +} + +.mode-btn { + flex: 1; + padding: 12px 6px; + background: #f0f4f8; + border: 2px solid transparent; + border-radius: 10px; + cursor: pointer; + font-size: 12px; + font-weight: 600; + color: #4a5568; + text-align: center; + transition: all 0.2s; + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + line-height: 1.3; +} + +.mode-btn i { + font-size: 20px; + color: #1B2A4A; + display: block; + margin-bottom: 0; +} + +.mode-btn:hover { + background: #e2e8f0; + border-color: #1B2A4A; +} + +/* Warna saat tombol mode aktif */ +.mode-btn.active, +.mode-btn.active[data-mode="prasejahtera"] { + background: #e74c3c; + border-color: #c0392b; + color: white; +} + +.mode-btn.active i, +.mode-btn.active[data-mode="prasejahtera"] i { + color: white; +} + +.mode-btn.active[data-mode="ibadah"], +.mode-btn.mode-ibadah.active { + background: #8e44ad; + border-color: #6c3483; + color: white; +} + +.mode-btn.active[data-mode="ibadah"] i, +.mode-btn.mode-ibadah.active i { + color: white; +} + +/* Mode lain (polyline, polygon, dll — tetap dipertahankan) */ +.mode-btn.active[data-mode="point"] { border-color: #e74c3c; color: #e74c3c; background: #fadbd8; } +.mode-btn.active[data-mode="polyline"] { border-color: #3498db; color: #3498db; background: #d6eaf8; } +.mode-btn.active[data-mode="polygon"] { border-color: #2ecc71; color: #2ecc71; background: #d5f5e3; } +.mode-btn.active[data-mode="edit_jalan"] { background: #f1c40f; border-color: #d4ac0d; color: white; } +.mode-btn.active[data-mode="edit_kavling"] { background: #27ae60; border-color: #1e8449; color: white; } + +/* ===== ACTION BUTTONS (panel dalam sidebar, dipertahankan) ===== */ +.action-buttons { + display: none; + background: #fff; + padding: 15px; + border-radius: 8px; + border: 1px solid #ddd; + margin-top: 4px; +} + +.action-buttons input, +.action-buttons select { + width: 100%; + margin-bottom: 15px; + padding: 8px; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 4px; +} + +.action-buttons button { + width: 100%; + padding: 10px; + margin-bottom: 8px; + cursor: pointer; + border-radius: 5px; + font-weight: bold; +} + +.btn-success { background-color: #2ecc71; color: white; border: none; } +.btn-danger { background-color: #e74c3c; color: white; border: none; } + +/* ===== MENU LINK (Kelola User) ===== */ +.menu-link { + display: flex; + align-items: center; + gap: 10px; + padding: 11px 14px; + background: #f0f4f8; + border-radius: 10px; + text-decoration: none; + font-size: 14px; + font-weight: 600; + color: #1B2A4A; + transition: background 0.2s; + width: 100%; + border: none; + cursor: pointer; +} + +.menu-link:hover { background: #e2e8f0; } + +/* ===== VIEWER INFO ===== */ .viewer-info { font-size: 13px; color: #888; text-align: center; - margin-bottom: 10px; -} - -.btn-login, .btn-logout, .menu-link { - display: block; - width: 100%; - padding: 10px; - text-align: center; - border-radius: 8px; - font-size: 14px; - font-weight: 600; - text-decoration: none; - margin-bottom: 8px; - cursor: pointer; - border: none; + padding: 12px; + background: #f0f4f8; + border-radius: 10px; } +/* ===== TOMBOL LOGIN & LOGOUT ===== */ .btn-login { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 12px; background: #1B2A4A; color: white; -} - -.btn-logout { - background: #fdecea; - color: #c0392b; -} - -.menu-link, -.btn-logout, -.btn-login { - width: auto; /* tidak full width lagi */ - display: block; - margin: 0 auto 8px auto; - padding: 10px 24px; - text-align: center; + border-radius: 10px; + text-decoration: none; + font-size: 14px; + font-weight: 600; + transition: background 0.2s; + width: 100%; + border: none; + cursor: pointer; } .btn-login:hover { background: #253d6e; } + +.btn-logout { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 11px; + background: #fdecea; + color: #c0392b; + border-radius: 10px; + text-decoration: none; + font-size: 14px; + font-weight: 600; + border: none; + cursor: pointer; + transition: background 0.2s; + width: 100%; + margin-top: auto; +} + .btn-logout:hover { background: #f5b7b1; } -.menu-link:hover { background: #dce4f0; } \ No newline at end of file + +/* ===== MAP CONTAINER ===== */ +#map-container { + flex: 1; + position: relative; +} + +#map { + position: absolute; + top: 0; bottom: 0; left: 0; right: 0; +} + +/* ===== LAYER CONTROL ===== */ +.leaflet-control-layers { + border-radius: 10px !important; + border: none !important; + box-shadow: 0 2px 12px rgba(0,0,0,0.12) !important; + font-family: 'Segoe UI', Arial, sans-serif !important; + font-size: 13px !important; +} \ No newline at end of file diff --git a/WebGISPovertyMapping/index.php b/WebGISPovertyMapping/index.php index c19a7e0..d269777 100644 --- a/WebGISPovertyMapping/index.php +++ b/WebGISPovertyMapping/index.php @@ -17,46 +17,62 @@ $role = $isLoggedIn ? $_SESSION['role'] : 'viewer'; - -
-
- Tambah User Baru + +
+ + +
+ + Tambah User Baru
+
-
- + + +
- +
- +
- + +
-
- + + +
@@ -390,8 +438,101 @@ $conn->close();
diff --git a/index.php b/index.php index 81f99a2..0d01b01 100644 --- a/index.php +++ b/index.php @@ -1,70 +1,298 @@ - - Landing Page - Tugas WebGIS + WebGIS Portfolio — Muhammad Fauzi + - -