@@ -352,6 +416,7 @@
let activeDrawHandler = null;
let currentDrawMode = 'polyline';
let appMode = 'view';
+ let isEditModeEnabled = true;
let pendingShape = null;
let pendingNewFeatureLayer = null;
let featureLayerMap = {};
@@ -360,6 +425,10 @@
let featureRecords = [];
let editingFeatureId = null;
let choroplethLayer = null;
+ let spbuBuka24JamLayer = L.layerGroup().addTo(map);
+ let spbuTidak24JamLayer = L.layerGroup().addTo(map);
+ let spbuLayerControl = null;
+ let utilityControl = null;
let roadDamageLayer = L.featureGroup().addTo(map);
let roadNetworkLayer = L.featureGroup().addTo(map);
let roadDamageRecords = [];
@@ -670,9 +739,38 @@
return `${year}-${month}-${day}`;
}
+ function getRegistryUi() {
+ const drawerPanel = document.getElementById('registryDrawer');
+ const drawerSearch = document.getElementById('registrySearchQuery');
+
+ if (drawerPanel && drawerSearch) {
+ return {
+ panel: drawerPanel,
+ count: document.getElementById('registryCount'),
+ list: document.getElementById('registryList'),
+ search: drawerSearch,
+ type: document.getElementById('registryTypeFilter'),
+ from: document.getElementById('registryDateFrom'),
+ to: document.getElementById('registryDateTo')
+ };
+ }
+
+ return {
+ panel: document.getElementById('inputRegistryPanel'),
+ count: document.getElementById('inputRegistryCount'),
+ list: document.getElementById('inputRegistryList'),
+ search: document.getElementById('inputSearchQuery'),
+ type: document.getElementById('inputTypeFilter'),
+ from: document.getElementById('inputDateFrom'),
+ to: document.getElementById('inputDateTo')
+ };
+ }
+
function enforceRegistryDateRange(showFeedback = false) {
- const fromEl = document.getElementById('inputDateFrom');
- const toEl = document.getElementById('inputDateTo');
+ const ui = getRegistryUi();
+ const fromEl = ui.from;
+ const toEl = ui.to;
+ if (!fromEl || !toEl) return;
const from = fromEl.value;
const to = toEl.value;
@@ -688,11 +786,12 @@
}
function getRegistryFilters() {
+ const ui = getRegistryUi();
return {
- search: document.getElementById('inputSearchQuery').value.toLowerCase().trim(),
- type: document.getElementById('inputTypeFilter').value,
- from: document.getElementById('inputDateFrom').value,
- to: document.getElementById('inputDateTo').value
+ search: String(ui.search && ui.search.value ? ui.search.value : '').toLowerCase().trim(),
+ type: ui.type && ui.type.value ? ui.type.value : 'all',
+ from: ui.from && ui.from.value ? ui.from.value : '',
+ to: ui.to && ui.to.value ? ui.to.value : ''
};
}
@@ -754,7 +853,18 @@
created_at: feature.created_at || null
}));
- return [...pointRecords, ...spatialRecords].sort((left, right) => {
+ const roadDamageRegistryRecords = roadDamageRecords.map(record => ({
+ id: Number(record.id),
+ type: 'roadDamage',
+ title: `Jalan Rusak - ${record.jenis_kerusakan || 'Tanpa jenis'}`,
+ subtitle: record.deskripsi || '-',
+ status: record.severity || '-',
+ created_at: record.created_at || null,
+ latitude: Number(record.latitude),
+ longitude: Number(record.longitude)
+ }));
+
+ return [...pointRecords, ...spatialRecords, ...roadDamageRegistryRecords].sort((left, right) => {
const leftDate = parseDateOnly(left.created_at);
const rightDate = parseDateOnly(right.created_at);
@@ -769,6 +879,7 @@
if (type === 'point') return 'Poin';
if (type === 'polyline') return 'Polyline';
if (type === 'polygon') return 'Polygon';
+ if (type === 'roadDamage') return 'Jalan Rusak';
return 'Data';
}
@@ -776,6 +887,7 @@
if (type === 'point') return 'bg-emerald-100 text-emerald-700';
if (type === 'polyline') return 'bg-indigo-100 text-indigo-700';
if (type === 'polygon') return 'bg-amber-100 text-amber-700';
+ if (type === 'roadDamage') return 'bg-red-100 text-red-700';
return 'bg-slate-100 text-slate-700';
}
@@ -788,6 +900,27 @@
return;
}
+ if (type === 'roadDamage') {
+ let selectedMarker = null;
+ roadDamageLayer.eachLayer(layer => {
+ if (layer && layer.roadDamageId === id) {
+ selectedMarker = layer;
+ }
+ });
+
+ if (selectedMarker) {
+ map.setView(selectedMarker.getLatLng(), Math.max(map.getZoom(), 16));
+ selectedMarker.openPopup();
+ return;
+ }
+
+ const record = roadDamageRecords.find(item => Number(item.id) === Number(id));
+ if (record && Number.isFinite(Number(record.latitude)) && Number.isFinite(Number(record.longitude))) {
+ map.setView([Number(record.latitude), Number(record.longitude)], Math.max(map.getZoom(), 16));
+ }
+ return;
+ }
+
const layer = featureLayerMap[id];
if (!layer) return;
if (layer.getBounds) {
@@ -797,8 +930,10 @@
}
function renderInputRegistry() {
- const listEl = document.getElementById('inputRegistryList');
- const countEl = document.getElementById('inputRegistryCount');
+ const ui = getRegistryUi();
+ const listEl = ui.list;
+ const countEl = ui.count;
+ if (!listEl || !countEl) return;
const filters = getRegistryFilters();
const records = buildRegistryRecords().filter(record => recordMatchesFilters(record, filters));
@@ -819,10 +954,14 @@
const dateLabel = formatInputDate(record.created_at);
const measure = record.type === 'point'
? `Telp: ${record.subtitle}`
- : `Kategori: ${record.subtitle}`;
+ : record.type === 'roadDamage'
+ ? `Deskripsi: ${record.subtitle}`
+ : `Kategori: ${record.subtitle}`;
const statusLabel = record.type === 'point'
? `24 Jam: ${record.status}`
- : `Status: ${record.status}`;
+ : record.type === 'roadDamage'
+ ? `Tingkat: ${record.status}`
+ : `Status: ${record.status}`;
return `