Files

425 lines
25 KiB
JavaScript

/* ============================================================
draw.js — WebGIS SPBU Pontianak
Handles: SPBU, Jalan, Parsil, Masjid + Radius, Penduduk Miskin
============================================================ */
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);
/* ── LAYER GROUPS ── */
var drawnItems = new L.FeatureGroup().addTo(map);
var layerGroup24 = L.featureGroup().addTo(map);
var layerGroupTidak = L.featureGroup().addTo(map);
var layerGroupMasjid = L.featureGroup().addTo(map);
var layerGroupPenduduk = L.featureGroup().addTo(map);
var show24 = true, showTidak = true;
var showMasjid = true, showPenduduk = true;
/* Storage kalkulasi radius */
var masjidData = [];
var pendudukData = [];
let currentLayer = null;
window.setMode = function(mode) {
console.log('Mode Pointing changed to: ' + mode);
};
/* ============================================================
TOGGLE LAYERS
============================================================ */
function toggleLayer(type) {
if (type === '24jam') {
show24 = !show24;
show24 ? map.addLayer(layerGroup24) : map.removeLayer(layerGroup24);
document.getElementById('btn24').classList.toggle('active', show24);
} else if (type === 'tidak') {
showTidak = !showTidak;
showTidak ? map.addLayer(layerGroupTidak) : map.removeLayer(layerGroupTidak);
document.getElementById('btnTidak').classList.toggle('active', showTidak);
} else if (type === 'masjid') {
showMasjid = !showMasjid;
showMasjid ? map.addLayer(layerGroupMasjid) : map.removeLayer(layerGroupMasjid);
document.getElementById('btnMasjid').classList.toggle('active', showMasjid);
} else if (type === 'penduduk') {
showPenduduk = !showPenduduk;
showPenduduk ? map.addLayer(layerGroupPenduduk) : map.removeLayer(layerGroupPenduduk);
document.getElementById('btnPenduduk').classList.toggle('active', showPenduduk);
}
}
/* ============================================================
DRAW CONTROL
============================================================ */
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);
/* ============================================================
HELPERS
============================================================ */
function getLineColor(s) {
return s==='Nasional' ? '#ef4444' : s==='Provinsi' ? '#38bdf8' : '#a855f7';
}
function getLength(ll) {
let t=0;
for(let i=0;i<ll.length-1;i++) t+=ll[i].distanceTo(ll[i+1]);
return t;
}
function fmtNum(n, dec=2) {
return parseFloat(n).toLocaleString('id-ID', { maximumFractionDigits: dec });
}
function statusBadge(s, type) {
if (type==='point') return s==='24 Jam' ? `<span class="ip-badge badge-green">24 Jam</span>` : `<span class="ip-badge badge-red">Tidak 24 Jam</span>`;
if (type==='line') { let c=s==='Nasional'?'badge-red':s==='Provinsi'?'badge-blue':'badge-gray'; return `<span class="ip-badge ${c}">${s}</span>`; }
return `<span class="ip-badge ${s==='SHM'?'badge-green':'badge-blue'}">${s}</span>`;
}
/* ── Icons ── */
function makeIcon(status) {
var c = status==='24 Jam' ? '#4ade80' : '#f87171';
return L.divIcon({ html:`<svg xmlns="http://www.w3.org/2000/svg" width="26" height="38" viewBox="0 0 26 38"><path d="M13 0C5.8 0 0 5.8 0 13c0 9.75 13 25 13 25S26 22.75 26 13C26 5.8 20.2 0 13 0z" fill="${c}" stroke="rgba(255,255,255,.25)" stroke-width="1.5"/><circle cx="13" cy="13" r="5" fill="rgba(0,0,0,.4)"/><circle cx="13" cy="13" r="3" fill="white"/></svg>`, iconSize:[26,38], iconAnchor:[13,38], popupAnchor:[0,-40], className:'' });
}
function makeMasjidIcon() {
return L.divIcon({ html:`<svg xmlns="http://www.w3.org/2000/svg" width="30" height="42" viewBox="0 0 30 42"><path d="M15 0C6.7 0 0 6.7 0 15c0 11.25 15 27 15 27S30 26.25 30 15C30 6.7 23.3 0 15 0z" fill="#f59e0b" stroke="rgba(255,255,255,.3)" stroke-width="1.5"/><text x="15" y="20" text-anchor="middle" font-size="13" fill="white">🕌</text></svg>`, iconSize:[30,42], iconAnchor:[15,42], popupAnchor:[0,-44], className:'' });
}
function makePendudukIcon(inRadius) {
var c = inRadius ? '#f59e0b' : '#e879f9';
return L.divIcon({ html:`<svg xmlns="http://www.w3.org/2000/svg" width="22" height="32" viewBox="0 0 22 32"><path d="M11 0C4.9 0 0 4.9 0 11c0 8.25 11 21 11 21S22 19.25 22 11C22 4.9 17.1 0 11 0z" fill="${c}" stroke="rgba(255,255,255,.3)" stroke-width="1.5"/><circle cx="11" cy="11" r="4" fill="rgba(0,0,0,.35)"/><circle cx="11" cy="11" r="2.5" fill="white"/></svg>`, iconSize:[22,32], iconAnchor:[11,32], popupAnchor:[0,-34], className:'' });
}
/* ============================================================
RADIUS LOGIC — cek semua penduduk vs semua masjid
Jika kena ≥2 radius → pilih masjid terdekat
============================================================ */
function recalcAllRadius(previewM = null) {
pendudukData.forEach(p => {
var inAny = false;
var minDist = Infinity;
// Cek semua masjid yang sudah tersimpan
masjidData.forEach(m => {
var d = map.distance([p.lat, p.lng], [m.lat, m.lng]);
if (d <= m.radius) { inAny = true; if (d < minDist) minDist = d; }
});
// Cek juga masjid yang sedang di-preview (sebelum simpan)
if (previewM) {
var d = map.distance([p.lat, p.lng], [previewM.lat, previewM.lng]);
if (d <= previewM.radius) { inAny = true; if (d < minDist) minDist = d; }
}
// Update icon jika status "dalam radius" berubah
if (p.inRadius !== inAny) {
p.inRadius = inAny;
p.markerLayer.setIcon(makePendudukIcon(inAny));
}
});
}
/* ============================================================
POPUP BUILDERS
============================================================ */
function buildInfoPopup(d, type) {
const hc = { point:'linear-gradient(135deg,#1d4ed8,#3b82f6)', line:'linear-gradient(135deg,#7c3aed,#a855f7)', polygon:'linear-gradient(135deg,#065f46,#10b981)', masjid:'linear-gradient(135deg,#92400e,#f59e0b)', penduduk:'linear-gradient(135deg,#701a75,#e879f9)' };
const ic = { point:'⛽', line:'🛣️', polygon:'📐', masjid:'🕌', penduduk:'👨‍👩‍👧‍👦' };
const ti = { point:`SPBU — ${d.nama}`, line:`Jalan — ${d.nama}`, polygon:`Parsil — ${d.nama}`, masjid:`Masjid — ${d.nama}`, penduduk:`KK — ${d.nama_kk}` };
let rows = '';
if (type==='point') {
rows = `<div class="ip-row"><span class="ip-label">No. SPBU</span><span class="ip-val">${d.no_spbu}</span></div>
<div class="ip-row"><span class="ip-label">Status</span><span class="ip-val">${statusBadge(d.status,'point')}</span></div>
<div class="ip-row"><span class="ip-label">Koordinat</span><span class="ip-val" style="font-size:10px">${parseFloat(d.latitude).toFixed(5)}, ${parseFloat(d.longitude).toFixed(5)}</span></div>`;
} else if (type==='line') {
rows = `<div class="ip-row"><span class="ip-label">Status</span><span class="ip-val">${statusBadge(d.status,'line')}</span></div>
<div class="ip-row"><span class="ip-label">Panjang</span><span class="ip-val">${fmtNum(d.panjang)} m</span></div>`;
} else if (type==='polygon') {
rows = `<div class="ip-row"><span class="ip-label">Status</span><span class="ip-val">${statusBadge(d.status,'polygon')}</span></div>
<div class="ip-row"><span class="ip-label">Luas</span><span class="ip-val">${fmtNum(d.luas)} m²</span></div>`;
} else if (type==='masjid') {
rows = `<div class="ip-row"><span class="ip-label">PIC</span><span class="ip-val">${d.pic}</span></div>
<div class="ip-row"><span class="ip-label">Radius</span><span class="ip-val" id="radiusDisplay_${d.id}">${fmtNum(d.radius,0)} m</span></div>
<div class="radius-slider-wrap">
<input type="range" min="100" max="5000" step="50" value="${d.radius}" id="radiusSlider_${d.id}" oninput="onRadiusSlide(${d.id}, this.value)">
<div class="radius-val"><span>100m</span><span>5000m</span></div>
</div>
<button class="pf-btn" style="margin-top:10px" onclick="saveRadius(${d.id})">💾 Simpan Radius</button>`;
} else if (type==='penduduk') {
rows = `<div class="ip-row"><span class="ip-label">Jml. Anggota KK</span><span class="ip-val">${d.jumlah_anggota} orang</span></div>
<div class="ip-row"><span class="ip-label">Alamat</span><span class="ip-val" style="font-size:11px">${d.alamat}</span></div>
<div class="ip-row"><span class="ip-label">Koordinat</span><span class="ip-val" style="font-size:10px">${parseFloat(d.latitude).toFixed(5)}, ${parseFloat(d.longitude).toFixed(5)}</span></div>`;
}
return `<div class="ip"><div class="ip-head" style="background:${hc[type]}">${ic[type]} ${ti[type]}</div><div class="ip-body">${rows}<button class="ip-del" onclick="hapusData(${d.id},'${type}')">🗑 Hapus</button></div></div>`;
}
function onRadiusSlide(masjidId, val) {
val = parseFloat(val);
var el = document.getElementById('radiusDisplay_' + masjidId);
if (el) el.textContent = fmtNum(val,0) + ' m';
var m = masjidData.find(x => x.id === masjidId);
if (m) { m.radius = val; m.circleLayer.setRadius(val); recalcAllRadius(); }
}
function saveRadius(masjidId) {
var m = masjidData.find(x => x.id === masjidId);
if (!m) return;
fetch('php/update_masjid_radius.php', {
method:'POST', headers:{'Content-Type':'application/json'},
body: JSON.stringify({ id: masjidId, radius: m.radius })
}).then(r=>r.json()).then(r=>{
if (r.message && r.message.includes('Berhasil')) alert('Radius berhasil disimpan!');
else alert('Gagal: ' + r.message);
});
}
/* ============================================================
LOAD DATA
============================================================ */
fetch('php/show.php')
.then(res => res.json())
.then(data => {
var pendudukRaw = [];
data.forEach(d => {
if (d.type === 'point') {
var layer = L.marker([d.latitude, d.longitude], { icon: makeIcon(d.status) });
layer._type='point'; layer._db_id=d.id;
layer.bindPopup(buildInfoPopup(d,'point'), { maxWidth:260 });
d.status==='24 Jam' ? layerGroup24.addLayer(layer) : layerGroupTidak.addLayer(layer);
}
if (d.type === 'line') {
var coords = JSON.parse(d.geom);
var layer = L.polyline(coords, { color:getLineColor(d.status), weight:4, opacity:0.9 });
layer._type='line'; layer._db_id=d.id;
layer.bindPopup(buildInfoPopup(d,'line'), { maxWidth:260 });
drawnItems.addLayer(layer);
}
if (d.type === 'polygon') {
var coords = JSON.parse(d.geom);
var layer = L.polygon(coords, { color:'#10b981', weight:2, fillColor:'#10b981', fillOpacity:0.3 });
layer._type='polygon'; layer._db_id=d.id;
layer.bindPopup(buildInfoPopup(d,'polygon'), { maxWidth:260 });
drawnItems.addLayer(layer);
}
if (d.type === 'masjid') {
var mLat=parseFloat(d.latitude), mLng=parseFloat(d.longitude), mR=parseFloat(d.radius);
var circle = L.circle([mLat,mLng], { radius:mR, color:'#f59e0b', fillColor:'#f59e0b', fillOpacity:0.08, weight:2, dashArray:'6 4' });
layerGroupMasjid.addLayer(circle);
var marker = L.marker([mLat,mLng], { icon:makeMasjidIcon() });
marker._type='masjid'; marker._db_id=d.id;
marker.bindPopup(buildInfoPopup(d,'masjid'), { maxWidth:290 });
layerGroupMasjid.addLayer(marker);
masjidData.push({ id:parseInt(d.id), lat:mLat, lng:mLng, radius:mR, circleLayer:circle, markerLayer:marker });
}
if (d.type === 'penduduk') pendudukRaw.push(d);
});
/* Load penduduk setelah masjid siap */
pendudukRaw.forEach(d => {
var pLat=parseFloat(d.latitude), pLng=parseFloat(d.longitude);
var inRadius=false, minDist=Infinity;
masjidData.forEach(m => {
var dist = map.distance([pLat,pLng],[m.lat,m.lng]);
if (dist<=m.radius && dist<minDist) { minDist=dist; inRadius=true; }
});
var marker = L.marker([pLat,pLng], { icon:makePendudukIcon(inRadius) });
marker._type='penduduk'; marker._db_id=d.id;
marker.bindPopup(buildInfoPopup(d,'penduduk'), { maxWidth:260 });
layerGroupPenduduk.addLayer(marker);
pendudukData.push({ id:parseInt(d.id), lat:pLat, lng:pLng, markerLayer:marker, inRadius });
});
})
.catch(err => console.error('Gagal load data:', err));
/* ============================================================
HAPUS
============================================================ */
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));
});
}
/* ============================================================
MODE SELECTOR (pojok kiri bawah)
============================================================ */
/* ============================================================
ON CREATED
============================================================ */
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer;
// Get mode directly from the DOM to ensure reliability
var activeMode = 'spbu';
var modeInput = document.querySelector('input[name="mode"]:checked');
if (modeInput) activeMode = modeInput.value;
console.log('Creating marker in mode: ' + activeMode);
if (e.layerType === 'marker') {
if (activeMode==='spbu') { drawnItems.addLayer(layer); handlePoint(layer); }
else if (activeMode==='masjid') { handleMasjid(layer); }
else if (activeMode==='penduduk') { handlePenduduk(layer); }
}
if (e.layerType==='polyline') { drawnItems.addLayer(layer); handleLine(layer); }
if (e.layerType==='polygon') { drawnItems.addLayer(layer); handlePolygon(layer); }
});
/* ── SPBU ── */
function handlePoint(layer) {
var ll = layer.getLatLng();
layer.bindPopup(`<div class="pf"><div class="pf-head pf-head-point">⛽ Tambah SPBU</div><div class="pf-body">
<label>Nama SPBU</label><input id="pNama" placeholder="contoh: SPBU Sungai Jawi">
<label>No. SPBU</label><input id="pNo" placeholder="contoh: 64.761.xx">
<label>Status Operasional</label>
<select id="pStatus"><option value="24 Jam">24 Jam</option><option value="Tidak">Tidak 24 Jam</option></select>
<div class="pf-info">📍 ${ll.lat.toFixed(6)}, ${ll.lng.toFixed(6)}</div>
<button class="pf-btn" onclick="savePoint(${ll.lat},${ll.lng})">💾 Simpan</button>
</div></div>`, { maxWidth:280 }).openPopup();
}
function savePoint(lat, lng) {
var nama=document.getElementById('pNama').value.trim(), no=document.getElementById('pNo').value.trim(), status=document.getElementById('pStatus').value;
if (!nama||!no) { alert('Nama dan No. SPBU wajib diisi!'); return; }
fetch('php/insert.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.message); });
}
/* ── MASJID ── */
function handleMasjid(layer) {
var ll = layer.getLatLng();
var defaultRadius = 500;
window._previewLatLng = ll;
// Tambahkan marker ke peta agar popup bisa muncul
layer.addTo(map);
var previewCircle = L.circle([ll.lat,ll.lng], { radius:defaultRadius, color:'#f59e0b', fillColor:'#f59e0b', fillOpacity:0.08, weight:2, dashArray:'6 4' }).addTo(map);
window._previewCircle = previewCircle;
recalcAllRadius({ lat:ll.lat, lng:ll.lng, radius:defaultRadius });
layer.bindPopup(`<div class="pf"><div class="pf-head" style="background:linear-gradient(135deg,#92400e,#f59e0b);color:#fff;">🕌 Tambah Masjid</div><div class="pf-body">
<label>Nama Masjid</label><input id="mNama" placeholder="contoh: Masjid Al-Falah">
<label>PIC Masjid</label><input id="mPIC" placeholder="contoh: Ust. Ahmad">
<label>Radius Deteksi</label>
<div class="radius-slider-wrap">
<input type="range" min="100" max="5000" step="50" value="${defaultRadius}" id="mRadiusSlider" oninput="previewRadius(this.value)">
<div class="radius-val"><span>100m</span><span id="mRadiusVal">${defaultRadius} m</span><span>5000m</span></div>
</div>
<div class="pf-info">📍 ${ll.lat.toFixed(6)}, ${ll.lng.toFixed(6)}</div>
<button class="pf-btn" onclick="saveMasjid(${ll.lat},${ll.lng})">💾 Simpan</button>
</div></div>`, { maxWidth:290 }).openPopup();
layer.on('popupclose', function() {
map.removeLayer(previewCircle);
window._previewCircle=null;
window._previewLatLng=null;
map.removeLayer(layer);
recalcAllRadius();
});
}
function previewRadius(val) {
val = parseFloat(val);
document.getElementById('mRadiusVal').textContent = fmtNum(val,0)+' m';
if (window._previewCircle) window._previewCircle.setRadius(val);
if (window._previewLatLng) {
recalcAllRadius({ lat:window._previewLatLng.lat, lng:window._previewLatLng.lng, radius:val });
}
}
function saveMasjid(lat, lng) {
var nama=document.getElementById('mNama').value.trim(), pic=document.getElementById('mPIC').value.trim(), radius=parseFloat(document.getElementById('mRadiusSlider').value);
if (!nama||!pic) { alert('Nama dan PIC wajib diisi!'); return; }
fetch('php/insert_masjid.php',{ method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({nama,pic,radius,lat,lng}) })
.then(r=>r.json()).then(r=>{ if(r.id) location.reload(); else alert('Gagal: '+(r.error||r.message)); });
}
/* ── PENDUDUK ── */
function handlePenduduk(layer) {
var ll = layer.getLatLng();
layer.addTo(map); // Tambahkan marker ke peta agar popup bisa muncul
layer.bindPopup(`<div class="pf"><div class="pf-head" style="background:linear-gradient(135deg,#701a75,#e879f9);color:#fff;">👨‍👩‍👧‍👦 Tambah Penduduk Miskin</div><div class="pf-body">
<label>Nama Kepala Keluarga</label><input id="pdNama" placeholder="contoh: Bapak Suratman">
<label>Jumlah Anggota KK</label><input id="pdJml" type="number" min="1" value="1">
<label>Alamat</label><input id="pdAlamat" placeholder="contoh: Jl. Imam Bonjol No. 5">
<div class="pf-info">📍 ${ll.lat.toFixed(6)}, ${ll.lng.toFixed(6)}</div>
<button class="pf-btn" onclick="savePenduduk(${ll.lat},${ll.lng})">💾 Simpan</button>
</div></div>`, { maxWidth:290 }).openPopup();
layer.on('popupclose', function() { map.removeLayer(layer); });
}
function savePenduduk(lat, lng) {
var nama_kk=document.getElementById('pdNama').value.trim(), jumlah_anggota=parseInt(document.getElementById('pdJml').value)||1, alamat=document.getElementById('pdAlamat').value.trim();
if (!nama_kk||!alamat) { alert('Nama KK dan Alamat wajib diisi!'); return; }
fetch('php/insert_penduduk.php',{ method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({nama_kk,jumlah_anggota,alamat,lat,lng}) })
.then(r=>r.json()).then(r=>{ if(r.id) location.reload(); else alert('Gagal: '+(r.error||r.message)); });
}
/* ── LINE ── */
function handleLine(layer) {
currentLayer=layer;
var ll=layer.getLatLngs(), p=getLength(ll); layer._temp={latlngs:ll,panjang:p};
L.popup({maxWidth:280}).setLatLng(layer.getBounds().getCenter()).setContent(`<div class="pf"><div class="pf-head pf-head-line">🛣️ Tambah Jalan</div><div class="pf-body">
<label>Nama Jalan</label><input id="lNama" placeholder="contoh: Jl. Ahmad Yani">
<label>Klasifikasi</label><select id="lStatus"><option value="Nasional">Nasional</option><option value="Provinsi">Provinsi</option><option value="Kabupaten">Kabupaten</option></select>
<div class="pf-info">📏 ${fmtNum(p)} m</div>
<button class="pf-btn" onclick="saveLine()">💾 Simpan</button>
</div></div>`).openOn(map);
}
function saveLine() {
var layer=currentLayer; if(!layer){alert('Layer tidak ditemukan');return;}
var nama=document.getElementById('lNama').value.trim(), 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)); });
}
/* ── POLYGON ── */
function handlePolygon(layer) {
currentLayer=layer;
var ll=layer.getLatLngs(), luas=L.GeometryUtil.geodesicArea(ll[0]); layer._temp={latlngs:ll,luas};
L.popup({maxWidth:280}).setLatLng(layer.getBounds().getCenter()).setContent(`<div class="pf"><div class="pf-head pf-head-polygon">📐 Tambah Parsil</div><div class="pf-body">
<label>Nama Area</label><input id="gNama" placeholder="contoh: Lahan A">
<label>Status Kepemilikan</label><select id="gStatus"><option value="SHM">SHM</option><option value="HGB">HGB</option><option value="HGU">HGU</option><option value="HP">HP</option></select>
<div class="pf-info">📐 ${fmtNum(luas)} m²</div>
<button class="pf-btn" onclick="savePolygon()">💾 Simpan</button>
</div></div>`).openOn(map);
}
function savePolygon() {
var layer=currentLayer; if(!layer){alert('Layer tidak ditemukan');return;}
var nama=document.getElementById('gNama').value.trim(), 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)); });
}
/* ── EDIT & DELETE ── */
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}`);
});
});