Upload perdana untuk deploy

This commit is contained in:
2026-06-11 13:17:31 +07:00
parent 5857b15aec
commit 72133d0a9a
63 changed files with 10057 additions and 457 deletions
+642 -193
View File
@@ -1,9 +1,28 @@
<?php
<?php
// ============================================================
// index.php Halaman Utama WebGIS
// ============================================================
session_start();
// Cek apakah sudah login
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$currentUser = $_SESSION['username'];
$currentRole = $_SESSION['role'];
$modul = $_GET['modul'] ?? 'utuh';
include 'koneksi.php';
// Eksekusi ALTER TABLE secara diam-diam jika kolom belum ada
try {
$pdo->exec("ALTER TABLE penduduk_miskin ADD COLUMN status_bantuan ENUM('Belum Disalurkan', 'Proses', 'Sudah Disalurkan') DEFAULT 'Belum Disalurkan'");
} catch(PDOException $e) {
// Abaikan error jika kolom sudah ada
}
// Ambil semua data
$stmt = $pdo->query("SELECT * FROM points ORDER BY id DESC");
$points = $stmt->fetchAll();
@@ -26,6 +45,10 @@ $totalPM = count($pendudukMiskin);
$ditangani = count(array_filter($pendudukMiskin, fn($p) => $p['status_jangkauan'] === 'Dalam Jangkauan'));
$belumDitangani = $totalPM - $ditangani;
$persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
$totalSPBU = count($points);
$spbu24 = count(array_filter($points, fn($p) => $p['buka_24_jam'] === 'Ya'));
$spbuTidak = $totalSPBU - $spbu24;
?>
<!DOCTYPE html>
<html lang="id">
@@ -38,200 +61,437 @@ $persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin="">
<!-- Google Fonts -->
<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:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<!-- App CSS -->
<link rel="stylesheet" href="assets/css/style.css?v=1">
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Lottie Web -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
<!-- Custom CSS -->
<link rel="stylesheet" href="assets/css/style.css?v=36">
<style>
/* Sticky Header Sidebar */
.sidebar-top-sticky {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(12px);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border-bottom: 1px solid transparent;
flex-shrink: 0;
z-index: 10;
}
/* Saat di-scroll */
.sidebar-top-sticky.scrolled {
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
border-bottom: 1px solid var(--sidebar-border);
}
/* Animasi logo sub */
.logo-sub {
transition: all 0.3s ease;
max-height: 20px;
opacity: 1;
overflow: hidden;
}
.sidebar-top-sticky.scrolled .btn-back-dashboard {
padding: 8px 16px !important;
font-size: 0.75rem !important;
}
.sidebar-top-sticky.scrolled .sidebar-header {
padding: 10px 16px !important;
}
.sidebar-top-sticky.scrolled .logo-sub {
max-height: 0;
opacity: 0;
margin-top: 0;
}
.sidebar-top-sticky.scrolled .logo-icon svg {
width: 18px;
height: 18px;
}
.sidebar-scrollable {
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
display: flex;
flex-direction: column;
}
/* Custom Scrollbar Merah Putih untuk sidebar-scrollable */
.sidebar-scrollable::-webkit-scrollbar {
width: 6px;
}
.sidebar-scrollable::-webkit-scrollbar-track {
background: rgba(0,0,0,0.02);
}
.sidebar-scrollable::-webkit-scrollbar-thumb {
background: rgba(225, 29, 72, 0.2); /* Merah transparan */
border-radius: 6px;
}
.sidebar-scrollable::-webkit-scrollbar-thumb:hover {
background: rgba(225, 29, 72, 0.5); /* Merah saat dihover */
}
</style>
</head>
<body>
<!-- ═══════════════════════════════════════════════════════════
<!-- ============================================================
SPLASH SCREEN PRELOADER
============================================================ -->
<div id="splashScreen" style="position:fixed; inset:0; z-index:9999; background:rgba(15, 23, 42, 0.85); backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px); display:flex; flex-direction:column; align-items:center; justify-content:center; transition:opacity 0.5s ease, visibility 0.5s ease;">
<!-- Lottie Container -->
<div id="lottieContainer" style="width:250px; height:250px; margin-bottom:20px;"></div>
<!-- Pulse Text -->
<div style="color:white; font-family:'Plus Jakarta Sans', sans-serif; font-weight:600; font-size:16px; letter-spacing:0.5px; animation:pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;">
Menyiapkan Engine Geospasial...
</div>
<style>
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: .5; }
}
.splash-hidden {
opacity: 0 !important;
visibility: hidden !important;
}
</style>
</div>
<!-- ============================================================
SIDEBAR
═══════════════════════════════════════════════════════════ -->
============================================================ -->
<aside class="sidebar" id="sidebar">
<div class="sidebar-top-sticky" id="sidebarSticky">
<a href="dashboard.php" class="btn-back-dashboard" style="display:flex;align-items:center;gap:8px;padding:12px 16px;color:var(--sidebar-text);text-decoration:none;border-bottom:1px solid var(--sidebar-border);transition:all 0.3s;font-size:0.85rem;font-weight:600;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
Kembali ke Dashboard
</a>
<!-- Header Sidebar -->
<div class="sidebar-header">
<div class="sidebar-logo">
<div class="logo-icon">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z" fill="currentColor" opacity=".9"/>
<circle cx="12" cy="9" r="2.5" fill="white"/>
<!-- Header Sidebar -->
<div class="sidebar-header">
<div class="sidebar-logo">
<div class="logo-icon">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z" fill="currentColor" opacity=".9"/>
<circle cx="12" cy="9" r="2.5" fill="white"/>
</svg>
</div>
<?php
$modulNames = [
'utuh' => 'Semua Modul',
'spbu' => 'Modul SPBU',
'bantuan' => 'Modul Bantuan',
'tematik' => 'Peta Tematik',
'digitasi' => 'Modul Digitasi'
];
$modulTitle = $modulNames[$modul] ?? 'Analisis Spasial';
?>
<div class="logo-text">
<span class="logo-title">WebGIS</span>
<span class="logo-sub" style="color: var(--accent); font-weight: 700;"><?= $modulTitle ?></span>
</div>
</div>
<button class="sidebar-toggle" id="sidebarToggle" title="Sembunyikan Sidebar">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
<path d="M15 18l-6-6 6-6"/>
</svg>
</div>
<div class="logo-text">
<span class="logo-title">WebGIS</span>
<span class="logo-sub">Analisis Spasial</span>
</div>
</button>
</div>
<button class="sidebar-toggle" id="sidebarToggle" title="Sembunyikan Sidebar">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
<path d="M15 18l-6-6 6-6"/>
</svg>
</button>
</div>
<!-- Kotak Pencarian Baru -->
<div class="sidebar-search">
<div class="search-input-wrap">
<svg class="search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input type="text" id="searchInput" placeholder="Cari nama, NIK, atau lokasi..." autocomplete="off">
</div>
<div class="search-results hidden" id="searchResults"></div>
</div>
<!-- Dashboard Statistik -->
<div class="sidebar-section">
<div class="section-label">Dashboard Statistik</div>
<div class="stats-grid">
<div class="stat-card stat-blue">
<div class="stat-icon">🏢</div>
<div class="stat-body">
<div class="stat-value" id="statTotalRI"><?= $totalFP ?></div>
<div class="stat-label">Fasilitas Publik</div>
<!-- Scrollable Area -->
<div class="sidebar-scrollable" id="sidebarScrollable">
<!-- User Info -->
<div class="sidebar-user">
<div class="user-info">
<div class="user-avatar"><?= strtoupper(substr($currentUser, 0, 1)) ?></div>
<div class="user-detail">
<span class="user-name"><?= htmlspecialchars($currentUser) ?></span>
<span class="user-role"><?= ucfirst($currentRole) ?></span>
</div>
</div>
<div class="stat-card stat-amber">
<div class="stat-icon">👥</div>
<div class="stat-body">
<div class="stat-value" id="statTotalPM"><?= $totalPM ?></div>
<div class="stat-label">Penduduk Miskin</div>
<a href="logout.php" class="btn-logout" title="Logout">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
<polyline points="16 17 21 12 16 7"/>
<line x1="21" y1="12" x2="9" y2="12"/>
</svg>
</a>
</div>
<!-- Dashboard Statistik -->
<?php if (in_array($modul, ['spbu', 'bantuan', 'utuh'])): ?>
<div class="sidebar-section">
<div class="section-label">Dashboard Statistik</div>
<?php if ($modul === 'spbu' || $modul === 'utuh'): ?>
<div class="stats-grid mb-4">
<div class="stat-card stat-blue">
<div class="stat-icon">⛽</div>
<div class="stat-body">
<div class="stat-value" id="statTotalSPBU"><?= $totalSPBU ?></div>
<div class="stat-label">Total SPBU</div>
</div>
</div>
<div class="stat-card stat-green">
<div class="stat-icon">✅</div>
<div class="stat-body">
<div class="stat-value" id="statSPBU24"><?= $spbu24 ?></div>
<div class="stat-label">Buka 24 Jam</div>
</div>
</div>
<div class="stat-card stat-red">
<div class="stat-icon">⚠️</div>
<div class="stat-body">
<div class="stat-value" id="statSPBUTidak"><?= $spbuTidak ?></div>
<div class="stat-label">Tidak 24 Jam</div>
</div>
</div>
</div>
<div class="stat-card stat-green">
<div class="stat-icon">✅</div>
<div class="stat-body">
<div class="stat-value" id="statDitangani"><?= $ditangani ?></div>
<div class="stat-label">Ditangani</div>
<?php endif; ?>
<?php if ($modul === 'bantuan' || $modul === 'utuh'): ?>
<div class="stats-grid">
<div class="stat-card stat-blue">
<div class="stat-icon">🏢</div>
<div class="stat-body">
<div class="stat-value" id="statTotalRI"><?= $totalFP ?></div>
<div class="stat-label">Fasilitas Publik</div>
</div>
</div>
<div class="stat-card stat-amber">
<div class="stat-icon">👥</div>
<div class="stat-body">
<div class="stat-value" id="statTotalPM"><?= $totalPM ?></div>
<div class="stat-label">Penduduk Miskin</div>
</div>
</div>
<div class="stat-card stat-green">
<div class="stat-icon">✅</div>
<div class="stat-body">
<div class="stat-value" id="statDitangani"><?= $ditangani ?></div>
<div class="stat-label">Ditangani</div>
</div>
</div>
<div class="stat-card stat-red">
<div class="stat-icon">⚠️</div>
<div class="stat-body">
<div class="stat-value" id="statBelum"><?= $belumDitangani ?></div>
<div class="stat-label">Belum Ditangani</div>
</div>
</div>
</div>
<div class="stat-card stat-red">
<div class="stat-icon">⚠️</div>
<div class="stat-body">
<div class="stat-value" id="statBelum"><?= $belumDitangani ?></div>
<div class="stat-label">Belum Ditangani</div>
<!-- Progress cakupan -->
<div class="coverage-bar-wrap">
<div class="coverage-bar-header">
<span>Cakupan Bantuan</span>
<strong id="statPersen"><?= $persen ?>%</strong>
</div>
<div class="coverage-bar-track">
<div class="coverage-bar-fill" id="statProgressBar" style="width: <?= $persen ?>%"></div>
</div>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<!-- Tools -->
<?php if (in_array($modul, ['spbu', 'bantuan', 'digitasi', 'utuh'])): ?>
<div class="sidebar-section<?= $currentRole === 'guest' ? ' hidden' : '' ?>" id="sectionTools">
<div class="section-label">Alat Peta</div>
<div class="tool-grid">
<?php if ($modul === 'spbu' || $modul === 'utuh'): ?>
<?php if ($currentRole === 'admin' || $currentRole === 'petugas'): ?>
<button class="tool-btn active" id="btnToolPoint" data-mode="point" title="Tambah SPBU/Titik">
<span class="tool-icon">📍</span>
<span><?= $modul === 'spbu' ? 'Tambah SPBU' : 'Titik' ?></span>
</button>
<?php endif; ?>
<?php endif; ?>
<?php if ($modul === 'digitasi' || $modul === 'utuh'): ?>
<?php if ($currentRole === 'admin'): ?>
<button class="tool-btn" id="btnToolJalan" data-mode="jalan" title="Gambar Jalan">
<span class="tool-icon">🛣️</span>
<span>Jalan</span>
</button>
<button class="tool-btn" id="btnToolPolygon" data-mode="polygon" title="Gambar Polygon">
<span class="tool-icon">⬜</span>
<span>Polygon</span>
</button>
<button class="tool-btn" id="btnToolFasilitasPublik" data-mode="fasilitas_publik" title="Fasilitas Publik">
<span class="tool-icon">🏢</span>
<span>Fasilitas</span>
</button>
<?php endif; ?>
<?php endif; ?>
<?php if ($modul === 'bantuan' || $modul === 'utuh'): ?>
<?php if ($currentRole === 'admin' || $currentRole === 'petugas'): ?>
<button class="tool-btn<?= ($modul === 'bantuan' || $currentRole === 'petugas') ? ' active' : '' ?>" id="btnToolPenduduk" data-mode="penduduk_miskin" title="Penduduk Miskin">
<span class="tool-icon">👥</span>
<span>Miskin</span>
</button>
<?php endif; ?>
<?php endif; ?>
<button class="tool-btn" id="btnToolLokasi" data-mode="lokasi" title="Lokasi Saya">
<span class="tool-icon">📡</span>
<span>Lokasi</span>
</button>
</div>
<div class="help-text" id="helpText">
Pilih alat lalu klik pada peta untuk menambahkan data.
</div>
</div>
<?php endif; ?>
<!-- Kontrol Layer -->
<div class="sidebar-section">
<div class="section-label">Kontrol Layer</div>
<div class="layer-list" id="layerList">
<?php if (in_array($modul, ['bantuan', 'utuh'])): ?>
<label class="layer-item">
<input type="checkbox" id="layerFasilitasPublik" checked>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">🏢</span>
<span>Fasilitas Publik</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerPendudukDalam" checked>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">✅</span>
<span>Penduduk Ditangani</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerPendudukLuar" checked>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">❌</span>
<span>Penduduk Luar Jangkauan</span>
</label>
<?php endif; ?>
<?php if (in_array($modul, ['spbu', 'utuh'])): ?>
<label class="layer-item">
<input type="checkbox" id="layerSpbu24" checked>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">⛽</span>
<span>SPBU Buka 24 Jam</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerSpbuTidak" checked>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">🚧</span>
<span>SPBU Tidak 24 Jam</span>
</label>
<?php endif; ?>
<?php if (in_array($modul, ['tematik', 'utuh'])): ?>
<label class="layer-item">
<input type="checkbox" id="layerKecamatan" <?= $modul === 'tematik' ? 'checked' : '' ?>>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">🗺️</span>
<span>Batas Kecamatan</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerSungai" <?= $modul === 'tematik' ? 'checked' : '' ?>>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">🌊</span>
<span>Sungai Besar</span>
</label>
<label class="layer-item"><input type="checkbox" id="layerGeoJalan" <?= $modul === 'tematik' ? 'checked' : '' ?>>
<span class="layer-icon" style="font-size:14px; margin-right:6px;">🛣️</span>
<span>Jaringan Jalan</span>
</label>
<?php endif; ?>
<?php if (in_array($modul, ['digitasi', 'utuh'])): ?>
<label class="layer-item">
<input type="checkbox" id="layerJalan">
<span class="layer-icon" style="font-size:14px; margin-right:6px;">🛣️</span>
<span>Jalan (Data)</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerPolygon">
<span class="layer-icon" style="font-size:14px; margin-right:6px;">⬜</span>
<span>Polygon (Data)</span>
</label>
<?php endif; ?>
</div>
</div>
<!-- Progress cakupan -->
<div class="coverage-bar-wrap">
<div class="coverage-bar-header">
<span>Cakupan Bantuan</span>
<strong id="statPersen"><?= $persen ?>%</strong>
</div>
<div class="coverage-bar-track">
<div class="coverage-bar-fill" id="statProgressBar" style="width: <?= $persen ?>%"></div>
</div>
</div>
<!-- Tools -->
<div class="sidebar-section">
<div class="section-label">Alat Peta</div>
<div class="tool-grid">
<button class="tool-btn active" id="btnToolPoint" data-mode="point" title="Tambah Titik">
<span class="tool-icon">📍</span>
<span>Titik</span>
</button>
<button class="tool-btn" id="btnToolJalan" data-mode="jalan" title="Gambar Jalan">
<span class="tool-icon">🛣️</span>
<span>Jalan</span>
</button>
<button class="tool-btn" id="btnToolPolygon" data-mode="polygon" title="Gambar Polygon">
<span class="tool-icon">⬜</span>
<span>Polygon</span>
</button>
<button class="tool-btn" id="btnToolFasilitasPublik" data-mode="fasilitas_publik" title="Fasilitas Publik">
<span class="tool-icon">🏢</span>
<span>Fasilitas</span>
</button>
<button class="tool-btn" id="btnToolPenduduk" data-mode="penduduk_miskin" title="Penduduk Miskin">
<span class="tool-icon">👥</span>
<span>Miskin</span>
</button>
<button class="tool-btn" id="btnToolLokasi" data-mode="lokasi" title="Lokasi Saya">
<span class="tool-icon">📡</span>
<span>Lokasi</span>
</button>
</div>
<div class="help-text" id="helpText">
Pilih alat lalu klik pada peta untuk menambahkan data.
</div>
</div>
<!-- Legenda -->
<?php if ($modul !== 'digitasi'): ?>
<div class="sidebar-section">
<div class="section-label">Legenda</div>
<div class="legend-list">
<?php if (in_array($modul, ['bantuan', 'utuh'])): ?>
<div class="legend-item">
<span class="legend-marker-wrapper"><span class="legend-pin fp"></span></span>
<span>Fasilitas Publik + Radius</span>
</div>
<div class="legend-item">
<span class="legend-marker-wrapper"><span class="legend-pin pm-dalam"></span></span>
<span>Penduduk Ditangani (Dalam Jangkauan)</span>
</div>
<div class="legend-item">
<span class="legend-marker-wrapper"><span class="legend-pin pm-luar"></span></span>
<span>Penduduk Luar Jangkauan</span>
</div>
<div class="legend-item" style="flex-direction:column; align-items:flex-start; margin-top:10px; background: rgba(0,0,0,0.02); padding: 8px; border-radius: 8px;">
<span style="font-size:10px; font-weight:700; color:#64748b; margin-bottom:6px; letter-spacing:0.5px;">STATUS BANTUAN (BADGE)</span>
<div style="display:flex; gap:6px; flex-wrap:wrap;">
<span style="font-size:9.5px; padding:3px 8px; border-radius:6px; font-weight:700; background:#f1f5f9; color:#475569; border: 1px solid rgba(0,0,0,0.05);">Belum Disalurkan</span>
<span style="font-size:9.5px; padding:3px 8px; border-radius:6px; font-weight:700; background:#fef3c7; color:#d97706; border: 1px solid rgba(217,119,6,0.1);">Proses</span>
<span style="font-size:9.5px; padding:3px 8px; border-radius:6px; font-weight:700; background:#dcfce7; color:#166534; border: 1px solid rgba(22,101,52,0.1);">Sudah Disalurkan</span>
</div>
</div>
<?php endif; ?>
<?php if (in_array($modul, ['spbu', 'utuh'])): ?>
<div class="legend-item">
<span class="legend-marker-wrapper"><span class="legend-pin" style="background:#2e7d32"></span></span>
<span>SPBU Buka 24 Jam</span>
</div>
<div class="legend-item">
<span class="legend-marker-wrapper"><span class="legend-pin" style="background:#e53935"></span></span>
<span>SPBU Tidak 24 Jam</span>
</div>
<?php endif; ?>
<!-- Layer Control -->
<div class="sidebar-section">
<div class="section-label">Kontrol Layer</div>
<div class="layer-list" id="layerList">
<label class="layer-item">
<input type="checkbox" id="layerFasilitasPublik" checked>
<span class="layer-dot" style="background:#e53935"></span>
<span>Fasilitas Publik</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerPendudukDalam" checked>
<span class="layer-dot" style="background:#e53935;border:2px solid #333"></span>
<span>Penduduk Ditangani</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerPendudukLuar" checked>
<span class="layer-dot" style="background:#2e7d32"></span>
<span>Penduduk Luar Jangkauan</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerTitik"><span class="layer-dot" style="background:#78909c"></span><span>Titik Lokasi (Data)</span></label><label class="layer-item"><input type="checkbox" id="layerJalan"><span class="layer-dot" style="background:#f57c00"></span><span>Jalan (Data)</span></label><label class="layer-item"><input type="checkbox" id="layerPolygon"><span class="layer-dot" style="background:#ba68c8"></span><span>Polygon (Data)</span></label><label class="layer-item"><input type="checkbox" id="layerGeoJalan">
<span class="layer-dot" style="background:#d32f2f"></span>
<span>Jaringan Jalan</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerKecamatan">
<span class="layer-dot" style="background:#ef6c00;border-radius:2px"></span>
<span>Batas Kecamatan</span>
</label>
<label class="layer-item">
<input type="checkbox" id="layerSungai">
<span class="layer-dot" style="background:#0d47a1"></span>
<span>Sungai Besar</span>
</label>
</div>
</div>
<!-- Legenda -->
<div class="sidebar-section">
<div class="section-label">Legenda</div>
<div class="legend-list">
<div class="legend-item">
<span class="legend-marker marker-ri"></span>
<span>Fasilitas Publik + Radius</span>
</div>
<div class="legend-item">
<span class="legend-circle" style="background:rgba(229,57,53,0.2);border:2px solid #e53935"></span>
<span>Penduduk Ditangani</span>
</div>
<div class="legend-item">
<span class="legend-circle" style="background:rgba(46,125,50,0.2);border:2px solid #2e7d32"></span>
<span>Penduduk Luar Jangkauan</span>
</div>
<div class="legend-item">
<span class="legend-line" style="background:#d32f2f"></span>
<span>Jalan Nasional</span>
</div>
<div class="legend-item">
<span class="legend-line" style="background:#f57c00"></span>
<span>Jalan Provinsi</span>
</div>
<div class="legend-item">
<span class="legend-line" style="background:#388e3c"></span>
<span>Jalan Kabupaten</span>
<?php if (in_array($modul, ['tematik', 'utuh'])): ?>
<div class="legend-item">
<span class="legend-line" style="background:#d32f2f"></span>
<span>Jalan Nasional</span>
</div>
<div class="legend-item">
<span class="legend-line" style="background:#f57c00"></span>
<span>Jalan Provinsi</span>
</div>
<div class="legend-item">
<span class="legend-line" style="background:#388e3c"></span>
<span>Jalan Kabupaten</span>
</div>
<?php endif; ?> <!-- Endif for in_array tematik, utuh -->
</div>
</div>
</div>
<?php endif; ?> <!-- Endif for modul !== digitasi -->
</div> <!-- End sidebar-scrollable -->
<!-- Footer -->
<!-- Sidebar Footer (Sticky Bottom) -->
<div class="sidebar-footer">
<span>© 2025 WebGIS Spasial</span>
<button class="btn-statistik" id="btnLihatStatistik">
<span class="btn-statistik-icon">📊</span>
<span class="btn-statistik-text">
<strong>Lihat Statistik Modul</strong>
<small>Grafik interaktif &amp; ringkasan data</small>
</span>
<span class="btn-statistik-arrow"></span>
</button>
<p class="sidebar-footer-copy">&copy; 2026 WebGIS Sistem Pengentasan Kemiskinan.<br>Semua Hak Cipta Dilindungi.</p>
</div>
</aside>
@@ -242,9 +502,81 @@ $persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
</svg>
</button>
<!-- ═══════════════════════════════════════════════════════════
<!-- ============================================================
RIGHT SIDEBAR (PANEL KANAN)
============================================================ -->
<aside id="rightSidebar">
<!-- Header -->
<div class="right-sidebar-header">
<div class="right-sidebar-title">
<div class="right-sidebar-title-icon">🗂️</div>
<span>Data <?= $modulTitle ?></span>
</div>
<button class="right-sidebar-close" id="rightSidebarClose" title="Tutup Panel">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M18 6L6 18M6 6l12 12"/></svg>
</button>
</div>
<!-- Search Bar -->
<div class="right-search-wrap">
<div class="right-search-inner">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" id="rightSearchInput" placeholder="Cari nama, NIK, atau lokasi..." autocomplete="off">
</div>
</div>
<?php if ($modul === 'bantuan'): ?>
<div style="padding: 10px 16px 0;">
<button id="btnManajemenData" class="btn-manajemen" onclick="openManajemenModal()">
<span style="font-size:18px">🗃️</span> Buka Manajemen Data
</button>
</div>
<?php endif; ?>
<?php if ($modul === 'utuh'): ?>
<!-- Tabs untuk Modul Utuh -->
<div class="right-tabs" id="rightTabs">
<button class="right-tab-btn active" data-tab="spbu">⛽ SPBU</button>
<button class="right-tab-btn" data-tab="bantuan">👥 Bantuan</button>
<button class="right-tab-btn" data-tab="jalan">🛣️ Jalan</button>
<button class="right-tab-btn" data-tab="polygon">⬜ Parsil</button>
</div>
<?php endif; ?>
<!-- Meta info -->
<div class="right-sidebar-meta">
<span class="right-sidebar-meta-label">Daftar Data</span>
<span class="right-count-badge" id="rightCardCount">— entri</span>
</div>
<!-- Card List -->
<div class="right-card-list" id="rightCardList">
<!-- Skeleton loading awal -->
<?php if ($modul !== 'tematik'): ?>
<?php for ($i = 0; $i < 4; $i++): ?>
<div class="skeleton-card">
<div class="skeleton-icon"></div>
<div class="skeleton-lines">
<div class="skeleton-line w-80"></div>
<div class="skeleton-line w-50"></div>
</div>
</div>
<?php endfor; ?>
<?php endif; ?>
</div>
</aside>
<!-- Toggle Button untuk Right Sidebar -->
<button id="rightSidebarToggleBtn" title="Panel Data">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
<path d="M15 18l-6-6 6-6"/>
</svg>
<span class="rs-toggle-label">Data</span>
</button>
<!-- ============================================================
MAP
═══════════════════════════════════════════════════════════ -->
============================================================ -->
<div id="mapContainer">
<div id="map"></div>
@@ -258,9 +590,9 @@ $persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
</div>
</div>
<!-- ═══════════════════════════════════════════════════════════
<!-- ============================================================
MODALS
═══════════════════════════════════════════════════════════ -->
============================================================ -->
<!-- BACKDROP -->
<div class="modal-backdrop hidden" id="modalBackdrop"></div>
@@ -281,12 +613,12 @@ $persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
<input type="hidden" id="point_id">
<div class="form-row">
<div class="form-group">
<label class="form-label">Nama <span class="req">*</span></label>
<input type="text" class="form-input" id="point_nama" placeholder="Nama titik...">
<label class="form-label">Nama <span style="color:#e63946">*</span></label>
<input type="text" class="form-input" id="point_nama" placeholder="Nama titik..." autocomplete="off">
</div>
<div class="form-group">
<label class="form-label">No. WhatsApp <span class="req">*</span></label>
<input type="text" class="form-input" id="point_no_wa" placeholder="08xx...">
<label class="form-label">No. WhatsApp <span style="color:#e63946">*</span></label>
<input type="text" class="form-input" id="point_no_wa" placeholder="08xx..." autocomplete="off">
</div>
</div>
<div class="form-group">
@@ -430,8 +762,8 @@ $persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
<input type="hidden" id="fp_id">
<div class="form-row">
<div class="form-group">
<label class="form-label">Nama Fasilitas Publik <span class="req">*</span></label>
<input type="text" class="form-input" id="fp_nama" placeholder="Nama...">
<label class="form-label">Nama Fasilitas <span style="color:#e63946">*</span></label>
<input type="text" class="form-input" id="fp_nama" placeholder="Cth: SDN 01 Pagi" autocomplete="off">
</div>
<div class="form-group">
<label class="form-label">Jenis</label>
@@ -499,22 +831,42 @@ $persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
<input type="hidden" id="pm_id">
<div class="form-row">
<div class="form-group">
<label class="form-label">Nama Lengkap <span class="req">*</span></label>
<input type="text" class="form-input" id="pm_nama" placeholder="Nama...">
<label class="form-label">Nama Lengkap <span style="color:#e63946">*</span></label>
<input type="text" class="form-input" id="pm_nama" placeholder="Sesuai KTP" autocomplete="off">
</div>
<div class="form-group">
<label class="form-label">NIK</label>
<input type="text" class="form-input mono" id="pm_nik" placeholder="16 digit NIK...">
<label class="form-label">NIK <span style="color:#e63946">*</span></label>
<input type="text" class="form-input" id="pm_nik" placeholder="16 digit angka" autocomplete="off">
</div>
</div>
<div class="form-group">
<label class="form-label">Keterangan</label>
<textarea class="form-input" id="pm_keterangan" rows="2" placeholder="Kondisi ekonomi, pekerjaan, dll..."></textarea>
<div class="form-row">
<div class="form-group" style="flex:2">
<label class="form-label">Keterangan</label>
<textarea class="form-input" id="pm_keterangan" rows="2" placeholder="Kondisi ekonomi, pekerjaan, dll..."></textarea>
</div>
<div class="form-group" style="flex:1">
<label class="form-label">Status Penyaluran</label>
<select class="form-input" id="pm_status_bantuan">
<option value="Belum Disalurkan">Belum Disalurkan</option>
<option value="Proses">Proses</option>
<option value="Sudah Disalurkan">Sudah Disalurkan</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Foto Rumah</label>
<input type="file" class="form-input" id="pm_foto_rumah" accept="image/png, image/jpeg" style="padding:10px;">
</div>
<div class="form-group">
<label class="form-label">Foto KK</label>
<input type="file" class="form-input" id="pm_foto_kk" accept="image/png, image/jpeg" style="padding:10px;">
</div>
</div>
<!-- Status Jangkauan (auto) -->
<div class="status-jangkauan-card" id="statusJangkauanCard">
<div class="sj-label">Status Jangkauan</div>
<div class="sj-value" id="pm_status">—</div>
<div class="sj-value" id="pm_status"></div>
<div class="sj-ditangani" id="pm_ditangani"></div>
</div>
<div class="form-row">
@@ -553,11 +905,93 @@ $persen = $totalPM > 0 ? round(($ditangani / $totalPM) * 100, 1) : 0;
</div>
</div>
<!-- ═══════════════════════════════════════════════════════════
DATA PHP → JS
═══════════════════════════════════════════════════════════ -->
<!-- ============================================================
CHART MODAL
============================================================ -->
<div id="chartModal" class="hidden">
<div class="chart-modal-box">
<div class="chart-modal-header">
<div class="chart-modal-icon" id="chartModalIcon">📊</div>
<div class="chart-modal-meta">
<div class="chart-modal-title" id="chartModalTitle">Statistik Modul</div>
<div class="chart-modal-subtitle" id="chartModalSubtitle">Visualisasi data interaktif</div>
</div>
<button class="chart-modal-close" id="chartModalClose">✕</button>
</div>
<div class="chart-modal-body" id="chartModalBody">
<!-- Konten dinamis diisi oleh JS -->
</div>
</div>
</div>
<!-- MODAL: Manajemen Data Penduduk -->
<div class="modal hidden" id="manajemenModal" style="max-width: 900px; width: 95%;">
<div class="modal-header" style="justify-content: space-between;">
<div class="modal-title-wrap">
<div class="modal-icon" style="background:#fce4ec;color:#e91e63">🗃️</div>
<div>
<h3 class="modal-title">Manajemen Data Penduduk</h3>
<p class="modal-subtitle">Pusat kontrol penyaluran bantuan sosial</p>
</div>
</div>
<div style="display: flex; gap: 10px;">
<button class="btn btn-primary" onclick="window.print()" style="padding: 6px 12px; font-size: 0.85rem;">
📥 Cetak Data
</button>
<button class="modal-close" id="closeManajemenModal" style="position:static; margin-left:10px;">✕</button>
</div>
</div>
<div class="modal-body" style="background: #f8fafc; padding: 0;">
<div class="manajemen-filter" style="padding: 16px; border-bottom: 1px solid #e2e8f0; display:flex; gap:10px; flex-wrap:wrap; background:white;">
<button class="btn btn-ghost mj-tab active" data-filter="Semua">Semua</button>
<button class="btn btn-ghost mj-tab" data-filter="Belum Disalurkan">Belum Disalurkan</button>
<button class="btn btn-ghost mj-tab" data-filter="Proses">Proses</button>
<button class="btn btn-ghost mj-tab" data-filter="Sudah Disalurkan">Sudah Disalurkan</button>
</div>
<div class="table-responsive" style="max-height: 60vh; overflow-y: auto; padding: 16px;">
<table class="mj-table" style="width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.05);">
<thead style="background: #f1f5f9; text-align: left;">
<tr>
<th style="padding: 12px 16px; font-weight: 600; font-size: 0.8rem; color:#475569; text-transform:uppercase;">No</th>
<th style="padding: 12px 16px; font-weight: 600; font-size: 0.8rem; color:#475569; text-transform:uppercase;">Identitas</th>
<th style="padding: 12px 16px; font-weight: 600; font-size: 0.8rem; color:#475569; text-transform:uppercase;">Jarak (Status)</th>
<th style="padding: 12px 16px; font-weight: 600; font-size: 0.8rem; color:#475569; text-transform:uppercase;">Foto Rumah</th>
<th style="padding: 12px 16px; font-weight: 600; font-size: 0.8rem; color:#475569; text-transform:uppercase;">Status Bantuan</th>
</tr>
</thead>
<tbody id="manajemenTableBody">
<!-- Data akan di-render via JS -->
</tbody>
</table>
</div>
</div>
</div>
<!-- MODAL: Alert / Peringatan -->
<div class="modal modal-sm hidden" id="alertModal" style="z-index: 9999;">
<div class="modal-header">
<div class="modal-title-wrap">
<div class="modal-icon" style="background:#fff3e0;color:#e65100">⚠️</div>
<div>
<h3 class="modal-title" id="alertTitle">Perhatian</h3>
</div>
</div>
</div>
<div class="modal-body">
<p id="alertMessage" style="font-size: 13px; color: #334155; line-height: 1.5;"></p>
</div>
<div class="modal-footer" style="justify-content: center;">
<button class="btn btn-primary" id="btnAlertOk" style="width: 100%;">Mengerti</button>
</div>
</div>
<!-- ============================================================
DATA PHP → JS
============================================================ -->
<script>
const USER_ROLE = '<?= $currentRole ?>';
const APP_DATA = {
modul: '<?= htmlspecialchars($modul) ?>',
points: <?= json_encode($points, JSON_UNESCAPED_UNICODE) ?>,
jalan: <?= json_encode($jalan, JSON_UNESCAPED_UNICODE) ?>,
polygons: <?= json_encode($polygons, JSON_UNESCAPED_UNICODE) ?>,
@@ -569,8 +1003,23 @@ const APP_DATA = {
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
<!-- App JS -->
<script src="assets/js/app.js?v=1"></script>
<script src="assets/js/app.js?v=36"></script>
<script>
// Fitur scroll dinamis untuk mengecilkan header sidebar tanpa blink
document.addEventListener('DOMContentLoaded', function() {
const scrollable = document.getElementById('sidebarScrollable');
const stickyHeader = document.getElementById('sidebarSticky');
if (scrollable && stickyHeader) {
scrollable.addEventListener('scroll', function() {
if (scrollable.scrollTop > 10) {
stickyHeader.classList.add('scrolled');
} else {
stickyHeader.classList.remove('scrolled');
}
});
}
});
</script>
</body>
</html>