Update Lahan CPCL
This commit is contained in:
@@ -0,0 +1,448 @@
|
||||
@extends('layout.main')
|
||||
|
||||
@push('style')
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" />
|
||||
|
||||
<style>
|
||||
#map {
|
||||
height: 600px;
|
||||
width: 100%;
|
||||
background-color: #f8f9fa;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom mb-4 d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mb-0">Edit Data Lahan</h5>
|
||||
<a href="{{ route('lahan-cpcl.index') }}" class="btn btn-sm btn-label-secondary">
|
||||
<i class="ti tabler-arrow-left me-1"></i> Kembali
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form id="formLahanCPCL" action="{{ route('lahan-cpcl.update', $lahan->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mb-4">
|
||||
<h6 class="mb-3 text-primary"><i class="ti tabler-info-circle me-1"></i> Form Info Lahan</h6>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Nama Lahan <span class="text-danger">*</span></label>
|
||||
<input type="text" name="nama" class="form-control" value="{{ old('nama', $lahan->nama) }}" placeholder="Masukkan nama lahan" required />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Pemilik Pemilik<span class="text-danger">*</span></label>
|
||||
<input type="text" name="nama_pemilik" class="form-control" value="{{ old('nama_pemilik', $lahan->nama_pemilik) }}" placeholder="Masukkan nama pemilik" required />
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Status Kepemilikan <span class="text-danger">*</span></label>
|
||||
<select name="status_kepemilikan" id="status_kepemilikan" class="form-select" required>
|
||||
<option value="">Pilih Status</option>
|
||||
@php $status = old('status_kepemilikan', $lahan->status_kepemilikan->value); @endphp
|
||||
@foreach(App\Enums\StatusLahan::cases() as $lahanEnum)
|
||||
<option value="{{ $lahanEnum->value }}" {{ old('status_kepemilikan') == $lahanEnum->value ? 'selected' : '' }}>
|
||||
{{ ucfirst($lahanEnum->value) }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Luas Lahan (Ha/m2) <span class="text-danger">*</span></label>
|
||||
<input type="number" step="0.01" name="luas_lahan" class="form-control" value="{{ old('luas_lahan', $lahan->luas_lahan) }}" placeholder="Contoh: 1.5" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h6 class="mb-3 text-primary"><i class="ti tabler-map-pin me-1"></i> Lokasi Wilayah</h6>
|
||||
|
||||
@php
|
||||
$selectedDesa = $lahan->desakelurahan ?? null;
|
||||
$selectedKec = $selectedDesa ? $selectedDesa->kecamatan : null;
|
||||
$selectedKab = $selectedKec ? $selectedKec->kabupatenkota : null;
|
||||
$selectedProv = $selectedKab ? $selectedKab->provinsi : null;
|
||||
@endphp
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Provinsi <span class="text-danger">*</span></label>
|
||||
<select name="provinsi_id" id="provinsi_id" class="form-select" required>
|
||||
<option value="" data-path="">Pilih Provinsi</option>
|
||||
@foreach($provinsi as $prov)
|
||||
<option value="{{ $prov->id }}" data-path="{{ is_string($prov->path) ? $prov->path : json_encode($prov->path) }}" {{ ($selectedProv && $selectedProv->id == $prov->id) ? 'selected' : '' }}>
|
||||
{{ $prov->nama }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Kabupaten/Kota <span class="text-danger">*</span></label>
|
||||
<select name="kabupatenkota_id" id="kabupatenkota_id" class="form-select" required>
|
||||
<option value="" data-path="">Pilih Kabupaten/Kota</option>
|
||||
@if($selectedKab)
|
||||
<option value="{{ $selectedKab->id }}" selected data-path="{{ is_string($selectedKab->path) ? $selectedKab->path : json_encode($selectedKab->path) }}">{{ $selectedKab->nama }}</option>
|
||||
@endif
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Kecamatan <span class="text-danger">*</span></label>
|
||||
<select name="kecamatan_id" id="kecamatan_id" class="form-select" required>
|
||||
<option value="" data-path="">Pilih Kecamatan</option>
|
||||
@if($selectedKec)
|
||||
<option value="{{ $selectedKec->id }}" selected data-path="{{ is_string($selectedKec->path) ? $selectedKec->path : json_encode($selectedKec->path) }}">{{ $selectedKec->nama }}</option>
|
||||
@endif
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Desa/Kelurahan <span class="text-danger">*</span></label>
|
||||
<select name="desa_kelurahan_id" id="desa_kelurahan_id" class="form-select" required>
|
||||
<option value="" data-path="">Pilih Desa/Kelurahan</option>
|
||||
@if($selectedDesa)
|
||||
<option value="{{ $selectedDesa->id }}" selected data-path="{{ is_string($selectedDesa->path) ? $selectedDesa->path : json_encode($selectedDesa->path) }}">{{ $selectedDesa->nama }}</option>
|
||||
@endif
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<label class="form-label">Raw Data Koordinat Lahan (Auto-generated JSON) <span class="text-danger">*</span></label>
|
||||
<textarea name="path" id="path" class="form-control bg-lighter font-monospace" rows="4" readonly required placeholder="Koordinat akan terisi otomatis setelah Anda menggambar polygon di peta...">{{ old('path', is_string($lahan->path) ? $lahan->path : json_encode($lahan->path)) }}</textarea>
|
||||
<small class="text-muted">Gunakan tombol edit (pensil) atau hapus (tong sampah) di peta untuk mengubah bentuk lahan.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6 mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="text-primary mb-0"><i class="ti tabler-map me-1"></i> Gambar Area Lahan</h6>
|
||||
<span class="badge bg-label-warning">Mode Edit Polygon Aktif</span>
|
||||
</div>
|
||||
|
||||
<div id="map" class="border rounded shadow-sm"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 text-end">
|
||||
<a href="{{ route('lahan.index') }}" class="btn btn-label-secondary me-2">Batal</a>
|
||||
<button type="submit" class="btn btn-primary"><i class="ti tabler-device-floppy me-2"></i> Update Data</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
let map = L.map('map').setView([-0.789275, 113.921327], 5);
|
||||
|
||||
L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 22,
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
|
||||
attribution: '© Google Maps Satellite'
|
||||
}).addTo(map);
|
||||
|
||||
let regionBoundaryLayer = L.featureGroup().addTo(map);
|
||||
|
||||
function focusToRegionBoundary(selectElement, shouldZoom = true) {
|
||||
regionBoundaryLayer.clearLayers();
|
||||
|
||||
let selectedOption = selectElement.options[selectElement.selectedIndex];
|
||||
if (!selectedOption || !selectedOption.hasAttribute('data-path')) return;
|
||||
|
||||
let pathStr = selectedOption.getAttribute('data-path');
|
||||
if (!pathStr || pathStr === "null" || pathStr === "") return;
|
||||
|
||||
try {
|
||||
let rawData = typeof pathStr === 'string' ? JSON.parse(pathStr) : pathStr;
|
||||
|
||||
if (Array.isArray(rawData) && rawData.length > 0) {
|
||||
function formatCoordinates(coords) {
|
||||
if (coords.length === 2 && typeof coords[0] === 'number') {
|
||||
return [coords[0], coords[1]];
|
||||
}
|
||||
return coords.map(formatCoordinates);
|
||||
}
|
||||
|
||||
let latLngs = formatCoordinates(rawData);
|
||||
|
||||
let polygon = L.polygon(latLngs, {
|
||||
color: '#ffc107',
|
||||
fillColor: '#ffc107',
|
||||
fillOpacity: 0.15,
|
||||
weight: 3,
|
||||
dashArray: '8, 6',
|
||||
interactive: false
|
||||
});
|
||||
|
||||
regionBoundaryLayer.addLayer(polygon);
|
||||
if (shouldZoom) map.fitBounds(polygon.getBounds(), { padding: [20, 20] });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Format JSON path wilayah tidak valid:", error);
|
||||
}
|
||||
}
|
||||
|
||||
let drawnItems = new L.FeatureGroup();
|
||||
map.addLayer(drawnItems);
|
||||
|
||||
let drawControl = new L.Control.Draw({
|
||||
draw: {
|
||||
polygon: {
|
||||
allowIntersection: false,
|
||||
showArea: true,
|
||||
shapeOptions: { color: '#28c76f', fillColor: '#28c76f', fillOpacity: 0.4, weight: 3 }
|
||||
},
|
||||
polyline: false, circle: false, rectangle: false, marker: false, circlemarker: false
|
||||
},
|
||||
edit: {
|
||||
featureGroup: drawnItems,
|
||||
remove: true
|
||||
}
|
||||
});
|
||||
map.addControl(drawControl);
|
||||
|
||||
let rawLahanPath = document.getElementById('path').value;
|
||||
if (rawLahanPath) {
|
||||
try {
|
||||
let parsedPath = JSON.parse(rawLahanPath);
|
||||
if (Array.isArray(parsedPath) && parsedPath.length > 0) {
|
||||
let existingLatLngs = parsedPath.map(function(coord) {
|
||||
return [coord[1], coord[0]];
|
||||
});
|
||||
|
||||
let existingPolygon = L.polygon(existingLatLngs, {
|
||||
color: '#28c76f', fillColor: '#28c76f', fillOpacity: 0.4, weight: 3
|
||||
});
|
||||
|
||||
drawnItems.addLayer(existingPolygon);
|
||||
|
||||
setTimeout(() => { map.fitBounds(existingPolygon.getBounds(), { padding: [30, 30] }); }, 500);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Gagal merender polygon lahan eksisting: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
map.on(L.Draw.Event.CREATED, function (e) {
|
||||
let layer = e.layer;
|
||||
drawnItems.clearLayers();
|
||||
drawnItems.addLayer(layer);
|
||||
updatePathTextarea(layer);
|
||||
});
|
||||
|
||||
map.on(L.Draw.Event.EDITED, function (e) {
|
||||
e.layers.eachLayer(function (layer) {
|
||||
updatePathTextarea(layer);
|
||||
});
|
||||
});
|
||||
|
||||
map.on(L.Draw.Event.DELETED, function () {
|
||||
document.getElementById('path').value = '';
|
||||
|
||||
let luasInput = document.querySelector('input[name="luas_lahan"]');
|
||||
if (luasInput) luasInput.value = '';
|
||||
});
|
||||
|
||||
function updatePathTextarea(layer) {
|
||||
let latlngs = layer.getLatLngs()[0];
|
||||
|
||||
let pathData = latlngs.map(function(latlng) {
|
||||
return [latlng.lng, latlng.lat];
|
||||
});
|
||||
document.getElementById('path').value = JSON.stringify(pathData);
|
||||
|
||||
let areaSquareMeters = L.GeometryUtil.geodesicArea(latlngs);
|
||||
let areaHectares = areaSquareMeters / 10000;
|
||||
|
||||
let luasInput = document.querySelector('input[name="luas_lahan"]');
|
||||
if (luasInput) {
|
||||
luasInput.value = areaHectares.toFixed(2);
|
||||
luasInput.style.transition = "background-color 0.5s ease";
|
||||
luasInput.style.backgroundColor = "#e8fdf0";
|
||||
|
||||
setTimeout(() => {
|
||||
luasInput.style.backgroundColor = "";
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
const provSelect = document.getElementById('provinsi_id');
|
||||
const kabSelect = document.getElementById('kabupatenkota_id');
|
||||
const kecSelect = document.getElementById('kecamatan_id');
|
||||
const desaSelect = document.getElementById('desa_kelurahan_id');
|
||||
|
||||
if (desaSelect.value) focusToRegionBoundary(desaSelect, false);
|
||||
else if (provSelect.value) focusToRegionBoundary(provSelect, false);
|
||||
|
||||
function resetDropdown(element, defaultText) {
|
||||
element.innerHTML = `<option value="" data-path="">${defaultText}</option>`;
|
||||
element.disabled = true;
|
||||
}
|
||||
|
||||
provSelect.addEventListener('change', function() {
|
||||
let provId = this.value;
|
||||
focusToRegionBoundary(this);
|
||||
|
||||
resetDropdown(kabSelect, 'Pilih Kabupaten/Kota');
|
||||
resetDropdown(kecSelect, 'Pilih Kecamatan');
|
||||
resetDropdown(desaSelect, 'Pilih Desa/Kelurahan');
|
||||
|
||||
if (provId) {
|
||||
kabSelect.innerHTML = '<option value="" data-path="">Memuat...</option>';
|
||||
fetch(`{{ url('kabupatenkotabyprovinsi') }}/${provId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resetDropdown(kabSelect, 'Pilih Kabupaten/Kota');
|
||||
kabSelect.disabled = false;
|
||||
data.forEach(item => {
|
||||
let option = new Option(item.nama, item.id);
|
||||
if(item.path) {
|
||||
option.setAttribute('data-path', typeof item.path === 'string' ? item.path : JSON.stringify(item.path));
|
||||
}
|
||||
kabSelect.add(option);
|
||||
});
|
||||
})
|
||||
.catch(error => console.error('Error fetching Kabupaten:', error));
|
||||
}
|
||||
});
|
||||
|
||||
kabSelect.addEventListener('change', function() {
|
||||
let kabId = this.value;
|
||||
focusToRegionBoundary(this);
|
||||
|
||||
resetDropdown(kecSelect, 'Pilih Kecamatan');
|
||||
resetDropdown(desaSelect, 'Pilih Desa/Kelurahan');
|
||||
|
||||
if (kabId) {
|
||||
kecSelect.innerHTML = '<option value="" data-path="">Memuat...</option>';
|
||||
fetch(`{{ url('kecamatanbykabupatenkota') }}/${kabId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resetDropdown(kecSelect, 'Pilih Kecamatan');
|
||||
kecSelect.disabled = false;
|
||||
data.forEach(item => {
|
||||
let option = new Option(item.nama, item.id);
|
||||
if(item.path) {
|
||||
option.setAttribute('data-path', typeof item.path === 'string' ? item.path : JSON.stringify(item.path));
|
||||
}
|
||||
kecSelect.add(option);
|
||||
});
|
||||
})
|
||||
.catch(error => console.error('Error fetching Kecamatan:', error));
|
||||
}
|
||||
});
|
||||
|
||||
kecSelect.addEventListener('change', function() {
|
||||
let kecId = this.value;
|
||||
focusToRegionBoundary(this);
|
||||
|
||||
resetDropdown(desaSelect, 'Pilih Desa/Kelurahan');
|
||||
|
||||
if (kecId) {
|
||||
desaSelect.innerHTML = '<option value="" data-path="">Memuat...</option>';
|
||||
fetch(`{{ url('desakelurahanbykecamatan') }}/${kecId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resetDropdown(desaSelect, 'Pilih Desa/Kelurahan');
|
||||
desaSelect.disabled = false;
|
||||
data.forEach(item => {
|
||||
let option = new Option(item.nama, item.id);
|
||||
if(item.path) {
|
||||
option.setAttribute('data-path', typeof item.path === 'string' ? item.path : JSON.stringify(item.path));
|
||||
}
|
||||
desaSelect.add(option);
|
||||
});
|
||||
})
|
||||
.catch(error => console.error('Error fetching Desa:', error));
|
||||
}
|
||||
});
|
||||
|
||||
desaSelect.addEventListener('change', function() {
|
||||
focusToRegionBoundary(this);
|
||||
});
|
||||
|
||||
const formLahanCPCL = document.getElementById('formLahanCPCL');
|
||||
|
||||
if(formLahanCPCL) {
|
||||
formLahanCPCL.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
let form = this;
|
||||
let formData = new FormData(form);
|
||||
let submitBtn = form.querySelector('button[type="submit"]');
|
||||
let originalBtnText = submitBtn.innerHTML;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.innerHTML = 'Menyimpan...';
|
||||
|
||||
fetch(form.action, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.innerHTML = originalBtnText;
|
||||
|
||||
if (data.status === 'success') {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berhasil!',
|
||||
text: data.message,
|
||||
showConfirmButton: false,
|
||||
timer: 2000
|
||||
}).then(() => {
|
||||
window.location.href = "{{ route('lahan-cpcl.index') }}";
|
||||
});
|
||||
} else {
|
||||
let errorMsg = data.message || 'Terjadi kesalahan saat menyimpan data.';
|
||||
if (data.errors) {
|
||||
errorMsg = Object.values(data.errors).map(err => err.join(', ')).join('<br>');
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal Menyimpan!',
|
||||
html: errorMsg
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.innerHTML = originalBtnText;
|
||||
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error Sistem',
|
||||
text: 'Terjadi kesalahan pada server atau koneksi internet.'
|
||||
});
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
Reference in New Issue
Block a user