Project UAS Sistem Informasi Geografis (SIG)

This commit is contained in:
2026-06-08 20:24:54 +07:00
commit c6087ed7dd
33 changed files with 4549 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
<?php
session_start();
if (!isset($_SESSION['is_admin']) || $_SESSION['is_admin'] !== true) {
header('Location: login.php');
exit;
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Panel Admin — WebGIS Sosial</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=DM+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
<link rel="stylesheet" href="https://unpkg.com/leaflet-draw/dist/leaflet.draw.css"/>
<!-- App styles -->
<link rel="stylesheet" href="../css/style.css"/>
</head>
<body>
<header>
<a href="index.php" class="back-btn" title="Lihat Dashboard Publik">👁</a>
<div class="logo">
<div class="logo-icon" style="background:#ef4444;">🛡</div>
<div class="logo-text">PANEL<span style="color:#ef4444;">ADMIN</span></div>
</div>
<div class="header-divider"></div>
<span style="font-size:12px;color:var(--muted);">Kelola Data & Parameter</span>
<div class="legend">
<div class="legend-item">
<div class="legend-dot" style="background:#f59e0b"></div> Masjid
</div>
<div class="legend-item">
<div class="legend-dot" style="background:#e879f9"></div> Pend. Miskin
</div>
<div class="legend-item">
<div class="legend-dot" style="background:#f59e0b; opacity:0.5;"></div> Dlm. Radius
</div>
</div>
<div class="layer-sep"></div>
<!-- Toggle Masjid & Penduduk -->
<div class="layer-control">
<button class="layer-btn btn-masjid active" id="btnMasjid" onclick="toggleLayer('masjid')">
<span class="dot" style="background:#f59e0b"></span>
Masjid
</button>
<button class="layer-btn btn-penduduk active" id="btnPenduduk" onclick="toggleLayer('penduduk')">
<span class="dot" style="background:#e879f9"></span>
Pend. Miskin
</button>
<button class="layer-btn" id="btnHeatmap" onclick="toggleLayer('heatmap')">
🔥 Heatmap
</button>
<div class="layer-sep"></div>
<a href="logout.php" class="layer-btn" style="text-decoration:none; color:#ef4444; border-color:#ef444433;">Keluar</a>
</div>
</header>
<div id="map"></div>
<!-- Stats Panel -->
<div class="stats-panel-container glass" style="position:absolute; top:80px; right:10px; z-index:1000; width:220px; border-radius:8px; padding:12px; background:#0a0d14ea; border:1px solid #1e2233; color:#fff;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; border-bottom:1px solid #1e2233; padding-bottom:5px;">
<span style="font-weight:700; font-size:12px;">📊 STATISTIK SOSIAL</span>
<button id="statsToggleBtn" onclick="toggleStats()" style="background:none;border:none;color:#9ca3af;cursor:pointer">▲</button>
</div>
<div id="statsContent">
<!-- Rendered by JS -->
</div>
</div>
<!-- Blind Spot Alert -->
<div id="blindSpotPanel" class="glass" style="display:none; position:absolute; bottom:30px; right:10px; z-index:1000; background:#7f1d1d; border:1px solid #ef4444; border-radius:8px; padding:12px; color:#fff; cursor:pointer; align-items:center; gap:10px; box-shadow:0 10px 15px -3px rgba(239,68,68,0.3)" onclick="zoomToBlindSpots()">
<span style="font-size:24px">⚠️</span>
<div>
<div style="font-weight:700;font-size:14px"><span id="blindSpotCount">0</span> Keluarga di Blind Spot!</div>
<div style="font-size:11px;color:#fca5a5">Sangat Rentan & Tidak terjangkau masjid (Klik untuk Zoom)</div>
</div>
</div>
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.heat/dist/leaflet-heat.js"></script>
<script src="https://unpkg.com/leaflet-draw/dist/leaflet.draw.js"></script>
<script src="https://unpkg.com/leaflet-geometryutil/src/leaflet.geometryutil.js"></script>
<!-- Mode Selector Panel (Bottom Left) -->
<div class="mode-panel-container" style="position: absolute; bottom: 30px; left: 10px; z-index: 1000;">
<div class="mode-panel-box glass">
<div class="mode-panel-title">Pilih Mode Pointing</div>
<div class="mode-options">
<label class="mode-panel-label">
<input type="radio" name="mode" value="masjid" checked onclick="setMode('masjid')">
<div class="mode-item">
<span class="mode-panel-icon">🕌</span> <span>Tambah Masjid</span>
</div>
</label>
<label class="mode-panel-label">
<input type="radio" name="mode" value="penduduk" onclick="setMode('penduduk')">
<div class="mode-item">
<span class="mode-panel-icon">👨‍👩‍👧‍👦</span> <span>Tambah Pend. Miskin</span>
</div>
</label>
</div>
</div>
</div>
<!-- App script -->
<script src="../js/draw_sosial.js?v=<?= time() ?>"></script>
<script>
window.setMode = function(mode) {
console.log('Mode changed to: ' + mode);
};
</script>
</body>
</html>
+184
View File
@@ -0,0 +1,184 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36" version="29.3.7">
<diagram id="erd" name="ERD">
<mxGraphModel dx="918" dy="498" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="1100" pageHeight="700" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="title" parent="1" style="text;html=1;fontSize=15;fontStyle=1;align=center;" value="Entity Relationship Diagram — WebGIS Sosial" vertex="1">
<mxGeometry height="30" width="600" x="205" y="27" as="geometry" />
</mxCell>
<mxCell id="tbl-masjid" parent="1" style="shape=table;startSize=30;container=1;collapsible=0;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;strokeColor=#82b366;fillColor=#d5e8d4;fontSize=13;" value="MASJID" vertex="1">
<mxGeometry height="222" width="280" x="80" y="100" as="geometry" />
</mxCell>
<mxCell id="m1" parent="tbl-masjid" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="280" y="30" as="geometry" />
</mxCell>
<mxCell id="m1k" parent="m1" style="shape=partialRectangle;connectable=0;fillColor=#d5e8d4;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;" value="PK" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m1v" parent="m1" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="id (INT, AUTO_INCREMENT)" vertex="1">
<mxGeometry height="32" width="240" x="40" as="geometry">
<mxRectangle height="32" width="240" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m2" parent="tbl-masjid" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="280" y="62" as="geometry" />
</mxCell>
<mxCell id="m2k" parent="m2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m2v" parent="m2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="nama (VARCHAR 100)" vertex="1">
<mxGeometry height="32" width="240" x="40" as="geometry">
<mxRectangle height="32" width="240" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m3" parent="tbl-masjid" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="280" y="94" as="geometry" />
</mxCell>
<mxCell id="m3k" parent="m3" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m3v" parent="m3" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="pic (VARCHAR 100)" vertex="1">
<mxGeometry height="32" width="240" x="40" as="geometry">
<mxRectangle height="32" width="240" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m4" parent="tbl-masjid" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="280" y="126" as="geometry" />
</mxCell>
<mxCell id="m4k" parent="m4" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m4v" parent="m4" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="radius (FLOAT)" vertex="1">
<mxGeometry height="32" width="240" x="40" as="geometry">
<mxRectangle height="32" width="240" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m5" parent="tbl-masjid" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="280" y="158" as="geometry" />
</mxCell>
<mxCell id="m5k" parent="m5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m5v" parent="m5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="latitude (DOUBLE)" vertex="1">
<mxGeometry height="32" width="240" x="40" as="geometry">
<mxRectangle height="32" width="240" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m6" parent="tbl-masjid" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="280" y="190" as="geometry" />
</mxCell>
<mxCell id="m6k" parent="m6" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="m6v" parent="m6" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="longitude (DOUBLE)" vertex="1">
<mxGeometry height="32" width="240" x="40" as="geometry">
<mxRectangle height="32" width="240" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="rel-box" parent="1" style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=10;align=center;" value="Melayani" vertex="1">
<mxGeometry height="68" width="74" x="466" y="177" as="geometry" />
</mxCell>
<mxCell id="tbl-pm" parent="1" style="shape=table;startSize=30;container=1;collapsible=0;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;strokeColor=#d79b00;fillColor=#ffe6cc;fontSize=13;" value="PENDUDUK_MISKIN" vertex="1">
<mxGeometry height="222" width="300" x="650" y="100" as="geometry" />
</mxCell>
<mxCell id="p1" parent="tbl-pm" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="300" y="30" as="geometry" />
</mxCell>
<mxCell id="p1k" parent="p1" style="shape=partialRectangle;connectable=0;fillColor=#ffe6cc;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;" value="PK" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p1v" parent="p1" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="id (INT, AUTO_INCREMENT)" vertex="1">
<mxGeometry height="32" width="260" x="40" as="geometry">
<mxRectangle height="32" width="260" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p2" parent="tbl-pm" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="300" y="62" as="geometry" />
</mxCell>
<mxCell id="p2k" parent="p2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p2v" parent="p2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="nama_kk (VARCHAR 150)" vertex="1">
<mxGeometry height="32" width="260" x="40" as="geometry">
<mxRectangle height="32" width="260" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p3" parent="tbl-pm" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="300" y="94" as="geometry" />
</mxCell>
<mxCell id="p3k" parent="p3" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p3v" parent="p3" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="jumlah_anggota (INT)" vertex="1">
<mxGeometry height="32" width="260" x="40" as="geometry">
<mxRectangle height="32" width="260" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p4" parent="tbl-pm" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="300" y="126" as="geometry" />
</mxCell>
<mxCell id="p4k" parent="p4" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p4v" parent="p4" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="alamat (TEXT)" vertex="1">
<mxGeometry height="32" width="260" x="40" as="geometry">
<mxRectangle height="32" width="260" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p5" parent="tbl-pm" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="300" y="158" as="geometry" />
</mxCell>
<mxCell id="p5k" parent="p5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p5v" parent="p5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="latitude (DOUBLE)" vertex="1">
<mxGeometry height="32" width="260" x="40" as="geometry">
<mxRectangle height="32" width="260" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p6" parent="tbl-pm" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="32" width="300" y="190" as="geometry" />
</mxCell>
<mxCell id="p6k" parent="p6" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="" vertex="1">
<mxGeometry height="32" width="40" as="geometry">
<mxRectangle height="32" width="40" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="p6v" parent="p6" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;" value="longitude (DOUBLE)" vertex="1">
<mxGeometry height="32" width="260" x="40" as="geometry">
<mxRectangle height="32" width="260" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="rel1" edge="1" parent="1" source="tbl-masjid" style="endArrow=ERone;startArrow=ERone;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#d6b656;fontStyle=1;" target="rel-box" value="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="rel2" edge="1" parent="1" source="rel-box" style="endArrow=ERmanyToOne;startArrow=ERmanyToOne;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#d6b656;fontStyle=1;" target="tbl-pm" value="N">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+99
View File
@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGIS Sosial Penduduk Miskin & Masjid</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=DM+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
<!-- App styles -->
<link rel="stylesheet" href="../css/style.css"/>
</head>
<body>
<header>
<a href="../" class="back-btn" title="Kembali ke Menu"></a>
<div class="logo">
<div class="logo-icon" style="background:#f59e0b;">🕌</div>
<div class="logo-text">WEB<span style="color:#f59e0b;">GIS</span> SOSIAL</div>
</div>
<div class="header-divider"></div>
<span style="font-size:12px;color:var(--muted);">Pendataan Penduduk Miskin & Masjid</span>
<div class="legend">
<div class="legend-item">
<div class="legend-dot" style="background:#f59e0b"></div> Masjid
</div>
<div class="legend-item">
<div class="legend-dot" style="background:#e879f9"></div> Pend. Miskin
</div>
<div class="legend-item">
<div class="legend-dot" style="background:#f59e0b; opacity:0.5;"></div> Dlm. Radius
</div>
</div>
<div class="layer-sep"></div>
<!-- Toggle Masjid & Penduduk -->
<div class="layer-control">
<button class="layer-btn btn-masjid active" id="btnMasjid" onclick="toggleLayer('masjid')">
<span class="dot" style="background:#f59e0b"></span>
Masjid
</button>
<button class="layer-btn btn-penduduk active" id="btnPenduduk" onclick="toggleLayer('penduduk')">
<span class="dot" style="background:#e879f9"></span>
Pend. Miskin
</button>
<button class="layer-btn" id="btnHeatmap" onclick="toggleLayer('heatmap')">
🔥 Heatmap
</button>
<div class="layer-sep"></div>
<a href="login.php" class="layer-btn" style="text-decoration:none; color:#f59e0b; border-color:#f59e0b33;">Admin Login</a>
</div>
</header>
<div id="map"></div>
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.heat/dist/leaflet-heat.js"></script>
<!-- App script (Public - Read Only) -->
<script src="../js/draw_sosial_public.js?v=<?= time() ?>"></script>
<!-- Stats Panel -->
<div class="stats-panel-container glass" style="position:absolute; top:80px; right:10px; z-index:1000; width:220px; border-radius:8px; padding:12px; background:#0a0d14ea; border:1px solid #1e2233; color:#fff;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; border-bottom:1px solid #1e2233; padding-bottom:5px;">
<span style="font-weight:700; font-size:12px;">📊 STATISTIK SOSIAL</span>
<button id="statsToggleBtn" onclick="toggleStats()" style="background:none;border:none;color:#9ca3af;cursor:pointer"></button>
</div>
<div id="statsContent">
<!-- Rendered by JS -->
</div>
</div>
<!-- Blind Spot Alert -->
<div id="blindSpotPanel" class="glass" style="display:none; position:absolute; bottom:30px; right:10px; z-index:1000; background:#7f1d1d; border:1px solid #ef4444; border-radius:8px; padding:12px; color:#fff; cursor:pointer; align-items:center; gap:10px; box-shadow:0 10px 15px -3px rgba(239,68,68,0.3)" onclick="zoomToBlindSpots()">
<span style="font-size:24px">⚠️</span>
<div>
<div style="font-weight:700;font-size:14px"><span id="blindSpotCount">0</span> Keluarga di Blind Spot!</div>
<div style="font-size:11px;color:#fca5a5">Sangat Rentan & Tidak terjangkau masjid (Klik untuk Zoom)</div>
</div>
</div>
<!-- App script -->
<script src="../js/draw_sosial.js?v=<?= time() ?>"></script>
<script>
window.setMode = function(mode) {
console.log('Mode changed to: ' + mode);
};
</script>
</body>
</html>
+209
View File
@@ -0,0 +1,209 @@
<?php
session_start();
// Kredensial Admin — bisa diganti sesuai kebutuhan
$ADMIN_USER = 'admin';
$ADMIN_PASS = 'admin123';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user = $_POST['username'] ?? '';
$pass = $_POST['password'] ?? '';
if ($user === $ADMIN_USER && $pass === $ADMIN_PASS) {
$_SESSION['is_admin'] = true;
header('Location: admin.php');
exit;
} else {
$error = 'Username atau password salah.';
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Admin — WebGIS Sosial</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=DM+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'DM Sans', sans-serif;
background: #0a0d14;
color: #e2e8f0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
/* Background grid effect */
body::before {
content: '';
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(245,158,11,0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(245,158,11,0.03) 1px, transparent 1px);
background-size: 40px 40px;
}
/* Glow blob */
body::after {
content: '';
position: absolute;
top: -20%;
left: 50%;
transform: translateX(-50%);
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(245,158,11,0.08) 0%, transparent 70%);
pointer-events: none;
}
.login-card {
position: relative;
z-index: 1;
width: 100%;
max-width: 380px;
background: #1a1d27;
border: 1px solid #2a2d3a;
border-radius: 16px;
padding: 36px 32px;
box-shadow: 0 25px 60px rgba(0,0,0,0.5);
}
.login-logo {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 28px;
}
.login-logo-icon {
width: 44px;
height: 44px;
background: linear-gradient(135deg, #92400e, #f59e0b);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
}
.login-logo-text {
font-family: 'Space Mono', monospace;
font-size: 14px;
font-weight: 700;
letter-spacing: 0.05em;
}
.login-logo-text span { color: #f59e0b; }
.login-logo-sub {
font-size: 11px;
color: #6b7280;
margin-top: 1px;
}
h1 {
font-size: 20px;
font-weight: 700;
margin-bottom: 6px;
}
.login-desc {
font-size: 13px;
color: #6b7280;
margin-bottom: 24px;
line-height: 1.5;
}
label {
display: block;
font-size: 11px;
color: #9ca3af;
font-weight: 600;
letter-spacing: 0.05em;
text-transform: uppercase;
margin-bottom: 6px;
margin-top: 16px;
}
input[type=text], input[type=password] {
width: 100%;
background: #0f1117;
border: 1px solid #2a2d3a;
color: #e2e8f0;
border-radius: 8px;
padding: 10px 14px;
font-size: 14px;
font-family: 'DM Sans', sans-serif;
outline: none;
transition: border-color 0.15s;
}
input[type=text]:focus, input[type=password]:focus {
border-color: #f59e0b;
}
.error-msg {
background: rgba(239,68,68,0.1);
border: 1px solid rgba(239,68,68,0.3);
color: #f87171;
border-radius: 8px;
padding: 10px 14px;
font-size: 13px;
margin-top: 16px;
}
.btn-login {
display: block;
width: 100%;
margin-top: 24px;
padding: 12px;
background: linear-gradient(135deg, #92400e, #f59e0b);
color: #fff;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 700;
font-family: 'DM Sans', sans-serif;
cursor: pointer;
transition: opacity 0.15s, transform 0.1s;
letter-spacing: 0.03em;
}
.btn-login:hover { opacity: 0.9; transform: translateY(-1px); }
.btn-login:active { transform: translateY(0); }
.back-link {
display: block;
text-align: center;
margin-top: 16px;
font-size: 12px;
color: #6b7280;
text-decoration: none;
transition: color 0.15s;
}
.back-link:hover { color: #e2e8f0; }
</style>
</head>
<body>
<div class="login-card">
<div class="login-logo">
<div class="login-logo-icon">🕌</div>
<div>
<div class="login-logo-text">WEB<span>GIS</span> SOSIAL</div>
<div class="login-logo-sub">Portal Administrasi</div>
</div>
</div>
<h1>🔐 Masuk sebagai Admin</h1>
<p class="login-desc">Halaman ini khusus untuk petugas yang berwenang mengelola data penduduk dan masjid.</p>
<?php if ($error): ?>
<div class="error-msg">⚠️ <?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<form method="POST">
<label for="username">Username</label>
<input type="text" id="username" name="username" placeholder="admin" autocomplete="off" required>
<label for="password">Password</label>
<input type="password" id="password" name="password" placeholder="••••••••" required>
<button type="submit" class="btn-login">Masuk ke Panel Admin →</button>
</form>
<a href="index.php" class="back-link">← Kembali ke Dashboard Publik</a>
</div>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
<?php
session_start();
session_destroy();
header('Location: index.php');
exit;
?>
+15
View File
@@ -0,0 +1,15 @@
Buatkan saya dokumen Spesifikasi Kebutuhan Perangkat Lunak (SKPL) atau Software Requirement Specification (SRS) untuk sebuah sistem WebGIS yang bertujuan untuk mengentaskan kemiskinan dengan melibatkan partisipasi masyarakat, khususnya rumah ibadah (Masjid).
Sistem ini adalah aplikasi berbasis web yang dibangun menggunakan HTML, CSS (Vanilla), JavaScript (Leaflet.js untuk pemetaan), dan PHP native dengan database MySQL. Aplikasi ini memiliki dua entitas data spasial utama: titik lokasi Masjid dan titik lokasi Penduduk Miskin. Admin atau pengguna dapat menambahkan titik lokasi Masjid pada peta beserta informasi Penanggung Jawab (PIC) dan menentukan "Radius Deteksi" (jangkauan pelayanan/perhatian sosial dari masjid tersebut dalam satuan meter). Pengguna juga dapat menambahkan titik lokasi Penduduk Miskin beserta data Nama Kepala Keluarga, Jumlah Anggota Keluarga, dan Alamat.
Fitur inti dari aplikasi ini adalah analisis spasial otomatis (berbasis radius). Ketika titik Penduduk Miskin ditambahkan atau ketika radius Masjid disesuaikan, sistem akan secara real-time mengevaluasi jarak antara penduduk miskin dengan masjid-masjid terdekat. Jika seorang penduduk miskin berada di dalam radius pelayanan salah satu masjid, indikator visual (warna marker) pada peta akan berubah untuk menandakan bahwa keluarga tersebut "terjangkau" atau berada dalam wilayah cakupan sosial masjid. Hal ini memungkinkan pemetaan yang jelas mana warga miskin yang sudah berada dalam pengawasan program bantuan masjid dan mana warga miskin yang posisinya berada di luar radius ("blind spot") sehingga membutuhkan intervensi dari pemerintah atau pihak lain.
Tolong buatkan SKPL/SRS lengkap yang mencakup:
1. Pendahuluan (Tujuan, lingkup masalah, definisi/istilah, referensi)
2. Deskripsi Umum (Perspektif produk, fungsi produk, karakteristik pengguna, batasan)
3. Kebutuhan Fungsional (Uraian rinci fitur sistem, input, proses, output)
4. Kebutuhan Non-Fungsional (Performa, keamanan, usability, reliabilitas, portabilitas)
5. Antarmuka Eksternal (UI, hardware, software, komunikasi)
6. Definisi Fungsi dan Kebutuhan Pengguna
Lakukan analisis bisnis proses yang lebih mendalam mengenai bagaimana aplikasi ini digunakan dalam skenario nyata pengentasan kemiskinan agar dokumen SKPL ini terlihat komprehensif dan relevan dengan tujuan akhirnya.
+85
View File
@@ -0,0 +1,85 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36" version="29.3.7">
<diagram id="ucd" name="Use Case Diagram">
<mxGraphModel dx="872" dy="473" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="title" parent="1" style="text;html=1;fontSize=15;fontStyle=1;align=center;" value="Use Case Diagram — WebGIS Sosial (Pengentasan Kemiskinan)" vertex="1">
<mxGeometry height="30" width="620" x="130" y="10" as="geometry" />
</mxCell>
<mxCell id="sys" parent="1" style="points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];shape=mxgraph.uml.systemBoundary;whiteSpace=wrap;html=1;align=center;verticalAlign=top;spacingTop=8;fontSize=13;fontStyle=1;strokeColor=#1a73e8;fillColor=#EBF3FB;" value="Sistem WebGIS Sosial" vertex="1">
<mxGeometry height="568" width="445" x="180" y="55" as="geometry" />
</mxCell>
<mxCell id="uc1" parent="1" style="ellipse;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=11;" value="Melihat Peta&#xa;Persebaran" vertex="1">
<mxGeometry height="55" width="160" x="217.5" y="99" as="geometry" />
</mxCell>
<mxCell id="uc2" parent="1" style="ellipse;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=11;" value="Tambah Titik Masjid" vertex="1">
<mxGeometry height="55" width="155" x="220" y="175" as="geometry" />
</mxCell>
<mxCell id="uc3" parent="1" style="ellipse;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=11;" value="Ubah Radius&#xa;Pelayanan Masjid" vertex="1">
<mxGeometry height="55" width="155" x="220" y="338" as="geometry" />
</mxCell>
<mxCell id="uc4" parent="1" style="ellipse;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=11;" value="Hapus Data Masjid" vertex="1">
<mxGeometry height="55" width="155" x="220" y="420" as="geometry" />
</mxCell>
<mxCell id="uc5" parent="1" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontSize=11;" value="Tambah Titik&#xa;Penduduk Miskin" vertex="1">
<mxGeometry height="55" width="155" x="220" y="255" as="geometry" />
</mxCell>
<mxCell id="uc6" parent="1" style="ellipse;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontSize=11;" value="Hapus Data&#xa;Penduduk Miskin" vertex="1">
<mxGeometry height="55" width="155" x="222.5" y="508" as="geometry" />
</mxCell>
<mxCell id="uc7" parent="1" style="ellipse;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;fontStyle=2;" value="Analisis Spasial&#xa;Radius (Otomatis)" vertex="1">
<mxGeometry height="60" width="160" x="450" y="243" as="geometry" />
</mxCell>
<mxCell id="leg" parent="1" style="text;html=0;fontSize=10;fillColor=#f5f5f5;strokeColor=#666666;align=left;spacingLeft=8;" value="Keterangan: 🟡 Umum 🟢 Fitur Masjid 🟠 Fitur Penduduk Miskin 🔴 Proses Otomatis Sistem" vertex="1">
<mxGeometry height="28" width="580" x="180" y="710" as="geometry" />
</mxCell>
<mxCell id="e1" edge="1" parent="1" source="ajy3wIZuD7tetmBaQCAl-1" style="endArrow=none;" target="uc1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="102" y="306.875" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="e2" edge="1" parent="1" source="ajy3wIZuD7tetmBaQCAl-1" style="endArrow=none;" target="uc2">
<mxGeometry relative="1" as="geometry">
<mxPoint x="102" y="311.73605640810365" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="e3" edge="1" parent="1" source="ajy3wIZuD7tetmBaQCAl-1" style="endArrow=none;" target="uc3">
<mxGeometry relative="1" as="geometry">
<mxPoint x="102" y="324.1986429723855" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="e4" edge="1" parent="1" source="ajy3wIZuD7tetmBaQCAl-1" style="endArrow=none;" target="uc4">
<mxGeometry relative="1" as="geometry">
<mxPoint x="102" y="336.6649670004532" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="e5" edge="1" parent="1" source="ajy3wIZuD7tetmBaQCAl-1" style="endArrow=none;" target="uc5">
<mxGeometry relative="1" as="geometry">
<mxPoint x="102" y="317.1094832911109" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="e6" edge="1" parent="1" source="ajy3wIZuD7tetmBaQCAl-1" style="endArrow=none;" target="uc6">
<mxGeometry relative="1" as="geometry">
<mxPoint x="102" y="323" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="i1" edge="1" parent="1" source="uc1" style="dashed=1;endArrow=open;endFill=0;fontSize=10;" target="uc7" value="&lt;&lt;include&gt;&gt;">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="i2" edge="1" parent="1" source="uc2" style="dashed=1;endArrow=open;endFill=0;fontSize=10;" target="uc7" value="&lt;&lt;include&gt;&gt;">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="i3" edge="1" parent="1" source="uc3" style="dashed=1;endArrow=open;endFill=0;fontSize=10;" target="uc7" value="&lt;&lt;include&gt;&gt;">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="i4" edge="1" parent="1" source="uc5" style="dashed=1;endArrow=open;endFill=0;fontSize=10;" target="uc7" value="&lt;&lt;include&gt;&gt;">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ajy3wIZuD7tetmBaQCAl-1" parent="1" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" value="Admin" vertex="1">
<mxGeometry height="60" width="30" x="59" y="288" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>