From 7c1b4375e7d9d77aee8e6f5bb2c87219fa2ac396 Mon Sep 17 00:00:00 2001 From: powji17 Date: Wed, 10 Jun 2026 16:02:04 +0700 Subject: [PATCH] menambahkan fitur login dan edit data --- .../api/prasejahtera/get_prasejahtera.php | 19 + .../api/prasejahtera/hapus_prasejahtera.php | 3 + .../api/prasejahtera/simpan_prasejahtera.php | 3 + .../api/prasejahtera/update_prasejahtera.php | 46 +- .../api/rumahibadah/get_ibadah.php | 19 + .../api/rumahibadah/hapus_ibadah.php | 3 + .../api/rumahibadah/simpan_ibadah.php | 3 + .../api/rumahibadah/update_ibadah.php | 37 +- WebGISPovertyMapping/assets/css/style.css | 92 +++- WebGISPovertyMapping/assets/js/script.js | 274 +++++++++++- WebGISPovertyMapping/auth.php | 35 ++ WebGISPovertyMapping/index.html | 37 -- WebGISPovertyMapping/index.php | 77 ++++ WebGISPovertyMapping/login.php | 209 +++++++++ WebGISPovertyMapping/logout.php | 6 + WebGISPovertyMapping/users.php | 399 ++++++++++++++++++ index.html => index.php | 6 +- 17 files changed, 1201 insertions(+), 67 deletions(-) create mode 100644 WebGISPovertyMapping/api/prasejahtera/get_prasejahtera.php create mode 100644 WebGISPovertyMapping/api/rumahibadah/get_ibadah.php create mode 100644 WebGISPovertyMapping/auth.php delete mode 100644 WebGISPovertyMapping/index.html create mode 100644 WebGISPovertyMapping/index.php create mode 100644 WebGISPovertyMapping/login.php create mode 100644 WebGISPovertyMapping/logout.php create mode 100644 WebGISPovertyMapping/users.php rename index.html => index.php (85%) diff --git a/WebGISPovertyMapping/api/prasejahtera/get_prasejahtera.php b/WebGISPovertyMapping/api/prasejahtera/get_prasejahtera.php new file mode 100644 index 0000000..7344961 --- /dev/null +++ b/WebGISPovertyMapping/api/prasejahtera/get_prasejahtera.php @@ -0,0 +1,19 @@ +prepare("SELECT * FROM rumah_prasejahtera 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" => "Data tidak ditemukan"]); + +$stmt->close(); +$conn->close(); +?> \ No newline at end of file diff --git a/WebGISPovertyMapping/api/prasejahtera/hapus_prasejahtera.php b/WebGISPovertyMapping/api/prasejahtera/hapus_prasejahtera.php index a231a56..4338d33 100644 --- a/WebGISPovertyMapping/api/prasejahtera/hapus_prasejahtera.php +++ b/WebGISPovertyMapping/api/prasejahtera/hapus_prasejahtera.php @@ -1,4 +1,7 @@ prepare("UPDATE rumah_prasejahtera SET lat=?, lng=? WHERE id=?"); -$stmt->bind_param("ddi", $data['lat'], $data['lng'], $data['id']); -echo $stmt->execute() - ? json_encode(['status' => 'success']) - : json_encode(['status' => 'error']); +$conn = new mysqli("localhost", "root", "", "webgis"); +$data = json_decode(file_get_contents("php://input"), true); + +if (!$data || !isset($data['id'])) { + echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]); + exit; +} + +// Update koordinat saja (dari drag marker) +if (isset($data['lat']) && isset($data['lng']) && count($data) === 3) { + $stmt = $conn->prepare("UPDATE rumah_prasejahtera SET lat=?, lng=? WHERE id=?"); + $stmt->bind_param("ddi", $data['lat'], $data['lng'], $data['id']); + +// Update semua field (dari form edit) +} else { + $stmt = $conn->prepare("UPDATE rumah_prasejahtera SET + nama_kepala_keluarga=?, penghasilan=?, jumlah_anak=?, umur_anak=?, + status_ortu=?, ada_pensiun=?, nominal_pensiun=?, + ada_terusan=?, nominal_terusan=?, keterangan=? + WHERE id=?"); + $stmt->bind_param("sdisssdsdsi", + $data['nama_kk'], $data['penghasilan'], $data['jumlah_anak'], + $data['umur_anak'], $data['status_ortu'], $data['ada_pensiun'], + $data['nominal_pensiun'], $data['ada_terusan'], $data['nominal_terusan'], + $data['keterangan'], $data['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/rumahibadah/get_ibadah.php b/WebGISPovertyMapping/api/rumahibadah/get_ibadah.php new file mode 100644 index 0000000..109fa87 --- /dev/null +++ b/WebGISPovertyMapping/api/rumahibadah/get_ibadah.php @@ -0,0 +1,19 @@ +prepare("SELECT * FROM rumah_ibadah 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" => "Data tidak ditemukan"]); + +$stmt->close(); +$conn->close(); +?> \ No newline at end of file diff --git a/WebGISPovertyMapping/api/rumahibadah/hapus_ibadah.php b/WebGISPovertyMapping/api/rumahibadah/hapus_ibadah.php index d67571d..0eeba62 100644 --- a/WebGISPovertyMapping/api/rumahibadah/hapus_ibadah.php +++ b/WebGISPovertyMapping/api/rumahibadah/hapus_ibadah.php @@ -1,4 +1,7 @@ prepare("UPDATE rumah_ibadah SET lat=?, lng=? WHERE id=?"); -$stmt->bind_param("ddi", $data['lat'], $data['lng'], $data['id']); -echo $stmt->execute() - ? json_encode(['status' => 'success']) - : json_encode(['status' => 'error']); +$conn = new mysqli("localhost", "root", "", "webgis"); +$data = json_decode(file_get_contents("php://input"), true); + +if (!$data || !isset($data['id'])) { + echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]); + exit; +} + +// Update koordinat saja (dari drag marker) +if (isset($data['lat']) && isset($data['lng']) && count($data) === 3) { + $stmt = $conn->prepare("UPDATE rumah_ibadah SET lat=?, lng=? WHERE id=?"); + $stmt->bind_param("ddi", $data['lat'], $data['lng'], $data['id']); + +// Update semua field (dari form edit) +} else { + $stmt = $conn->prepare("UPDATE rumah_ibadah SET nama_ibadah=?, jenis=?, radius_m=? WHERE id=?"); + $stmt->bind_param("ssii", $data['nama_ibadah'], $data['jenis'], $data['radius_m'], $data['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 352ba25..b17bdfd 100644 --- a/WebGISPovertyMapping/assets/css/style.css +++ b/WebGISPovertyMapping/assets/css/style.css @@ -12,11 +12,17 @@ html, body { /* Styling Ikon Mode */ .mode-selector { margin-bottom: 20px; } -.mode-buttons { display: flex; gap: 10px; justify-content: space-between; } +.mode-buttons { + display: flex; + justify-content: center; + gap: 8px; + margin-bottom: 8px; +} .mode-btn { - flex: 1; padding: 15px 5px; background: #fff; border: 2px solid #ccc; - border-radius: 8px; cursor: pointer; text-align: center; - transition: all 0.3s ease; color: #555; font-size: 12px; font-weight: bold; + 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; } @@ -51,4 +57,80 @@ html, body { .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; } \ No newline at end of file +#map { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } + +.user-info { + display: flex; + flex-direction: column; + align-items: center; + padding: 12px; + background: #f0f4f8; + border-radius: 8px; + margin-bottom: 12px; + gap: 4px; +} + +.user-info i { + font-size: 28px; + color: #1B2A4A; +} + +.user-info span { + font-weight: 600; + font-size: 14px; + color: #1B2A4A; +} + +.user-info small { + font-size: 11px; + background: #1B2A4A; + color: white; + padding: 2px 8px; + border-radius: 20px; + text-transform: uppercase; +} + +.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; +} + +.btn-login { + 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; +} + +.btn-login:hover { background: #253d6e; } +.btn-logout:hover { background: #f5b7b1; } +.menu-link:hover { background: #dce4f0; } \ No newline at end of file diff --git a/WebGISPovertyMapping/assets/js/script.js b/WebGISPovertyMapping/assets/js/script.js index 481372e..df96197 100644 --- a/WebGISPovertyMapping/assets/js/script.js +++ b/WebGISPovertyMapping/assets/js/script.js @@ -117,6 +117,8 @@ function perbaruiWarnaPrasejahtera() { // --- MANAJEMEN MODE UI --- function ubahMode(mode) { + if (ROLE === 'viewer') return; + console.log('Mode diklik:', mode, '| Mode saat ini:', currentMode); // ← tambah ini if (currentMode === mode) { @@ -169,7 +171,10 @@ function ubahMode(mode) { function loadIbadah() { fetch('api/rumahibadah/load_ibadah.php').then(res => res.json()).then(data => { data.forEach(ib => { - let marker = L.marker([ib.lat, ib.lng], { icon: buatIkonIbadah(ib.jenis), draggable: true }) + let marker = L.marker([ib.lat, ib.lng], { + icon: buatIkonIbadah(ib.jenis), + draggable: ROLE === 'admin' || ROLE === 'operator' + }) .addTo(layerIbadah); // Lingkaran radius @@ -178,9 +183,27 @@ function loadIbadah() { fillColor: '#8e44ad', fillOpacity: 0.1, weight: 1, dashArray: '5,5' }).addTo(layerIbadah); - marker.bindPopup(`${ib.nama_ibadah}
Jenis Rumah Ibadah: ${ib.jenis}
Jangkauan Bantuan: ${ib.radius_m} m
- `); + marker.bindPopup(`${ib.nama_ibadah}
+ Jenis Rumah Ibadah: ${ib.jenis}
+ Jangkauan Bantuan: ${ib.radius_m} m +
+
+ ${ROLE === 'admin' || ROLE === 'operator' ? ` + + ` : ''} + ${ROLE === 'admin' ? ` + + ` : ''} +
` + ); marker.on('dragend', function(e) { let pos = e.target.getLatLng(); @@ -225,13 +248,29 @@ function loadDB() { ${statusOrtuTeks} Keterangan: ${rumah.keterangan || '-'}

- +
+ ${ROLE === 'admin' || ROLE === 'operator' ? ` + + ` : ''} + ${ROLE === 'admin' ? ` + + ` : ''} +
`; - let marker = L.marker([rumah.lat, rumah.lng], { icon: ikonPrasejahtera, draggable: true }) + let marker = L.marker([rumah.lat, rumah.lng], { + icon: ikonPrasejahtera, + draggable: ROLE === 'admin' || ROLE === 'operator' + }) .addTo(layerPrasejahtera); marker.bindPopup(isiPopup); marker.on('dragend', function(e) { @@ -266,6 +305,8 @@ function refreshPeta() { // --- EVENT KLIK PETA --- function onMapClick(e) { + if (ROLE === 'viewer') return; + if (currentMode === 'point') { let formHtml = `
@@ -516,4 +557,221 @@ function toggleTerusan() { let ada = document.getElementById('ada_terusan').value; document.getElementById('grup_nominal_terusan').style.display = (ada === 'Ya') ? 'block' : 'none'; if(ada === 'Tidak') document.getElementById('nominal_terusan').value = 0; +} + +// --- EDIT PRASEJAHTERA --- +function editPrasejahtera(id) { + fetch(`api/prasejahtera/get_prasejahtera.php?id=${id}`) + .then(res => res.json()) + .then(d => { + let formHtml = ` +
+

+ Edit Data Prasejahtera +

+ + + + + + + + + + + + + +
+ + +
+ +
+ + +
+ + +
+
+ +
+ + +
+ + +
+
+ + + + + +
`; + + // Ganti konten popup yang sudah terbuka dengan form edit + daftarMarker['p_' + id].getPopup().setContent(formHtml); + }) + .catch(() => Toast.fire({ icon: 'error', title: 'Gagal memuat data!' })); +} + +function toggleEditStatusOrtu() { + let status = document.getElementById('edit_status_ortu').value; + document.getElementById('edit_grup_bekerja').style.display = status === 'Bekerja' ? 'block' : 'none'; + document.getElementById('edit_grup_pensiun').style.display = status === 'Pensiun' ? 'block' : 'none'; + document.getElementById('edit_grup_meninggal').style.display = status === 'Meninggal' ? 'block' : 'none'; + if (status !== 'Bekerja') document.getElementById('edit_penghasilan').value = 0; + if (status !== 'Pensiun') { document.getElementById('edit_ada_pensiun').value = 'Tidak'; toggleEditPensiun(); } + if (status !== 'Meninggal') { document.getElementById('edit_ada_terusan').value = 'Tidak'; toggleEditTerusan(); } +} + +function toggleEditPensiun() { + let ada = document.getElementById('edit_ada_pensiun').value; + document.getElementById('edit_grup_nominal_pensiun').style.display = ada === 'Ya' ? 'block' : 'none'; + if (ada === 'Tidak') document.getElementById('edit_nominal_pensiun').value = 0; +} + +function toggleEditTerusan() { + let ada = document.getElementById('edit_ada_terusan').value; + document.getElementById('edit_grup_nominal_terusan').style.display = ada === 'Ya' ? 'block' : 'none'; + if (ada === 'Tidak') document.getElementById('edit_nominal_terusan').value = 0; +} + +function simpanEditPrasejahtera(id) { + let nama_kk = document.getElementById('edit_nama_kk').value.trim(); + if (!nama_kk) { + Toast.fire({ icon: 'warning', title: 'Nama Kepala Keluarga wajib diisi!' }); + return; + } + + let dataKirim = { + id: id, + nama_kk: nama_kk, + jumlah_anak: parseInt(document.getElementById('edit_jumlah_anak').value) || 0, + umur_anak: document.getElementById('edit_umur_anak').value, + status_ortu: document.getElementById('edit_status_ortu').value, + penghasilan: parseInt(document.getElementById('edit_penghasilan').value) || 0, + ada_pensiun: document.getElementById('edit_ada_pensiun').value, + nominal_pensiun: parseInt(document.getElementById('edit_nominal_pensiun').value) || 0, + ada_terusan: document.getElementById('edit_ada_terusan').value, + nominal_terusan: parseInt(document.getElementById('edit_nominal_terusan').value) || 0, + keterangan: document.getElementById('edit_keterangan').value + }; + + fetch('api/prasejahtera/update_prasejahtera.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(dataKirim) + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + Toast.fire({ icon: 'success', title: 'Data Berhasil Diperbarui!' }); + map.closePopup(); + refreshPeta(); + } else { + Toast.fire({ icon: 'error', title: 'Gagal: ' + (data.message || 'Error') }); + } + }); +} + +// --- EDIT IBADAH --- +function editIbadah(id) { + fetch(`api/rumahibadah/get_ibadah.php?id=${id}`) + .then(res => res.json()) + .then(d => { + let jenisOptions = ['Masjid', 'Gereja', 'Vihara', 'Pura', 'Klenteng'].map(j => + `` + ).join(''); + + let formHtml = ` +
+

+ Edit Rumah Ibadah +

+ + + + + + + + + + + +
`; + + daftarMarker['ib_' + id].getPopup().setContent(formHtml); + }) + .catch(() => Toast.fire({ icon: 'error', title: 'Gagal memuat data!' })); +} + +function simpanEditIbadah(id) { + let nama = document.getElementById('edit_nama_ibadah').value.trim(); + if (!nama) { + Toast.fire({ icon: 'warning', title: 'Nama Rumah Ibadah wajib diisi!' }); + return; + } + + let dataKirim = { + id: id, + nama_ibadah: nama, + jenis: document.getElementById('edit_jenis_ibadah').value, + radius_m: parseInt(document.getElementById('edit_radius_ibadah').value) + }; + + fetch('api/rumahibadah/update_ibadah.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(dataKirim) + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'success') { + Toast.fire({ icon: 'success', title: 'Rumah Ibadah Diperbarui!' }); + map.closePopup(); + refreshPeta(); + } else { + Toast.fire({ icon: 'error', title: 'Gagal: ' + (data.message || 'Error') }); + } + }); } \ No newline at end of file diff --git a/WebGISPovertyMapping/auth.php b/WebGISPovertyMapping/auth.php new file mode 100644 index 0000000..01bf71e --- /dev/null +++ b/WebGISPovertyMapping/auth.php @@ -0,0 +1,35 @@ + "error", "message" => "Akses ditolak."]); + exit; + } +} + +/** + * Helper: cek role tanpa exit, untuk dipakai di kondisi if + */ +function hasRole(...$roles) { + return isset($_SESSION['role']) && in_array($_SESSION['role'], $roles); +} \ No newline at end of file diff --git a/WebGISPovertyMapping/index.html b/WebGISPovertyMapping/index.html deleted file mode 100644 index e31f272..0000000 --- a/WebGISPovertyMapping/index.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Sistem Pemetaan - - - - - - - - - - - - -
-
-
- - - - - - - \ No newline at end of file diff --git a/WebGISPovertyMapping/index.php b/WebGISPovertyMapping/index.php new file mode 100644 index 0000000..c19a7e0 --- /dev/null +++ b/WebGISPovertyMapping/index.php @@ -0,0 +1,77 @@ + + + + + + + Sistem Pemetaan + + + + + + + + + +
+
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/WebGISPovertyMapping/login.php b/WebGISPovertyMapping/login.php new file mode 100644 index 0000000..36ce25c --- /dev/null +++ b/WebGISPovertyMapping/login.php @@ -0,0 +1,209 @@ +prepare("SELECT id, nama, username, password, role FROM users WHERE username = ?"); + $stmt->bind_param("s", $username); + $stmt->execute(); + $result = $stmt->get_result(); + $user = $result->fetch_assoc(); + + if ($user && password_verify($password, $user['password'])) { + // Login berhasil + $_SESSION['user'] = $user['id']; + $_SESSION['nama'] = $user['nama']; + $_SESSION['role'] = $user['role']; + header("Location: index.php"); + exit; + } else { + $error = "Username atau password salah."; + } + + $stmt->close(); + } else { + $error = "Username dan password wajib diisi."; + } + + $conn->close(); +} +?> + + + + + + Login - Sistem Pemetaan + + + + + + + \ No newline at end of file diff --git a/WebGISPovertyMapping/logout.php b/WebGISPovertyMapping/logout.php new file mode 100644 index 0000000..0071947 --- /dev/null +++ b/WebGISPovertyMapping/logout.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/WebGISPovertyMapping/users.php b/WebGISPovertyMapping/users.php new file mode 100644 index 0000000..6a9bda0 --- /dev/null +++ b/WebGISPovertyMapping/users.php @@ -0,0 +1,399 @@ +prepare("SELECT id FROM users WHERE username = ?"); + $cek->bind_param("s", $username); + $cek->execute(); + $cek->store_result(); + + if ($cek->num_rows > 0) { + $error = "Username $username 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 $username 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(); +?> + + + + + + Kelola User - Sistem Pemetaan + + + + + + + +
+ + +
+
+ Daftar User +
+
+ + +
+ + +
+ + + +
+ + +
+ + + + + + + + + + + + + + + fetch_assoc()): ?> + + + + + + + + + + +
#NamaUsernameRoleDibuatAksi
+ + + Anda + + + + + + +
+ + + +
+
+
+
+ + +
+
+ Tambah User Baru +
+
+
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/index.html b/index.php similarity index 85% rename from index.html rename to index.php index 67df260..81f99a2 100644 --- a/index.html +++ b/index.php @@ -59,9 +59,9 @@

Nama: Muhammad Fauzi | NIM: D1041231083