`;
return html;
}
function kirimNotifOdp(id) {
console.log("Kirim ODP ID:", id);
fetch(`api/laporan_odp.php?kirim=1&id=${id}`)
.then(res => res.json())
.then(res => {
if (res.success) {
alert("✅ Notif terkirim ke group");
} else {
alert("❌ Gagal kirim");
}
})
.catch(err => {
console.error(err);
alert("❌ Error koneksi");
});
}
// Generate item list HTML
// Generate item list HTML
function generateItemListHtml(items) {
let html = `
Jenis
Nama
Alamat
Koordinat
Status
Aksi
`;
items.forEach(function(item) {
html += `
${item.item_type_name}
${item.name}
${item.address || '-'}
${(isNaN(parseFloat(item.latitude)) || isNaN(parseFloat(item.longitude))) ? 'Koordinat tidak valid' : `${parseFloat(item.latitude).toFixed(6)}, ${parseFloat(item.longitude).toFixed(6)}`}
${getStatusText(item.status)}
`;
});
html += `
`;
return html;
}
// Get item color
function getItemColor(typeName) {
switch(typeName) {
case 'OLT': return '#FF6B6B';
case 'Tiang Tumpu': return '#4ECDC4';
case 'ODP': return '#45B7D1';
case 'ODC': return '#96CEB4';
case 'Pelanggan': return '#FFA500';
default: return '#999';
}
}
// Focus on item in map
function focusOnItem(itemId) {
if (markers[itemId]) {
let marker = markers[itemId];
map.setView(marker.getLatLng(), 16);
marker.openPopup();
}
}
// Show route list
function showRouteList() {
$.ajax({
url: 'api/routes.php',
method: 'GET',
success: function(response) {
if (response.success) {
let routeListHtml = generateRouteListHtml(response.data);
showModal('Daftar Routing Kabel', routeListHtml, 'modal-xl');
}
},
error: function() {
showNotification('Error loading route list', 'error');
}
});
}
// Generate route list HTML
function generateRouteListHtml(routes) {
let html = `
Dari
Ke
Jarak
Tipe Kabel
Core
Status
Aksi
`;
routes.forEach(function(route) {
let distance = route.distance ? (route.distance / 1000).toFixed(2) + ' km' : '-';
html += `
${route.from_item_name || 'Unknown'}
${route.to_item_name || 'Unknown'}
${distance}
${route.cable_type || '-'}
${route.core_count || '-'}
${getStatusText(route.status)}
`;
});
html += `
`;
return html;
}
// Focus on route in map
function focusOnRoute(routeId) {
if (routes[routeId]) {
let route = routes[routeId];
map.fitBounds(route.getBounds());
route.openPopup();
}
}
// Delete route
function deleteRoute(routeId) {
if (confirm('Apakah Anda yakin ingin menghapus route ini?')) {
$.ajax({
url: 'api/routes.php',
method: 'DELETE',
data: { id: routeId },
success: function(response) {
if (response.success) {
if (routes[routeId]) {
map.removeLayer(routes[routeId]);
delete routes[routeId];
}
showNotification('Route berhasil dihapus', 'success');
} else {
showNotification(response.message || 'Error deleting route', 'error');
}
},
error: function() {
showNotification('Error deleting route', 'error');
}
});
}
}
// Generic modal function
function showModal(title, content, size = 'modal-lg') {
if (!$('#genericModal').length) {
$('body').append(`
`);
}
$('#genericModalTitle').text(title);
$('#genericModalBody').html(content);
$('#genericModal').modal('show');
}
// Edit route function
function editRoute(routeId) {
// Get route data first
$.ajax({
url: 'api/routes.php',
method: 'GET',
data: { id: routeId },
success: function(response) {
if (response.success && response.data) {
let route = response.data;
showEditRouteModal(route);
} else {
showNotification('Error loading route data', 'error');
}
},
error: function() {
showNotification('Error loading route data', 'error');
}
});
}
//terpasang kabel rx power
// Contoh marker pelanggan
// Event saat dropdown status diubah
// Fungsi untuk memuat RX Power di tengah kabel
// Show edit route modal
function showEditRouteModal(route) {
let modalHtml = `
`;
// Create modal if doesn't exist
if (!$('#routeEditModal').length) {
$('body').append(`
Edit Routing Kabel
`);
}
$('#routeEditModalBody').html(modalHtml);
$('#routeEditModal').modal('show');
// Handle form submission
$('#editRouteForm').on('submit', function(e) {
e.preventDefault();
saveRouteEdit();
});
}
// Save route edit
function saveRouteEdit() {
let formData = new FormData();
formData.append('_method', 'PUT');
formData.append('id', $('#editRouteId').val());
formData.append('cable_type', $('#editCableType').val());
formData.append('core_count', $('#editCoreCount').val());
formData.append('status', $('#editRouteStatus').val());
console.log('🚀 Route Edit Data being sent:');
for (let pair of formData.entries()) {
console.log(' ' + pair[0] + ': ' + pair[1]);
}
$.ajax({
url: 'api/routes.php',
type: 'POST',
method: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json',
cache: false,
success: function(response) {
console.log('✅ Route update response:', response);
if (response.success) {
$('#routeEditModal').modal('hide');
showNotification('Route berhasil diupdate', 'success');
// Refresh route list if open
if ($('#genericModal').hasClass('show')) {
showRouteList();
}
// Update route on map
loadRoutes();
} else {
console.error('❌ Route update failed:', response.message);
showNotification(response.message || 'Error updating route', 'error');
}
},
error: function(xhr, status, error) {
console.error('❌ AJAX Error:', error, xhr.responseText);
console.error('Response Text:', xhr.responseText);
try {
let errorResponse = JSON.parse(xhr.responseText);
showNotification(errorResponse.message || 'Error updating route', 'error');
} catch(e) {
showNotification('Error updating route: ' + error, 'error');
}
}
});
}
// Calculate core available
function calculateCoreAvailable() {
let totalCapacity = parseInt($('#totalCoreCapacity').val()) || 0;
let coreUsed = parseInt($('#coreUsed').val()) || 0;
let coreAvailable = totalCapacity - coreUsed;
$('#coreAvailable').val(coreAvailable + ' / ' + totalCapacity + ' Core');
// Set color based on availability
if (coreAvailable <= 0) {
$('#coreAvailable').removeClass('text-success text-warning').addClass('text-danger');
} else if (coreAvailable <= totalCapacity * 0.2) {
$('#coreAvailable').removeClass('text-success text-danger').addClass('text-warning');
} else {
$('#coreAvailable').removeClass('text-danger text-warning').addClass('text-success');
}
}
// Sync core usage from routes
function syncCoreUsageFromRoutes(itemId) {
if (!itemId) return;
$.ajax({
url: 'api/routes.php',
method: 'GET',
success: function(response) {
if (response.success) {
let totalCoreUsed = 0;
response.data.forEach(function(route) {
if (route.from_item_id == itemId || route.to_item_id == itemId) {
totalCoreUsed += parseInt(route.core_count) || 0;
}
});
// Update core used in form
$('#coreUsed').val(totalCoreUsed);
calculateCoreAvailable();
console.log(`📊 Core usage synced for item ${itemId}: ${totalCoreUsed} cores used`);
}
},
error: function() {
console.error('Failed to sync core usage from routes');
}
});
}
// Enhanced edit item to include core sync
function editItemEnhanced(itemId) {
editItem(itemId);
// Sync core usage after loading item data
setTimeout(() => syncCoreUsageFromRoutes(itemId), 500);
}
// Show item detail
function showItemDetail(itemId) {
$.ajax({
url: 'api/items.php',
method: 'GET',
data: { id: itemId },
success: function(response) {
if (response.success && response.data) {
let item = response.data;
showItemDetailModal(item);
} else {
showNotification('Error loading item data', 'error');
}
},
error: function() {
showNotification('Error loading item data', 'error');
}
});
}
// Show item detail modal //ini detail jika mau edit
function showItemDetailModal(item) {
let modalHtml = `
`;
// Create modal if doesn't exist
if (!$('#itemDetailModal').length) {
$('body').append(`
Detail Item FTTH
`);
}
$('#itemDetailModalBody').html(modalHtml);
$('#itemDetailModal').modal('show');
}
//detailredaman
// Fungsi untuk menampilkan detail redaman
function showRedamanDetail(item) {
let modalHtml = `