/* ============================================================ 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(`
📍 Tambah Point
📍 ${ll.lat.toFixed(6)}, ${ll.lng.toFixed(6)}
`, { 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(`
▱ Tambah Jalan
${fmtNum(panjang)} m
`).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(`
▰ Tambah Parsil
${fmtNum(luas)} m²
`).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}`); } }); }); }