feat: refresh UI and add sidebar navigation
This commit is contained in:
+30
-12
@@ -1,9 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>WebGIS Miskin & Ibadah</title>
|
||||
<title>WebGIS Pemetaan Kemiskinan</title>
|
||||
|
||||
<!-- Leaflet -->
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
|
||||
@@ -16,19 +17,31 @@
|
||||
<!-- Plus Jakarta Sans Font -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
|
||||
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap"
|
||||
rel="stylesheet">
|
||||
|
||||
<style>
|
||||
* {
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-weight: 500;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6, .btn, .card-title, .stat-value {
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
.btn,
|
||||
.card-title,
|
||||
.stat-value {
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
#bgMap {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -39,11 +52,13 @@
|
||||
opacity: 0.5;
|
||||
filter: saturate(1.2) brightness(0.7);
|
||||
}
|
||||
|
||||
.hero {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
/* Glass effect for content */
|
||||
.hero-content {
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
@@ -53,14 +68,16 @@
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hero-content {
|
||||
background: rgba(15, 23, 42, 0.7);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="min-h-screen bg-base-200 flex flex-col items-center justify-center overflow-hidden">
|
||||
|
||||
|
||||
<!-- Background Map -->
|
||||
<div id="bgMap"></div>
|
||||
|
||||
@@ -68,9 +85,9 @@
|
||||
<div class="hero-content text-center flex-col gap-2">
|
||||
<!-- Logo -->
|
||||
<div class="text-7xl mb-2">🏘️</div>
|
||||
<h1 class="text-4xl font-bold tracking-tight text-primary">WebGIS Miskin & Ibadah</h1>
|
||||
<h1 class="text-4xl font-bold tracking-tight text-primary">WebGIS Pemetaan Kemiskinan</h1>
|
||||
<p class="max-w-md text-base-content/60 mt-2 mb-6 leading-relaxed">
|
||||
Sistem Informasi Geografis untuk pemetaan rumah ibadah dan
|
||||
Sistem Informasi Geografis untuk pemetaan rumah ibadah dan
|
||||
analisis sebaran keluarga kurang mampu.
|
||||
</p>
|
||||
|
||||
@@ -99,7 +116,7 @@
|
||||
let val = 0;
|
||||
const bar = document.getElementById('redirectProgress');
|
||||
const tick = setInterval(() => {
|
||||
val += 100 / 50;
|
||||
val += 100 / 50;
|
||||
bar.value = val;
|
||||
if (val >= 100) clearInterval(tick);
|
||||
}, 100);
|
||||
@@ -133,7 +150,7 @@
|
||||
fetch('api/get_miskin.php').then(r => r.json())
|
||||
]).then(([ibadah, miskin]) => {
|
||||
const markers = [];
|
||||
|
||||
|
||||
ibadah.forEach(item => {
|
||||
L.circleMarker([+item.latitude, +item.longitude], {
|
||||
radius: 7, fillColor: "#22c55e", color: "#fff", weight: 2, opacity: 1, fillOpacity: 0.8
|
||||
@@ -151,14 +168,15 @@
|
||||
if (markers.length) {
|
||||
map.fitBounds(markers, { padding: [50, 50] });
|
||||
}
|
||||
|
||||
|
||||
// Subtle animation: slow pan
|
||||
let lat = map.getCenter().lat;
|
||||
setInterval(() => {
|
||||
lat += 0.000005;
|
||||
map.panTo([lat, map.getCenter().lng], { animate: true, duration: 1 });
|
||||
}, 1000);
|
||||
}).catch(() => {});
|
||||
}).catch(() => { });
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
+38
-13
@@ -1,9 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Data Tabular - WebGIS Miskin & Ibadah</title>
|
||||
<title>Data Tabular - WebGIS Pemetaan Kemiskinan</title>
|
||||
|
||||
<!-- DaisyUI + Tailwind -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@4/dist/full.min.css" rel="stylesheet">
|
||||
@@ -13,14 +14,34 @@
|
||||
<!-- Plus Jakarta Sans Font -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap"
|
||||
rel="stylesheet">
|
||||
|
||||
<style>
|
||||
* { font-family: 'Plus Jakarta Sans', sans-serif; }
|
||||
body { font-weight: 500; background-color: #f8fafc; }
|
||||
h1, h2, h3, h4, h5, h6, .btn, .card-title, .stat-value { font-weight: 700 !important; letter-spacing: -0.01em; }
|
||||
* {
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-weight: 500;
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
.btn,
|
||||
.card-title,
|
||||
.stat-value {
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="min-h-screen">
|
||||
|
||||
<!-- ═══ NAVBAR ═══════════════════════════════════════════════════════════ -->
|
||||
@@ -28,20 +49,21 @@
|
||||
<div class="flex-1">
|
||||
<a href="../index.html" class="btn btn-ghost text-lg font-bold gap-2 text-primary">
|
||||
<i class="fa-solid fa-house-chimney-crack"></i>
|
||||
WebGIS Miskin & Ibadah
|
||||
WebGIS Pemetaan Kemiskinan
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex-none">
|
||||
<ul class="menu menu-horizontal px-1 gap-1">
|
||||
<li><a href="map.html" class="font-medium"><i class="fa-solid fa-map"></i> Peta</a></li>
|
||||
<li><a href="data.html" class="font-semibold bg-primary/10 text-primary rounded-lg"><i class="fa-solid fa-table-list"></i> Data Tabular</a></li>
|
||||
<li><a href="data.html" class="font-semibold bg-primary/10 text-primary rounded-lg"><i
|
||||
class="fa-solid fa-table-list"></i> Data Tabular</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ MAIN CONTENT ════════════════════════════════════════════════════ -->
|
||||
<main class="max-w-screen-xl mx-auto px-4 py-8">
|
||||
|
||||
|
||||
<!-- Header -->
|
||||
<div class="flex flex-wrap items-center justify-between gap-4 mb-8">
|
||||
<div>
|
||||
@@ -52,7 +74,8 @@
|
||||
<p class="text-base-content/50 mt-1">Daftar rumah ibadah dan keluarga miskin dalam matriks tabular.</p>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<a href="map.html" class="btn btn-primary shadow-lg"><i class="fa-solid fa-plus"></i> Tambah Data di Peta</a>
|
||||
<a href="map.html" class="btn btn-primary shadow-lg"><i class="fa-solid fa-plus"></i> Tambah Data di
|
||||
Peta</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -77,7 +100,8 @@
|
||||
|
||||
<!-- Tabs -->
|
||||
<div role="tablist" class="tabs tabs-lifted tabs-lg mb-6">
|
||||
<input type="radio" name="data_tabs" role="tab" class="tab font-bold" aria-label="🕌 Rumah Ibadah" checked />
|
||||
<input type="radio" name="data_tabs" role="tab" class="tab font-bold" aria-label="🕌 Rumah Ibadah"
|
||||
checked />
|
||||
<div role="tabpanel" class="tab-content bg-base-100 border-base-300 rounded-box p-6 shadow-sm">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-zebra w-full" id="tableIbadah">
|
||||
@@ -189,8 +213,8 @@
|
||||
|
||||
document.getElementById('confirmDeleteBtn').onclick = async () => {
|
||||
const { type, id } = deleteTarget;
|
||||
const res = await fetch(`../api/delete_${type}.php`, {
|
||||
method: 'POST', body: JSON.stringify(type === 'ibadah' ? { id } : { id_rumah: id })
|
||||
const res = await fetch(`../api/delete_${type}.php`, {
|
||||
method: 'POST', body: JSON.stringify(type === 'ibadah' ? { id } : { id_rumah: id })
|
||||
});
|
||||
const resJson = await res.json();
|
||||
if (resJson.success) {
|
||||
@@ -210,4 +234,5 @@
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
+104
-62
@@ -1,9 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id" data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Peta Interaktif - WebGIS Miskin & Ibadah</title>
|
||||
<title>Peta Interaktif - WebGIS Pemetaan Kemiskinan</title>
|
||||
|
||||
<!-- Leaflet -->
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
|
||||
@@ -18,15 +19,46 @@
|
||||
<!-- Plus Jakarta Sans Font -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap"
|
||||
rel="stylesheet">
|
||||
|
||||
<style>
|
||||
* { font-family: 'Plus Jakarta Sans', sans-serif; }
|
||||
body { font-weight: 500; height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
|
||||
h1, h2, h3, h4, h5, h6, .btn, .card-title, .stat-value { font-weight: 700 !important; letter-spacing: -0.01em; }
|
||||
.map-wrapper { flex: 1; position: relative; min-height: 0; }
|
||||
#map { width: 100%; height: 100%; }
|
||||
|
||||
* {
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
font-weight: 500;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
.btn,
|
||||
.card-title,
|
||||
.stat-value {
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.map-wrapper {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Floating Controls */
|
||||
.floating-panel {
|
||||
position: absolute;
|
||||
@@ -37,7 +69,7 @@
|
||||
max-height: calc(100vh - 100px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
||||
.glass-card {
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
backdrop-filter: blur(10px);
|
||||
@@ -46,7 +78,8 @@
|
||||
}
|
||||
|
||||
/* Marker dragging hint */
|
||||
#dragHint, #mapHint {
|
||||
#dragHint,
|
||||
#mapHint {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
left: 50%;
|
||||
@@ -65,6 +98,7 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- ═══ NAVBAR ═══════════════════════════════════════════════════════════ -->
|
||||
@@ -72,7 +106,7 @@
|
||||
<div class="flex-1">
|
||||
<a href="../index.html" class="btn btn-ghost text-lg font-bold gap-2 text-primary">
|
||||
<i class="fa-solid fa-house-chimney-crack"></i>
|
||||
WebGIS Miskin & Ibadah
|
||||
WebGIS Pemetaan Kemiskinan
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex-none">
|
||||
@@ -104,13 +138,16 @@
|
||||
Mode Operasi
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 gap-2">
|
||||
<button class="btn btn-sm btn-outline btn-primary justify-start gap-2 active" id="btnModeView" onclick="setMode('view')">
|
||||
<button class="btn btn-sm btn-outline btn-primary justify-start gap-2 active" id="btnModeView"
|
||||
onclick="setMode('view')">
|
||||
<i class="fa-solid fa-eye"></i> View & Analisis
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline btn-success justify-start gap-2" id="btnModeIbadah" onclick="setMode('ibadah')">
|
||||
<button class="btn btn-sm btn-outline btn-success justify-start gap-2" id="btnModeIbadah"
|
||||
onclick="setMode('ibadah')">
|
||||
<i class="fa-solid fa-plus"></i> Tambah Rumah Ibadah
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline btn-error justify-start gap-2" id="btnModeMiskin" onclick="setMode('miskin')">
|
||||
<button class="btn btn-sm btn-outline btn-error justify-start gap-2" id="btnModeMiskin"
|
||||
onclick="setMode('miskin')">
|
||||
<i class="fa-solid fa-plus"></i> Tambah Rumah Miskin
|
||||
</button>
|
||||
</div>
|
||||
@@ -130,12 +167,13 @@
|
||||
<div class="text-xs font-bold text-primary truncate" id="activeName">Nama Ibadah</div>
|
||||
<div class="text-[10px] text-base-content/40" id="activeAddr">Alamat</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-control mb-4">
|
||||
<label class="label py-1">
|
||||
<span class="label-text-alt font-bold">Radius: <span id="radiusVal">500</span>m</span>
|
||||
</label>
|
||||
<input type="range" min="50" max="2000" value="500" step="50" class="range range-xs range-primary" id="radiusSlider">
|
||||
<input type="range" min="50" max="2000" value="500" step="50"
|
||||
class="range range-xs range-primary" id="radiusSlider">
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
@@ -168,7 +206,7 @@
|
||||
</div>
|
||||
|
||||
<!-- ═══ MODALS ═══════════════════════════════════════════════════════════ -->
|
||||
|
||||
|
||||
<!-- Modal: Input Ibadah -->
|
||||
<dialog id="modalIbadah" class="modal">
|
||||
<div class="modal-box">
|
||||
@@ -179,11 +217,13 @@
|
||||
<div class="bg-base-200 p-2 rounded text-xs font-mono" id="ib_coords">Lat: -, Lng: -</div>
|
||||
<label class="form-control w-full">
|
||||
<div class="label"><span class="label-text font-bold">Nama Rumah Ibadah</span></div>
|
||||
<input type="text" id="ib_nama" placeholder="Contoh: Masjid Nurul Iman" class="input input-bordered w-full" />
|
||||
<input type="text" id="ib_nama" placeholder="Contoh: Masjid Nurul Iman"
|
||||
class="input input-bordered w-full" />
|
||||
</label>
|
||||
<label class="form-control w-full">
|
||||
<div class="label"><span class="label-text font-bold">Alamat</span></div>
|
||||
<textarea id="ib_alamat" class="textarea textarea-bordered h-20" placeholder="Alamat lengkap..."></textarea>
|
||||
<textarea id="ib_alamat" class="textarea textarea-bordered h-20"
|
||||
placeholder="Alamat lengkap..."></textarea>
|
||||
</label>
|
||||
<label class="form-control w-full">
|
||||
<div class="label"><span class="label-text font-bold">Radius Default Analysis (Meter)</span></div>
|
||||
@@ -207,7 +247,8 @@
|
||||
<div class="bg-base-200 p-2 rounded text-xs font-mono" id="rm_coords">Lat: -, Lng: -</div>
|
||||
<label class="form-control w-full">
|
||||
<div class="label"><span class="label-text font-bold">Alamat</span></div>
|
||||
<textarea id="rm_alamat" class="textarea textarea-bordered h-20" placeholder="Alamat lengkap..."></textarea>
|
||||
<textarea id="rm_alamat" class="textarea textarea-bordered h-20"
|
||||
placeholder="Alamat lengkap..."></textarea>
|
||||
</label>
|
||||
<label class="form-control w-full">
|
||||
<div class="label"><span class="label-text font-bold">ID Rumah / Nama Pemilik</span></div>
|
||||
@@ -255,7 +296,7 @@
|
||||
let activeCircle = null, activeIbadah = null;
|
||||
let ibadahData = [], miskinData = [];
|
||||
let tempMarker = null;
|
||||
|
||||
|
||||
let ibadahMarkers = new Map(); // id -> marker
|
||||
let miskinMarkers = new Map(); // id_rumah -> marker
|
||||
|
||||
@@ -286,7 +327,7 @@
|
||||
|
||||
function initMap() {
|
||||
map = L.map('map', { zoomControl: false }).setView([-0.0553, 109.3463], 17);
|
||||
|
||||
|
||||
const osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19 });
|
||||
const satellite = L.layerGroup([
|
||||
L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { maxZoom: 19 }),
|
||||
@@ -296,9 +337,9 @@
|
||||
|
||||
satellite.addTo(map);
|
||||
L.control.zoom({ position: 'bottomright' }).addTo(map);
|
||||
L.control.layers({ "Satelit": satellite, "Street": osm },
|
||||
{ "Rumah Ibadah": layerIbadah, "Rumah Miskin": layerMiskin },
|
||||
{ position: 'topright' }).addTo(map);
|
||||
L.control.layers({ "Satelit": satellite, "Street": osm },
|
||||
{ "Rumah Ibadah": layerIbadah, "Rumah Miskin": layerMiskin },
|
||||
{ position: 'topright' }).addTo(map);
|
||||
|
||||
layerIbadah.addTo(map);
|
||||
layerMiskin.addTo(map);
|
||||
@@ -315,7 +356,7 @@
|
||||
fetch('../api/get_ibadah.php').then(r => r.json()),
|
||||
fetch('../api/get_miskin.php').then(r => r.json())
|
||||
]);
|
||||
|
||||
|
||||
// Validate data is array
|
||||
if (!Array.isArray(ri) || !Array.isArray(rm)) {
|
||||
console.error("Invalid API response", { ri, rm });
|
||||
@@ -324,7 +365,7 @@
|
||||
|
||||
ibadahData = ri;
|
||||
miskinData = rm;
|
||||
|
||||
|
||||
// Sync activeIbadah to point to the new object in the fresh data
|
||||
if (activeIbadah) {
|
||||
const matched = ibadahData.find(i => i.id == activeIbadah.id);
|
||||
@@ -332,9 +373,9 @@
|
||||
}
|
||||
|
||||
renderMarkers();
|
||||
} catch (e) {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showToast('Gagal memuat data', 'error');
|
||||
showToast('Gagal memuat data', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,16 +389,16 @@
|
||||
const m = L.marker([item.latitude, item.longitude], { icon: icons.ibadah(), draggable: true })
|
||||
.bindPopup(buildPopupIbadah(item))
|
||||
.on('click', () => handleIbadahClick(item));
|
||||
|
||||
|
||||
m.on('dragend', e => updateLocation('ibadah', item.id, e.target.getLatLng(), item));
|
||||
layerIbadah.addLayer(m);
|
||||
ibadahMarkers.set(item.id, m);
|
||||
});
|
||||
|
||||
miskinData.forEach(item => {
|
||||
const marker = L.marker([item.latitude, item.longitude], {
|
||||
const marker = L.marker([item.latitude, item.longitude], {
|
||||
icon: icons.miskin('#ef4444'),
|
||||
draggable: true
|
||||
draggable: true
|
||||
}).bindPopup(buildPopupMiskin(item));
|
||||
|
||||
marker.on('dragend', e => updateLocation('miskin', item.id_rumah, e.target.getLatLng(), item));
|
||||
@@ -376,10 +417,10 @@
|
||||
currentMode = mode;
|
||||
document.querySelectorAll('.btn-outline').forEach(b => b.classList.remove('active'));
|
||||
document.getElementById('btnMode' + mode.charAt(0).toUpperCase() + mode.slice(1)).classList.add('active');
|
||||
|
||||
|
||||
document.getElementById('mapHint').classList.toggle('hidden', mode === 'view');
|
||||
document.getElementById('analysisPanel').classList.toggle('hidden', mode !== 'view');
|
||||
|
||||
|
||||
if (mode !== 'view') {
|
||||
if (activeCircle) { map.removeLayer(activeCircle); activeCircle = null; }
|
||||
document.getElementById('statsContent').classList.add('hidden');
|
||||
@@ -391,13 +432,13 @@
|
||||
function handleMapClick(latlng) {
|
||||
if (tempMarker) map.removeLayer(tempMarker);
|
||||
tempMarker = L.marker(latlng, { icon: icons.temp() }).addTo(map);
|
||||
|
||||
|
||||
if (currentMode === 'ibadah') {
|
||||
document.getElementById('ib_coords').innerText = `Lat: ${latlng.lat.toFixed(6)}, Lng: ${latlng.lng.toFixed(6)}`;
|
||||
document.getElementById('ib_nama').value = '';
|
||||
document.getElementById('ib_alamat').value = 'Mencari alamat...';
|
||||
modalIbadah.showModal();
|
||||
|
||||
|
||||
// Auto fetch address
|
||||
reverseGeocode(latlng.lat, latlng.lng, 'ib_alamat');
|
||||
} else {
|
||||
@@ -432,7 +473,7 @@
|
||||
document.getElementById('statsContent').classList.remove('hidden');
|
||||
document.getElementById('activeName').innerText = item.nama;
|
||||
document.getElementById('activeAddr').innerText = item.alamat;
|
||||
|
||||
|
||||
const radius = document.getElementById('radiusSlider').value = item.radius || 500;
|
||||
updateRadius(item.latitude, item.longitude, radius);
|
||||
}
|
||||
@@ -441,25 +482,25 @@
|
||||
function updateRadius(lat, lng, radius) {
|
||||
if (activeCircle) map.removeLayer(activeCircle);
|
||||
activeCircle = L.circle([lat, lng], {
|
||||
radius: parseInt(radius),
|
||||
color: '#2563eb',
|
||||
fillColor: '#3b82f6',
|
||||
fillOpacity: 0.2,
|
||||
radius: parseInt(radius),
|
||||
color: '#2563eb',
|
||||
fillColor: '#3b82f6',
|
||||
fillOpacity: 0.2,
|
||||
weight: 2,
|
||||
dashArray: '5, 10'
|
||||
}).addTo(map);
|
||||
|
||||
|
||||
document.getElementById('radiusVal').innerText = radius;
|
||||
updateAnalysisUI([lat, lng], radius);
|
||||
}
|
||||
|
||||
function updateAnalysisUI(center, radius) {
|
||||
let houses = 0, kk = 0, jiwa = 0;
|
||||
|
||||
|
||||
miskinData.forEach(h => {
|
||||
const houseMarker = miskinMarkers.get(h.id_rumah);
|
||||
const isH = isInside(h, center, radius);
|
||||
|
||||
|
||||
if (isH) {
|
||||
houses++;
|
||||
kk += parseInt(h.jumlah_kk);
|
||||
@@ -484,7 +525,7 @@
|
||||
// center can be [lat, lng] or {lat, lng}
|
||||
const cLat = center.lat !== undefined ? center.lat : center[0];
|
||||
const cLng = center.lng !== undefined ? center.lng : center[1];
|
||||
|
||||
|
||||
const p1 = turf.point([Number(point.longitude), Number(point.latitude)]);
|
||||
const p2 = turf.point([Number(cLng), Number(cLat)]);
|
||||
return turf.distance(p1, p2, { units: 'meters' }) <= radius;
|
||||
@@ -499,7 +540,7 @@
|
||||
// Save radius to DB when user finishes sliding
|
||||
document.getElementById('radiusSlider').addEventListener('change', async e => {
|
||||
if (!activeIbadah) return;
|
||||
|
||||
|
||||
const newRadius = e.target.value;
|
||||
try {
|
||||
const res = await fetch('../api/update_ibadah.php', {
|
||||
@@ -559,11 +600,11 @@
|
||||
};
|
||||
const btn = document.getElementById('btnSaveIbadah');
|
||||
btn.disabled = true;
|
||||
|
||||
const res = await fetch('../api/save_ibadah.php', {
|
||||
method: 'POST',
|
||||
|
||||
const res = await fetch('../api/save_ibadah.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
const resJson = await res.json();
|
||||
if (resJson.success) {
|
||||
@@ -586,10 +627,10 @@
|
||||
const btn = document.getElementById('btnSaveMiskin');
|
||||
btn.disabled = true;
|
||||
|
||||
const res = await fetch('../api/save_miskin.php', {
|
||||
method: 'POST',
|
||||
const res = await fetch('../api/save_miskin.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
const resJson = await res.json();
|
||||
if (resJson.success) {
|
||||
@@ -602,15 +643,15 @@
|
||||
|
||||
async function updateLocation(type, id, latlng, oldData) {
|
||||
const endpoint = `../api/update_${type}.php`;
|
||||
const payload = type === 'ibadah'
|
||||
const payload = type === 'ibadah'
|
||||
? { id, nama: oldData.nama, alamat: oldData.alamat, latitude: latlng.lat, longitude: latlng.lng, radius: oldData.radius }
|
||||
: { id_rumah: id, alamat: oldData.alamat, jumlah_kk: oldData.jumlah_kk, jumlah_orang: oldData.jumlah_orang, latitude: latlng.lat, longitude: latlng.lng };
|
||||
|
||||
|
||||
try {
|
||||
const res = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
const res = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
const resJson = await res.json();
|
||||
if (resJson.success) {
|
||||
@@ -635,10 +676,10 @@
|
||||
|
||||
document.getElementById('confirmDeleteBtn').onclick = async () => {
|
||||
const { type, id } = deleteTarget;
|
||||
const res = await fetch(`../api/delete_${type}.php`, {
|
||||
method: 'POST',
|
||||
const res = await fetch(`../api/delete_${type}.php`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(type === 'ibadah' ? { id } : { id_rumah: id })
|
||||
body: JSON.stringify(type === 'ibadah' ? { id } : { id_rumah: id })
|
||||
});
|
||||
const resJson = await res.json();
|
||||
if (resJson.success) {
|
||||
@@ -659,4 +700,5 @@
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user