-
@@ -95,11 +90,9 @@
Navegación GPS
-
Calculando ruta...
-
-
-
@@ -149,15 +140,24 @@
let localServices = [];
let systemStatuses = [];
-
let currentWeekStart = new Date();
let selectedDateStr = "";
+ // Helper seguro para iconos
+ function safeLoadIcons() {
+ try { if (typeof lucide !== 'undefined') lucide.createIcons(); }
+ catch(e) { console.warn("Iconos no cargados aún"); }
+ }
+
+ // Helper seguro para fechas
function toISODate(dateObj) {
- const y = dateObj.getFullYear();
- const m = String(dateObj.getMonth() + 1).padStart(2, '0');
- const d = String(dateObj.getDate()).padStart(2, '0');
- return `${y}-${m}-${d}`;
+ try {
+ if (!dateObj || isNaN(dateObj)) return "";
+ const y = dateObj.getFullYear();
+ const m = String(dateObj.getMonth() + 1).padStart(2, '0');
+ const d = String(dateObj.getDate()).padStart(2, '0');
+ return `${y}-${m}-${d}`;
+ } catch(e) { return ""; }
}
function getMonday(d) {
@@ -172,46 +172,52 @@
window.location.href = "index.html"; return;
}
- lucide.createIcons();
+ safeLoadIcons();
- const today = new Date();
- currentWeekStart = getMonday(today);
- selectedDateStr = toISODate(today);
-
- buildWeekCalendar();
- loadStatuses();
- refreshData();
+ try {
+ const today = new Date();
+ currentWeekStart = getMonday(today);
+ selectedDateStr = toISODate(today);
+ buildWeekCalendar();
+ loadStatuses();
+ refreshData();
+ } catch(error) {
+ alert("Error iniciando calendario: " + error.message);
+ }
});
function buildWeekCalendar() {
- const strip = document.getElementById('weekStrip');
- strip.innerHTML = '';
-
- const monthName = currentWeekStart.toLocaleDateString('es-ES', { month: 'long', year: 'numeric' });
- document.getElementById('monthYearDisplay').innerText = monthName;
-
- for(let i = 0; i < 7; i++) {
- let d = new Date(currentWeekStart);
- d.setDate(currentWeekStart.getDate() + i);
+ try {
+ const strip = document.getElementById('weekStrip');
+ strip.innerHTML = '';
- const isoDate = toISODate(d);
- const dayName = d.toLocaleDateString('es-ES', { weekday: 'short' }).replace('.', '');
- const dayNum = d.getDate();
+ const monthName = currentWeekStart.toLocaleDateString('es-ES', { month: 'long', year: 'numeric' });
+ document.getElementById('monthYearDisplay').innerText = monthName;
+
+ for(let i = 0; i < 7; i++) {
+ let d = new Date(currentWeekStart);
+ d.setDate(currentWeekStart.getDate() + i);
+
+ const isoDate = toISODate(d);
+ const dayName = d.toLocaleDateString('es-ES', { weekday: 'short' }).replace('.', '');
+ const dayNum = d.getDate();
- const isSelected = isoDate === selectedDateStr;
- const baseClass = isSelected ? 'day-active' : 'day-inactive';
+ const isSelected = isoDate === selectedDateStr;
+ const baseClass = isSelected ? 'day-active' : 'day-inactive';
- strip.innerHTML += `
-
- `;
- }
- if(localServices.length > 0) updateBadges();
+ strip.innerHTML += `
+
+ `;
+ }
+ if(localServices.length > 0) updateBadges();
+ safeLoadIcons();
+ } catch(e) { console.error(e); }
}
function changeWeek(offsetWeeks) {
@@ -246,18 +252,17 @@
const data = await res.json();
if (data.ok) {
- // Ahora SÍ permitimos los SYSTEM_BLOCK y servicios con fecha
localServices = data.services.filter(s => {
const raw = s.raw_data || {};
- const hasDate = raw.scheduled_date && raw.scheduled_date.trim() !== "";
- return hasDate;
+ const dateStr = String(raw.scheduled_date || "").trim();
+ return dateStr !== "";
});
buildWeekCalendar();
renderServices();
}
} catch (e) {
- alert("Error de conexión");
+ console.error(e);
} finally {
document.getElementById('loader').classList.add('hidden');
document.getElementById('dayTitle').classList.remove('hidden');
@@ -270,7 +275,7 @@
const counts = {};
localServices.forEach(s => {
- const date = (s.raw_data.scheduled_date || "").trim();
+ const date = String(s.raw_data.scheduled_date || "").trim();
if(date) counts[date] = (counts[date] || 0) + 1;
});
@@ -281,75 +286,74 @@
}
function renderServices() {
- const container = document.getElementById('servicesList');
- const displayDate = selectedDateStr.split('-').reverse().join('/');
- document.getElementById('dayTitle').innerText = `Servicios del ${displayDate}`;
+ try {
+ const container = document.getElementById('servicesList');
+ const displayDate = selectedDateStr.split('-').reverse().join('/');
+ document.getElementById('dayTitle').innerText = `Servicios del ${displayDate}`;
- const dayServices = localServices.filter(s => {
- const d = (s.raw_data.scheduled_date || "").trim();
- return d === selectedDateStr;
- });
+ const dayServices = localServices.filter(s => {
+ const d = String(s.raw_data.scheduled_date || "").trim();
+ return d === selectedDateStr;
+ });
- dayServices.sort((a, b) => {
- const timeA = a.raw_data.scheduled_time || "23:59";
- const timeB = b.raw_data.scheduled_time || "23:59";
- return timeA.localeCompare(timeB);
- });
+ // Ordenación segura a prueba de fallos de formato
+ dayServices.sort((a, b) => {
+ const timeA = String(a.raw_data.scheduled_time || "23:59");
+ const timeB = String(b.raw_data.scheduled_time || "23:59");
+ return timeA.localeCompare(timeB);
+ });
- if (dayServices.length === 0) {
- container.innerHTML = `
-
-
-
Día Libre
-
No tienes citas agendadas para hoy.
-
`;
- lucide.createIcons();
- return;
- }
-
- container.innerHTML = dayServices.map(s => {
- const raw = s.raw_data || {};
- const time = raw.scheduled_time || "A convenir";
-
- // RENDERIZADO ESPECIAL PARA BLOQUEOS
- if (s.provider === 'SYSTEM_BLOCK') {
- const desc = raw["Descripción"] || "Operario no disponible";
- return `
-
- `;
+ if (dayServices.length === 0) {
+ container.innerHTML = `
+
+
+
Día Libre
+
No tienes citas agendadas para hoy.
+
`;
+ safeLoadIcons();
+ return;
}
- // RENDERIZADO NORMAL PARA REPARACIONES
- const name = raw["Nombre Cliente"] || raw["CLIENTE"] || "Asegurado";
- const addr = raw["Dirección"] || "Sin dirección";
- const pop = raw["Población"] || "";
- const isUrgent = s.is_urgent;
+ container.innerHTML = dayServices.map(s => {
+ const raw = s.raw_data || {};
+ const time = raw.scheduled_time || "A convenir";
+
+ if (s.provider === 'SYSTEM_BLOCK') {
+ const desc = raw["Descripción"] || "Operario no disponible";
+ return `
+
`;
+ }
- return `
-
- `;
- }).join('');
+ const name = raw["Nombre Cliente"] || raw["CLIENTE"] || "Asegurado";
+ const addr = raw["Dirección"] || "Sin dirección";
+ const pop = raw["Población"] || "";
+ const isUrgent = s.is_urgent;
- lucide.createIcons();
+ return `
+
`;
+ }).join('');
+
+ safeLoadIcons();
+ } catch(e) { console.error("Render error:", e); }
}
// ==========================================
@@ -370,12 +374,10 @@
const fullAddress = `${raw["Dirección"] || ""}, ${raw["Código Postal"] || ""} ${raw["Población"] || ""}`;
document.getElementById('detAddress').innerText = fullAddress;
- // Mostrar modal
const modal = document.getElementById('serviceModal');
modal.classList.remove('hidden');
setTimeout(() => modal.classList.remove('translate-y-full'), 10);
- // Iniciar GPS automático
calculateDistance(fullAddress);
}
@@ -383,57 +385,86 @@
const modal = document.getElementById('serviceModal');
modal.classList.add('translate-y-full');
setTimeout(() => modal.classList.add('hidden'), 300);
-
- // Reset GPS view
document.getElementById('gpsLoading').classList.remove('hidden');
document.getElementById('gpsResult').classList.add('hidden');
}
- // --- SISTEMA GPS INTELIGENTE ---
async function calculateDistance(destAddress) {
- if(!navigator.geolocation) {
- showGpsError("GPS no soportado"); return;
- }
+ if(!navigator.geolocation) { showGpsError("GPS no soportado"); return; }
- // 1. Pedir ubicación al móvil
navigator.geolocation.getCurrentPosition(async (position) => {
const userLat = position.coords.latitude;
const userLon = position.coords.longitude;
-
try {
- // 2. Traducir la dirección del cliente a coordenadas (API Gratuita OSM)
const res = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(destAddress + ', España')}`);
const data = await res.json();
if (data && data.length > 0) {
const destLat = parseFloat(data[0].lat);
const destLon = parseFloat(data[0].lon);
-
- // 3. Fórmula Haversine (Distancia en línea recta)
- const R = 6371; // Radio de la tierra en KM
+ const R = 6371;
const dLat = (destLat - userLat) * Math.PI / 180;
const dLon = (destLon - userLon) * Math.PI / 180;
- const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
- Math.cos(userLat * Math.PI / 180) * Math.cos(destLat * Math.PI / 180) *
- Math.sin(dLon/2) * Math.sin(dLon/2);
+ const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(userLat * Math.PI / 180) * Math.cos(destLat * Math.PI / 180) * Math.sin(dLon/2) * Math.sin(dLon/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const distanceKm = R * c;
+ const mins = Math.round((distanceKm / 35) * 60) + 5;
- // Estimación de tiempo (Asumiendo 35 km/h media en ciudad)
- const mins = Math.round((distanceKm / 35) * 60) + 5; // +5 mins de margen de aparcamiento
-
- // Pintar en pantalla
document.getElementById('gpsLoading').classList.add('hidden');
document.getElementById('gpsResult').classList.remove('hidden');
document.getElementById('gpsKm').innerText = distanceKm.toFixed(1);
document.getElementById('gpsMins').innerText = mins;
+ } else { showGpsError("Dirección no encontrada en el mapa"); }
+ } catch(e) { showGpsError("Error de red GPS"); }
+ }, (err) => { showGpsError("Permiso de GPS denegado"); }, { enableHighAccuracy: true });
+ }
- } else {
- showGpsError("Dirección no encontrada en el mapa");
- }
- } catch(e) {
- showGpsError("Error de red GPS");
- }
- }, (err) => {
- showGpsError("Permiso de GPS denegado");
- }, { enableHigh
\ No newline at end of file
+ function showGpsError(msg) {
+ document.getElementById('gpsLoading').innerHTML = `
${msg}`;
+ safeLoadIcons();
+ }
+
+ async function quickUpdate(action) {
+ if(!currentServiceId) return;
+ let searchWord = ""; let confirmMsg = "";
+ if(action === 'camino') { searchWord = "camino"; confirmMsg = "¿Avisar al cliente que estás de camino?"; }
+ if(action === 'trabajando') { searchWord = "trabaja"; confirmMsg = "¿Confirmar llegada e iniciar reparación?"; }
+ if(action === 'finalizado') { searchWord = "finaliza"; confirmMsg = "¿Cerrar expediente definitivamente?"; }
+ if(action === 'encuesta') { searchWord = "finaliza"; confirmMsg = "¿Finalizar y mandar encuesta al cliente?"; }
+
+ if(!confirm(confirmMsg)) return;
+
+ const st = systemStatuses.find(s => s.name.toLowerCase().includes(searchWord));
+ if(!st) return alert("Error: El estado no existe en la base de datos.");
+
+ try {
+ showToast("Procesando...");
+ const res = await fetch(`${API_URL}/providers/scraped/${currentServiceId}`, {
+ method: 'PUT',
+ headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` },
+ body: JSON.stringify({ status_operativo: st.id })
+ });
+
+ if(res.ok) {
+ showToast("Estado actualizado correctamente");
+ closeModal();
+ refreshData();
+ } else { alert("Error guardando estado"); }
+ } catch (e) { alert("Error de conexión al servidor"); }
+ }
+
+ function showToast(msg) {
+ const t = document.getElementById('toast');
+ document.getElementById('toastMsg').innerText = msg;
+ t.classList.remove('opacity-0', 'pointer-events-none', '-translate-y-10');
+ t.classList.add('translate-y-0');
+ setTimeout(() => {
+ t.classList.add('opacity-0', 'pointer-events-none', '-translate-y-10');
+ t.classList.remove('translate-y-0');
+ }, 2500);
+ }
+
+ function logout() { localStorage.clear(); window.location.href = "index.html"; }
+
+