const parsilCfg = { SHM: { color: '#16a34a', label: 'Sertifikat Hak Milik' }, HGB: { color: '#2563eb', label: 'Hak Guna Bangunan' }, HGU: { color: '#d97706', label: 'Hak Guna Usaha' }, HP: { color: '#7c3aed', label: 'Hak Pakai' } }; function renderParsilPanel(pb) { return callAPI('data_parsil.php').then(res => { const data = res.data || []; const cnt = k => data.filter(d => d.jenis_hak === k).length; pb.innerHTML = `
Filter Layer
${Object.entries(parsilCfg).map(([k, v]) => `
${layerVisible['parsil' + k] ? '✓' : ''}
${k} — ${v.label}
${cnt(k)}
`).join('')}
Cara Menambahkan Data Parsil
1. Klik ikon polygon di toolbar kiri peta
2. Klik titik-titik batas bidang tanah
3. Klik titik awal / double-klik untuk menutup
4. Form simpan + luas otomatis muncul
Data Parsil (${data.length})
${data.length ? data.map(d => `
📐
${esc(d.nama_pemilik)}
${d.luas_m2.toFixed(1)} m² · ${d.no_sertifikat || '—'}
${d.jenis_hak}
`).join('') : '
Belum ada data parsil
'}
`; loadParsilLayer(data); registerSearchEntries('parsil', data.map(d => ({ key: `parsil:${d.id}`, label: d.nama_pemilik, subtitle: `Parsil ${d.jenis_hak} · ${d.luas_m2.toFixed(1)} m²${d.no_sertifikat ? ` · ${d.no_sertifikat}` : ''}`, typeLabel: 'Parsil', icon: '📐', searchText: normalizeSearchText(`${d.nama_pemilik} ${d.jenis_hak} parsil tanah`), focus: () => focusGeom(d.id, 'parsil') }))); updateStatusCount(); }); } function loadParsilLayer(data) { ['SHM', 'HGB', 'HGU', 'HP'].forEach(k => layers['parsil' + k].clearLayers()); data.forEach(d => { const cfg = parsilCfg[d.jenis_hak], coords = d.geojson.coordinates[0].map(c => [c[1], c[0]]); const poly = L.polygon(coords, { color: cfg.color, fillColor: cfg.color, fillOpacity: 0.18, weight: 2 }) .bindPopup(`

📐 ${esc(d.nama_pemilik)}

Jenis Hak: ${d.jenis_hak} — ${cfg.label}

Luas: ${d.luas_m2.toFixed(2)} m² (${(d.luas_m2 / 10000).toFixed(4)} ha)

${d.no_sertifikat ? `

No. Sertifikat: ${d.no_sertifikat}

` : ''} ${d.keterangan ? `

${esc(d.keterangan)}

` : ''} `); poly._dataId = d.id; poly._groupKey = 'parsil' + d.jenis_hak; layers['parsil' + d.jenis_hak].addLayer(poly); }); } function openParsilForm() { openModal('Simpan Parsil Tanah', `
📐 Luas: ${pendingArea.toFixed(2)} m² = ${(pendingArea / 10000).toFixed(4)} ha
`, ` `); } async function saveParsil() { const body = { nama_pemilik: document.getElementById('ps-nama').value.trim(), jenis_hak: document.getElementById('ps-hak').value, no_sertifikat: document.getElementById('ps-sert').value, luas_m2: pendingArea, keterangan: document.getElementById('ps-ket').value, geojson: pendingGeoJSON }; if (!body.nama_pemilik) return toast('Nama wajib diisi', 'error'); const res = await callAPI('data_parsil.php', 'POST', body); if (res.status === 'success') { toast(res.message, 'success'); closeModal(); drawnItems.clearLayers(); pendingGeoJSON = null; pendingArea = null; switchTab('parsil'); } else { toast(res.message, 'error'); } } async function editParsil(id) { map.closePopup(); const res = await callAPI(`data_parsil.php?id=${id}`); const data = res.data; const sourceLayer = findGeomLayer('parsil', id); if (!data) return toast('Data parsil tidak ditemukan', 'error'); const groupKey = getGeometryGroupKey('parsil', data); const editLayer = sourceLayer ? cloneEditableLayer('parsil', sourceLayer) : buildGeometryLayer('parsil', data); editLayer._dataId = id; editLayer._groupKey = groupKey; if (sourceLayer) layers[groupKey].removeLayer(sourceLayer); drawnItems.clearLayers(); drawnItems.addLayer(editLayer); geometryEditState = { type: 'parsil', id, groupKey, sourceLayer, editLayer }; if (editLayer.editing && editLayer.editing.enable) { editLayer.editing.enable(); } else { const handler = getGeometryEditHandler(); if (!handler) { drawnItems.clearLayers(); if (sourceLayer) layers[groupKey].addLayer(sourceLayer); geometryEditState = null; return toast('Mode edit geometri belum siap', 'error'); } handler.enable(); } map.fitBounds(editLayer.getBounds(), { padding: [50, 50], duration: 1 }); document.getElementById('panel-title').textContent = 'Edit Parsil Tanah'; document.getElementById('panel-body').innerHTML = `
Edit Parsil
Geser titik-titik batas bidang di peta lalu simpan perubahan.
`; document.getElementById('panel-body').insertAdjacentHTML('beforeend', `
`); } async function saveParsilEdit(id) { const state = geometryEditState; if (!state || state.type !== 'parsil') return; const layer = state.editLayer; const ringLatLngs = layer.getLatLngs()[0]; const ring = ringLatLngs.map(ll => [ll.lng, ll.lat]); ring.push([ringLatLngs[0].lng, ringLatLngs[0].lat]); const luas_m2 = turf.area(turf.polygon([ring])); const body = { nama_pemilik: document.getElementById('ps-edit-nama').value.trim(), jenis_hak: document.getElementById('ps-edit-hak').value, no_sertifikat: document.getElementById('ps-edit-sert').value, luas_m2, keterangan: document.getElementById('ps-edit-ket').value, geojson: { type: 'Polygon', coordinates: [ring] } }; if (!body.nama_pemilik) return toast('Nama wajib diisi', 'error'); const res = await callAPI(`data_parsil.php?id=${id}`, 'PUT', body); if (res.status === 'success') { toast(res.message, 'success'); if (layer.editing && layer.editing.disable) layer.editing.disable(); const handler = getGeometryEditHandler(); if (handler) handler.disable(); drawnItems.clearLayers(); geometryEditState = null; switchTab('parsil'); } else { toast(res.message, 'error'); } } async function deleteParsil(id) { if (!confirm('Hapus?')) return; const r = await callAPI(`data_parsil.php?id=${id}`, 'DELETE'); if (r.status === 'success') { toast('Dihapus', 'success'); map.closePopup(); switchTab('parsil'); } }