306 lines
12 KiB
HTML
306 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>WebGIS — Spatial Data Management System</title>
|
||
|
||
<!-- Leaflet CSS -->
|
||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
|
||
<!-- Leaflet Draw CSS -->
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css">
|
||
<!-- App CSS -->
|
||
<link rel="stylesheet" href="assets/css/style.css">
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ═══════════════════════ HEADER ═══════════════════════ -->
|
||
<header id="header">
|
||
<div class="logo">WEB<span>GIS</span></div>
|
||
<div class="tagline">Spatial Data Management System · Soreang, West Java</div>
|
||
<div class="spacer"></div>
|
||
<div class="status-badge">● LIVE</div>
|
||
</header>
|
||
|
||
<!-- ═══════════════════════ MAIN APP ═══════════════════════ -->
|
||
<div id="app">
|
||
|
||
<!-- ───────── SIDEBAR ───────── -->
|
||
<aside id="sidebar">
|
||
|
||
<!-- Tab Navigation -->
|
||
<nav id="sidebar-tabs">
|
||
<button class="tab-btn active" data-tab="layers">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
|
||
</svg>
|
||
LAYERS
|
||
</button>
|
||
<button class="tab-btn" data-tab="points">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="12" r="4"/><circle cx="12" cy="12" r="10" stroke-dasharray="2 3"/>
|
||
</svg>
|
||
POINTS
|
||
</button>
|
||
<button class="tab-btn" data-tab="roads">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M5 3v18M19 3v18M5 12h14"/>
|
||
</svg>
|
||
ROADS
|
||
</button>
|
||
<button class="tab-btn" data-tab="parcels">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<rect x="3" y="3" width="18" height="18" rx="2"/>
|
||
<path d="M9 3v18M3 9h18"/>
|
||
</svg>
|
||
PARCELS
|
||
</button>
|
||
<button class="tab-btn" data-tab="laporan">
|
||
📢 LAPORAN
|
||
</button>
|
||
</nav>
|
||
|
||
<!-- Tab Content -->
|
||
<div id="sidebar-content">
|
||
|
||
<!-- ════ LAYERS PANEL ════ -->
|
||
<div class="panel active" id="panel-layers">
|
||
<div class="section-title">⛽ SPBU — Gas Stations</div>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="spbu24" checked>
|
||
<div class="layer-swatch circle" style="background:#22c55e"></div>
|
||
<span class="layer-label">24 Hours SPBU</span>
|
||
<span class="layer-count" data-count-layer="spbu24">0</span>
|
||
</label>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="spbuNot" checked>
|
||
<div class="layer-swatch circle" style="background:#eab308"></div>
|
||
<span class="layer-label">Not 24 Hours SPBU</span>
|
||
<span class="layer-count" data-count-layer="spbuNot">0</span>
|
||
</label>
|
||
|
||
<div class="section-title">🕌 Other Points</div>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="mosque" checked>
|
||
<div class="layer-swatch circle" style="background:#a78bfa"></div>
|
||
<span class="layer-label">Mosques</span>
|
||
<span class="layer-count" data-count-layer="mosque">0</span>
|
||
</label>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="poor" checked>
|
||
<div class="layer-swatch circle" style="background:#f43f5e"></div>
|
||
<span class="layer-label">Poor Population Zones</span>
|
||
<span class="layer-count" data-count-layer="poor">0</span>
|
||
</label>
|
||
|
||
<div class="section-title">🛣️ Roads</div>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="national" checked>
|
||
<div class="layer-swatch" style="background:#ef4444"></div>
|
||
<span class="layer-label">National Road</span>
|
||
<span class="layer-count" data-count-layer="national">0</span>
|
||
</label>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="provincial" checked>
|
||
<div class="layer-swatch" style="background:#f97316"></div>
|
||
<span class="layer-label">Provincial Road</span>
|
||
<span class="layer-count" data-count-layer="provincial">0</span>
|
||
</label>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="district" checked>
|
||
<div class="layer-swatch" style="background:#3b82f6"></div>
|
||
<span class="layer-label">District Road</span>
|
||
<span class="layer-count" data-count-layer="district">0</span>
|
||
</label>
|
||
|
||
<div class="section-title">🗺️ Land Parcels</div>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="shm" checked>
|
||
<div class="layer-swatch" style="background:#10b981"></div>
|
||
<span class="layer-label">SHM — Freehold</span>
|
||
<span class="layer-count" data-count-layer="shm">0</span>
|
||
</label>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="hgb" checked>
|
||
<div class="layer-swatch" style="background:#6366f1"></div>
|
||
<span class="layer-label">HGB — Building Rights</span>
|
||
<span class="layer-count" data-count-layer="hgb">0</span>
|
||
</label>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="hgu" checked>
|
||
<div class="layer-swatch" style="background:#f59e0b"></div>
|
||
<span class="layer-label">HGU — Business Rights</span>
|
||
<span class="layer-count" data-count-layer="hgu">0</span>
|
||
</label>
|
||
<label class="layer-item">
|
||
<input type="checkbox" class="layer-cb" data-layer="hp" checked>
|
||
<div class="layer-swatch" style="background:#ec4899"></div>
|
||
<span class="layer-label">HP — Usage Rights</span>
|
||
<span class="layer-count" data-count-layer="hp">0</span>
|
||
</label>
|
||
</div>
|
||
|
||
<!-- ════ POINTS PANEL ════ -->
|
||
<div class="panel" id="panel-points">
|
||
<div class="info-box accent">
|
||
Click the map to place a point, then fill in the form.
|
||
</div>
|
||
<div class="btn-row" style="margin-top:0;margin-bottom:12px">
|
||
<button class="btn btn-primary btn-full" data-mode="point" onclick="enablePointAdd()">
|
||
➕ Add Point on Map
|
||
</button>
|
||
|
||
<button
|
||
class="btn btn-secondary btn-full"
|
||
onclick="enableLaporanAdd()"
|
||
style="margin-top:8px">
|
||
|
||
📢 Laporkan Warga Miskin
|
||
|
||
</button>
|
||
|
||
</div>
|
||
<div class="section-title">All Points</div>
|
||
<div class="feature-list" id="point-list">
|
||
<div class="info-box">Loading…</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ════ ROADS PANEL ════ -->
|
||
<div class="panel" id="panel-roads">
|
||
<div class="info-box accent">
|
||
Draw a polyline on the map. Length is calculated automatically.
|
||
</div>
|
||
<div class="btn-row" style="margin-top:0;margin-bottom:12px">
|
||
<button class="btn btn-primary btn-full" data-mode="road" onclick="startAddRoad()">
|
||
✏️ Draw Road on Map
|
||
</button>
|
||
</div>
|
||
<div class="section-title">All Roads</div>
|
||
<div class="feature-list" id="road-list">
|
||
<div class="info-box">Loading…</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ════ PARCELS PANEL ════ -->
|
||
<div class="panel" id="panel-parcels">
|
||
<div class="info-box accent">
|
||
Draw a polygon on the map. Area is calculated automatically.
|
||
</div>
|
||
<div class="btn-row" style="margin-top:0;margin-bottom:12px">
|
||
<button class="btn btn-primary btn-full" data-mode="parcel" onclick="startAddParcel()">
|
||
🗺️ Draw Parcel on Map
|
||
</button>
|
||
</div>
|
||
<div class="section-title">All Parcels</div>
|
||
<div class="feature-list" id="parcel-list">
|
||
<div class="info-box">Loading…</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ════ LAPORAN PANEL ════ -->
|
||
<div class="panel" id="panel-laporan">
|
||
|
||
<div class="info-box accent">
|
||
Daftar laporan masyarakat yang menunggu verifikasi.
|
||
</div>
|
||
|
||
<div class="section-title">
|
||
Laporan Masyarakat
|
||
</div>
|
||
|
||
<div class="feature-list" id="laporan-list">
|
||
<div class="info-box">
|
||
Loading...
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
</div><!-- /sidebar-content -->
|
||
</aside>
|
||
|
||
|
||
|
||
<!-- ───────── MAP CONTAINER ───────── -->
|
||
<div id="map-container">
|
||
|
||
<!-- 🔥 PINDAH KE SINI -->
|
||
<div style="
|
||
position:absolute;
|
||
top:10px;
|
||
left:50px;
|
||
z-index:1000;
|
||
background:white;
|
||
padding:10px;
|
||
border-radius:8px;
|
||
box-shadow:0 2px 6px rgba(0,0,0,0.2);
|
||
">
|
||
Radius: <span id="radiusValue">500</span> m<br>
|
||
<input type="range" id="radiusSlider" min="100" max="2000" value="500">
|
||
</div>
|
||
|
||
<div id="map"></div>
|
||
|
||
<!-- Coordinates display -->
|
||
<div id="coords-display">0.000000, 0.000000</div>
|
||
|
||
<!-- Cancel draw hint (shown only during draw mode) -->
|
||
<div id="draw-hint" style="
|
||
display:none;
|
||
position:absolute;
|
||
top:12px;
|
||
left:50%;
|
||
transform:translateX(-50%);
|
||
z-index:500;
|
||
background:rgba(15,17,23,0.9);
|
||
border:1px solid var(--accent2);
|
||
color:var(--accent2);
|
||
border-radius:8px;
|
||
padding:6px 16px;
|
||
font-size:12px;
|
||
font-family:'Space Mono',monospace;
|
||
pointer-events:none;
|
||
">Press <strong>ESC</strong> to cancel</div>
|
||
</div>
|
||
|
||
</div><!-- /app -->
|
||
|
||
<!-- ═══════════════════════ STATS BAR ═══════════════════════ -->
|
||
<footer id="stats-bar">
|
||
<div class="stat-item">
|
||
<span class="stat-label">POINTS</span>
|
||
<span class="stat-val" id="stat-points">0</span>
|
||
</div>
|
||
<div class="stat-item">
|
||
<span class="stat-label">ROADS</span>
|
||
<span class="stat-val" id="stat-roads">0</span>
|
||
</div>
|
||
<div class="stat-item">
|
||
<span class="stat-label">PARCELS</span>
|
||
<span class="stat-val" id="stat-parcels">0</span>
|
||
</div>
|
||
<span style="margin-left:auto;color:var(--text-muted)">© WebGIS · OpenStreetMap</span>
|
||
</footer>
|
||
|
||
<!-- ═══════════════════════ MODAL ═══════════════════════ -->
|
||
<div id="modal-overlay">
|
||
<div id="modal"><!-- dynamically filled --></div>
|
||
</div>
|
||
|
||
<!-- ═══════════════════════ TOAST ═══════════════════════ -->
|
||
<div id="toast-container"></div>
|
||
|
||
<!-- ─── Leaflet JS ─── -->
|
||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||
<!-- Leaflet Draw -->
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
|
||
<!-- Leaflet Geometry Util (for geodesic area calculation) -->
|
||
<script src="https://cdn.jsdelivr.net/npm/leaflet-geometryutil@0.10.3/src/leaflet.geometryutil.js"></script>
|
||
<!-- App JS -->
|
||
<script src="assets/js/app.js"></script>
|
||
|
||
</body>
|
||
</html>
|