first commit

This commit is contained in:
2026-06-11 21:14:16 +07:00
parent b08a058a34
commit 027f1cc26b
28 changed files with 3428 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
CREATE DATABASE IF NOT EXISTS webgis_spbu;
USE webgis_spbu;
CREATE TABLE IF NOT EXISTS spbu (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(100) NOT NULL,
no_spbu VARCHAR(50) NOT NULL,
status ENUM('24jam', 'tidak') NOT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS jalan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(100) NOT NULL,
status ENUM('Jalan Nasional', 'Jalan Provinsi', 'Jalan Kabupaten') NOT NULL,
panjang DOUBLE NOT NULL,
geom LONGTEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS kavling (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(100) NOT NULL,
status ENUM('SHM', 'HGB', 'HGU', 'HP') NOT NULL,
luas DOUBLE NOT NULL,
geom LONGTEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS kemiskinan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_kepala_keluarga VARCHAR(150) NOT NULL,
jumlah_kk INT NOT NULL,
alamat TEXT NOT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS masjid (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_masjid VARCHAR(150) NOT NULL,
pic_masjid VARCHAR(150) NOT NULL,
alamat TEXT NOT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
radius DOUBLE NOT NULL DEFAULT 500,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE spbu
MODIFY COLUMN nama VARCHAR(100) NOT NULL,
MODIFY COLUMN no_spbu VARCHAR(50) NOT NULL,
MODIFY COLUMN status ENUM('24jam', 'tidak') NOT NULL,
MODIFY COLUMN latitude DOUBLE NOT NULL,
MODIFY COLUMN longitude DOUBLE NOT NULL;
ALTER TABLE jalan
MODIFY COLUMN nama VARCHAR(100) NOT NULL,
MODIFY COLUMN status ENUM('Jalan Nasional', 'Jalan Provinsi', 'Jalan Kabupaten') NOT NULL,
MODIFY COLUMN panjang DOUBLE NOT NULL,
MODIFY COLUMN geom LONGTEXT NOT NULL;
ALTER TABLE kavling
MODIFY COLUMN nama VARCHAR(100) NOT NULL,
MODIFY COLUMN status ENUM('SHM', 'HGB', 'HGU', 'HP') NOT NULL,
MODIFY COLUMN luas DOUBLE NOT NULL,
MODIFY COLUMN geom LONGTEXT NOT NULL;
ALTER TABLE kemiskinan
MODIFY COLUMN nama_kepala_keluarga VARCHAR(150) NOT NULL,
MODIFY COLUMN jumlah_kk INT NOT NULL,
MODIFY COLUMN alamat TEXT NOT NULL,
MODIFY COLUMN latitude DOUBLE NOT NULL,
MODIFY COLUMN longitude DOUBLE NOT NULL;
ALTER TABLE masjid
MODIFY COLUMN nama_masjid VARCHAR(150) NOT NULL,
MODIFY COLUMN pic_masjid VARCHAR(150) NOT NULL,
MODIFY COLUMN alamat TEXT NOT NULL,
MODIFY COLUMN latitude DOUBLE NOT NULL,
MODIFY COLUMN longitude DOUBLE NOT NULL,
MODIFY COLUMN radius DOUBLE NOT NULL DEFAULT 500;
+934
View File
@@ -0,0 +1,934 @@
<!DOCTYPE html>
<html>
<head>
<title>WebGIS SPBU</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css"/>
<style>
:root {
--primary: #5b5cf6;
--primary-strong: #4f46e5;
--primary-soft: #ecebff;
--success: #16a34a;
--danger: #ef4444;
--warning: #f97316;
--info: #2563eb;
--ink: #0f172a;
--muted: #667085;
--line: #e6eaf2;
--panel: rgba(255, 255, 255, 0.96);
--shadow: 0 18px 45px rgba(15, 23, 42, 0.14);
}
html,
body {
height: 100%;
}
body {
margin: 0;
font-family: Inter, "Segoe UI", Arial, sans-serif;
color: var(--ink);
background: #eef2f7;
height: 100vh;
overflow: hidden;
}
button,
input {
font: inherit;
}
.navbar {
position: fixed;
top: 14px;
left: 18px;
right: 18px;
z-index: 1200;
height: 64px;
padding: 10px 14px;
border: 1px solid rgba(226, 232, 240, 0.92);
border-radius: 14px;
background: rgba(255, 255, 255, 0.97);
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.12);
backdrop-filter: blur(16px);
display: grid;
grid-template-columns: minmax(320px, 1fr) auto;
align-items: center;
gap: 16px;
box-sizing: border-box;
}
.brand {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
overflow: hidden;
}
.brand-icon {
width: 36px;
height: 36px;
border-radius: 9px;
display: grid;
place-items: center;
color: var(--primary);
background: var(--primary-soft);
border: 1px solid #d9d8ff;
font-size: 18px;
flex: 0 0 auto;
}
.navbar h2 {
margin: 0;
font-size: 15px;
color: var(--primary-strong);
line-height: 1.2;
white-space: nowrap;
}
.navbar p {
margin: 2px 0 0;
color: var(--muted);
font-size: 11px;
max-width: 540px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.top-actions {
display: flex;
align-items: center;
gap: 6px;
}
.top-actions {
justify-self: end;
}
.navbar button,
.panel-button,
.action-chip {
border: 1px solid var(--line);
border-radius: 11px;
background: #fff;
color: #475467;
cursor: pointer;
font-weight: 700;
transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;
}
.action-chip {
display: inline-flex;
align-items: center;
justify-content: center;
height: 40px;
padding: 0 14px;
color: #344054;
background: #fff;
white-space: nowrap;
cursor: default;
}
.status-text {
color: #667085;
border-color: #edf0f6;
background: #f8fafc;
}
.map-stage {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
#map {
position: absolute;
inset: 0;
z-index: 1;
}
.left-panel,
#sidebar,
.stats-card {
position: absolute;
z-index: 1100;
border: 1px solid rgba(226, 232, 240, 0.95);
border-radius: 16px;
background: var(--panel);
box-shadow: var(--shadow);
backdrop-filter: blur(16px);
box-sizing: border-box;
}
.left-panel {
top: 92px;
left: 18px;
bottom: 18px;
width: 292px;
padding: 16px;
overflow-y: auto;
overflow-x: hidden;
}
#sidebar {
top: 92px;
right: 18px;
bottom: 18px;
width: 410px;
padding: 18px;
overflow-y: auto;
overflow-x: hidden;
}
.stats-card {
left: 336px;
bottom: 24px;
width: 430px;
padding: 16px 18px;
}
.mode-switch {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
padding: 4px;
margin-bottom: 18px;
border: 1px solid var(--line);
border-radius: 12px;
background: #f8fafc;
}
.mode-switch button {
min-height: 40px;
padding: 0 10px;
border: 1px solid transparent;
border-radius: 9px;
color: #667085;
background: transparent;
box-shadow: none;
font-size: 13px;
font-weight: 800;
}
.mode-switch button.active {
color: #fff;
border-color: transparent;
background: var(--primary);
box-shadow: 0 8px 18px rgba(91, 92, 246, 0.24);
}
.panel-button {
min-height: 44px;
padding: 0 12px;
color: #667085;
background: #f8fafc;
border-color: #e8edf5;
border-radius: 10px;
font-size: 13px;
font-weight: 800;
}
.panel-button.active {
color: #fff;
border-color: transparent;
background: var(--primary);
box-shadow: 0 8px 18px rgba(91, 92, 246, 0.24);
}
.panel-section {
margin-bottom: 18px;
}
.panel-section h3,
.section h3,
.stats-title {
margin: 0 0 10px;
color: #667085;
font-size: 11px;
font-weight: 800;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.type-list {
display: grid;
gap: 7px;
}
.panel-button {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 12px;
text-align: left;
}
.tool-icon {
width: 28px;
height: 28px;
display: inline-grid;
place-items: center;
border-radius: 8px;
color: #667085;
background: #eef2f7;
font-size: 15px;
line-height: 1;
flex: 0 0 28px;
}
.panel-button.active .tool-icon {
color: var(--primary);
background: #fff;
}
.legend-list {
display: grid;
gap: 9px;
color: #536179;
font-size: 13px;
}
.legend-item {
display: flex;
align-items: center;
gap: 9px;
}
.legend-dot {
width: 11px;
height: 11px;
border-radius: 99px;
flex: 0 0 auto;
}
.sidebar-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 16px;
}
.sidebar-title {
margin: 0;
color: var(--primary-strong);
font-size: 18px;
line-height: 1.2;
}
.sidebar-subtitle {
margin: 7px 0 0;
color: var(--muted);
font-size: 12px;
line-height: 1.45;
}
.panel-close {
width: 30px;
height: 30px;
border: none;
border-radius: 8px;
color: #667085;
background: transparent;
cursor: default;
font-size: 18px;
}
.section {
margin-bottom: 18px;
}
.section h3 {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
padding-bottom: 8px;
border-bottom: 1px solid var(--line);
}
.section-count {
min-width: 24px;
height: 24px;
padding: 0 8px;
display: inline-grid;
place-items: center;
border-radius: 99px;
background: #eef2ff;
color: var(--primary-strong);
font-size: 11px;
letter-spacing: 0;
}
.card {
padding: 14px;
margin-bottom: 12px;
border: 1px solid var(--line);
border-radius: 12px;
background: #fff;
cursor: pointer;
transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.card:hover {
border-color: #c8cdfd;
box-shadow: 0 12px 24px rgba(15, 23, 42, 0.08);
transform: translateY(-1px);
}
.title {
font-size: 16px;
font-weight: 800;
color: var(--ink);
margin-bottom: 6px;
}
.card-body {
color: #175cd3;
font-size: 13px;
font-weight: 800;
margin-bottom: 6px;
}
.meta {
font-size: 12px;
color: var(--muted);
line-height: 1.45;
}
.card-actions {
display: flex;
justify-content: space-between;
align-items: center;
gap: 10px;
margin-top: 12px;
}
.badge {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 4px 8px;
border-radius: 7px;
font-size: 11px;
font-weight: 800;
color: white;
}
.green {
background: #dcfce7;
color: #15803d;
}
.red {
background: #fee2e2;
color: #dc2626;
}
.blue {
background: #dbeafe;
color: #1d4ed8;
}
.orange {
background: #ffedd5;
color: #ea580c;
}
.gray {
background: #eef2f7;
color: #475467;
}
.delete-btn,
.secondary-btn {
min-width: 42px;
min-height: 38px;
border: 1px solid var(--line);
border-radius: 10px;
padding: 8px 10px;
font-size: 12px;
font-weight: 800;
cursor: pointer;
background: #fff;
color: #667085;
}
.delete-btn:hover {
color: #dc2626;
border-color: #fecaca;
background: #fff5f5;
}
.secondary-btn:hover {
color: #1d4ed8;
border-color: #bfdbfe;
background: #eff6ff;
}
.delete-btn:disabled,
.secondary-btn:disabled {
background: #f3f4f6;
color: #a2aab8;
cursor: not-allowed;
}
.custom-point-icon {
background: transparent;
border: none;
}
.point-dot {
width: 20px;
height: 20px;
display: block;
border-radius: 999px;
border: 3px solid white;
box-shadow: 0 4px 12px rgba(15, 23, 42, 0.35);
}
.empty-state {
padding: 14px;
border-radius: 12px;
border: 1px dashed #d7dce7;
background: #f8fafc;
color: var(--muted);
font-size: 13px;
line-height: 1.5;
}
.modal-backdrop {
position: fixed;
inset: 0;
z-index: 2000;
display: none;
align-items: center;
justify-content: center;
padding: 20px;
background: rgba(15, 23, 42, 0.46);
backdrop-filter: blur(4px);
box-sizing: border-box;
}
.modal-backdrop.is-open {
display: flex;
}
.edit-modal {
width: min(460px, 100%);
max-height: min(720px, 92vh);
overflow: hidden;
border: 1px solid rgba(226, 232, 240, 0.95);
border-radius: 16px;
background: #fff;
box-shadow: 0 24px 70px rgba(15, 23, 42, 0.26);
display: flex;
flex-direction: column;
}
.edit-modal-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 14px;
padding: 18px 20px 14px;
border-bottom: 1px solid var(--line);
}
.edit-modal-title {
margin: 0;
color: var(--ink);
font-size: 18px;
line-height: 1.25;
}
.edit-modal-subtitle {
margin: 5px 0 0;
color: var(--muted);
font-size: 12px;
line-height: 1.45;
}
.edit-modal-close {
width: 34px;
height: 34px;
border: 1px solid var(--line);
border-radius: 10px;
color: #667085;
background: #fff;
cursor: pointer;
font-size: 18px;
font-weight: 800;
}
.edit-modal-body {
padding: 18px 20px;
overflow-y: auto;
}
.form-grid {
display: grid;
gap: 14px;
}
.form-field {
display: grid;
gap: 7px;
}
.form-field label {
color: #344054;
font-size: 12px;
font-weight: 800;
}
.form-field input,
.form-field select,
.form-field textarea {
width: 100%;
min-height: 42px;
border: 1px solid #dbe2ec;
border-radius: 10px;
padding: 10px 12px;
color: var(--ink);
background: #fff;
box-sizing: border-box;
outline: none;
font-size: 13px;
}
.form-field textarea {
min-height: 86px;
resize: vertical;
}
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(91, 92, 246, 0.12);
}
.form-error {
display: none;
padding: 10px 12px;
border-radius: 10px;
color: #b42318;
background: #fff1f3;
font-size: 12px;
font-weight: 700;
}
.form-error.is-visible {
display: block;
}
.edit-modal-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
padding: 14px 20px 18px;
border-top: 1px solid var(--line);
background: #fbfcff;
}
.modal-btn {
min-height: 40px;
border: 1px solid var(--line);
border-radius: 10px;
padding: 0 14px;
color: #475467;
background: #fff;
cursor: pointer;
font-size: 13px;
font-weight: 800;
}
.modal-btn.primary {
color: #fff;
border-color: transparent;
background: var(--primary);
box-shadow: 0 8px 18px rgba(91, 92, 246, 0.24);
}
.filter-box {
display: grid;
gap: 6px;
}
.filter-item {
display: flex;
align-items: center;
gap: 9px;
min-height: 38px;
padding: 7px 10px;
border-radius: 10px;
color: #536179;
background: #f8fafc;
font-size: 12px;
font-weight: 700;
cursor: pointer;
box-sizing: border-box;
}
.filter-item input {
width: 16px;
height: 16px;
accent-color: var(--primary);
cursor: pointer;
}
.stats-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
padding-top: 10px;
border-top: 1px solid var(--line);
}
.stat-value {
color: var(--primary);
font-size: 24px;
font-weight: 900;
line-height: 1;
}
.stat-label {
margin-top: 6px;
color: #667085;
font-size: 10px;
font-weight: 800;
text-transform: uppercase;
}
.leaflet-control-zoom {
border: none !important;
box-shadow: var(--shadow) !important;
}
.leaflet-top.leaflet-left {
top: 108px;
left: 320px;
}
.leaflet-top.leaflet-right {
top: 92px;
right: 446px;
}
.leaflet-control-zoom a,
.leaflet-control-layers {
border-radius: 10px !important;
}
@media (max-width: 1180px) {
.navbar {
grid-template-columns: minmax(260px, 1fr) auto;
}
#sidebar {
width: 360px;
}
.stats-card {
left: 336px;
width: 360px;
}
}
@media (max-width: 900px) {
body {
overflow: auto;
}
.map-stage {
height: auto;
min-height: 100vh;
display: grid;
grid-template-rows: 70vh auto auto auto;
padding-top: 92px;
overflow: visible;
box-sizing: border-box;
}
.navbar,
.left-panel,
#sidebar,
.stats-card,
#map {
position: relative;
inset: auto;
}
.navbar {
position: fixed;
top: 10px;
left: 10px;
right: 10px;
height: 58px;
grid-template-columns: 1fr;
}
.navbar p {
display: none;
}
#map {
height: 70vh;
width: 100%;
}
.leaflet-top.leaflet-left {
top: 12px;
left: 12px;
}
.leaflet-top.leaflet-right {
top: 12px;
right: 12px;
}
.left-panel,
#sidebar,
.stats-card {
width: auto;
margin: 12px;
box-shadow: 0 10px 28px rgba(15, 23, 42, 0.1);
}
.stats-card {
order: 3;
}
#sidebar {
order: 4;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
}
</style>
</head>
<body>
<div class="navbar">
<div class="brand">
<div class="brand-icon"></div>
<div>
<h2>Admin WebGIS SPBU</h2>
<p id="mapHint">Mode view aktif. Pindah ke edit jika ingin menambah atau menghapus data.</p>
</div>
</div>
<div class="top-actions">
<span class="action-chip status-text">Admin SPBU</span>
</div>
</div>
<div class="map-stage">
<div id="map"></div>
<aside class="left-panel">
<div class="mode-switch">
<button id="modeViewBtn" onclick="setMode('view')">◉ Lihat</button>
<button id="modeEditBtn" onclick="setMode('edit')">✎ Edit</button>
</div>
<div class="panel-section">
<h3>Alat Peta</h3>
<div class="type-list">
<button class="panel-button" id="typeSpbuBtn" onclick="setDataType('spbu')"><span class="tool-icon">S</span><span>Tambah SPBU</span></button>
<button class="panel-button" id="typeKemiskinanBtn" onclick="setDataType('kemiskinan')"><span class="tool-icon">K</span><span>Tambah Kemiskinan</span></button>
<button class="panel-button" id="typeMasjidBtn" onclick="setDataType('masjid')"><span class="tool-icon">M</span><span>Tambah Masjid</span></button>
<button class="panel-button" id="typeJalanBtn" onclick="setDataType('jalan')"><span class="tool-icon">J</span><span>Tambah Jalan</span></button>
<button class="panel-button" id="typeKavlingBtn" onclick="setDataType('kavling')"><span class="tool-icon">V</span><span>Tambah Kavling</span></button>
</div>
</div>
<div id="layerFilters"></div>
<div class="panel-section">
<h3>Legenda Peta</h3>
<div class="legend-list">
<div class="legend-item"><span class="legend-dot" style="background:#28a745"></span>SPBU 24 jam</div>
<div class="legend-item"><span class="legend-dot" style="background:#dc3545"></span>SPBU tidak 24 jam</div>
<div class="legend-item"><span class="legend-dot" style="background:#ff8c00"></span>Kemiskinan</div>
<div class="legend-item"><span class="legend-dot" style="background:#007bff"></span>Masjid dan radius</div>
<div class="legend-item"><span class="legend-dot" style="background:#6f42c1"></span>Kavling</div>
</div>
</div>
</aside>
<section class="stats-card">
<div class="stats-head">
<h3 class="stats-title">Statistik Wilayah</h3>
</div>
<div class="stats-grid">
<div>
<div class="stat-value" id="statSpbu">0</div>
<div class="stat-label">Total SPBU</div>
</div>
<div>
<div class="stat-value" id="statMasjid">0</div>
<div class="stat-label">Masjid</div>
</div>
<div>
<div class="stat-value" id="statJalan">0</div>
<div class="stat-label">Jalan</div>
</div>
<div>
<div class="stat-value" id="statKavling">0</div>
<div class="stat-label">Kavling</div>
</div>
</div>
</section>
<div id="sidebar"></div>
</div>
<div class="modal-backdrop" id="editModalBackdrop" aria-hidden="true">
<form class="edit-modal" id="editModalForm">
<div class="edit-modal-header">
<div>
<h2 class="edit-modal-title" id="editModalTitle">Edit Data</h2>
<p class="edit-modal-subtitle" id="editModalSubtitle">Perbarui atribut data terpilih.</p>
</div>
<button class="edit-modal-close" id="editModalClose" type="button">×</button>
</div>
<div class="edit-modal-body">
<div class="form-error" id="editModalError"></div>
<div class="form-grid" id="editModalFields"></div>
</div>
<div class="edit-modal-actions">
<button class="modal-btn" id="editModalCancel" type="button">Batal</button>
<button class="modal-btn primary" type="submit">Simpan Perubahan</button>
</div>
</form>
</div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<script src="js/map.js"></script>
<script src="js/line.js"></script>
<script src="js/polygon.js"></script>
<script src="js/loadData.js"></script>
</body>
</html>
+93
View File
@@ -0,0 +1,93 @@
window.getRoadColor = function (status) {
if (status === "Jalan Nasional") {
return "#dc3545";
}
if (status === "Jalan Provinsi") {
return "#007bff";
}
return "#28a745";
};
window.normalizeRoadStatus = function (value) {
var normalized = String(value || "").trim().toLowerCase();
if (normalized === "jalan nasional" || normalized === "nasional") {
return "Jalan Nasional";
}
if (normalized === "jalan provinsi" || normalized === "provinsi") {
return "Jalan Provinsi";
}
if (normalized === "jalan kabupaten" || normalized === "kabupaten") {
return "Jalan Kabupaten";
}
return "";
};
window.serializeGeometry = function (latlngs) {
return JSON.stringify(latlngs.map(function (point) {
return [
Number(point.lat.toFixed(6)),
Number(point.lng.toFixed(6))
];
}));
};
window.parseGeometry = function (geom) {
try {
var parsed = JSON.parse(geom);
return Array.isArray(parsed) ? parsed : [];
} catch (error) {
return [];
}
};
window.collectRoadData = async function () {
return window.openEditModal({
title: "Tambah Jalan",
subtitle: "Lengkapi atribut jalan untuk garis yang sudah digambar.",
fields: [
{ name: "nama", label: "Nama Jalan", value: "", required: true },
{
name: "status",
label: "Status Jalan",
type: "select",
value: "Jalan Nasional",
options: [
{ value: "Jalan Nasional", label: "Jalan Nasional" },
{ value: "Jalan Provinsi", label: "Jalan Provinsi" },
{ value: "Jalan Kabupaten", label: "Jalan Kabupaten" }
]
}
],
validate: function (data) {
if (!data.nama || !window.normalizeRoadStatus(data.status)) {
return "Nama dan status jalan wajib valid.";
}
return "";
}
});
};
window.buildRoadLayer = function (jalan) {
var coordinates = window.parseGeometry(jalan.geom).map(function (point) {
return L.latLng(point[0], point[1]);
});
if (coordinates.length < 2) {
return null;
}
return L.polyline(coordinates, {
color: window.getRoadColor(jalan.status),
weight: 4
}).bindPopup(
"<b>" + window.escapeHtml(jalan.nama) + "</b><br>" +
"Status: " + window.escapeHtml(jalan.status) + "<br>" +
"Panjang: " + window.formatMeters(jalan.panjang)
);
};
+1007
View File
File diff suppressed because it is too large Load Diff
+567
View File
@@ -0,0 +1,567 @@
window.appState = {
mode: "view",
activeType: "spbu",
drawControl: null,
layers: {},
layerControl: null,
layerVisibility: {
spbu24: true,
spbuTidak: true,
kemiskinan: true,
masjid: true,
jalan: true,
kavling: true
}
};
window.escapeHtml = function (value) {
return String(value ?? "")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
};
window.createPointIcon = function (color) {
return L.divIcon({
className: "custom-point-icon",
html: '<span class="point-dot" style="background:' + color + ';"></span>',
iconSize: [18, 18],
iconAnchor: [9, 9],
popupAnchor: [0, -12]
});
};
window.greenIcon = window.createPointIcon("#28a745");
window.redIcon = window.createPointIcon("#dc3545");
window.orangeIcon = window.createPointIcon("#ff8c00");
window.blueIcon = window.createPointIcon("#007bff");
window.calculateLineLength = function (latlngs) {
var total = 0;
for (var i = 1; i < latlngs.length; i += 1) {
total += map.distance(latlngs[i - 1], latlngs[i]);
}
return total;
};
window.calculatePolygonArea = function (latlngs) {
if (L.GeometryUtil && typeof L.GeometryUtil.geodesicArea === "function") {
return L.GeometryUtil.geodesicArea(latlngs);
}
if (!latlngs.length) {
return 0;
}
var earthRadius = 6378137;
var avgLat = latlngs.reduce(function (sum, point) {
return sum + point.lat;
}, 0) / latlngs.length;
var avgLatRad = avgLat * Math.PI / 180;
var projected = latlngs.map(function (point) {
return {
x: earthRadius * point.lng * Math.PI / 180 * Math.cos(avgLatRad),
y: earthRadius * point.lat * Math.PI / 180
};
});
var area = 0;
for (var i = 0; i < projected.length; i += 1) {
var next = projected[(i + 1) % projected.length];
area += (projected[i].x * next.y) - (next.x * projected[i].y);
}
return Math.abs(area / 2);
};
window.formatMeters = function (value) {
return Number(value).toLocaleString("id-ID", {
maximumFractionDigits: 2
}) + " m";
};
window.formatSquareMeters = function (value) {
return Number(value).toLocaleString("id-ID", {
maximumFractionDigits: 2
}) + " m²";
};
window.postForm = async function (url, payload) {
var response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(payload)
});
var text = (await response.text()).trim();
if (!response.ok || text !== "success") {
throw new Error(text || "Permintaan gagal.");
}
};
window.collectSpbuData = async function () {
return window.openEditModal({
title: "Tambah SPBU",
subtitle: "Lengkapi atribut SPBU untuk titik yang dipilih di peta.",
fields: [
{ name: "nama", label: "Nama SPBU", value: "", required: true },
{ name: "no", label: "Nomor SPBU", value: "", required: true },
{
name: "status",
label: "Status Operasional",
type: "select",
value: "24jam",
options: [
{ value: "24jam", label: "24 Jam" },
{ value: "tidak", label: "Tidak 24 Jam" }
]
}
],
validate: function (data) {
if (!data.nama || !data.no) {
return "Nama dan nomor SPBU wajib diisi.";
}
return "";
}
});
};
window.collectKemiskinanData = async function () {
return window.openEditModal({
title: "Tambah Data Kemiskinan",
subtitle: "Lengkapi data keluarga untuk titik yang dipilih di peta.",
fields: [
{ name: "nama_kepala_keluarga", label: "Nama Kepala Keluarga", value: "", required: true },
{ name: "jumlah_kk", label: "Jumlah KK", type: "number", min: 1, step: 1, value: 1, required: true },
{ name: "alamat", label: "Alamat", type: "textarea", value: "", required: true }
],
validate: function (data) {
if (!data.nama_kepala_keluarga || !data.alamat) {
return "Nama kepala keluarga dan alamat wajib diisi.";
}
if (!Number.isInteger(data.jumlah_kk) || data.jumlah_kk < 1) {
return "Jumlah KK harus angka minimal 1.";
}
return "";
}
});
};
window.collectMasjidData = async function () {
return window.openEditModal({
title: "Tambah Masjid",
subtitle: "Lengkapi identitas masjid untuk titik yang dipilih di peta.",
fields: [
{ name: "nama_masjid", label: "Nama Masjid", value: "", required: true },
{ name: "pic_masjid", label: "PIC Masjid", value: "", required: true },
{ name: "alamat", label: "Alamat Masjid", type: "textarea", value: "", required: true },
{ name: "radius", label: "Radius Jangkauan (meter)", type: "number", min: 100, max: 5000, step: 1, value: 500, required: true }
],
validate: function (data) {
if (!data.nama_masjid || !data.pic_masjid || !data.alamat) {
return "Nama, PIC, dan alamat masjid wajib diisi.";
}
if (!Number.isInteger(data.radius) || data.radius < 100 || data.radius > 5000) {
return "Radius harus angka antara 100 sampai 5000 meter.";
}
return "";
}
});
};
window.updateMapHint = function () {
var hint = document.getElementById("mapHint");
if (!hint) {
return;
}
if (appState.mode === "view") {
hint.textContent = "Mode lihat aktif. Data hanya ditampilkan di peta dan sidebar.";
return;
}
if (appState.activeType === "spbu") {
hint.textContent = "Mode edit SPBU aktif. Klik peta untuk menambahkan titik SPBU.";
return;
}
if (appState.activeType === "kemiskinan") {
hint.textContent = "Mode edit Kemiskinan aktif. Klik peta untuk menambahkan titik data kemiskinan.";
return;
}
if (appState.activeType === "masjid") {
hint.textContent = "Mode edit Masjid aktif. Klik peta untuk menambahkan titik masjid dengan radius awal 500 meter.";
return;
}
if (appState.activeType === "jalan") {
hint.textContent = "Mode edit Jalan aktif. Gunakan tool draw polyline pada peta.";
return;
}
hint.textContent = "Mode edit Kavling aktif. Gunakan tool draw polygon pada peta.";
};
window.updateToolbarState = function () {
var buttonStates = {
modeViewBtn: appState.mode === "view",
modeEditBtn: appState.mode === "edit",
typeSpbuBtn: appState.activeType === "spbu",
typeKemiskinanBtn: appState.activeType === "kemiskinan",
typeMasjidBtn: appState.activeType === "masjid",
typeJalanBtn: appState.activeType === "jalan",
typeKavlingBtn: appState.activeType === "kavling"
};
Object.keys(buttonStates).forEach(function (id) {
var button = document.getElementById(id);
if (button) {
button.classList.toggle("active", buttonStates[id]);
}
});
};
window.configureDrawControl = function () {
if (!window.map) {
return;
}
if (appState.drawControl) {
map.removeControl(appState.drawControl);
appState.drawControl = null;
}
if (appState.mode !== "edit" || appState.activeType === "spbu" || appState.activeType === "kemiskinan" || appState.activeType === "masjid") {
return;
}
var drawOptions = {
polyline: false,
polygon: false,
rectangle: false,
circle: false,
marker: false,
circlemarker: false
};
if (appState.activeType === "jalan") {
drawOptions.polyline = {
shapeOptions: {
color: "#dc3545",
weight: 4
}
};
}
if (appState.activeType === "kavling") {
drawOptions.polygon = {
allowIntersection: false,
shapeOptions: {
color: "#ff8c00",
weight: 3,
fillOpacity: 0.35
}
};
}
appState.drawControl = new L.Control.Draw({
edit: false,
draw: drawOptions
});
map.addControl(appState.drawControl);
};
window.setMode = function (mode) {
appState.mode = mode;
window.updateToolbarState();
window.updateMapHint();
window.configureDrawControl();
if (typeof window.loadAllData === "function") {
window.loadAllData();
}
};
window.setDataType = function (type) {
appState.activeType = type;
window.updateToolbarState();
window.updateMapHint();
window.configureDrawControl();
};
window.getLayerGroupByKey = function (key) {
if (key === "spbu24") {
return appState.layers.spbu24;
}
if (key === "spbuTidak") {
return appState.layers.spbuTidak;
}
if (key === "kemiskinan") {
return appState.layers.kemiskinan;
}
if (key === "masjid") {
return appState.layers.masjid;
}
if (key === "jalan") {
return appState.layers.jalan;
}
if (key === "kavling") {
return appState.layers.kavling;
}
return null;
};
window.setLayerVisibility = function (key, isVisible) {
appState.layerVisibility[key] = !!isVisible;
var layer = window.getLayerGroupByKey(key);
if (!layer || !window.map) {
return;
}
if (isVisible) {
if (!map.hasLayer(layer)) {
map.addLayer(layer);
}
return;
}
if (map.hasLayer(layer)) {
map.removeLayer(layer);
}
};
document.addEventListener("DOMContentLoaded", function () {
window.map = L.map("map").setView([-0.0263, 109.3425], 13);
appState.layers.spbu24 = L.layerGroup().addTo(map);
appState.layers.spbuTidak = L.layerGroup().addTo(map);
appState.layers.kemiskinan = L.layerGroup().addTo(map);
appState.layers.masjid = L.layerGroup().addTo(map);
appState.layers.jalan = L.layerGroup().addTo(map);
appState.layers.kavling = L.layerGroup().addTo(map);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "&copy; OpenStreetMap"
}).addTo(map);
appState.layerControl = L.control.layers(null, {
"SPBU 24 Jam": appState.layers.spbu24,
"SPBU Tidak 24 Jam": appState.layers.spbuTidak,
"Kemiskinan": appState.layers.kemiskinan,
"Masjid": appState.layers.masjid,
"Jalan": appState.layers.jalan,
"Kavling": appState.layers.kavling
}).addTo(map);
map.on("overlayadd", function (event) {
if (event.layer === appState.layers.spbu24) {
appState.layerVisibility.spbu24 = true;
} else if (event.layer === appState.layers.spbuTidak) {
appState.layerVisibility.spbuTidak = true;
} else if (event.layer === appState.layers.kemiskinan) {
appState.layerVisibility.kemiskinan = true;
} else if (event.layer === appState.layers.masjid) {
appState.layerVisibility.masjid = true;
} else if (event.layer === appState.layers.jalan) {
appState.layerVisibility.jalan = true;
} else if (event.layer === appState.layers.kavling) {
appState.layerVisibility.kavling = true;
}
if (typeof window.refreshLayerFilterUI === "function") {
window.refreshLayerFilterUI();
}
});
map.on("overlayremove", function (event) {
if (event.layer === appState.layers.spbu24) {
appState.layerVisibility.spbu24 = false;
} else if (event.layer === appState.layers.spbuTidak) {
appState.layerVisibility.spbuTidak = false;
} else if (event.layer === appState.layers.kemiskinan) {
appState.layerVisibility.kemiskinan = false;
} else if (event.layer === appState.layers.masjid) {
appState.layerVisibility.masjid = false;
} else if (event.layer === appState.layers.jalan) {
appState.layerVisibility.jalan = false;
} else if (event.layer === appState.layers.kavling) {
appState.layerVisibility.kavling = false;
}
if (typeof window.refreshLayerFilterUI === "function") {
window.refreshLayerFilterUI();
}
});
map.on("click", async function (event) {
if (appState.mode !== "edit") {
return;
}
if (appState.activeType === "spbu") {
var spbuData = await window.collectSpbuData();
if (!spbuData) {
return;
}
try {
await window.postForm("php/create.php", {
nama: spbuData.nama,
no: spbuData.no,
status: spbuData.status,
lat: event.latlng.lat.toFixed(6),
lng: event.latlng.lng.toFixed(6)
});
await window.loadAllData();
alert("Data SPBU berhasil disimpan.");
} catch (error) {
alert("Gagal menyimpan SPBU: " + error.message);
}
return;
}
if (appState.activeType === "kemiskinan") {
var kemiskinanData = await window.collectKemiskinanData();
if (!kemiskinanData) {
return;
}
try {
await window.postForm("php/create_kemiskinan.php", {
nama_kepala_keluarga: kemiskinanData.nama_kepala_keluarga,
jumlah_kk: kemiskinanData.jumlah_kk,
alamat: kemiskinanData.alamat,
lat: event.latlng.lat.toFixed(6),
lng: event.latlng.lng.toFixed(6)
});
await window.loadAllData();
alert("Data kemiskinan berhasil disimpan.");
} catch (error) {
alert("Gagal menyimpan data kemiskinan: " + error.message);
}
return;
}
if (appState.activeType === "masjid") {
var masjidData = await window.collectMasjidData();
if (!masjidData) {
return;
}
try {
await window.postForm("php/create_masjid.php", {
nama_masjid: masjidData.nama_masjid,
pic_masjid: masjidData.pic_masjid,
alamat: masjidData.alamat,
radius: masjidData.radius,
lat: event.latlng.lat.toFixed(6),
lng: event.latlng.lng.toFixed(6)
});
await window.loadAllData();
alert("Data masjid berhasil disimpan.");
} catch (error) {
alert("Gagal menyimpan data masjid: " + error.message);
}
}
});
map.on(L.Draw.Event.CREATED, async function (event) {
var layer = event.layer;
if (appState.mode !== "edit") {
alert("Pindah ke mode edit sebelum menggambar data.");
return;
}
if (event.layerType === "polyline") {
if (appState.activeType !== "jalan") {
alert("Tipe aktif saat ini bukan Jalan.");
return;
}
var lineLatLngs = layer.getLatLngs();
var panjang = window.calculateLineLength(lineLatLngs);
var roadData = await window.collectRoadData();
if (!roadData) {
return;
}
try {
await window.postForm("php/create_line.php", {
nama: roadData.nama,
status: roadData.status,
panjang: panjang.toFixed(2),
geom: window.serializeGeometry(lineLatLngs)
});
await window.loadAllData();
alert("Data jalan berhasil disimpan.");
} catch (error) {
alert("Gagal menyimpan jalan: " + error.message);
}
return;
}
if (event.layerType === "polygon") {
if (appState.activeType !== "kavling") {
alert("Tipe aktif saat ini bukan Kavling.");
return;
}
var polygonLatLngs = layer.getLatLngs()[0] || [];
var luas = window.calculatePolygonArea(polygonLatLngs);
var landData = await window.collectPolygonData();
if (!landData) {
return;
}
try {
await window.postForm("php/create_polygon.php", {
nama: landData.nama,
status: landData.status,
luas: luas.toFixed(2),
geom: window.serializeGeometry(polygonLatLngs)
});
await window.loadAllData();
alert("Data kavling berhasil disimpan.");
} catch (error) {
alert("Gagal menyimpan kavling: " + error.message);
}
}
});
window.setMode("view");
window.setDataType("spbu");
setTimeout(function () {
map.invalidateSize();
}, 300);
if (typeof window.loadAllData === "function") {
window.loadAllData();
}
});
+77
View File
@@ -0,0 +1,77 @@
window.getPolygonColor = function (status) {
if (status === "SHM") {
return "#ff8c00";
}
if (status === "HGB") {
return "#6f42c1";
}
if (status === "HGU") {
return "#20c997";
}
return "#6c757d";
};
window.normalizePolygonStatus = function (value) {
var normalized = String(value || "").trim().toUpperCase();
var allowed = ["SHM", "HGB", "HGU", "HP"];
if (allowed.indexOf(normalized) === -1) {
return "";
}
return normalized;
};
window.collectPolygonData = async function () {
return window.openEditModal({
title: "Tambah Kavling",
subtitle: "Lengkapi atribut kavling untuk polygon yang sudah digambar.",
fields: [
{ name: "nama", label: "Nama Kavling", value: "", required: true },
{
name: "status",
label: "Status Kavling",
type: "select",
value: "SHM",
options: [
{ value: "SHM", label: "SHM" },
{ value: "HGB", label: "HGB" },
{ value: "HGU", label: "HGU" },
{ value: "HP", label: "HP" }
]
}
],
validate: function (data) {
if (!data.nama || !window.normalizePolygonStatus(data.status)) {
return "Nama dan status kavling wajib valid.";
}
return "";
}
});
};
window.buildPolygonLayer = function (kavling) {
var coordinates = window.parseGeometry(kavling.geom).map(function (point) {
return L.latLng(point[0], point[1]);
});
if (coordinates.length < 3) {
return null;
}
var color = window.getPolygonColor(kavling.status);
return L.polygon(coordinates, {
color: color,
fillColor: color,
fillOpacity: 0.35,
weight: 3
}).bindPopup(
"<b>" + window.escapeHtml(kavling.nama) + "</b><br>" +
"Status: " + window.escapeHtml(kavling.status) + "<br>" +
"Luas: " + window.formatSquareMeters(kavling.luas)
);
};
+38
View File
@@ -0,0 +1,38 @@
<?php
include 'koneksi.php';
$nama = trim($_POST['nama'] ?? '');
$nomor = trim($_POST['no'] ?? '');
$status = trim($_POST['status'] ?? '');
$latitudeRaw = $_POST['lat'] ?? null;
$longitudeRaw = $_POST['lng'] ?? null;
$latitude = is_numeric($latitudeRaw) ? (float) $latitudeRaw : null;
$longitude = is_numeric($longitudeRaw) ? (float) $longitudeRaw : null;
$allowedStatus = ['24jam', 'tidak'];
if ($nama === '' || $nomor === '' || !in_array($status, $allowedStatus, true) || $latitude === null || $longitude === null) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"INSERT INTO spbu (nama, no_spbu, status, latitude, longitude) VALUES (?, ?, ?, ?, ?)"
);
mysqli_stmt_bind_param($statement, "sssdd", $nama, $nomor, $status, $latitude, $longitude);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+42
View File
@@ -0,0 +1,42 @@
<?php
include 'koneksi.php';
$namaKepalaKeluarga = trim($_POST['nama_kepala_keluarga'] ?? '');
$jumlahKkRaw = $_POST['jumlah_kk'] ?? null;
$jumlahKk = filter_var($jumlahKkRaw, FILTER_VALIDATE_INT);
$alamat = trim($_POST['alamat'] ?? '');
$latitudeRaw = $_POST['lat'] ?? null;
$longitudeRaw = $_POST['lng'] ?? null;
$latitude = is_numeric($latitudeRaw) ? (float) $latitudeRaw : null;
$longitude = is_numeric($longitudeRaw) ? (float) $longitudeRaw : null;
if ($namaKepalaKeluarga === '' || $alamat === '' || $jumlahKk === false || $jumlahKk === null || $jumlahKk < 1 || $latitude === null || $longitude === null) {
http_response_code(400);
exit('error');
}
$statement = null;
try {
$statement = mysqli_prepare(
$conn,
"INSERT INTO kemiskinan (nama_kepala_keluarga, jumlah_kk, alamat, latitude, longitude) VALUES (?, ?, ?, ?, ?)"
);
mysqli_stmt_bind_param($statement, "sisdd", $namaKepalaKeluarga, $jumlahKk, $alamat, $latitude, $longitude);
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
if ($statement) {
mysqli_stmt_close($statement);
}
?>
+36
View File
@@ -0,0 +1,36 @@
<?php
include 'koneksi.php';
$nama = trim($_POST['nama'] ?? '');
$status = trim($_POST['status'] ?? '');
$panjangRaw = $_POST['panjang'] ?? null;
$panjang = is_numeric($panjangRaw) ? (float) $panjangRaw : null;
$geom = trim($_POST['geom'] ?? '');
$allowedStatus = ['Jalan Nasional', 'Jalan Provinsi', 'Jalan Kabupaten'];
if ($nama === '' || $geom === '' || !in_array($status, $allowedStatus, true) || $panjang === null) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"INSERT INTO jalan (nama, status, panjang, geom) VALUES (?, ?, ?, ?)"
);
mysqli_stmt_bind_param($statement, "ssds", $nama, $status, $panjang, $geom);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+43
View File
@@ -0,0 +1,43 @@
<?php
include 'koneksi.php';
$namaMasjid = trim($_POST['nama_masjid'] ?? '');
$picMasjid = trim($_POST['pic_masjid'] ?? '');
$alamat = trim($_POST['alamat'] ?? '');
$latitudeRaw = $_POST['lat'] ?? null;
$longitudeRaw = $_POST['lng'] ?? null;
$radiusRaw = $_POST['radius'] ?? 500;
$latitude = is_numeric($latitudeRaw) ? (float) $latitudeRaw : null;
$longitude = is_numeric($longitudeRaw) ? (float) $longitudeRaw : null;
$radius = is_numeric($radiusRaw) ? (float) $radiusRaw : null;
if ($namaMasjid === '' || $picMasjid === '' || $alamat === '' || $latitude === null || $longitude === null || $radius === null || $radius < 100 || $radius > 5000) {
http_response_code(400);
exit('error');
}
$statement = null;
try {
$statement = mysqli_prepare(
$conn,
"INSERT INTO masjid (nama_masjid, pic_masjid, alamat, latitude, longitude, radius) VALUES (?, ?, ?, ?, ?, ?)"
);
mysqli_stmt_bind_param($statement, "sssddd", $namaMasjid, $picMasjid, $alamat, $latitude, $longitude, $radius);
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
if ($statement) {
mysqli_stmt_close($statement);
}
?>
+36
View File
@@ -0,0 +1,36 @@
<?php
include 'koneksi.php';
$nama = trim($_POST['nama'] ?? '');
$status = trim($_POST['status'] ?? '');
$luasRaw = $_POST['luas'] ?? null;
$luas = is_numeric($luasRaw) ? (float) $luasRaw : null;
$geom = trim($_POST['geom'] ?? '');
$allowedStatus = ['SHM', 'HGB', 'HGU', 'HP'];
if ($nama === '' || $geom === '' || !in_array($status, $allowedStatus, true) || $luas === null) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"INSERT INTO kavling (nama, status, luas, geom) VALUES (?, ?, ?, ?)"
);
mysqli_stmt_bind_param($statement, "ssds", $nama, $status, $luas, $geom);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+28
View File
@@ -0,0 +1,28 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
if ($id === false || $id === null || $id <= 0) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare($conn, "DELETE FROM spbu WHERE id = ?");
mysqli_stmt_bind_param($statement, "i", $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+28
View File
@@ -0,0 +1,28 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
if ($id === false || $id === null || $id <= 0) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare($conn, "DELETE FROM kemiskinan WHERE id = ?");
mysqli_stmt_bind_param($statement, "i", $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+28
View File
@@ -0,0 +1,28 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
if ($id === false || $id === null || $id <= 0) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare($conn, "DELETE FROM jalan WHERE id = ?");
mysqli_stmt_bind_param($statement, "i", $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+28
View File
@@ -0,0 +1,28 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
if ($id === false || $id === null || $id <= 0) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare($conn, "DELETE FROM masjid WHERE id = ?");
mysqli_stmt_bind_param($statement, "i", $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+28
View File
@@ -0,0 +1,28 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
if ($id === false || $id === null || $id <= 0) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare($conn, "DELETE FROM kavling WHERE id = ?");
mysqli_stmt_bind_param($statement, "i", $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+35
View File
@@ -0,0 +1,35 @@
<?php
$conn = mysqli_connect("127.0.0.1", "root", "", "webgis_spbu");
if (!$conn) {
die("Koneksi gagal: " . mysqli_connect_error());
}
mysqli_set_charset($conn, "utf8mb4");
$bootstrapQueries = [
"CREATE TABLE IF NOT EXISTS kemiskinan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_kepala_keluarga VARCHAR(150) NOT NULL,
jumlah_kk INT NOT NULL,
alamat TEXT NOT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS masjid (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_masjid VARCHAR(150) NOT NULL,
pic_masjid VARCHAR(150) NOT NULL,
alamat TEXT NOT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
radius DOUBLE NOT NULL DEFAULT 500,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)"
];
foreach ($bootstrapQueries as $query) {
mysqli_query($conn, $query);
}
?>
+17
View File
@@ -0,0 +1,17 @@
<?php
include 'koneksi.php';
header('Content-Type: application/json; charset=utf-8');
$query = "SELECT * FROM spbu ORDER BY id DESC";
$result = mysqli_query($conn, $query);
$data = [];
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}
}
echo json_encode($data);
?>
+17
View File
@@ -0,0 +1,17 @@
<?php
include 'koneksi.php';
header('Content-Type: application/json; charset=utf-8');
$query = "SELECT * FROM kemiskinan ORDER BY id DESC";
$result = mysqli_query($conn, $query);
$data = [];
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}
}
echo json_encode($data);
?>
+17
View File
@@ -0,0 +1,17 @@
<?php
include 'koneksi.php';
header('Content-Type: application/json; charset=utf-8');
$query = "SELECT * FROM jalan ORDER BY id DESC";
$result = mysqli_query($conn, $query);
$data = [];
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}
}
echo json_encode($data);
?>
+17
View File
@@ -0,0 +1,17 @@
<?php
include 'koneksi.php';
header('Content-Type: application/json; charset=utf-8');
$query = "SELECT * FROM masjid ORDER BY id DESC";
$result = mysqli_query($conn, $query);
$data = [];
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}
}
echo json_encode($data);
?>
+17
View File
@@ -0,0 +1,17 @@
<?php
include 'koneksi.php';
header('Content-Type: application/json; charset=utf-8');
$query = "SELECT * FROM kavling ORDER BY id DESC";
$result = mysqli_query($conn, $query);
$data = [];
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}
}
echo json_encode($data);
?>
+36
View File
@@ -0,0 +1,36 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
$nama = trim($_POST['nama'] ?? '');
$nomor = trim($_POST['no'] ?? '');
$status = trim($_POST['status'] ?? '');
$allowedStatus = ['24jam', 'tidak'];
if ($id === false || $id === null || $id <= 0 || $nama === '' || $nomor === '' || !in_array($status, $allowedStatus, true)) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"UPDATE spbu SET nama = ?, no_spbu = ?, status = ? WHERE id = ?"
);
mysqli_stmt_bind_param($statement, "sssi", $nama, $nomor, $status, $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+36
View File
@@ -0,0 +1,36 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
$namaKepalaKeluarga = trim($_POST['nama_kepala_keluarga'] ?? '');
$jumlahKkRaw = $_POST['jumlah_kk'] ?? null;
$jumlahKk = filter_var($jumlahKkRaw, FILTER_VALIDATE_INT);
$alamat = trim($_POST['alamat'] ?? '');
if ($id === false || $id === null || $id <= 0 || $namaKepalaKeluarga === '' || $jumlahKk === false || $jumlahKk === null || $jumlahKk < 1 || $alamat === '') {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"UPDATE kemiskinan SET nama_kepala_keluarga = ?, jumlah_kk = ?, alamat = ? WHERE id = ?"
);
mysqli_stmt_bind_param($statement, "sisi", $namaKepalaKeluarga, $jumlahKk, $alamat, $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+35
View File
@@ -0,0 +1,35 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
$nama = trim($_POST['nama'] ?? '');
$status = trim($_POST['status'] ?? '');
$allowedStatus = ['Jalan Nasional', 'Jalan Provinsi', 'Jalan Kabupaten'];
if ($id === false || $id === null || $id <= 0 || $nama === '' || !in_array($status, $allowedStatus, true)) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"UPDATE jalan SET nama = ?, status = ? WHERE id = ?"
);
mysqli_stmt_bind_param($statement, "ssi", $nama, $status, $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+37
View File
@@ -0,0 +1,37 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
$namaMasjid = trim($_POST['nama_masjid'] ?? '');
$picMasjid = trim($_POST['pic_masjid'] ?? '');
$alamat = trim($_POST['alamat'] ?? '');
$radiusRaw = $_POST['radius'] ?? null;
$radius = is_numeric($radiusRaw) ? (float) $radiusRaw : null;
if ($id === false || $id === null || $id <= 0 || $namaMasjid === '' || $picMasjid === '' || $alamat === '' || $radius === null || $radius < 100 || $radius > 5000) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"UPDATE masjid SET nama_masjid = ?, pic_masjid = ?, alamat = ?, radius = ? WHERE id = ?"
);
mysqli_stmt_bind_param($statement, "sssdi", $namaMasjid, $picMasjid, $alamat, $radius, $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+30
View File
@@ -0,0 +1,30 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$radiusRaw = $_POST['radius'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
$radius = is_numeric($radiusRaw) ? (float) $radiusRaw : null;
if ($id === false || $id === null || $id <= 0 || $radius === null || $radius < 100 || $radius > 5000) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare($conn, "UPDATE masjid SET radius = ? WHERE id = ?");
mysqli_stmt_bind_param($statement, "di", $radius, $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>
+35
View File
@@ -0,0 +1,35 @@
<?php
include 'koneksi.php';
$idRaw = $_POST['id'] ?? null;
$id = filter_var($idRaw, FILTER_VALIDATE_INT);
$nama = trim($_POST['nama'] ?? '');
$status = trim($_POST['status'] ?? '');
$allowedStatus = ['SHM', 'HGB', 'HGU', 'HP'];
if ($id === false || $id === null || $id <= 0 || $nama === '' || !in_array($status, $allowedStatus, true)) {
http_response_code(400);
exit('error');
}
$statement = mysqli_prepare(
$conn,
"UPDATE kavling SET nama = ?, status = ? WHERE id = ?"
);
mysqli_stmt_bind_param($statement, "ssi", $nama, $status, $id);
try {
if (mysqli_stmt_execute($statement)) {
echo 'success';
} else {
http_response_code(500);
echo 'error';
}
} catch (mysqli_sql_exception $exception) {
http_response_code(500);
echo 'error: ' . $exception->getMessage();
}
mysqli_stmt_close($statement);
?>