Initial commit untuk UAS SIG
This commit is contained in:
+429
@@ -0,0 +1,429 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Peta Kemiskinan & Rumah Ibadah — WebGIS</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
:root {
|
||||
--clr-bg: #0f172a; --clr-surface: #1e293b; --clr-surface-light: #334155;
|
||||
--clr-border: #334155; --clr-text: #f1f5f9; --clr-muted: #94a3b8;
|
||||
--clr-primary: #3b82f6; --clr-primary-dark: #2563eb;
|
||||
--clr-success: #22c55e; --clr-danger: #ef4444;
|
||||
--radius: 10px; --shadow: 0 4px 24px rgba(0,0,0,.45);
|
||||
--transition: .2s ease;
|
||||
--sidebar-width: 260px; --sidebar-collapsed: 70px;
|
||||
}
|
||||
html, body { height: 100%; font-family: 'Inter', sans-serif; background: var(--clr-bg); color: var(--clr-text); overflow: hidden; }
|
||||
|
||||
/* ---- Layout ---- */
|
||||
.app-wrapper { display: flex; height: 100vh; }
|
||||
|
||||
/* ---- Sidebar ---- */
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
background: linear-gradient(135deg, #1a2a42 0%, #0f172a 100%);
|
||||
border-right: 1px solid var(--clr-border);
|
||||
display: flex; flex-direction: column;
|
||||
transition: width var(--transition); z-index: 100;
|
||||
box-shadow: 2px 0 8px rgba(0,0,0,.3); overflow: hidden;
|
||||
}
|
||||
.sidebar.collapsed { width: var(--sidebar-collapsed); }
|
||||
.sidebar-header {
|
||||
padding: 20px; border-bottom: 1px solid var(--clr-border);
|
||||
display: flex; align-items: center; justify-content: space-between; flex-shrink: 0;
|
||||
}
|
||||
.sidebar-logo { display: flex; align-items: center; gap: 10px; flex: 1; overflow: hidden; }
|
||||
.sidebar-logo-icon {
|
||||
width: 40px; height: 40px; flex-shrink: 0;
|
||||
background: linear-gradient(135deg, #ef4444, #8b5cf6);
|
||||
border-radius: 8px; display: flex; align-items: center; justify-content: center;
|
||||
font-size: 14px; font-weight: 700; box-shadow: 0 0 12px rgba(239,68,68,.4);
|
||||
}
|
||||
.sidebar-logo-text { overflow: hidden; }
|
||||
.sidebar-logo-text h2 { font-size: 14px; font-weight: 700; white-space: nowrap; }
|
||||
.sidebar-logo-text p { font-size: 11px; color: var(--clr-muted); white-space: nowrap; }
|
||||
.sidebar.collapsed .sidebar-logo-text { display: none; }
|
||||
.sidebar-toggle { background: transparent; border: none; color: var(--clr-muted); cursor: pointer; font-size: 20px; padding: 4px; flex-shrink: 0; transition: color var(--transition); }
|
||||
.sidebar-toggle:hover { color: var(--clr-text); }
|
||||
.sidebar-nav { flex: 1; overflow-y: auto; padding: 16px 0; }
|
||||
.sidebar-section { padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,.05); }
|
||||
.sidebar-section:last-child { border-bottom: none; }
|
||||
.sidebar-section-title { padding: 10px 16px; font-size: 10px; font-weight: 700; color: var(--clr-muted); text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap; overflow: hidden; }
|
||||
.sidebar.collapsed .sidebar-section-title { opacity: 0; }
|
||||
.sidebar-menu { display: flex; flex-direction: column; }
|
||||
.sidebar-item {
|
||||
display: flex; align-items: center; gap: 12px; padding: 13px 16px;
|
||||
color: var(--clr-muted); cursor: pointer; text-decoration: none;
|
||||
transition: all var(--transition); border-left: 3px solid transparent;
|
||||
}
|
||||
.sidebar-item:hover { color: var(--clr-text); background: rgba(255,255,255,.05); border-left-color: var(--clr-primary); }
|
||||
.sidebar-item.active { color: var(--clr-danger); background: rgba(239,68,68,.1); border-left-color: var(--clr-danger); }
|
||||
.sidebar-item-icon { width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; }
|
||||
.sidebar-item-text { flex: 1; font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; }
|
||||
.sidebar.collapsed .sidebar-item-text { display: none; }
|
||||
.sidebar-item-user { font-size: 11px; color: var(--clr-muted); padding: 4px 16px 12px; white-space: nowrap; overflow: hidden; }
|
||||
.sidebar.collapsed .sidebar-item-user { display: none; }
|
||||
|
||||
/* ---- Main ---- */
|
||||
.main-wrapper { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
|
||||
header {
|
||||
flex-shrink: 0; height: 60px;
|
||||
background: linear-gradient(135deg, #3d1a1a 0%, #0f172a 100%);
|
||||
border-bottom: 1px solid var(--clr-border);
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: 0 20px; box-shadow: 0 2px 12px rgba(0,0,0,.5);
|
||||
}
|
||||
.header-title h1 { font-size: 18px; font-weight: 700; color: #fca5a5; }
|
||||
.header-breadcrumb { font-size: 13px; color: var(--clr-muted); margin-top: 2px; }
|
||||
.header-user { font-size: 13px; color: var(--clr-muted); background: rgba(255,255,255,.06); border: 1px solid var(--clr-border); padding: 6px 14px; border-radius: 8px; }
|
||||
.content-area { flex: 1; position: relative; overflow: hidden; }
|
||||
|
||||
/* ---- Map ---- */
|
||||
#map { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; }
|
||||
|
||||
/* ---- Controls Panel ---- */
|
||||
.controls-panel {
|
||||
position: absolute; top: 16px; right: 16px;
|
||||
background: rgba(30, 41, 59, 0.95); backdrop-filter: blur(8px);
|
||||
border: 1px solid var(--clr-border); border-radius: var(--radius);
|
||||
padding: 16px; z-index: 1000; width: 280px;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.controls-panel h3 { font-size: 13px; font-weight: 700; color: var(--clr-text); margin-bottom: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
|
||||
.ctrl-input {
|
||||
width: 100%; padding: 9px 12px; margin-bottom: 10px;
|
||||
background: var(--clr-bg); border: 1px solid var(--clr-border);
|
||||
border-radius: 6px; color: var(--clr-text); font-family: inherit; font-size: 13px; outline: none;
|
||||
}
|
||||
.ctrl-input:focus { border-color: var(--clr-primary); }
|
||||
|
||||
/* ---- Search Panel (Left) ---- */
|
||||
.search-panel {
|
||||
position: absolute; top: 16px; left: 60px; /* offset for leaflet zoom controls */
|
||||
background: rgba(30, 41, 59, 0.95); backdrop-filter: blur(8px);
|
||||
border: 1px solid var(--clr-border); border-radius: var(--radius);
|
||||
padding: 12px; z-index: 1000; width: 300px;
|
||||
box-shadow: var(--shadow); display: flex; flex-direction: column;
|
||||
}
|
||||
.search-panel h3 { font-size: 13px; font-weight: 700; color: var(--clr-text); margin-bottom: 10px; text-transform: uppercase; letter-spacing: 0.5px; display: flex; align-items: center; gap: 8px; }
|
||||
.search-input-wrap { position: relative; margin-bottom: 8px; }
|
||||
.search-input-wrap .ctrl-input { margin-bottom: 0; padding-right: 30px; }
|
||||
.search-results {
|
||||
max-height: 180px; overflow-y: auto; margin-top: 4px;
|
||||
display: none; flex-direction: column; gap: 4px;
|
||||
}
|
||||
.search-results.active { display: flex; margin-bottom: 8px; }
|
||||
.search-result-item {
|
||||
padding: 8px 10px; background: rgba(255,255,255,0.05); border-radius: 6px;
|
||||
cursor: pointer; transition: 0.2s; border: 1px solid transparent;
|
||||
}
|
||||
.search-result-item:hover { background: rgba(59,130,246,0.1); border-color: rgba(59,130,246,0.3); }
|
||||
.search-result-name { font-size: 13px; font-weight: 600; color: #f1f5f9; display: block; margin-bottom: 2px; }
|
||||
.search-result-desc { font-size: 11px; color: #94a3b8; display: block; }
|
||||
|
||||
.legend-panel {
|
||||
position: absolute; bottom: 16px; right: 16px;
|
||||
background: rgba(30, 41, 59, 0.95); backdrop-filter: blur(8px);
|
||||
border: 1px solid var(--clr-border); border-radius: var(--radius);
|
||||
padding: 14px; z-index: 1000; width: 230px; font-size: 13px;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.legend-panel h3 { font-size: 11px; font-weight: 700; color: var(--clr-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 10px; }
|
||||
.legend-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; color: var(--clr-text); font-size: 12px; }
|
||||
.legend-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
|
||||
|
||||
/* ---- Popup Slider ---- */
|
||||
.popup-slider-wrap { margin-top: 10px; }
|
||||
.popup-slider-label { font-size: 12px; font-weight: 600; color: #334155; display: block; margin-bottom: 4px; }
|
||||
.popup-slider { width: 100%; }
|
||||
|
||||
/* ---- Loader ---- */
|
||||
#loader { position: fixed; inset: 0; background: var(--clr-bg); color: var(--clr-text); display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 9999; gap: 12px; }
|
||||
.loader-spinner { width: 36px; height: 36px; border: 3px solid var(--clr-border); border-top-color: var(--clr-danger); border-radius: 50%; animation: spin 0.8s linear infinite; }
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="loader">
|
||||
<div class="loader-spinner"></div>
|
||||
<span>Verifikasi Akses...</span>
|
||||
</div>
|
||||
|
||||
<div class="app-wrapper">
|
||||
<!-- Sidebar -->
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="sidebar-logo">
|
||||
<div class="sidebar-logo-icon">KM</div>
|
||||
<div class="sidebar-logo-text">
|
||||
<h2>WebGIS</h2>
|
||||
<p>Peta Kemiskinan</p>
|
||||
</div>
|
||||
</div>
|
||||
<button class="sidebar-toggle" id="sidebar-toggle">≡</button>
|
||||
</div>
|
||||
<nav class="sidebar-nav">
|
||||
<div class="sidebar-section">
|
||||
<div class="sidebar-section-title">Navigasi</div>
|
||||
<div class="sidebar-menu">
|
||||
<div class="sidebar-item active">
|
||||
<div class="sidebar-item-icon">🗺</div>
|
||||
<div class="sidebar-item-text">Peta Kemiskinan</div>
|
||||
</div>
|
||||
<a href="index.html" class="sidebar-item">
|
||||
<div class="sidebar-item-icon">🏠</div>
|
||||
<div class="sidebar-item-text">Beranda</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-section">
|
||||
<div class="sidebar-menu">
|
||||
<div class="sidebar-item" id="logout-btn">
|
||||
<div class="sidebar-item-icon">⎋</div>
|
||||
<div class="sidebar-item-text">Logout</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- Main -->
|
||||
<div class="main-wrapper">
|
||||
<header>
|
||||
<div class="header-title">
|
||||
<h1>Peta Analisis Kemiskinan</h1>
|
||||
<div class="header-breadcrumb">Peta terproteksi — Login diperlukan</div>
|
||||
</div>
|
||||
<div class="header-user" id="header-user">Loading...</div>
|
||||
</header>
|
||||
<div class="content-area">
|
||||
<div id="map"></div>
|
||||
|
||||
<!-- Search Panel (Left) -->
|
||||
<div class="search-panel">
|
||||
<h3><i class="fa-solid fa-magnifying-glass" style="color:var(--clr-primary)"></i> Pencarian</h3>
|
||||
|
||||
<div style="font-size:11px; font-weight:600; color:#94a3b8; margin-bottom:4px;">RUMAH IBADAH</div>
|
||||
<div class="search-input-wrap">
|
||||
<input id="search-ibadah" class="ctrl-input" type="text" placeholder="Cari Rumah Ibadah..." autocomplete="off">
|
||||
</div>
|
||||
<div id="results-ibadah" class="search-results"></div>
|
||||
|
||||
<div style="font-size:11px; font-weight:600; color:#94a3b8; margin-top:8px; margin-bottom:4px;">PENDUDUK MISKIN</div>
|
||||
<div class="search-input-wrap">
|
||||
<input id="search-miskin" class="ctrl-input" type="text" placeholder="Cari Nama KK Penduduk Miskin..." autocomplete="off">
|
||||
</div>
|
||||
<div id="results-miskin" class="search-results"></div>
|
||||
</div>
|
||||
|
||||
<div class="legend-panel">
|
||||
<h3>Legenda</h3>
|
||||
<div class="legend-row"><div class="legend-dot" style="background:#22c55e;"></div> Rumah Ibadah</div>
|
||||
<div class="legend-row"><div class="legend-dot" style="background:#ef4444;"></div> Penduduk Miskin (Dalam Radius)</div>
|
||||
<div class="legend-row"><div class="legend-dot" style="background:#1e293b; border: 1px solid #64748b;"></div> Penduduk Miskin (Luar Radius)</div>
|
||||
<hr style="border-color:#334155; margin: 8px 0;">
|
||||
<div style="font-size:11px; color: var(--clr-muted);">💡 Klik Rumah Ibadah untuk atur radius jangkauan</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
|
||||
<script>
|
||||
// Sidebar toggle
|
||||
document.getElementById('sidebar-toggle').addEventListener('click', () => {
|
||||
document.getElementById('sidebar').classList.toggle('collapsed');
|
||||
});
|
||||
|
||||
// Logout
|
||||
document.getElementById('logout-btn').addEventListener('click', async () => {
|
||||
await fetch('backend/logout.php');
|
||||
window.location.href = 'index.html';
|
||||
});
|
||||
|
||||
// Global state
|
||||
let ibadahData = [], miskinData = [];
|
||||
let ibadahLayer, miskinLayer, map;
|
||||
let ibadahRadiuses = {}, ibadahPoints = [];
|
||||
let ibadahIcon, miskinRedIcon, miskinBlackIcon;
|
||||
|
||||
async function checkAuth() {
|
||||
try {
|
||||
const res = await fetch('backend/check_auth.php');
|
||||
if (!res.ok) { window.location.href = 'login.html?redirect=poverty.html'; return; }
|
||||
const data = await res.json();
|
||||
document.getElementById('header-user').textContent = '👤 ' + data.username;
|
||||
document.getElementById('loader').style.display = 'none';
|
||||
initMap();
|
||||
} catch (e) { window.location.href = 'login.html?redirect=poverty.html'; }
|
||||
}
|
||||
|
||||
async function initMap() {
|
||||
map = L.map('map').setView([-0.026, 109.342], 13);
|
||||
const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap', maxZoom: 19 });
|
||||
const dark = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', { maxZoom: 19 });
|
||||
osm.addTo(map);
|
||||
L.control.layers({ 'Standard': osm, 'Dark': dark }).addTo(map);
|
||||
|
||||
ibadahLayer = L.layerGroup().addTo(map);
|
||||
miskinLayer = L.layerGroup().addTo(map);
|
||||
|
||||
ibadahIcon = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25,41], iconAnchor: [12,41], popupAnchor: [1,-34], shadowSize: [41,41] });
|
||||
miskinRedIcon = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25,41], iconAnchor: [12,41], popupAnchor: [1,-34], shadowSize: [41,41] });
|
||||
miskinBlackIcon = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-black.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25,41], iconAnchor: [12,41], popupAnchor: [1,-34], shadowSize: [41,41] });
|
||||
|
||||
try {
|
||||
const [ir, mr] = await Promise.all([fetch('backend/read_ibadah.php'), fetch('backend/read_miskin.php')]);
|
||||
ibadahData = (await ir.json()).data || [];
|
||||
miskinData = (await mr.json()).data || [];
|
||||
ibadahData.forEach(item => { ibadahRadiuses[item.id] = 0; });
|
||||
renderAll();
|
||||
} catch (e) { console.error('Error loading data:', e); }
|
||||
}
|
||||
|
||||
window.updateRadius = function(id, val) {
|
||||
ibadahRadiuses[id] = parseInt(val);
|
||||
const el = document.getElementById('radius-val-' + id);
|
||||
if (el) el.textContent = val;
|
||||
renderBuffers();
|
||||
renderMiskin();
|
||||
};
|
||||
|
||||
function renderBuffers() {
|
||||
map.eachLayer(l => { if (l.options && l.options.isBuffer) map.removeLayer(l); });
|
||||
ibadahData.forEach(item => {
|
||||
const r = ibadahRadiuses[item.id];
|
||||
if (r > 0) {
|
||||
const lat = parseFloat(item.latitude), lng = parseFloat(item.longitude);
|
||||
if (!isNaN(lat) && !isNaN(lng)) {
|
||||
L.circle([lat, lng], { radius: r, color: '#ef4444', fillColor: '#ef4444', fillOpacity: 0.12, weight: 2, isBuffer: true, dashArray: '6,4' }).addTo(map);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderAll() { renderIbadah(); renderBuffers(); renderMiskin(); }
|
||||
|
||||
function renderIbadah(autoZoom = false) {
|
||||
ibadahLayer.clearLayers(); ibadahPoints = [];
|
||||
const bounds = [];
|
||||
const f = document.getElementById('search-ibadah').value.toLowerCase();
|
||||
ibadahData.forEach(item => {
|
||||
if (f && !item.nama.toLowerCase().includes(f)) return;
|
||||
const lat = parseFloat(item.latitude), lng = parseFloat(item.longitude);
|
||||
if (isNaN(lat) || isNaN(lng)) return;
|
||||
ibadahPoints.push({ id: item.id, pt: turf.point([lng, lat]) });
|
||||
const r = ibadahRadiuses[item.id] || 0;
|
||||
const popup = '<strong style="color:#166534;">' + item.nama + '</strong><br><small>' + item.alamat + '</small>'
|
||||
+ '<div class="popup-slider-wrap">'
|
||||
+ '<span class="popup-slider-label">Radius: <b><span id="radius-val-' + item.id + '">' + r + '</span> m</b></span>'
|
||||
+ '<input type="range" class="popup-slider" min="0" max="5000" step="100" value="' + r + '" oninput="window.updateRadius(' + item.id + ', this.value)">'
|
||||
+ '</div>';
|
||||
L.marker([lat, lng], { icon: ibadahIcon }).bindPopup(popup, { minWidth: 220 }).addTo(ibadahLayer);
|
||||
bounds.push([lat, lng]);
|
||||
});
|
||||
|
||||
if (autoZoom && f && bounds.length > 0) {
|
||||
if (bounds.length === 1) map.flyTo(bounds[0], 16);
|
||||
else map.fitBounds(bounds, { padding: [50, 50] });
|
||||
}
|
||||
}
|
||||
|
||||
function renderMiskin(autoZoom = false) {
|
||||
miskinLayer.clearLayers();
|
||||
const bounds = [];
|
||||
const f = document.getElementById('search-miskin').value.toLowerCase();
|
||||
miskinData.forEach(item => {
|
||||
if (f && !item.nama_kk.toLowerCase().includes(f)) return;
|
||||
const lat = parseFloat(item.latitude), lng = parseFloat(item.longitude);
|
||||
if (isNaN(lat) || isNaN(lng)) return;
|
||||
const pt = turf.point([lng, lat]);
|
||||
let inRadius = false;
|
||||
for (const ib of ibadahPoints) {
|
||||
const km = ibadahRadiuses[ib.id] / 1000;
|
||||
if (km > 0 && turf.distance(pt, ib.pt, { units: 'kilometers' }) <= km) { inRadius = true; break; }
|
||||
}
|
||||
L.marker([lat, lng], { icon: inRadius ? miskinRedIcon : miskinBlackIcon })
|
||||
.bindPopup('<strong>KK: ' + item.nama_kk + '</strong><br>' + (item.keterangan || '-') + '<br>Status: ' + (inRadius ? '🔴 Dalam Radius' : '⚫ Luar Radius'))
|
||||
.addTo(miskinLayer);
|
||||
bounds.push([lat, lng]);
|
||||
});
|
||||
|
||||
if (autoZoom && f && bounds.length > 0) {
|
||||
if (bounds.length === 1) map.flyTo(bounds[0], 17);
|
||||
else map.fitBounds(bounds, { padding: [50, 50] });
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('search-ibadah').addEventListener('input', e => {
|
||||
const f = e.target.value.toLowerCase();
|
||||
const resDiv = document.getElementById('results-ibadah');
|
||||
if (!f) {
|
||||
resDiv.classList.remove('active');
|
||||
renderIbadah(false);
|
||||
return;
|
||||
}
|
||||
const matched = ibadahData.filter(i => i.nama.toLowerCase().includes(f));
|
||||
if (matched.length > 0) {
|
||||
resDiv.innerHTML = matched.map(m => `
|
||||
<div class="search-result-item" onclick="window.selectIbadah(${m.id})">
|
||||
<span class="search-result-name">${m.nama}</span>
|
||||
<span class="search-result-desc">${m.alamat}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
} else {
|
||||
resDiv.innerHTML = '<div style="padding:8px 10px; color:#94a3b8; font-size:12px;">Tidak ditemukan.</div>';
|
||||
}
|
||||
resDiv.classList.add('active');
|
||||
renderIbadah(false);
|
||||
});
|
||||
|
||||
window.selectIbadah = function(id) {
|
||||
const item = ibadahData.find(i => i.id == id);
|
||||
if (!item) return;
|
||||
document.getElementById('search-ibadah').value = item.nama;
|
||||
document.getElementById('results-ibadah').classList.remove('active');
|
||||
renderIbadah(true);
|
||||
};
|
||||
|
||||
document.getElementById('search-miskin').addEventListener('input', e => {
|
||||
const f = e.target.value.toLowerCase();
|
||||
const resDiv = document.getElementById('results-miskin');
|
||||
if (!f) {
|
||||
resDiv.classList.remove('active');
|
||||
renderMiskin(false);
|
||||
return;
|
||||
}
|
||||
const matched = miskinData.filter(m => m.nama_kk.toLowerCase().includes(f));
|
||||
if (matched.length > 0) {
|
||||
resDiv.innerHTML = matched.map(m => `
|
||||
<div class="search-result-item" onclick="window.selectMiskin(${m.id})">
|
||||
<span class="search-result-name">KK: ${m.nama_kk}</span>
|
||||
<span class="search-result-desc">${m.keterangan || 'Tanpa keterangan'}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
} else {
|
||||
resDiv.innerHTML = '<div style="padding:8px 10px; color:#94a3b8; font-size:12px;">Tidak ditemukan.</div>';
|
||||
}
|
||||
resDiv.classList.add('active');
|
||||
renderMiskin(false);
|
||||
});
|
||||
|
||||
window.selectMiskin = function(id) {
|
||||
const item = miskinData.find(i => i.id == id);
|
||||
if (!item) return;
|
||||
document.getElementById('search-miskin').value = item.nama_kk;
|
||||
document.getElementById('results-miskin').classList.remove('active');
|
||||
renderMiskin(true);
|
||||
};
|
||||
|
||||
checkAuth();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user