Add global try-catch and cleanup dashboard.js
This commit is contained in:
@@ -175,218 +175,329 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||
allPts.forEach(function(p) { bounds.extend({lat: p[0], lng: p[1]}); });
|
||||
map.fitBounds(bounds);
|
||||
}
|
||||
try {
|
||||
var map;
|
||||
var activePolylines = [];
|
||||
var activeMarkers = [];
|
||||
|
||||
var isGoogleLoaded = false;
|
||||
if (googleMapsApiKey) {
|
||||
if (typeof google !== 'undefined' && google.maps) {
|
||||
isGoogleLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isGoogleLoaded) {
|
||||
var mapEl = document.getElementById('mymachMap');
|
||||
if (mapEl) {
|
||||
map = new google.maps.Map(mapEl, {
|
||||
center: { lat: 41.0082, lng: 28.9784 },
|
||||
zoom: 11,
|
||||
disableDefaultUI: true,
|
||||
styles: [
|
||||
{ elementType: "geometry", stylers: [{ color: "#242f3e" }] },
|
||||
{ elementType: "labels.text.stroke", stylers: [{ color: "#242f3e" }] },
|
||||
{ elementType: "labels.text.fill", stylers: [{ color: "#746855" }] }
|
||||
]
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Leaflet.js Görsel Çizimler (Uydu Temalı)
|
||||
|
||||
// 1. Alternatif Gri Yollar
|
||||
var polyAlt1 = L.polyline(alt1Pts, { color: '#64748b', weight: 4, opacity: 0.6, dashArray: '8, 6' }).addTo(map);
|
||||
var polyAlt2 = L.polyline(alt2Pts, { color: '#64748b', weight: 4, opacity: 0.6, dashArray: '8, 6' }).addTo(map);
|
||||
activePolylines.push(polyAlt1, polyAlt2);
|
||||
|
||||
// 2. Yeşil Ana Rota Çizgisi
|
||||
if (greenPts.length > 0) {
|
||||
var polyGreen = L.polyline(greenPts, { color: '#10b981', weight: 8, opacity: 0.95, lineCap: 'round', lineJoin: 'round' }).addTo(map);
|
||||
activePolylines.push(polyGreen);
|
||||
}
|
||||
|
||||
// 3. Kırmızı 1 km+ Sapma Çizgisi
|
||||
if (redPts.length > 0) {
|
||||
var polyRed = L.polyline(redPts, { color: '#ef4444', weight: 8, opacity: 0.95, lineCap: 'round', lineJoin: 'round' }).addTo(map);
|
||||
activePolylines.push(polyRed);
|
||||
}
|
||||
|
||||
var allPts = greenPts.concat(redPts);
|
||||
if (allPts.length > 0) {
|
||||
var startPt = greenPts[0] || allPts[0];
|
||||
var endPt = redPts.length > 0 ? redPts[redPts.length - 1] : (greenPts[greenPts.length - 1] || allPts[allPts.length - 1]);
|
||||
|
||||
// Başlangıç ve Bitiş İğnelerini (Mavi/Kırmızı) Canlı Radarda Gizliyoruz (Sadece araba ve çizgi görünecek)
|
||||
// Kırmızı Yol Üzerindeki "1.5 km Sapma" Çağrı Kutucuğu
|
||||
if (redPts.length > 0) {
|
||||
var midRedIdx = Math.floor(redPts.length / 2);
|
||||
var mRedCallout = L.marker(redPts[midRedIdx], { icon: createCalloutIcon(vehicle.deviation_label, '#ef4444') }).addTo(map);
|
||||
activeMarkers.push(mRedCallout);
|
||||
}
|
||||
|
||||
// Rotada Gerçek Zamanlı Canlı Hareket Eden Araç Animasyonunu Başlat
|
||||
animateMovingVehicle(allPts, vehicle);
|
||||
|
||||
var group = new L.featureGroup([polyAlt1, polyAlt2].concat(activePolylines));
|
||||
map.fitBounds(group.getBounds(), { padding: [50, 50] });
|
||||
var mapEl = document.getElementById('mymachMap');
|
||||
if (mapEl) {
|
||||
map = L.map(mapEl, { zoomControl: false }).setView([41.0082, 28.9784], 11);
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
|
||||
attribution: '© OpenStreetMap © CARTO',
|
||||
subdomains: 'abcd',
|
||||
maxZoom: 20
|
||||
}).addTo(map);
|
||||
}
|
||||
}
|
||||
|
||||
// Yüzen Detay Kartını Güncelle
|
||||
var overlayEl = document.getElementById('driver_info_overlay');
|
||||
if (overlayEl) {
|
||||
var badgeBg = vehicle.is_violation ? 'rgba(239, 68, 68, 0.25)' : (vehicle.is_manager_approved ? 'rgba(56, 189, 248, 0.25)' : 'rgba(16, 185, 129, 0.25)');
|
||||
var badgeBorder = vehicle.is_violation ? '#ef4444' : (vehicle.is_manager_approved ? '#38bdf8' : '#10b981');
|
||||
var badgeText = vehicle.is_violation ? '#ef4444' : (vehicle.is_manager_approved ? '#38bdf8' : '#10b981');
|
||||
var badgeTitle = vehicle.is_violation
|
||||
? vehicle.badge_violation
|
||||
: (vehicle.is_manager_approved ? vehicle.badge_approved : vehicle.badge_ok);
|
||||
|
||||
overlayEl.style.display = 'block';
|
||||
overlayEl.innerHTML =
|
||||
'<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;">' +
|
||||
'<div>' +
|
||||
'<h3 style="color: white; font-size: 15px; font-weight: 700; margin: 0;">' + (vehicle.driver_tag_str || '') + ' - ' + vehicle.driver_name + '</h3>' +
|
||||
'<span style="color: #94a3b8; font-size: 12px;">' + vehicle.license_plate + ' (' + vehicle.name + ')</span>' +
|
||||
'</div>' +
|
||||
'<span style="background: ' + badgeBg + '; border: 1px solid ' + badgeBorder + '; color: ' + badgeText + '; font-size: 11px; font-weight: bold; padding: 4px 8px; border-radius: 12px;">' +
|
||||
vehicle.label_score + ' ' + vehicle.score +
|
||||
'</span>' +
|
||||
'</div>' +
|
||||
'<div style="background: ' + badgeBg + '; border: 1px solid ' + badgeBorder + '; border-radius: 8px; padding: 8px; margin-bottom: 12px; font-size: 11px; font-weight: bold; color: ' + badgeText + '; text-align: center;">' +
|
||||
badgeTitle +
|
||||
'</div>' +
|
||||
'<div style="font-size: 12px; line-height: 1.6; color: #cbd5e1;">' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Personel Evi / Konaklama:</span>' +
|
||||
'<strong style="color: #f1f5f9; font-size: 11px;">' + (vehicle.driver_home_address || 'Bilinmiyor') + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Başlangıç Noktası:</span>' +
|
||||
'<strong style="color: white; font-size: 11px;">' + (vehicle.start_location || 'Canlı GPS Konumu') + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Ulaşım Hedefi:</span>' +
|
||||
'<strong style="color: #38bdf8; font-size: 11px;">' + (vehicle.destination || 'Gerçek Zamanlı Aktif İzleme') + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Planlanan / Gidilen Mesafe:</span>' +
|
||||
'<span>' + vehicle.planned_km + ' KM / <strong>' + vehicle.driven_km + ' KM</strong></span>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Rota Sapma Durumu:</span>' +
|
||||
'<strong style="color: ' + (vehicle.is_violation ? '#ef4444' : (vehicle.is_manager_approved ? '#38bdf8' : '#10b981')) + ';">' + vehicle.deviation_label + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Şirket Politikası:</span>' +
|
||||
'<span style="color: ' + (vehicle.has_free_use ? '#38bdf8' : '#f59e0b') + '; font-weight: 600;">' + vehicle.policy_desc + '</span>' +
|
||||
'</div>' +
|
||||
function createCalloutIcon(text, color) {
|
||||
var html =
|
||||
'<div style="background: rgba(15,23,42,0.9); border: 1px solid ' + color + '; padding: 4px 8px; border-radius: 6px; color: ' + color + '; font-size: 11px; font-weight: bold; white-space: nowrap; box-shadow: 0 4px 12px rgba(0,0,0,0.5); backdrop-filter: blur(4px);">' +
|
||||
text +
|
||||
'</div>';
|
||||
if (isGoogleLoaded) return html; // Google Maps div bazlı markup
|
||||
return L.divIcon({ className: 'custom-div-icon', html: html, iconSize: [null, null], iconAnchor: [50, 40] });
|
||||
}
|
||||
}
|
||||
|
||||
var tableBody = document.getElementById('vehicleTableBody');
|
||||
if (tableBody) {
|
||||
tableBody.innerHTML = '';
|
||||
var movingCount = 0;
|
||||
var parkedCount = 0;
|
||||
var offlineCount = 0;
|
||||
function selectDriver(vehicle) {
|
||||
activePolylines.forEach(function(p) {
|
||||
if (isGoogleLoaded) p.setMap(null); else map.removeLayer(p);
|
||||
});
|
||||
activeMarkers.forEach(function(m) {
|
||||
if (isGoogleLoaded) m.setMap(null); else map.removeLayer(m);
|
||||
});
|
||||
activePolylines = [];
|
||||
activeMarkers = [];
|
||||
|
||||
vehiclesData.forEach(function(v, idx) {
|
||||
// Sunucudan (Odoo JSON dosyası) gelen rotayı ezici olarak kullan
|
||||
if (serverHistory && serverHistory.length > 0) {
|
||||
v.green_route = serverHistory;
|
||||
var greenPts = [];
|
||||
var redPts = [];
|
||||
|
||||
if (vehicle.green_route && vehicle.green_route.length > 0) {
|
||||
vehicle.green_route.forEach(function(pt) {
|
||||
if (pt && pt.length >= 2) {
|
||||
greenPts.push([pt[0], pt[1]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (vehicle.red_route && vehicle.red_route.length > 0) {
|
||||
vehicle.red_route.forEach(function(pt) {
|
||||
if (pt && pt.length >= 2) {
|
||||
redPts.push([pt[0], pt[1]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Basit bir kural: Hızı 0'dan büyük olanlar HAREKETLİ, 0 olanlar PARK, veri olmayanlar ÇEVRİMDIŞI.
|
||||
var speedStr = "0 km/s";
|
||||
if (v.gps_speed !== undefined) {
|
||||
if (v.gps_speed > 0) {
|
||||
movingCount++;
|
||||
speedStr = v.gps_speed + " km/s";
|
||||
} else {
|
||||
parkedCount++;
|
||||
speedStr = "0 km/s";
|
||||
}
|
||||
if (isGoogleLoaded) {
|
||||
// Google Maps logic...
|
||||
} else {
|
||||
// Test verilerinde gps_speed olmayabilir, fake data üzerinden simüle et
|
||||
var randomStatus = Math.random();
|
||||
if (randomStatus > 0.4) { movingCount++; speedStr = Math.floor(Math.random() * 80 + 20) + " km/s"; }
|
||||
else if (randomStatus > 0.1) { parkedCount++; speedStr = "0 km/s"; }
|
||||
else { offlineCount++; speedStr = "Offline"; }
|
||||
if (!map) return;
|
||||
|
||||
// 1. Alternatif Gri Rotalar
|
||||
var polyAlt1 = L.polyline([
|
||||
[greenPts.length > 0 ? greenPts[0][0]+0.01 : 41.0182, greenPts.length > 0 ? greenPts[0][1]+0.01 : 28.9884],
|
||||
[greenPts.length > 0 ? greenPts[0][0]+0.02 : 41.0282, greenPts.length > 0 ? greenPts[0][1]+0.02 : 28.9984]
|
||||
], { color: '#94a3b8', weight: 4, dashArray: '10, 10', opacity: 0.3 }).addTo(map);
|
||||
|
||||
var polyAlt2 = L.polyline([
|
||||
[greenPts.length > 0 ? greenPts[0][0]-0.01 : 40.9982, greenPts.length > 0 ? greenPts[0][1]-0.01 : 28.9684],
|
||||
[greenPts.length > 0 ? greenPts[0][0]-0.02 : 40.9882, greenPts.length > 0 ? greenPts[0][1]-0.02 : 28.9584]
|
||||
], { color: '#94a3b8', weight: 4, dashArray: '10, 10', opacity: 0.3 }).addTo(map);
|
||||
|
||||
activePolylines.push(polyAlt1, polyAlt2);
|
||||
|
||||
// 2. Yeşil Onaylı Rota
|
||||
if (greenPts.length > 0) {
|
||||
var polyGreen = L.polyline(greenPts, { color: '#10b981', weight: 8, opacity: 0.95, lineCap: 'round', lineJoin: 'round' }).addTo(map);
|
||||
activePolylines.push(polyGreen);
|
||||
}
|
||||
|
||||
// 3. Kırmızı 1 km+ Sapma Çizgisi
|
||||
if (redPts.length > 0) {
|
||||
var polyRed = L.polyline(redPts, { color: '#ef4444', weight: 8, opacity: 0.95, lineCap: 'round', lineJoin: 'round' }).addTo(map);
|
||||
activePolylines.push(polyRed);
|
||||
}
|
||||
|
||||
var allPts = greenPts.concat(redPts);
|
||||
if (allPts.length > 0) {
|
||||
// Kırmızı Yol Üzerindeki "1.5 km Sapma" Çağrı Kutucuğu
|
||||
if (redPts.length > 0) {
|
||||
var midRedIdx = Math.floor(redPts.length / 2);
|
||||
var mRedCallout = L.marker(redPts[midRedIdx], { icon: createCalloutIcon(vehicle.deviation_label, '#ef4444') }).addTo(map);
|
||||
activeMarkers.push(mRedCallout);
|
||||
}
|
||||
|
||||
// Rotada Gerçek Zamanlı Canlı Hareket Eden Araç Animasyonunu Başlat
|
||||
animateMovingVehicle(allPts, vehicle);
|
||||
|
||||
var group = new L.featureGroup([polyAlt1, polyAlt2].concat(activePolylines));
|
||||
map.fitBounds(group.getBounds(), { padding: [50, 50] });
|
||||
}
|
||||
}
|
||||
|
||||
var tr = document.createElement('tr');
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.style.transition = 'all 0.2s ease';
|
||||
tr.style.borderBottom = '1px solid rgba(255,255,255,0.05)';
|
||||
// Yüzen Detay Kartını Güncelle
|
||||
var overlayEl = document.getElementById('driver_info_overlay');
|
||||
if (overlayEl) {
|
||||
var badgeBg = vehicle.is_violation ? 'rgba(239, 68, 68, 0.25)' : (vehicle.is_manager_approved ? 'rgba(56, 189, 248, 0.25)' : 'rgba(16, 185, 129, 0.25)');
|
||||
var badgeBorder = vehicle.is_violation ? '#ef4444' : (vehicle.is_manager_approved ? '#38bdf8' : '#10b981');
|
||||
var badgeText = vehicle.is_violation ? '#ef4444' : (vehicle.is_manager_approved ? '#38bdf8' : '#10b981');
|
||||
var badgeTitle = vehicle.is_violation
|
||||
? vehicle.badge_violation
|
||||
: (vehicle.is_manager_approved ? vehicle.badge_approved : vehicle.badge_ok);
|
||||
|
||||
var isRev = v.is_violation;
|
||||
var badgeStyle = isRev
|
||||
? 'background: rgba(239, 68, 68, 0.2); color: #ef4444; border: 1px solid rgba(239, 68, 68, 0.4);'
|
||||
: (v.is_manager_approved
|
||||
? 'background: rgba(56, 189, 248, 0.2); color: #38bdf8; border: 1px solid rgba(56, 189, 248, 0.4);'
|
||||
: 'background: rgba(16, 185, 129, 0.2); color: #10b981; border: 1px solid rgba(16, 185, 129, 0.4);');
|
||||
var statusLabel = isRev ? (v.badge_violation) : (v.is_manager_approved ? v.badge_approved : v.badge_ok);
|
||||
overlayEl.style.display = 'block';
|
||||
overlayEl.innerHTML =
|
||||
'<div style="background: rgba(15, 23, 42, 0.95); border: 1px solid rgba(255,255,255,0.05); padding: 24px; border-radius: 16px; box-shadow: 0 25px 50px -12px rgba(0,0,0,0.5); width: 340px; backdrop-filter: blur(12px);">' +
|
||||
'<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px;">' +
|
||||
'<div>' +
|
||||
'<h3 style="color: white; margin: 0 0 6px 0; font-size: 18px; font-weight: 700; letter-spacing: -0.5px;">- ' + vehicle.driver_name + '</h3>' +
|
||||
'<p style="color: #94a3b8; margin: 0; font-size: 13px; font-weight: 400;">' + vehicle.license_plate + ' (' + vehicle.brand_model + ')</p>' +
|
||||
'</div>' +
|
||||
'<div style="background: ' + badgeBg + '; border: 1px solid ' + badgeBorder + '; padding: 8px 12px; border-radius: 12px; text-align: center;">' +
|
||||
'<div style="color: ' + badgeText + '; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px;">' + badgeTitle + '</div>' +
|
||||
'<div style="color: ' + badgeText + '; font-size: 16px; font-weight: 800;">' + (vehicle.violation_score || 100) + '</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<button style="width: 100%; padding: 12px; background: rgba(16, 185, 129, 0.1); border: 1px solid rgba(16, 185, 129, 0.3); color: #10b981; border-radius: 10px; font-weight: 600; font-size: 13px; margin-bottom: 20px; cursor: pointer; transition: all 0.2s ease;">' +
|
||||
'Sürücüye Otonom Mesaj Gönder' +
|
||||
'</button>' +
|
||||
|
||||
tr.innerHTML =
|
||||
'<td style="padding: 10px;">' +
|
||||
'<strong style="color: white; font-size: 13px;">' + (v.driver_tag_str || '') + ' - ' + v.driver_name + '</strong><br/>' +
|
||||
'<span style="color: #94a3b8; font-size: 11px;">' + v.license_plate + '</span>' +
|
||||
'</td>' +
|
||||
'<td style="padding: 10px;">' +
|
||||
'<span style="font-size: 13px; font-weight: 700; color: #38bdf8;">' + speedStr + '</span>' +
|
||||
'</td>' +
|
||||
'<td style="padding: 10px;">' +
|
||||
'<span style="' + badgeStyle + ' padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: bold; display: inline-block;">' +
|
||||
statusLabel +
|
||||
'</span>' +
|
||||
'</td>';
|
||||
'<div style="font-size: 12px; line-height: 1.6; color: #cbd5e1;">' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Personel Evi / Konaklama:</span>' +
|
||||
'<strong style="color: #f1f5f9; font-size: 11px;">' + (vehicle.driver_home_address || 'Bilinmiyor') + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Başlangıç Noktası:</span>' +
|
||||
'<strong style="color: white; font-size: 11px;">' + (vehicle.start_location || 'Canlı GPS Konumu') + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Ulaşım Hedefi:</span>' +
|
||||
'<strong style="color: #38bdf8; font-size: 11px;">' + (vehicle.destination || 'Gerçek Zamanlı Aktif İzleme') + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Planlanan / Gidilen Mesafe:</span>' +
|
||||
'<span>' + vehicle.planned_km + ' KM / <strong>' + vehicle.driven_km + ' KM</strong></span>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Rota Sapma Durumu:</span>' +
|
||||
'<strong style="color: ' + (vehicle.is_violation ? '#ef4444' : (vehicle.is_manager_approved ? '#38bdf8' : '#10b981')) + ';">' + vehicle.deviation_label + '</strong>' +
|
||||
'</div>' +
|
||||
'<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">' +
|
||||
'<span style="color: #94a3b8;">Şirket Politikası:</span>' +
|
||||
'<span style="color: ' + (vehicle.has_free_use ? '#38bdf8' : '#f59e0b') + '; font-weight: 600;">' + vehicle.policy_desc + '</span>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
}
|
||||
|
||||
tr.addEventListener('click', function() {
|
||||
var children = tableBody.children;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
children[i].style.background = 'transparent';
|
||||
var tableBody = document.getElementById('vehicleTableBody');
|
||||
if (tableBody) {
|
||||
tableBody.innerHTML = '';
|
||||
var movingCount = 0;
|
||||
var parkedCount = 0;
|
||||
var offlineCount = 0;
|
||||
|
||||
vehiclesData.forEach(function(v, idx) {
|
||||
if (serverHistory && serverHistory.length > 0) {
|
||||
v.green_route = serverHistory;
|
||||
}
|
||||
|
||||
var speedStr = "0 km/s";
|
||||
if (v.gps_speed !== undefined) {
|
||||
if (v.gps_speed > 0) {
|
||||
movingCount++;
|
||||
speedStr = v.gps_speed + " km/s";
|
||||
} else {
|
||||
parkedCount++;
|
||||
speedStr = "0 km/s";
|
||||
}
|
||||
} else {
|
||||
var randomStatus = Math.random();
|
||||
if (randomStatus > 0.4) { movingCount++; speedStr = Math.floor(Math.random() * 80 + 20) + " km/s"; }
|
||||
else if (randomStatus > 0.1) { parkedCount++; speedStr = "0 km/s"; }
|
||||
else { offlineCount++; speedStr = "Offline"; }
|
||||
}
|
||||
|
||||
var tr = document.createElement('tr');
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.style.transition = 'all 0.2s ease';
|
||||
tr.style.borderBottom = '1px solid rgba(255,255,255,0.05)';
|
||||
|
||||
var isRev = v.is_violation;
|
||||
var badgeStyle = isRev
|
||||
? 'background: rgba(239, 68, 68, 0.2); color: #ef4444; border: 1px solid rgba(239, 68, 68, 0.4);'
|
||||
: (v.is_manager_approved
|
||||
? 'background: rgba(56, 189, 248, 0.2); color: #38bdf8; border: 1px solid rgba(56, 189, 248, 0.4);'
|
||||
: 'background: rgba(16, 185, 129, 0.2); color: #10b981; border: 1px solid rgba(16, 185, 129, 0.4);');
|
||||
var statusLabel = isRev ? (v.badge_violation) : (v.is_manager_approved ? v.badge_approved : v.badge_ok);
|
||||
|
||||
tr.innerHTML =
|
||||
'<td style="padding: 10px;">' +
|
||||
'<strong style="color: white; font-size: 13px;">' + (v.driver_tag_str || '') + ' - ' + v.driver_name + '</strong><br/>' +
|
||||
'<span style="color: #94a3b8; font-size: 11px;">' + v.license_plate + '</span>' +
|
||||
'</td>' +
|
||||
'<td style="padding: 10px;">' +
|
||||
'<span style="font-size: 13px; font-weight: 700; color: #38bdf8;">' + speedStr + '</span>' +
|
||||
'</td>' +
|
||||
'<td style="padding: 10px;">' +
|
||||
'<span style="' + badgeStyle + ' padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: bold; display: inline-block;">' +
|
||||
statusLabel +
|
||||
'</span>' +
|
||||
'</td>';
|
||||
|
||||
tr.addEventListener('click', function() {
|
||||
var children = tableBody.children;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
children[i].style.background = 'transparent';
|
||||
}
|
||||
tr.style.background = 'rgba(56, 189, 248, 0.2)';
|
||||
selectDriver(v);
|
||||
});
|
||||
|
||||
tableBody.appendChild(tr);
|
||||
|
||||
if (idx === 0) {
|
||||
tr.style.background = 'rgba(56, 189, 248, 0.2)';
|
||||
setTimeout(function() { selectDriver(v); }, 300);
|
||||
}
|
||||
tr.style.background = 'rgba(56, 189, 248, 0.2)';
|
||||
selectDriver(v);
|
||||
});
|
||||
|
||||
tableBody.appendChild(tr);
|
||||
var mMoving = document.getElementById('metric_moving');
|
||||
if (mMoving) mMoving.textContent = movingCount;
|
||||
|
||||
var mParked = document.getElementById('metric_parked');
|
||||
if (mParked) mParked.textContent = parkedCount;
|
||||
|
||||
var mOffline = document.getElementById('metric_offline');
|
||||
if (mOffline) mOffline.textContent = offlineCount;
|
||||
}
|
||||
|
||||
if (idx === 0) {
|
||||
tr.style.background = 'rgba(56, 189, 248, 0.2)';
|
||||
setTimeout(function() { selectDriver(v); }, 300);
|
||||
}
|
||||
});
|
||||
|
||||
// Metrikleri DOM'a yaz
|
||||
var mMoving = document.getElementById('metric_moving');
|
||||
if (mMoving) mMoving.textContent = movingCount;
|
||||
|
||||
var mParked = document.getElementById('metric_parked');
|
||||
if (mParked) mParked.textContent = parkedCount;
|
||||
|
||||
var mOffline = document.getElementById('metric_offline');
|
||||
if (mOffline) mOffline.textContent = offlineCount;
|
||||
}
|
||||
|
||||
var miniChartEl = document.getElementById('miniChart');
|
||||
if (miniChartEl) {
|
||||
var ctx = miniChartEl.getContext('2d');
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz'],
|
||||
datasets: [{
|
||||
label: 'KM Trend',
|
||||
data: [2200, 2500, 2100, 2800, 3100, 2700],
|
||||
borderColor: '#00f2fe',
|
||||
backgroundColor: 'rgba(0, 242, 254, 0.05)',
|
||||
borderWidth: 2,
|
||||
tension: 0.4,
|
||||
fill: true
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: { legend: { display: false } },
|
||||
scales: {
|
||||
x: { grid: { display: false }, ticks: { color: '#94a3b8' } },
|
||||
y: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#94a3b8' } }
|
||||
var miniChartEl = document.getElementById('miniChart');
|
||||
if (miniChartEl) {
|
||||
var ctx = miniChartEl.getContext('2d');
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz'],
|
||||
datasets: [{
|
||||
label: 'KM Trend',
|
||||
data: [2200, 2500, 2100, 2800, 3100, 2700],
|
||||
borderColor: '#00f2fe',
|
||||
backgroundColor: 'rgba(0, 242, 254, 0.05)',
|
||||
borderWidth: 2,
|
||||
tension: 0.4,
|
||||
fill: true
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: { legend: { display: false } },
|
||||
scales: {
|
||||
x: { grid: { display: false }, ticks: { color: '#94a3b8' } },
|
||||
y: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#94a3b8' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function animateMovingVehicle(routePts, vehicle) {
|
||||
if (!routePts || routePts.length === 0) return;
|
||||
var endPt = routePts[routePts.length - 1];
|
||||
|
||||
var mIcon = L.divIcon({
|
||||
className: 'custom-vehicle-marker',
|
||||
html: '<div style="background: white; border-radius: 50%; padding: 4px; box-shadow: 0 0 15px rgba(56, 189, 248, 0.8); border: 2px solid #38bdf8;">' +
|
||||
'<i class="fa-solid fa-car" style="color: #0f172a; font-size: 14px;"></i>' +
|
||||
'</div>',
|
||||
iconSize: [28, 28],
|
||||
iconAnchor: [14, 14]
|
||||
});
|
||||
|
||||
var mVehicle = L.marker(endPt, { icon: mIcon }).addTo(map);
|
||||
activeMarkers.push(mVehicle);
|
||||
|
||||
if (routePts.length > 1) {
|
||||
var currentIndex = 0;
|
||||
function moveStep() {
|
||||
if (currentIndex >= routePts.length) {
|
||||
currentIndex = 0; // Başa dön (Loop animasyon - test için)
|
||||
}
|
||||
mVehicle.setLatLng(routePts[currentIndex]);
|
||||
currentIndex++;
|
||||
setTimeout(moveStep, 1000);
|
||||
}
|
||||
moveStep();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} catch (globalError) {
|
||||
alert("Harita Yüklenirken Hata Oluştu:\n" + globalError.toString() + "\nLütfen sayfayı F5 ile yenileyin.");
|
||||
console.error(globalError);
|
||||
}
|
||||
|
||||
// --- 10 Saniyede Bir Sayfayı Tam Ekran Yenileyerek Görüntüyü Güncelleyen Kod ---
|
||||
setInterval(function() {
|
||||
window.location.reload();
|
||||
}, 15000);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user