update sistem proyek menjadi lebih struktural. dimulai dengan memisahkan dashboard publik dan administrator pada setiap proyek, membuat dockerfile untuk setup environment docker, dan merapikan database serta membuat file migration.

This commit is contained in:
2026-06-10 17:44:46 +07:00
parent c6087ed7dd
commit e98a8ecec9
34 changed files with 963 additions and 211 deletions
+71 -62
View File
@@ -13,20 +13,23 @@ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
var drawnItems = new L.FeatureGroup().addTo(map);
var layerGroupPoint = L.featureGroup().addTo(map);
var currentLayer = null;
var isAdmin = window.IS_ADMIN === true;
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);
if (isAdmin) {
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);
}
function getLineColor(status) {
return status === 'Nasional' ? '#ef4444' : status === 'Provinsi' ? '#38bdf8' : '#a855f7';
@@ -88,9 +91,11 @@ function buildInfoPopup(d, type) {
<div class="ip-row"><span class="ip-label">Luas</span><span class="ip-val">${fmtNum(d.luas)} m²</span></div>`;
}
var deleteButton = isAdmin ? `<button class="ip-del" onclick="hapusData(${d.id},'${type}')">Hapus</button>` : '';
return `<div class="ip">
<div class="ip-head" style="background:${headerColors[type]}">${icons[type]} ${titles[type]}</div>
<div class="ip-body">${rows}<button class="ip-del" onclick="hapusData(${d.id},'${type}')">Hapus</button></div>
<div class="ip-body">${rows}${deleteButton}</div>
</div>`;
}
@@ -142,22 +147,24 @@ function hapusData(id, type) {
});
}
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer;
if (isAdmin) {
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer;
if (e.layerType === 'marker') {
drawnItems.addLayer(layer);
handlePoint(layer);
}
if (e.layerType === 'polyline') {
drawnItems.addLayer(layer);
handleLine(layer);
}
if (e.layerType === 'polygon') {
drawnItems.addLayer(layer);
handlePolygon(layer);
}
});
if (e.layerType === 'marker') {
drawnItems.addLayer(layer);
handlePoint(layer);
}
if (e.layerType === 'polyline') {
drawnItems.addLayer(layer);
handleLine(layer);
}
if (e.layerType === 'polygon') {
drawnItems.addLayer(layer);
handlePolygon(layer);
}
});
}
function handlePoint(layer) {
var ll = layer.getLatLng();
@@ -180,7 +187,7 @@ function savePoint(lat, lng) {
alert('Nama dan kode point wajib diisi!');
return;
}
fetch('../php/insert.php', {
fetch('../php/insert_point.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nama, no, status, lat, lng })
@@ -294,38 +301,40 @@ function savePolygon() {
});
}
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])
})
});
}
if (isAdmin) {
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}`);
}
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}`);
}
});
});
});
}
+27 -21
View File
@@ -15,6 +15,7 @@ var layerGroup24 = L.featureGroup().addTo(map);
var layerGroupTidak = L.featureGroup().addTo(map);
var show24 = true;
var showTidak = true;
var isAdmin = window.IS_ADMIN === true;
function toggleLayer(type) {
if (type === '24jam') {
@@ -28,19 +29,21 @@ function toggleLayer(type) {
}
}
var drawControl = new L.Control.Draw({
position: 'topleft',
edit: { featureGroup: drawnItems },
draw: {
marker: true,
polyline: false,
polygon: false,
rectangle: false,
circle: false,
circlemarker: false
}
});
map.addControl(drawControl);
if (isAdmin) {
var drawControl = new L.Control.Draw({
position: 'topleft',
edit: { featureGroup: drawnItems },
draw: {
marker: true,
polyline: false,
polygon: false,
rectangle: false,
circle: false,
circlemarker: false
}
});
map.addControl(drawControl);
}
function makeIcon(status) {
var c = status === '24 Jam' ? '#4ade80' : '#f87171';
@@ -60,13 +63,14 @@ function statusBadge(status) {
}
function buildInfoPopup(d) {
var deleteButton = isAdmin ? `<button class="ip-del" onclick="hapusData(${d.id},'spbu')">Hapus</button>` : '';
return `<div class="ip">
<div class="ip-head" style="background:linear-gradient(135deg,#1d4ed8,#3b82f6)">⛽ SPBU - ${d.nama}</div>
<div class="ip-body">
<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)}</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>
<button class="ip-del" onclick="hapusData(${d.id},'point')">Hapus</button>
${deleteButton}
</div>
</div>`;
}
@@ -76,7 +80,7 @@ fetch('../php/show_spbu.php')
.then(data => {
data.forEach(d => {
var layer = L.marker([d.latitude, d.longitude], { icon: makeIcon(d.status) });
layer._type = 'point';
layer._type = 'spbu';
layer._db_id = d.id;
layer.bindPopup(buildInfoPopup(d), { maxWidth: 260 });
d.status === '24 Jam' ? layerGroup24.addLayer(layer) : layerGroupTidak.addLayer(layer);
@@ -94,12 +98,14 @@ function hapusData(id, type) {
});
}
map.on(L.Draw.Event.CREATED, function(e) {
if (e.layerType !== 'marker') return;
var layer = e.layer;
drawnItems.addLayer(layer);
handlePoint(layer);
});
if (isAdmin) {
map.on(L.Draw.Event.CREATED, function(e) {
if (e.layerType !== 'marker') return;
var layer = e.layer;
drawnItems.addLayer(layer);
handlePoint(layer);
});
}
function handlePoint(layer) {
var ll = layer.getLatLng();