-
+
+
Guardado
@@ -195,7 +170,7 @@
function safeLoadIcons() {
try { if (typeof lucide !== 'undefined') lucide.createIcons(); }
- catch(e) { console.warn("Iconos no cargados"); }
+ catch(e) { }
}
function toISODate(dateObj) {
@@ -220,17 +195,13 @@
window.location.href = "index.html"; return;
}
safeLoadIcons();
-
- try {
- const today = new Date();
- currentWeekStart = getMonday(today);
- selectedDateStr = toISODate(today);
- buildWeekCalendar();
-
- loadStatuses();
- await loadGuilds();
- refreshData();
- } catch(error) { alert("Error iniciando calendario"); }
+ const today = new Date();
+ currentWeekStart = getMonday(today);
+ selectedDateStr = toISODate(today);
+ buildWeekCalendar();
+ loadStatuses();
+ await loadGuilds();
+ refreshData();
});
async function loadGuilds() {
@@ -242,41 +213,31 @@
}
function buildWeekCalendar() {
- try {
- 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);
-
- 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';
-
- strip.innerHTML += `
-
- `;
- }
- if(localServices.length > 0) updateBadges();
- safeLoadIcons();
- } catch(e) {}
+ 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);
+ const isoDate = toISODate(d);
+ const dayName = d.toLocaleDateString('es-ES', { weekday: 'short' }).replace('.', '');
+ const dayNum = d.getDate();
+ const isSelected = isoDate === selectedDateStr;
+ strip.innerHTML += `
+
`;
+ }
+ updateBadges();
+ safeLoadIcons();
}
- function changeWeek(offsetWeeks) {
- currentWeekStart.setDate(currentWeekStart.getDate() + (offsetWeeks * 7));
+ function changeWeek(offset) {
+ currentWeekStart.setDate(currentWeekStart.getDate() + (offset * 7));
selectedDateStr = toISODate(currentWeekStart);
buildWeekCalendar();
renderServices();
@@ -299,18 +260,13 @@
async function refreshData() {
document.getElementById('servicesList').classList.add('hidden');
document.getElementById('loader').classList.remove('hidden');
-
try {
- const res = await fetch(`${API_URL}/services/active`, {
- headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
- });
+ const res = await fetch(`${API_URL}/services/active`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
const data = await res.json();
-
if (data.ok) {
localServices = data.services.filter(s => {
const raw = s.raw_data || {};
- const dateStr = String(raw.scheduled_date || "").trim();
- return dateStr !== "";
+ return String(raw.scheduled_date || "").trim() !== "";
});
buildWeekCalendar();
renderServices();
@@ -337,92 +293,48 @@
}
function renderServices() {
- try {
- const container = document.getElementById('servicesList');
- const displayDate = selectedDateStr.split('-').reverse().join('/');
- document.getElementById('dayTitle').innerText = `Servicios del ${displayDate}`;
+ const container = document.getElementById('servicesList');
+ const displayDate = selectedDateStr.split('-').reverse().join('/');
+ document.getElementById('dayTitle').innerText = `DÍA ${displayDate}`;
- const dayServices = localServices.filter(s => {
- const d = String(s.raw_data.scheduled_date || "").trim();
- return d === selectedDateStr;
- });
+ const dayServices = localServices.filter(s => String(s.raw_data.scheduled_date || "").trim() === selectedDateStr);
+ dayServices.sort((a, b) => String(a.raw_data.scheduled_time || "23:59").localeCompare(String(b.raw_data.scheduled_time || "23:59")));
- 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 de Descanso
No tienes servicios para este día.
`;
+ safeLoadIcons(); return;
+ }
- if (dayServices.length === 0) {
- container.innerHTML = `
-
-
-
Día Libre
-
No tienes citas agendadas para hoy.
-
`;
- safeLoadIcons();
- return;
+ container.innerHTML = dayServices.map(s => {
+ const raw = s.raw_data || {};
+ const time = raw.scheduled_time || "--:--";
+ if (s.provider === 'SYSTEM_BLOCK') {
+ return `
${time}
BLOQUEADO
${raw["Descripción"] || ""}
`;
}
- 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 `
-
`;
- }
+ const name = raw["Nombre Cliente"] || raw["CLIENTE"] || "Asegurado";
+ const addr = raw["Dirección"] || "---";
+ let compShort = (raw["Compañía"] || "Particular").split('-')[0].trim().substring(0, 15);
+ const guildObj = systemGuilds.find(g => String(g.id) === String(s.guild_id || raw.guild_id));
- 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;
-
- let compRaw = raw["Compañía"] || raw["COMPAÑIA"] || raw["Procedencia"] || "Particular";
- let compShort = compRaw.split('-')[0].trim().substring(0, 15);
- if(compRaw.includes("MULTI")) compShort = "MULTIASISTENCIA";
- if(compRaw.includes("HOME")) compShort = "HOMESERVE";
-
- const rawGuildId = s.guild_id || raw.guild_id || raw['guild_id'];
- const guildObj = systemGuilds.find(g => String(g.id) === String(rawGuildId));
- const guildName = guildObj ? guildObj.name : "Reparación";
-
- return `
-
- ${isUrgent ? '
Urgente
' : ''}
-
-
-
-
${time}
+ return `
+
+
`;
+ }).join('');
+ safeLoadIcons();
}
let currentServiceId = null;
@@ -434,166 +346,104 @@
currentServiceId = id;
document.getElementById('detId').value = s.id;
- document.getElementById('modTime').innerText = raw.scheduled_time || "S/H";
- document.getElementById('detRef').innerText = s.service_ref || "S/R";
-
- let compRaw = raw["Compañía"] || raw["COMPAÑIA"] || raw["Procedencia"] || "Particular";
- document.getElementById('detCompany').innerText = compRaw;
-
+ document.getElementById('modTime').innerText = raw.scheduled_time || "--:--";
+ document.getElementById('detRef').innerText = `#${s.service_ref || "---"}`;
+ document.getElementById('detCompany').innerText = raw["Compañía"] || "Particular";
document.getElementById('detName').innerText = raw["Nombre Cliente"] || "Asegurado";
-
const fullAddress = `${raw["Dirección"] || ""}, ${raw["Código Postal"] || ""} ${raw["Población"] || ""}`;
document.getElementById('detAddress').innerText = fullAddress;
- // Extraer teléfono
const rawPhone = raw["Teléfono"] || raw["TELEFONOS"] || raw["TELEFONO"] || "";
- const matchPhone = rawPhone.toString().match(/[6789]\d{8}/);
+ const matchPhone = String(rawPhone).match(/[6789]\d{8}/);
document.getElementById('detPhoneRaw').value = matchPhone ? matchPhone[0] : "";
- // Urgencia
- const isUrgent = s.is_urgent;
const banner = document.getElementById('urgentBanner');
- if (isUrgent) banner.classList.remove('hidden');
+ if (s.is_urgent) banner.classList.remove('hidden');
else banner.classList.add('hidden');
- // Descripción principal
- let desc = raw["Descripción"] || raw["DESCRIPCION"] || "No hay notas de avería.";
- document.getElementById('detDesc').innerHTML = desc.replace(/\n/g, '
');
+ document.getElementById('detDesc').innerHTML = (raw["Descripción"] || raw["DESCRIPCION"] || "Sin notas.").replace(/\n/g, '
');
- // VOLCAR TODOS LOS DATOS EXTRA
- const detailsContainer = document.getElementById('detExtraInfo');
+ const extraContainer = document.getElementById('extraDataBox');
let detailsHtml = '';
-
const skipKeys = ["Nombre Cliente", "CLIENTE", "Dirección", "DOMICILIO", "Población", "POBLACION-PROVINCIA", "scheduled_date", "scheduled_time", "status_operativo", "assigned_to", "guild_id", "Código Postal", "assigned_to_name", "Descripción", "DESCRIPCION", "Compañía", "COMPAÑIA"];
for(let key in raw) {
if(skipKeys.includes(key)) continue;
-
let val = raw[key];
- if(typeof val === 'object') val = JSON.stringify(val);
- if(!val || val.trim() === "") continue;
+ // ARREGLO TYPEERROR: Verificamos si val es string antes del trim
+ let valStr = String(val || "");
+ if(valStr.trim() === "") continue;
- detailsHtml += `
-
- ${key}
- ${val}
-
- `;
+ detailsHtml += `
${key}${valStr}
`;
}
-
- if(detailsHtml === '') detailsHtml = '
No hay más datos proporcionados.
';
- detailsContainer.innerHTML = detailsHtml;
+ extraContainer.innerHTML = detailsHtml || '
Sin datos adicionales.
';
const modal = document.getElementById('serviceModal');
- modal.classList.remove('hidden');
+ modal.style.display = 'flex';
setTimeout(() => modal.classList.remove('translate-y-full'), 10);
-
calculateDistance(fullAddress);
}
function closeModal() {
const modal = document.getElementById('serviceModal');
modal.classList.add('translate-y-full');
- setTimeout(() => modal.classList.add('hidden'), 300);
+ setTimeout(() => modal.style.display = 'none', 300);
document.getElementById('gpsLoading').classList.remove('hidden');
document.getElementById('gpsResult').classList.add('hidden');
- document.getElementById('extraDataBox').classList.add('hidden'); // Resetear caja extra
}
- function callClient() {
- const phone = document.getElementById('detPhoneRaw').value;
- if (phone) window.location.href = `tel:+34${phone}`;
- else alert("No hay un teléfono válido guardado.");
- }
+ function callClient() { const p = document.getElementById('detPhoneRaw').value; if (p) window.location.href = `tel:+34${p}`; else alert("Sin teléfono"); }
+ function openWhatsApp() { const p = document.getElementById('detPhoneRaw').value; if (p) window.open(`https://wa.me/34${p}`, '_blank'); else alert("Sin teléfono"); }
+ function openMaps() { const a = document.getElementById('detAddress').innerText; if (a) window.open(`maps://?q=${encodeURIComponent(a)}`, '_blank'); }
- function openWhatsApp() {
- const phone = document.getElementById('detPhoneRaw').value;
- if (phone) window.open(`https://wa.me/34${phone}`, '_blank');
- else alert("No hay un teléfono válido guardado.");
- }
-
- function openMaps() {
- const address = document.getElementById('detAddress').innerText;
- if (address) {
- const encodedAddr = encodeURIComponent(address);
- // Intenta abrir en la app de Apple Maps o Google Maps nativa del movil
- window.open(`maps://?q=${encodedAddr}`, '_blank');
- // Fallback a web si falla
- setTimeout(() => { window.open(`https://maps.google.com/?q=${encodedAddr}`, '_blank'); }, 500);
- }
- }
-
- async function calculateDistance(destAddress) {
- if(!navigator.geolocation) { showGpsError("GPS no soportado"); return; }
- navigator.geolocation.getCurrentPosition(async (position) => {
- const userLat = position.coords.latitude;
- const userLon = position.coords.longitude;
+ async function calculateDistance(dest) {
+ if(!navigator.geolocation) { showGpsError("No GPS"); return; }
+ navigator.geolocation.getCurrentPosition(async (pos) => {
+ const lat = pos.coords.latitude; const lon = pos.coords.longitude;
try {
- const res = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(destAddress + ', España')}`);
+ const res = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(dest + ', España')}`);
const data = await res.json();
- if (data && data.length > 0) {
- const destLat = parseFloat(data[0].lat);
- const destLon = parseFloat(data[0].lon);
- 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);
+ if (data && data[0]) {
+ const R = 6371; const dLat = (data[0].lat - lat) * Math.PI / 180; const dLon = (data[0].lon - lon) * Math.PI / 180;
+ const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat * Math.PI / 180) * Math.cos(data[0].lat * 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;
-
+ const km = R * c;
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 });
+ document.getElementById('gpsKm').innerText = km.toFixed(1);
+ document.getElementById('gpsMins').innerText = Math.round((km/35)*60)+5;
+ } else { showGpsError("Sin ubicación"); }
+ } catch(e) { showGpsError("Error GPS"); }
+ }, () => showGpsError("GPS off"), { enableHighAccuracy: true });
}
- function showGpsError(msg) {
- document.getElementById('gpsLoading').innerHTML = `
${msg}`;
- safeLoadIcons();
- }
+ function showGpsError(m) { document.getElementById('gpsLoading').innerHTML = `
${m}`; }
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?"; }
+ let word = ""; let msg = "";
+ if(action === 'camino') { word = "camino"; msg = "¿Enviar 'De Camino'?"; }
+ if(action === 'trabajando') { word = "trabaja"; msg = "¿Iniciar trabajo?"; }
+ if(action === 'finalizado') { word = "finaliza"; msg = "¿Finalizar expediente?"; }
+ if(action === 'encuesta') { word = "finaliza"; msg = "¿Enviar encuesta?"; }
- 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.");
+ if(!confirm(msg)) return;
+ const st = systemStatuses.find(s => s.name.toLowerCase().includes(word));
+ if(!st) return alert("Estado no encontrado");
try {
- showToast("Procesando...");
const res = await fetch(`${API_URL}/providers/scraped/${currentServiceId}`, {
- method: 'PUT',
- headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` },
+ 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"); }
+ if(res.ok) { showToast("¡Hecho!"); closeModal(); refreshData(); }
+ } catch (e) { alert("Error"); }
}
- 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 showToast(m) {
+ const t = document.getElementById('toast'); document.getElementById('toastMsg').innerText = m;
+ t.classList.remove('opacity-0', '-translate-y-10'); t.classList.add('translate-y-0');
+ setTimeout(() => { t.classList.add('opacity-0', '-translate-y-10'); t.classList.remove('translate-y-0'); }, 2000);
}
function logout() { localStorage.clear(); window.location.href = "index.html"; }