Merge pull request #16 from arieeefajar/fix/master-land

Fix/master land
This commit is contained in:
Arie Fajar Bachtiar 2025-03-03 01:32:46 +07:00 committed by GitHub
commit 7751f8371f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 361 additions and 220 deletions

View File

@ -53,6 +53,10 @@ public function store(Request $request)
'district_id.required' => 'Kecamatan wajib diisi',
'district_id.exists' => 'Kecamatan tidak ditemukan',
'address.required' => 'Alamat wajib diisi',
'address.max' => 'Alamat maksimal 100 karakter',
'address.string' => 'Alamat harus berupa string',
'lat.required' => 'Latitude wajib diisi',
'lat.numeric' => 'Latitude harus berupa angka',
@ -74,6 +78,7 @@ public function store(Request $request)
'province_id' => 'required|exists:provinces,id',
'regency_id' => 'required|exists:regencies,id',
'district_id' => 'required|exists:districts,id',
'address' => 'required|string|max:100',
'lat' => 'required|numeric',
'lng' => 'required|numeric',
], $customMessage);
@ -93,6 +98,7 @@ public function store(Request $request)
$land->province_code = $request->province_id;
$land->regency_code = $request->regency_id;
$land->district_code = $request->district_id;
$land->address = $request->address;
$land->latitude = $request->lat;
$land->longitude = $request->lng;
@ -143,6 +149,10 @@ public function update(Request $request, $id)
'district_id.required' => 'Kecamatan wajib diisi',
'district_id.exists' => 'Kecamatan tidak ditemukan',
'address.required' => 'Alamat wajib diisi',
'address.max' => 'Alamat maksimal 100 karakter',
'address.string' => 'Alamat harus berupa string',
'lat.required' => 'Latitude wajib diisi',
'lat.numeric' => 'Latitude harus berupa angka',
@ -164,6 +174,7 @@ public function update(Request $request, $id)
'province_id' => 'required|exists:provinces,id',
'regency_id' => 'required|exists:regencies,id',
'district_id' => 'required|exists:districts,id',
'address' => 'required|string|max:100',
'lat' => 'required|numeric',
'lng' => 'required|numeric',
], $customMessage);
@ -183,6 +194,7 @@ public function update(Request $request, $id)
$land->province_code = $request->province_id;
$land->regency_code = $request->regency_id;
$land->district_code = $request->district_id;
$land->address = $request->address;
$land->latitude = $request->lat;
$land->longitude = $request->lng;

View File

@ -22,6 +22,7 @@ public function up(): void
$table->string('province_code');
$table->string('regency_code');
$table->string('district_code');
$table->string('address');
$table->string('latitude');
$table->string('longitude');
$table->timestamps();

View File

@ -31,6 +31,12 @@ var districtEditVal = new Choices(districtEditField, {
shouldSort: false,
});
var addressContainer = form.querySelector("#address-container");
var addressField = form.querySelector("#address-field");
var addressEditContainer = formEdit.querySelector("#address-edit-container");
var addressEditField = formEdit.querySelector("#address-edit-field");
var mapContainer = form.querySelector("#map-container");
var latField = form.querySelector("#lat");
var lngField = form.querySelector("#lng");
@ -96,139 +102,9 @@ document.addEventListener("DOMContentLoaded", function () {
});
map.on("click", onMapClick);
mapEdit.on("click", onMapClick);
});
function validatePhoneNumber(input) {
input.value = input.value.replace(/\D/g, "");
if (input.value.length < 10 || input.value.length > 13) {
input.setCustomValidity("Nomor telepon tidak valid");
} else {
input.setCustomValidity("");
}
}
function validatePrice(input) {
let value = input.value.replace(/\D/g, "");
let formatted = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
minimumFractionDigits: 0,
}).format(value);
input.value = formatted.replace("Rp", "").trim();
}
function showmap(districtId) {
if (!navigator.geolocation) {
alert("Geolocation tidak didukung oleh browser ini.");
return;
}
navigator.geolocation.getCurrentPosition(
function (position) {
mapContainer.style.display = "block";
map.invalidateSize();
mapEditConatiner.style.display = "block";
mapEdit.invalidateSize();
btnContainer.style.display = "block";
btnEditContainer.style.display = "block";
var lat = position.coords.latitude;
var lng = position.coords.longitude;
console.log(lat, lng);
map.setView([lat, lng], 16);
mapEdit.setView([lat, lng], 16);
if (currentMarker || currentMarkerEdit) {
map.removeLayer(currentMarker);
mapEdit.removeLayer(currentMarkerEdit);
}
var iconMarker = L.icon({
iconUrl: "/assets/images/marker.png",
iconSize: [50, 50],
iconAnchor: [25, 50],
popupAnchor: [0, -50],
});
currentMarker = L.marker([lat, lng], {
icon: iconMarker,
draggable: true,
}).addTo(map);
currentMarkerEdit = L.marker([lat, lng], {
icon: iconMarker,
draggable: true,
}).addTo(mapEdit);
currentMarker.on("dragend", onMapDragend);
currentMarkerEdit.on("dragend", onMapDragend);
currentMarker
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
currentMarkerEdit
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
latField.value = lat;
lngField.value = lng;
latEditField.value = lat;
lngEditField.value = lng;
},
function (error) {
alert("Error: " + error.message);
}
);
}
function onMapClick(e) {
var lat = e.latlng.lat;
var lng = e.latlng.lng;
if (!currentMarker) {
currentMarker = L.marker(e.latlng).addTo(map);
} else {
currentMarker.setLatLng(e.latlng);
}
currentMarker.on("dragend", onMapDragend);
currentMarker
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
latField.value = lat;
lngField.value = lng;
}
function onMapDragend() {
if (!currentMarker) return;
var coordinates = currentMarker.getLatLng();
currentMarker
.setLatLng(coordinates)
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
latField.value = coordinates.lat;
lngField.value = coordinates.lng;
}
function getProvinces(provinceId) {
return new Promise(function (resolve, reject) {
$.ajax({
@ -257,6 +133,8 @@ function getRegencies(provinceId) {
regencyEditContainer.style.display = "none";
districtContainer.style.display = "none";
districtEditContainer.style.display = "none";
addressContainer.style.display = "none";
addressEditContainer.style.display = "none";
loading.style.display = "block";
loadingEdit.style.display = "block";
mapContainer.style.display = "none";
@ -344,6 +222,8 @@ function getRegencies(provinceId) {
function getDistricts(regencyId) {
districtContainer.style.display = "none";
districtEditContainer.style.display = "none";
addressContainer.style.display = "none";
addressEditContainer.style.display = "none";
loading.style.display = "block";
loadingEdit.style.display = "block";
mapContainer.style.display = "none";
@ -427,6 +307,92 @@ function getDistricts(regencyId) {
});
}
function showmap(districtId) {
loading.style.display = "block";
loadingEdit.style.display = "block";
if (!navigator.geolocation) {
alert("Geolocation tidak didukung oleh browser ini.");
return;
}
navigator.geolocation.getCurrentPosition(
function (position) {
loading.style.display = "none";
loadingEdit.style.display = "none";
mapContainer.style.display = "block";
map.invalidateSize();
addressContainer.style.display = "block";
mapEditConatiner.style.display = "block";
mapEdit.invalidateSize();
addressEditContainer.style.display = "block";
btnContainer.style.display = "block";
btnEditContainer.style.display = "block";
var lat = position.coords.latitude;
var lng = position.coords.longitude;
console.log(lat, lng);
map.setView([lat, lng], 16);
mapEdit.setView([lat, lng], 16);
if (currentMarker) {
map.removeLayer(currentMarker);
}
if (currentMarker || currentMarkerEdit) {
map.removeLayer(currentMarker);
mapEdit.removeLayer(currentMarkerEdit);
}
var iconMarker = L.icon({
iconUrl: "/assets/images/marker.png",
iconSize: [50, 50],
iconAnchor: [25, 50],
popupAnchor: [0, -50],
});
currentMarker = L.marker([lat, lng], {
icon: iconMarker,
draggable: true,
}).addTo(map);
currentMarkerEdit = L.marker([lat, lng], {
icon: iconMarker,
draggable: true,
}).addTo(mapEdit);
currentMarker.on("dragend", onPointerDragend);
currentMarkerEdit.on("dragend", onPointerDragend);
currentMarker
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
currentMarkerEdit
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
latField.value = lat;
lngField.value = lng;
latEditField.value = lat;
lngEditField.value = lng;
},
function (error) {
alert("Error: " + error.message);
}
);
}
async function updateData(data) {
const land = data.land;
const userRole = data.role;
@ -545,6 +511,9 @@ async function updateData(data) {
},
});
addressEditContainer.style.display = "block";
addressEditField.value = land.address;
mapEdit.setView([land.latitude, land.longitude], 16);
currentMarkerEdit
.setLatLng([land.latitude, land.longitude])
@ -576,6 +545,88 @@ function deleteData(data) {
}
}
function onMapClick(e) {
var lat = e.latlng.lat;
var lng = e.latlng.lng;
if (!currentMarker || !currentMarkerEdit) {
currentMarker = L.marker(e.latlng).addTo(map);
currentMarkerEdit = L.marker(e.latlng).addTo(mapEdit);
} else {
currentMarker.setLatLng(e.latlng);
currentMarkerEdit.setLatLng(e.latlng);
}
currentMarker.on("dragend", onPointerDragend);
currentMarkerEdit.on("dragend", onPointerDragend);
currentMarker
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
currentMarkerEdit
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
latField.value = lat;
lngField.value = lng;
}
function onPointerDragend() {
if (!currentMarker) return;
var coordinates = currentMarker.getLatLng();
currentMarker
.setLatLng(coordinates)
.bindPopup(
`<div class="text-center"><b>Anda berada di sini</b><br />Silahkan priksa lokasi petamu sudah benar.</div>`
)
.openPopup();
latField.value = coordinates.lat;
lngField.value = coordinates.lng;
}
function validatePhoneNumber(input) {
input.value = input.value.replace(/\D/g, "");
if (input.value.length < 10 || input.value.length > 13) {
input.setCustomValidity("Nomor telepon tidak valid");
} else {
input.setCustomValidity("");
}
}
function validatePrice(input) {
let value = input.value.replace(/\D/g, "");
let formatted = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
minimumFractionDigits: 0,
}).format(value);
input.value = formatted.replace("Rp", "").trim();
}
var checkAll = document.getElementById("checkAll");
checkAll &&
(checkAll.onclick = function () {
for (
var e = document.querySelectorAll(
'.form-check-all input[type="checkbox"]'
),
t = 0;
t < e.length;
t++
)
(e[t].checked = this.checked),
e[t].checked
? e[t].closest("tr").classList.add("table-active")
: e[t].closest("tr").classList.remove("table-active");
});
var perPage = 10,
options = {
valueNames: ["id", "land_name", "owner", "rental_price", "status"],
@ -671,33 +722,7 @@ function updateList() {
})),
userList.update();
}
refreshCallbacks(),
filterContact("All"),
document
.getElementById("showModal")
.addEventListener("show.bs.modal", function (e) {
e.relatedTarget.classList.contains("edit-item-btn")
? ((document.getElementById("exampleModalLabel").innerHTML =
"Edit Customer"),
(document
.getElementById("showModal")
.querySelector(".modal-footer").style.display = "block"),
(document.getElementById("add-btn").style.display = "none"),
(document.getElementById("edit-btn").style.display = "block"))
: e.relatedTarget.classList.contains("add-btn")
? ((document.getElementById("exampleModalLabel").innerHTML =
"Tambah Data Lahan"),
(document
.getElementById("showModal")
.querySelector(".modal-footer").style.display = "block"),
(document.getElementById("edit-btn").style.display = "none"),
(document.getElementById("add-btn").style.display = "block"))
: ((document.getElementById("exampleModalLabel").innerHTML =
"List Customer"),
(document
.getElementById("showModal")
.querySelector(".modal-footer").style.display = "none"));
}),
filterContact("All"),
ischeckboxcheck(),
document
.getElementById("showModal")
@ -707,7 +732,7 @@ refreshCallbacks(),
document
.querySelector("#customerList")
.addEventListener("click", function () {
refreshCallbacks(), ischeckboxcheck();
ischeckboxcheck();
});
var table = document.getElementById("customerTable"),
tr = table.getElementsByTagName("tr"),
@ -731,27 +756,49 @@ addBtn.addEventListener("click", function (e) {
}),
document.getElementById("close-modal").click(),
clearFields(),
refreshCallbacks(),
filterContact("All"),
count++);
}),
// var statusVal = new Choices(statusField);
function isStatus(e) {
switch (e) {
case "Active":
return (
'<span class="badge badge-soft-success text-uppercase">' +
e +
"</span>"
);
case "Block":
return (
'<span class="badge badge-soft-danger text-uppercase">' +
e +
"</span>"
);
}
};
editBtn.addEventListener("click", function (e) {
(document.getElementById("exampleModalLabel").innerHTML =
"Edit Customer"),
customerList.get({ id: idField.value }).forEach(function (e) {
(isid = new DOMParser().parseFromString(
e._values.id,
"text/html"
)),
isid.body.firstElementChild.innerHTML == itemId &&
e.values({
id:
'<a href="javascript:void(0);" class="fw-medium link-primary">' +
idField.value +
"</a>",
customer_name: customerNameField.value,
email: emailField.value,
date: dateField.value,
phone: phoneField.value,
status: isStatus(statusField.value),
});
}),
document.getElementById("close-modal").click(),
clearFields();
});
function isStatus(e) {
switch (e) {
case "Active":
return (
'<span class="badge badge-soft-success text-uppercase">' +
e +
"</span>"
);
case "Block":
return (
'<span class="badge badge-soft-danger text-uppercase">' +
e +
"</span>"
);
}
}
function ischeckboxcheck() {
document.getElementsByName("checkAll").forEach(function (e) {
e.addEventListener("click", function (e) {
@ -761,29 +808,97 @@ function ischeckboxcheck() {
});
});
}
function refreshCallbacks() {
removeBtns.forEach(function (e) {
e.addEventListener("click", function (e) {
e.target.closest("tr").children[1].innerText,
(itemId = e.target.closest("tr").children[1].innerText),
customerList.get({ id: itemId }).forEach(function (e) {
deleteid = new DOMParser().parseFromString(
e._values.id,
"text/html"
);
var t = deleteid.body.firstElementChild;
deleteid.body.firstElementChild.innerHTML == itemId &&
document
.getElementById("delete-record")
.addEventListener("click", function () {
customerList.remove("id", t.outerHTML),
document
.getElementById("deleteRecordModal")
.click();
});
});
});
});
// function refreshCallbacks() {
// removeBtns.forEach(function (e) {
// e.addEventListener("click", function (e) {
// e.target.closest("tr").children[1].innerText,
// (itemId = e.target.closest("tr").children[1].innerText),
// customerList.get({ id: itemId }).forEach(function (e) {
// deleteid = new DOMParser().parseFromString(
// e._values.id,
// "text/html"
// );
// var t = deleteid.body.firstElementChild;
// deleteid.body.firstElementChild.innerHTML == itemId &&
// document
// .getElementById("delete-record")
// .addEventListener("click", function () {
// customerList.remove("id", t.outerHTML),
// document
// .getElementById("deleteRecordModal")
// .click();
// });
// });
// });
// });
// // editBtns.forEach(function (e) {
// // e.addEventListener("click", function (e) {
// // e.target.closest("tr").children[1].innerText,
// // (itemId = e.target.closest("tr").children[1].innerText),
// // customerList.get({ id: itemId }).forEach(function (e) {
// // isid = new DOMParser().parseFromString(
// // e._values.id,
// // "text/html"
// // );
// // var t = isid.body.firstElementChild.innerHTML;
// // t == itemId &&
// // ((idField.value = t),
// // (customerNameField.value = e._values.customer_name),
// // (emailField.value = e._values.email),
// // (dateField.value = e._values.date),
// // (phoneField.value = e._values.phone),
// // statusVal && statusVal.destroy(),
// // (statusVal = new Choices(statusField)),
// // (val = new DOMParser().parseFromString(
// // e._values.status,
// // "text/html"
// // )),
// // (t = val.body.firstElementChild.innerHTML),
// // statusVal.setChoiceByValue(t),
// // flatpickr("#date-field", {
// // dateFormat: "d M, Y",
// // defaultDate: e._values.date,
// // }));
// // });
// // });
// // });
// }
function clearFields() {
var ownerField = form.querySelector("#owner-field");
var noHpField = form.querySelector("#nohp-field");
var rentalPriceField = form.querySelector("#rentalprice-field");
var rentalStartField = form.querySelector("#rentalstart-field");
var rentalEndField = form.querySelector("#rentaluntil-field");
var landNameField = form.querySelector("#landname-field");
var addressField = form.querySelector("#address-field");
(ownerField.value = ""),
(noHpField.value = ""),
(rentalPriceField.value = ""),
(rentalStartField.value = ""),
(rentalEndField.value = ""),
(landNameField.value = ""),
(addressField.value = "");
provinceVal.setChoices([
{
value: "",
label: "Pilih Provinsi",
selected: true,
disabled: true,
},
]);
regencyVal.clearStore();
districtVal.clearStore();
latField.value = "";
lngField.value = "";
regencyContainer.style.display = "none";
districtContainer.style.display = "none";
addressContainer.style.display = "none";
mapContainer.style.display = "none";
btnContainer.style.display = "none";
}
document
.querySelector(".pagination-next")

View File

@ -1,5 +1,5 @@
@extends('layouts.app')
@push('title', 'Data Tanah')
@push('title', 'Data Lahan')
@section('content')
@push('other-css')
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
@ -26,12 +26,12 @@
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0">Data Lahan</h4>
<h4 class="mb-sm-0">Data lahan</h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="javascript: void(0);">Master Data</a></li>
<li class="breadcrumb-item active">Data Lahan</li>
<li class="breadcrumb-item active">Data lahan</li>
</ol>
</div>
@ -71,9 +71,7 @@ class="ri-add-line align-bottom me-1"></i> Tambah</button>
<table class="table align-middle table-nowrap" id="customerTable">
<thead class="table-light">
<tr class="text-center">
<th class="sort" data-sort="id">
No
</th>
<th class="sort" data-sort="no">No</th>
<th class="sort" data-sort="land_name">Nama Lahan</th>
<th class="sort" data-sort="owner">Pemilik</th>
<th class="sort" data-sort="rental_price">Harga Sewa</th>
@ -128,7 +126,7 @@ class="fw-medium link-primary">#VZ2101</a></td>
<div class="d-flex justify-content-end">
<div class="pagination-wrap hstack gap-2">
<a class="page-item pagination-prev disabled" href="#">
Kembali
Sebelumnya
</a>
<ul class="pagination listjs-pagination mb-0"></ul>
<a class="page-item pagination-next" href="#">
@ -154,9 +152,8 @@ class="fw-medium link-primary">#VZ2101</a></td>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
id="close-modal"></button>
</div>
<form
action="{{ Auth::user()->role == 'admin' ? route('master_data.lahan.store') : route('lahan.store') }}"
class="needs-validation" method="POST" novalidate id="add-form">
<form id="add-form" class="needs-validation" method="POST" novalidate
action="{{ Auth::user()->role == 'admin' ? route('master_data.lahan.store') : route('lahan.store') }}">
@csrf
<div class="modal-body">
@ -274,6 +271,15 @@ class="needs-validation" method="POST" novalidate id="add-form">
</div>
</div>
<div class="mb-3" id="address-container" style="display: none">
<label for="address-field" class="form-label">Alamat</label>
<textarea name="address" id="address-field" rows="3" class="form-control"
placeholder="Masukan Alamat, cnth: Jl. Jend. Sudirman No. 12" required></textarea>
<div class="invalid-feedback">
Masukan Alamat
</div>
</div>
<div id="map-container" style="display: none">
<label for="map" class="form-label">Lokasi</label>
<div id="map"></div>
@ -307,7 +313,7 @@ class="needs-validation" method="POST" novalidate id="add-form">
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
id="close-modal"></button>
</div>
<form action="" class="needs-validation" method="POST" novalidate id="edit-form">
<form id="edit-form" action="" method="POST" class="needs-validation" novalidate>
@csrf
@method('PUT')
<div class="modal-body">
@ -426,6 +432,15 @@ class="needs-validation" method="POST" novalidate id="add-form">
</div>
</div>
<div class="mb-3" id="address-edit-container" style="display: none">
<label for="address-edit-field" class="form-label">Alamat</label>
<textarea name="address" id="address-edit-field" rows="3" class="form-control"
placeholder="Masukan Alamat, cnth: Jl. Jend. Sudirman No. 12" required></textarea>
<div class="invalid-feedback">
Masukan Alamat
</div>
</div>
<div id="map-edit-container">
<label for="map-edit" class="form-label">Lokasi</label>
<div id="map-edit"></div>
@ -441,7 +456,7 @@ class="needs-validation" method="POST" novalidate id="add-form">
<div class="modal-footer" id="edit-footer">
<div class="hstack gap-2 justify-content-end">
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Tutup</button>
<button type="submit" class="btn btn-success" id="add-btn">Ubah</button>
<button type="submit" class="btn btn-success" id="edit-btn">Update</button>
</div>
</div>
</form>
@ -469,10 +484,10 @@ class="needs-validation" method="POST" novalidate id="add-form">
</div>
<div class="d-flex gap-2 justify-content-center mt-4 mb-2">
<button type="button" class="btn w-sm btn-light" data-bs-dismiss="modal">Tutup</button>
<form action="" method="POST" id="delete-form">
<form action="" method="post" id="delete-form">
@csrf
@method('DELETE')
<button type="submit" class="btn w-sm btn-danger" id="delete-record">Ya,
<button type="submit" class="btn w-sm btn-danger" id="delete-record">Ya
Hapus!</button>
</form>
</div>
@ -489,14 +504,12 @@ class="needs-validation" method="POST" novalidate id="add-form">
@push('other-js')
<!-- prismjs plugin -->
<script src="assets/libs/prismjs/prism.js"></script>
<script src="assets/libs/list.js/list.min.js"></script>
<script src="assets/libs/list.pagination.js/list.pagination.min.js"></script>
<script src="{{ asset('/assets/libs/prismjs/prism.js') }}"></script>
<script src="{{ asset('/assets/libs/list.js/list.min.js') }}"></script>
<script src="{{ asset('assets/libs/list.pagination.js/list.pagination.min.js') }}"></script>
<!-- listjs init -->
<script src="assets/js/pages/customJs/master-data/lahan/index.js"></script>
<script src="assets/js/pages/form-validation.init.js"></script>
<script src="{{ asset('assets/js/pages/customJs/master-data/lahan/index.js') }}"></script>
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"