Fix PHP variable errors and add API fetch handlers for roads and parcels

This commit is contained in:
2026-06-14 20:46:52 +07:00
parent 61b1879377
commit 422c6cb496
2 changed files with 194 additions and 57 deletions
+111 -42
View File
@@ -195,13 +195,13 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Panjang Jalan (otomatis)</label> <label>Panjang Jalan (otomatis)</label>
<input type="text" id="panjang_tampil" readonly value="<?= $input['panjang_meter'] !== '' ? htmlspecialchars($input['panjang_meter']) . ' meter' : '0 meter' ?>"> <input type="text" id="panjang_tampil" readonly value="0 meter">
<input type="hidden" name="panjang_meter" id="panjang_meter" value="<?= htmlspecialchars($input['panjang_meter']) ?>"> <input type="hidden" name="panjang_meter" id="panjang_meter" value="">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Koordinat JSON (otomatis)</label> <label>Koordinat JSON (otomatis)</label>
<textarea readonly rows="3" id="koordinat_tampil" style="resize: vertical; background: #e2e8f0;"><?= htmlspecialchars($input['koordinat_json']) ?></textarea> <textarea readonly rows="3" id="koordinat_tampil" style="resize: vertical; background: #e2e8f0;"></textarea>
<input type="hidden" name="koordinat_json" id="koordinat_json" value="<?= htmlspecialchars($input['koordinat_json']) ?>"> <input type="hidden" name="koordinat_json" id="koordinat_json" value="">
</div> </div>
<div class="button-row"> <div class="button-row">
<button type="button" class="btn btn-secondary" id="reset-button">Reset Garis</button> <button type="button" class="btn btn-secondary" id="reset-button">Reset Garis</button>
@@ -212,23 +212,77 @@
<section class="card"> <section class="card">
<h2>Daftar Jalan Tersimpan</h2> <h2>Daftar Jalan Tersimpan</h2>
<div class="road-list"> <div class="road-list" id="road-list-container">
<?php if (count($jalanList) === 0): ?> <div class="road-item">Memuat data dari API...</div>
<div class="road-item">Belum ada data jalan yang tersimpan.</div>
<?php else: ?>
<?php foreach ($jalanList as $jalan): ?>
<div class="road-item">
<strong><?= htmlspecialchars($jalan['nama_jalan']) ?></strong>
<div class="meta">Status: <?= htmlspecialchars($jalan['status_jalan']) ?> | Panjang: <?= htmlspecialchars($jalan['panjang_meter']) ?> meter</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div> </div>
</section> </section>
</main> </main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script> <script>
// Load existing roads from API
let existingRoads = [];
function loadRoadsFromAPI() {
fetch('api/get_roads.php')
.then(response => response.json())
.then(data => {
if (data.success && Array.isArray(data.roads)) {
existingRoads = data.roads;
renderExistingRoads();
}
})
.catch(error => console.error('Error loading roads:', error));
}
function renderExistingRoads() {
const statusColors = {
nasional: '#DC3545',
provinsi: '#007BFF',
kabupaten: '#28A745'
};
// Clear existing layers
map.eachLayer(layer => {
if (layer instanceof L.Polyline && !layer.hasOwnProperty('_userDrawn')) {
map.removeLayer(layer);
}
});
// Render roads on map
existingRoads.forEach(road => {
const coords = typeof road.koordinat === 'string' ? JSON.parse(road.koordinat) : road.koordinat;
if (!Array.isArray(coords) || coords.length < 2) return;
const line = L.polyline(coords.map(([lat, lng]) => [lat, lng]), {
color: statusColors[road.status_jalan] || '#444',
weight: 6,
opacity: 0.8,
smoothFactor: 1
}).addTo(map);
line.bindPopup(`
<strong>${road.nama_jalan}</strong><br>
Status: ${road.status_jalan}<br>
Panjang: ${road.panjang_meter} meter
`);
});
// Update list display
const listContainer = document.getElementById('road-list-container');
if (existingRoads.length === 0) {
listContainer.innerHTML = '<div class="road-item">Belum ada data jalan yang tersimpan.</div>';
} else {
listContainer.innerHTML = existingRoads.map(road => `
<div class="road-item">
<strong>${road.nama_jalan}</strong>
<div class="meta">Status: ${road.status_jalan} | Panjang: ${road.panjang_meter} meter</div>
</div>
`).join('');
}
}
// Initialize map
const map = L.map('map').setView([-0.0263, 109.3425], 13); const map = L.map('map').setView([-0.0263, 109.3425], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
@@ -236,39 +290,15 @@
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>' attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map); }).addTo(map);
// Load existing roads on page load
loadRoadsFromAPI();
const statusColors = { const statusColors = {
nasional: '#DC3545', nasional: '#DC3545',
provinsi: '#007BFF', provinsi: '#007BFF',
kabupaten: '#28A745' kabupaten: '#28A745'
}; };
const jalanData = <?= json_encode(array_map(function ($row) {
return [
'id' => $row['id'],
'nama_jalan' => $row['nama_jalan'],
'status_jalan' => $row['status_jalan'],
'panjang_meter' => $row['panjang_meter'],
'koordinat' => json_decode($row['koordinat_json'], true)
];
}, $jalanList), JSON_UNESCAPED_UNICODE) ?>;
jalanData.forEach(jalan => {
if (!Array.isArray(jalan.koordinat) || jalan.koordinat.length < 2) {
return;
}
const line = L.polyline(jalan.koordinat.map(([lat, lng]) => [lat, lng]), {
color: statusColors[jalan.status_jalan] || '#444',
weight: 6,
opacity: 0.8,
smoothFactor: 1
}).addTo(map);
line.bindPopup(`
<strong>${jalan.nama_jalan}</strong><br>
Status: ${jalan.status_jalan}<br>
Panjang: ${jalan.panjang_meter} meter
`);
});
let currentPoints = []; let currentPoints = [];
let currentLine = null; let currentLine = null;
@@ -304,6 +334,7 @@
dashArray: '8, 8', dashArray: '8, 8',
opacity: 0.85 opacity: 0.85
}).addTo(map); }).addTo(map);
currentLine._userDrawn = true;
} else if (currentPoints.length === 1) { } else if (currentPoints.length === 1) {
currentLine = L.circleMarker(currentPoints[0], { currentLine = L.circleMarker(currentPoints[0], {
radius: 6, radius: 6,
@@ -312,6 +343,7 @@
weight: 2, weight: 2,
fillOpacity: 1 fillOpacity: 1
}).addTo(map); }).addTo(map);
currentLine._userDrawn = true;
} }
} }
@@ -331,6 +363,43 @@
updateFormFields(); updateFormFields();
// Handle form submission via API
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
const formData = {
nama_jalan: document.getElementById('nama_jalan').value,
status_jalan: document.getElementById('status_jalan').value,
panjang_meter: panjangMeterInput.value,
koordinat_json: koordinatInput.value
};
if (!formData.nama_jalan || !formData.status_jalan || !formData.panjang_meter || !formData.koordinat_json) {
alert('Semua field harus diisi dan polyline harus dibuat sebelum submit');
return;
}
fetch('api/save_road.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Data jalan berhasil disimpan!');
currentPoints = [];
if (currentLine) map.removeLayer(currentLine);
updateFormFields();
loadRoadsFromAPI();
this.reset();
} else {
alert('Error: ' + (data.message || 'Gagal menyimpan data'));
}
})
.catch(error => alert('Error: ' + error));
});
window.addEventListener('load', function () { window.addEventListener('load', function () {
map.invalidateSize(); map.invalidateSize();
}); });
+83 -15
View File
@@ -121,20 +121,59 @@
HP: '#1d4ed8' HP: '#1d4ed8'
}; };
const existingData = []; // Data diambil dari API let existingData = [];
existingData.forEach(item => {
if (!Array.isArray(item.coords)) return; // Load data from API
const coords = item.coords.map(c => [c.lat, c.lng]); function loadTanahDataFromAPI() {
const fillColor = statusColor[item.status_kepemilikan] || '#475569'; fetch('api/get_parcels.php')
const poly = L.polygon(coords, { .then(response => response.json())
color: fillColor, .then(data => {
fillColor: fillColor, if (data.success && Array.isArray(data.parcels)) {
fillOpacity: 0.15, existingData = data.parcels;
weight: 2, renderExistingParcels();
opacity: 0.9 }
}).addTo(polygonLayerGroup); })
poly.bindPopup(`<strong>${escapeHtml(item.nama_pemilik)}</strong><br>${escapeHtml(item.status_kepemilikan)}<br>Luas: ${Number(item.luas_sqm).toLocaleString('id-ID', {minimumFractionDigits:2, maximumFractionDigits:2})} m²`); .catch(error => console.error('Error loading parcels:', error));
}); }
function renderExistingParcels() {
// Clear existing layers
polygonLayerGroup.clearLayers();
// Render parcels on map
existingData.forEach(item => {
const coords = typeof item.coordinates === 'string' ? JSON.parse(item.coordinates) : item.coordinates;
if (!Array.isArray(coords)) return;
const fillColor = statusColor[item.owner_status] || '#475569';
const poly = L.polygon(coords.map(c => [c.lat || c[0], c.lng || c[1]]), {
color: fillColor,
fillColor: fillColor,
fillOpacity: 0.15,
weight: 2,
opacity: 0.9
}).addTo(polygonLayerGroup);
poly.bindPopup(`<strong>${escapeHtml(item.owner_name || 'N/A')}</strong><br>${escapeHtml(item.owner_status)}<br>Luas: ${Number(item.area).toLocaleString('id-ID', {minimumFractionDigits:2, maximumFractionDigits:2})} m²`);
});
// Update list display
const listContainer = document.getElementById('tanah-list');
if (existingData.length === 0) {
listContainer.innerHTML = '<div class="info-card">Belum ada data parsil yang tersimpan.</div>';
} else {
listContainer.innerHTML = existingData.map(item => `
<div class="info-card">
<strong>${escapeHtml(item.owner_name || 'N/A')} · ${escapeHtml(item.owner_status)}</strong>
<div>Luas: ${Number(item.area).toLocaleString('id-ID', {minimumFractionDigits:2, maximumFractionDigits:2})} m²</div>
<div style="margin-top: 10px;"><span class="status-pill status-${item.owner_status.toLowerCase()}">${escapeHtml(item.owner_status)}</span></div>
</div>
`).join('');
}
}
// Load data on page load
loadTanahDataFromAPI();
function escapeHtml(str) { function escapeHtml(str) {
return String(str) return String(str)
@@ -257,10 +296,39 @@
const form = document.getElementById('tanahForm'); const form = document.getElementById('tanahForm');
form.addEventListener('submit', event => { form.addEventListener('submit', event => {
event.preventDefault();
if (currentCoordinates.length < 4 || !document.getElementById('luas_sqm').value) { if (currentCoordinates.length < 4 || !document.getElementById('luas_sqm').value) {
event.preventDefault();
alert('Buat polygon tertutup terlebih dahulu sebelum submit. Klik titik awal lagi untuk menutup polygon.'); alert('Buat polygon tertutup terlebih dahulu sebelum submit. Klik titik awal lagi untuk menutup polygon.');
return;
} }
const formData = {
owner_name: document.getElementById('nama_pemilik').value,
owner_status: document.getElementById('status_kepemilikan').value,
area: document.getElementById('luas_sqm').value,
coordinates: document.getElementById('koordinat_json').value
};
fetch('api/save_parcel.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Data parsil berhasil disimpan!');
currentCoordinates = [];
redrawCurrentShape();
updateForm();
form.reset();
loadTanahDataFromAPI();
} else {
alert('Error: ' + (data.message || 'Gagal menyimpan data'));
}
})
.catch(error => alert('Error: ' + error));
}); });
</script> </script>
</body> </body>