Historial
@@ -77,11 +73,11 @@
let urlToken = "";
let etasToInit = [];
- document.addEventListener("DOMContentLoaded", async () => {
+ document.addEventListener("DOMContentLoaded", async () => {
lucide.createIcons();
const urlParams = new URLSearchParams(window.location.search);
urlToken = urlParams.get('token');
- const serviceParam = urlParams.get('service'); // Por si viene el ID del servicio
+ const serviceParam = urlParams.get('service');
if (!urlToken) {
showError();
@@ -89,7 +85,6 @@
}
try {
- // Le pasamos el token y opcionalmente el ID del servicio si viene en la URL
let fetchUrl = `${API_URL}/public/portal/${urlToken}`;
if (serviceParam) {
fetchUrl += `?service=${serviceParam}`;
@@ -100,9 +95,7 @@
if (!data.ok) throw new Error("Token inválido");
- // Si no hay servicios, no mostramos error, mostramos el portal vacío
const servicesList = data.services || [];
-
renderPortal(data.client, data.company, servicesList);
} catch (e) {
console.error("Error cargando portal:", e);
@@ -156,7 +149,12 @@
document.getElementById('companyLogo').src = company.logo;
document.getElementById('companyLogoContainer').classList.remove('hidden');
}
- document.getElementById('clientName').innerText = client.name.split(' ')[0].toUpperCase();
+
+ let cName = "Cliente";
+ if (client && client.name) {
+ cName = client.name.split(' ')[0];
+ }
+ document.getElementById('clientName').innerText = cName.toUpperCase();
const activeContainer = document.getElementById('activeServicesContainer');
const historyContainerWrapper = document.getElementById('historyContainerWrapper');
@@ -169,29 +167,38 @@
let hasHistory = false;
allServices.forEach(srv => {
- const isFinalized = srv.is_final;
- const raw = srv.raw_data || {};
- const descLimpia = summarizeDescription(srv.description);
+ let isFinalized = srv.is_final === true;
+ let raw = srv.raw_data || {};
+ let descLimpia = summarizeDescription(srv.description);
- const stName = (srv.status_name || '').toLowerCase();
- const hasDate = !!(srv.scheduled_date && srv.scheduled_time);
+ let stNameLower = "";
+ if (srv.status_name) {
+ stNameLower = srv.status_name.toLowerCase();
+ }
+
+ let hasDate = false;
+ if (srv.scheduled_date && srv.scheduled_time) {
+ hasDate = true;
+ }
+
+ // DEFINICIÓN SEGURA (Esta es la línea que rompía todo en la versión anterior)
+ let hasWorker = false;
+ if (srv.assigned_worker && srv.assigned_worker !== 'Pendiente' && srv.assigned_worker !== 'Sin asignar') {
+ hasWorker = true;
+ }
+
let statusHtml = '';
- // ESTRUCTURA INTELIGENTE DE ESTADOS
- const stNameLower = (srv.status_name || '').toLowerCase();
-
if (isFinalized || stNameLower.includes('finalizado') || stNameLower.includes('anulado')) {
- statusHtml = `
-
+ statusHtml = `
${srv.status_name || 'Cerrado'}
`;
}
else if (stNameLower.includes('camino')) {
- const fullAddr = `${raw["Dirección"] || ""}, ${raw["Código Postal"] || ""} ${raw["Población"] || ""}`;
+ let fullAddr = `${raw["Dirección"] || ""}, ${raw["Código Postal"] || ""} ${raw["Población"] || ""}`;
etasToInit.push({ id: srv.id, address: fullAddr });
- statusHtml = `
-
- `;
+
`;
}
else if (stNameLower.includes('trabajando') || stNameLower.includes('reparación')) {
- statusHtml = `
-
+ statusHtml = `
Trabajando
@@ -217,8 +222,7 @@
`;
}
else if (stNameLower.includes('incidencia')) {
- statusHtml = `
-
+ statusHtml = `
`;
}
else if (hasDate && !stNameLower.includes('anulado') && !stNameLower.includes('desasignado')) {
- // ESTÁ AGENDADO (COMPROBAMOS SI LLEGA TARDE)
- const endT = addOneHour(srv.scheduled_time);
- const now = new Date();
- const schedParts = srv.scheduled_date.split('-');
- const endTimeParts = endT.split(':');
+ let endT = addOneHour(srv.scheduled_time);
+ let now = new Date();
+ let schedParts = srv.scheduled_date.split('-');
+ let endTimeParts = endT.split(':');
let isLate = false;
if (schedParts.length === 3 && endTimeParts.length === 2) {
- const limitDate = new Date(schedParts[0], schedParts[1] - 1, schedParts[2], endTimeParts[0], endTimeParts[1], 0);
+ let limitDate = new Date(schedParts[0], schedParts[1] - 1, schedParts[2], endTimeParts[0], endTimeParts[1], 0);
if (now > limitDate) isLate = true;
}
if (isLate) {
- statusHtml = `
-
+ statusHtml = `
`;
} else {
- statusHtml = `
-
+ statusHtml = `
@@ -280,9 +281,7 @@
}
}
else if (raw.appointment_status === 'pending' && raw.requested_date) {
- // CITA SOLICITADA PERO NO CONFIRMADA
- statusHtml = `
-
+ statusHtml = `
`;
}
- econst hasWorker = srv.assigned_worker && srv.assigned_worker !== 'Pendiente';lse if (stNameLower.includes('esperando') || stNameLower.includes('asignado') || (hasWorker && !hasDate)) {
- // ASIGNADO / ESPERANDO AL CLIENTE -> AGENDAR CITA AHORA
- statusHtml = `
-
+ else if (stNameLower.includes('esperando') || stNameLower.includes('asignado') || (hasWorker && !hasDate)) {
+ statusHtml = `
@@ -317,8 +314,7 @@
`;
}
else if (stNameLower.includes('desasignado')) {
- statusHtml = `
-
+ statusHtml = `
`;
}
else {
- // PENDIENTE DE ASIGNAR / DEFAULT
- statusHtml = `
-
+ statusHtml = `
`;
}
- // =====================================
- // BLOQUE DE BOTONES DE CONTACTO
- // =====================================
let contactHtml = '';
- const hasWorker = srv.assigned_worker && srv.assigned_worker !== 'Pendiente';
-
if (hasWorker && !isFinalized) {
- const workerPhone = srv.worker_phone ? srv.worker_phone.replace('+', '') : "34000000000";
-
- contactHtml = `
-
+ let workerPhone = "34000000000";
+ if (srv.worker_phone) {
+ workerPhone = srv.worker_phone.replace('+', '');
+ }
+ contactHtml = `
- `;
+
`;
}
- // =====================================
- // DATOS DEL ASEGURADO
- // =====================================
- const clientDataHtml = `
-
+ let cNameClient = raw["Nombre Cliente"] || raw["CLIENTE"] || cName;
+ let cAddr = raw["Dirección"] || raw["DOMICILIO"] || "Dirección no especificada";
+ let cCP = raw["Código Postal"] || "";
+ let cPop = raw["Población"] || raw["POBLACION-PROVINCIA"] || "";
+ let cComp = raw["Compañía"] || raw["COMPAÑIA"] || "Particular";
+
+ let clientDataHtml = `
Información del Siniestro
-
${raw["Nombre Cliente"] || raw["CLIENTE"] || client.name || "Asegurado"}
+
${cNameClient}
- ${raw["Dirección"] || raw["DOMICILIO"] || "Dirección no especificada"}
- ${raw["Código Postal"] || ""} ${raw["Población"] || raw["POBLACION-PROVINCIA"] || ""}
+ ${cAddr}
+ ${cCP} ${cPop}
-
${raw["Compañía"] || raw["COMPAÑIA"] || "Particular"}
+
${cComp}
-
- `;
+
`;
- // ENSAMBLAJE DE LA TARJETA FINAL
- let cardHtml = `
-
-
-
${srv.title}
- ${hasWorker ?
- `
+ let workerNameBox = '';
+ if (hasWorker) {
+ let wNameShort = srv.assigned_worker.split(' ')[0];
+ workerNameBox = `
Técnico
-
${srv.assigned_worker.split(' ')[0]}
-
` : ''
- }
+
${wNameShort}
+
`;
+ }
+
+ let srvTitle = srv.title || "Aviso";
+
+ let cardHtml = `
+
+ ${srvTitle}
+ ${workerNameBox}
-
${statusHtml}
-
${contactHtml}
-
${clientDataHtml}
-
Motivo de la Visita
${descLimpia}
-
- `;
+
`;
if (isFinalized) {
historyContainer.innerHTML += cardHtml;
@@ -443,9 +432,6 @@
}, 300);
}
- // ==========================================
- // CÁLCULO DE ETA (TIEMPO ESTIMADO) INTELIGENTE
- // ==========================================
async function calculateClientETA(serviceId, destAddress) {
const container = document.getElementById(`eta-container-${serviceId}`);
if (!container) return;
@@ -483,24 +469,20 @@
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const km = R * c;
- // Tiempo total estimado basado en la distancia
const totalMins = Math.round((km/35)*60) + 5;
- // Extraemos la hora exacta en la que el técnico pulsó el botón
let startedAt = new Date().getTime();
if (data.location.updated_at) {
const parsed = new Date(data.location.updated_at).getTime();
if (!isNaN(parsed)) startedAt = parsed;
}
- // CREAMOS UNA FUNCIÓN INTERNA PARA ACTUALIZAR EN TIEMPO REAL
function renderETA() {
const now = new Date().getTime();
const diffMins = Math.floor((now - startedAt) / 60000);
- // Restamos el tiempo que ya ha pasado conduciendo
let remainingMins = totalMins - diffMins;
- if (remainingMins < 1) remainingMins = 1; // Nunca bajará de 1 minuto
+ if (remainingMins < 1) remainingMins = 1;
let progressPercent = (diffMins / totalMins) * 100;
if (progressPercent > 95) progressPercent = 95;
@@ -523,10 +505,7 @@
lucide.createIcons();
}
- // 1. Lo pintamos inmediatamente al cargar
renderETA();
-
- // 2. Lo actualizamos automáticamente cada 60 segundos (Magia en tiempo real)
setInterval(renderETA, 60000);
} else {