/* ============================================================
draw_geometri.js - WebGIS Point, Polyline, Polygon
============================================================ */
var map = L.map('map', { zoomControl: false }).setView([-0.0263, 109.3425], 13);
L.control.zoom({ position: 'bottomright' }).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxZoom: 19
}).addTo(map);
var drawnItems = new L.FeatureGroup().addTo(map);
var layerGroupPoint = L.featureGroup().addTo(map);
var currentLayer = null;
var isAdmin = window.IS_ADMIN === true;
if (isAdmin) {
var drawControl = new L.Control.Draw({
position: 'topleft',
edit: { featureGroup: drawnItems },
draw: {
marker: true,
polyline: { shapeOptions: { color: '#a855f7', weight: 3 } },
polygon: { shapeOptions: { color: '#10b981', weight: 2, fillOpacity: 0.35 } },
rectangle: false,
circle: false,
circlemarker: false
}
});
map.addControl(drawControl);
}
function getLineColor(status) {
return status === 'Nasional' ? '#ef4444' : status === 'Provinsi' ? '#38bdf8' : '#a855f7';
}
function getLength(latlngs) {
var total = 0;
for (var i = 0; i < latlngs.length - 1; i++) {
total += latlngs[i].distanceTo(latlngs[i + 1]);
}
return total;
}
function fmtNum(n, dec = 2) {
return parseFloat(n).toLocaleString('id-ID', { maximumFractionDigits: dec });
}
function statusBadge(status, type) {
if (type === 'line') {
var c = status === 'Nasional' ? 'badge-red' : status === 'Provinsi' ? 'badge-blue' : 'badge-gray';
return `${status}`;
}
return `${status}`;
}
function makePointIcon() {
var c = '#3b82f6';
return L.divIcon({
html: ``,
iconSize: [26, 38],
iconAnchor: [13, 38],
popupAnchor: [0, -40],
className: ''
});
}
function buildInfoPopup(d, type) {
var headerColors = {
point: 'linear-gradient(135deg,#1d4ed8,#3b82f6)',
line: 'linear-gradient(135deg,#7c3aed,#a855f7)',
polygon: 'linear-gradient(135deg,#065f46,#10b981)'
};
var icons = { point: '📍', line: '▱', polygon: '▰' };
var titles = {
point: `Point - ${d.nama}`,
line: `Jalan - ${d.nama}`,
polygon: `Parsil - ${d.nama}`
};
var rows = '';
if (type === 'point') {
rows = `
Nama${d.nama}
Kode Point${d.no_spbu}
`;
} else if (type === 'line') {
rows = `Status${statusBadge(d.status, 'line')}
Panjang${fmtNum(d.panjang)} m
`;
} else if (type === 'polygon') {
rows = `Status${statusBadge(d.status, 'polygon')}
Luas${fmtNum(d.luas)} m²
`;
}
var deleteButton = isAdmin ? `` : '';
return `
${icons[type]} ${titles[type]}
${rows}${deleteButton}
`;
}
fetch('../php/show_geometri.php')
.then(res => res.json())
.then(data => {
data.forEach(d => {
if (d.type === 'point') {
var pointLayer = L.marker([d.latitude, d.longitude], { icon: makePointIcon() });
pointLayer._type = 'point';
pointLayer._db_id = d.id;
pointLayer.bindPopup(buildInfoPopup(d, 'point'), { maxWidth: 260 });
layerGroupPoint.addLayer(pointLayer);
}
if (d.type === 'line') {
var lineCoords = JSON.parse(d.geom);
var lineLayer = L.polyline(lineCoords, { color: getLineColor(d.status), weight: 4, opacity: 0.9 });
lineLayer._type = 'line';
lineLayer._db_id = d.id;
lineLayer.bindPopup(buildInfoPopup(d, 'line'), { maxWidth: 260 });
drawnItems.addLayer(lineLayer);
}
if (d.type === 'polygon') {
var polygonCoords = JSON.parse(d.geom);
var polygonLayer = L.polygon(polygonCoords, {
color: '#10b981',
weight: 2,
fillColor: '#10b981',
fillOpacity: 0.3
});
polygonLayer._type = 'polygon';
polygonLayer._db_id = d.id;
polygonLayer.bindPopup(buildInfoPopup(d, 'polygon'), { maxWidth: 260 });
drawnItems.addLayer(polygonLayer);
}
});
})
.catch(err => console.error('Gagal load data:', err));
function hapusData(id, type) {
if (!confirm('Yakin ingin menghapus?')) return;
fetch(`../php/delete.php?id=${id}&type=${type}`)
.then(r => r.json())
.then(r => {
if (r.message && r.message.toLowerCase().includes('berhasil')) location.reload();
else alert('Gagal: ' + (r.error || r.message));
});
}
if (isAdmin) {
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer;
if (e.layerType === 'marker') {
drawnItems.addLayer(layer);
handlePoint(layer);
}
if (e.layerType === 'polyline') {
drawnItems.addLayer(layer);
handleLine(layer);
}
if (e.layerType === 'polygon') {
drawnItems.addLayer(layer);
handlePolygon(layer);
}
});
}
function handlePoint(layer) {
var ll = layer.getLatLng();
layer.bindPopup(``, { maxWidth: 280 }).openPopup();
}
function savePoint(lat, lng) {
var nama = document.getElementById('pNama').value.trim();
var no = document.getElementById('pNo').value.trim();
var status = '24 Jam';
if (!nama || !no) {
alert('Nama dan kode point wajib diisi!');
return;
}
fetch('../php/insert_point.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nama, no, status, lat, lng })
})
.then(r => r.json())
.then(r => {
if (r.message && r.message.includes('berhasil')) location.reload();
else alert('Gagal: ' + (r.error || r.message));
});
}
function handleLine(layer) {
currentLayer = layer;
var latlngs = layer.getLatLngs();
var panjang = getLength(latlngs);
layer._temp = { latlngs, panjang };
L.popup({ maxWidth: 280 }).setLatLng(layer.getBounds().getCenter()).setContent(``).openOn(map);
}
function saveLine() {
var layer = currentLayer;
if (!layer) {
alert('Layer tidak ditemukan');
return;
}
var nama = document.getElementById('lNama').value.trim();
var status = document.getElementById('lStatus').value;
if (!nama) {
alert('Nama wajib diisi!');
return;
}
fetch('../php/insert_line.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nama,
status,
panjang: layer._temp.panjang,
geom: JSON.stringify(layer._temp.latlngs)
})
})
.then(r => r.json())
.then(r => {
if (r.id) {
layer._db_id = r.id;
layer._type = 'line';
map.closePopup();
alert('Berhasil!');
} else {
alert('Gagal: ' + (r.error || r.message));
}
});
}
function handlePolygon(layer) {
currentLayer = layer;
var latlngs = layer.getLatLngs();
var luas = L.GeometryUtil.geodesicArea(latlngs[0]);
layer._temp = { latlngs, luas };
L.popup({ maxWidth: 280 }).setLatLng(layer.getBounds().getCenter()).setContent(``).openOn(map);
}
function savePolygon() {
var layer = currentLayer;
if (!layer) {
alert('Layer tidak ditemukan');
return;
}
var nama = document.getElementById('gNama').value.trim();
var status = document.getElementById('gStatus').value;
if (!nama) {
alert('Nama wajib diisi!');
return;
}
fetch('../php/insert_polygon.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nama,
status,
luas: layer._temp.luas,
geom: JSON.stringify(layer._temp.latlngs)
})
})
.then(r => r.json())
.then(r => {
if (r.id) {
layer._db_id = r.id;
layer._type = 'polygon';
map.closePopup();
alert('Berhasil!');
} else {
alert('Gagal: ' + (r.error || r.message));
}
});
}
if (isAdmin) {
map.on('draw:edited', function(e) {
e.layers.eachLayer(layer => {
if (!layer._db_id) return;
if (layer._type === 'line') {
fetch('../php/update_line.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: layer._db_id,
geom: JSON.stringify(layer.getLatLngs()),
panjang: getLength(layer.getLatLngs())
})
});
}
if (layer._type === 'polygon') {
fetch('../php/update_polygon.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: layer._db_id,
geom: JSON.stringify(layer.getLatLngs()),
luas: L.GeometryUtil.geodesicArea(layer.getLatLngs()[0])
})
});
}
});
});
map.on('draw:deleted', function(e) {
e.layers.eachLayer(layer => {
if (layer._db_id && layer._type) {
fetch(`../php/delete.php?id=${layer._db_id}&type=${layer._type}`);
}
});
});
}