Actualizar index.html
This commit is contained in:
115
index.html
115
index.html
@@ -75,7 +75,7 @@
|
||||
: 'https://integrarepara-api.integrarepara.es';
|
||||
|
||||
let urlToken = "";
|
||||
let etasToInit = []; // Para procesar los tiempos de llegada al cargar
|
||||
let etasToInit = [];
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
lucide.createIcons();
|
||||
@@ -149,7 +149,6 @@
|
||||
const historyContainerWrapper = document.getElementById('historyContainerWrapper');
|
||||
const historyContainer = document.getElementById('historyServicesContainer');
|
||||
|
||||
// Limpiar contenedores por si acaso (útil si hay recargas)
|
||||
activeContainer.innerHTML = '';
|
||||
historyContainer.innerHTML = '';
|
||||
|
||||
@@ -157,12 +156,12 @@
|
||||
let hasHistory = false;
|
||||
|
||||
allServices.forEach(srv => {
|
||||
// Usamos la nueva variable booleana que nos manda el servidor
|
||||
const isFinalized = srv.is_final;
|
||||
const raw = srv.raw_data || {};
|
||||
const descLimpia = summarizeDescription(srv.description);
|
||||
let statusHtml = '';
|
||||
|
||||
// ESTRUCTURA PRINCIPAL DE ESTADOS
|
||||
if (isFinalized) {
|
||||
statusHtml = `
|
||||
<div class="bg-slate-50 border border-slate-200 p-4 rounded-2xl flex items-center justify-between opacity-70 grayscale">
|
||||
@@ -214,13 +213,21 @@
|
||||
else if (srv.status_name === 'Visita Agendada' || (srv.scheduled_date && srv.scheduled_time)) {
|
||||
const endT = addOneHour(srv.scheduled_time);
|
||||
statusHtml = `
|
||||
<div class="bg-gradient-to-br from-emerald-400 to-emerald-600 p-6 rounded-3xl flex items-center gap-5 text-white shadow-lg shadow-emerald-500/30 relative overflow-hidden">
|
||||
<div class="w-14 h-14 bg-white/20 rounded-2xl flex items-center justify-center backdrop-blur-md border border-white/30 shrink-0 relative z-10"><i data-lucide="calendar-check" class="w-7 h-7 text-white"></i></div>
|
||||
<div class="relative z-10">
|
||||
<p class="text-[9px] font-black uppercase tracking-widest text-emerald-100 mb-0.5">Visita Confirmada</p>
|
||||
<p class="font-black uppercase text-lg leading-none mb-1.5">${formatDate(srv.scheduled_date)}</p>
|
||||
<p class="text-sm font-bold text-emerald-50 flex items-center gap-1.5"><i data-lucide="clock" class="w-4 h-4"></i> Llegada aprox: ${srv.scheduled_time} - ${endT}</p>
|
||||
<div class="bg-gradient-to-br from-emerald-400 to-emerald-600 p-6 rounded-3xl text-white shadow-lg shadow-emerald-500/30 relative overflow-hidden">
|
||||
<div class="flex items-center gap-5 mb-4">
|
||||
<div class="w-14 h-14 bg-white/20 rounded-2xl flex items-center justify-center backdrop-blur-md border border-white/30 shrink-0 relative z-10">
|
||||
<i data-lucide="calendar-check" class="w-7 h-7 text-white"></i>
|
||||
</div>
|
||||
<div class="relative z-10 flex-1">
|
||||
<p class="text-[9px] font-black uppercase tracking-widest text-emerald-100 mb-0.5">Visita Confirmada</p>
|
||||
<p class="font-black uppercase text-lg leading-none mb-1.5">${formatDate(srv.scheduled_date)}</p>
|
||||
<p class="text-sm font-bold text-emerald-50 flex items-center gap-1.5"><i data-lucide="clock" class="w-4 h-4"></i> ${srv.scheduled_time} - ${endT}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="cita.html?token=${urlToken}&service=${srv.id}" class="w-full bg-white/20 hover:bg-white/30 text-white border border-white/30 backdrop-blur-md font-black py-3 rounded-xl flex items-center justify-center gap-2 transition-colors text-[10px] uppercase tracking-widest relative z-10">
|
||||
<i data-lucide="calendar-clock" class="w-4 h-4"></i> Modificar Cita
|
||||
</a>
|
||||
</div>`;
|
||||
}
|
||||
else {
|
||||
@@ -231,21 +238,76 @@
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// NUEVO: BLOQUE DE BOTONES DE CONTACTO
|
||||
// =====================================
|
||||
let contactHtml = '';
|
||||
const hasWorker = srv.assigned_worker && srv.assigned_worker !== 'Pendiente';
|
||||
|
||||
if (hasWorker && !isFinalized) {
|
||||
// Extraemos el teléfono del trabajador (si la BD lo manda) o usamos uno temporal para que funcione el enlace
|
||||
const workerPhone = srv.worker_phone ? srv.worker_phone.replace('+', '') : "34000000000";
|
||||
|
||||
contactHtml = `
|
||||
<div class="flex gap-2 mt-5">
|
||||
<a href="tel:+${workerPhone}" class="flex-1 bg-blue-50 hover:bg-blue-100 border border-blue-200 text-blue-600 font-black py-3 rounded-xl flex items-center justify-center gap-1.5 active:scale-95 transition-transform shadow-sm text-[10px] uppercase tracking-widest">
|
||||
<i data-lucide="phone" class="w-4 h-4"></i> Llamar Técnico
|
||||
</a>
|
||||
<a href="https://wa.me/${workerPhone}" target="_blank" class="flex-1 bg-emerald-50 hover:bg-emerald-100 border border-emerald-200 text-emerald-600 font-black py-3 rounded-xl flex items-center justify-center gap-1.5 active:scale-95 transition-transform shadow-sm text-[10px] uppercase tracking-widest">
|
||||
<i data-lucide="message-circle" class="w-4 h-4"></i> WhatsApp
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// NUEVO: DATOS DEL ASEGURADO (CAJA LIMPIA)
|
||||
// =====================================
|
||||
const clientDataHtml = `
|
||||
<div class="bg-slate-50/50 rounded-2xl p-4 mt-5 border border-slate-100 text-left">
|
||||
<p class="text-[9px] font-black text-slate-400 uppercase tracking-widest mb-3 border-b border-slate-100 pb-2">Información del Siniestro</p>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start gap-2.5">
|
||||
<i data-lucide="user" class="w-4 h-4 text-slate-400 mt-0.5"></i>
|
||||
<p class="text-xs font-bold text-slate-700 leading-tight">${raw["Nombre Cliente"] || raw["CLIENTE"] || client.name || "Asegurado"}</p>
|
||||
</div>
|
||||
<div class="flex items-start gap-2.5">
|
||||
<i data-lucide="map-pin" class="w-4 h-4 text-slate-400 mt-0.5"></i>
|
||||
<p class="text-xs font-bold text-slate-700 leading-tight">
|
||||
${raw["Dirección"] || raw["DOMICILIO"] || "Dirección no especificada"}<br>
|
||||
<span class="text-[10px] text-slate-500 font-medium">${raw["Código Postal"] || ""} ${raw["Población"] || raw["POBLACION-PROVINCIA"] || ""}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-start gap-2.5">
|
||||
<i data-lucide="building" class="w-4 h-4 text-slate-400 mt-0.5"></i>
|
||||
<p class="text-xs font-bold text-slate-700 leading-tight">${raw["Compañía"] || raw["COMPAÑIA"] || "Particular"}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// ENSAMBLAJE DE LA TARJETA FINAL
|
||||
let cardHtml = `
|
||||
<div class="bg-white/80 backdrop-blur-xl border border-white shadow-xl shadow-slate-200/40 rounded-[2.5rem] p-6 mb-6 relative overflow-hidden">
|
||||
<div class="bg-white/80 backdrop-blur-xl border border-white shadow-xl shadow-slate-200/40 rounded-[2.5rem] p-6 mb-6 relative overflow-hidden text-left">
|
||||
<div class="flex justify-between items-start mb-5">
|
||||
<span class="text-[10px] font-black text-slate-400 uppercase tracking-widest">${srv.title}</span>
|
||||
${srv.assigned_worker && srv.assigned_worker !== 'Pendiente' ?
|
||||
${hasWorker ?
|
||||
`<div class="bg-slate-50 border border-slate-100 px-3 py-1.5 rounded-lg text-center shrink-0">
|
||||
<p class="text-[8px] uppercase font-black text-slate-400 mb-0.5">Técnico</p>
|
||||
<p class="text-[10px] font-bold text-blue-600">${srv.assigned_worker.split(' ')[0]}</p>
|
||||
</div>` : ''
|
||||
}
|
||||
</div>
|
||||
<div class="mb-6">${statusHtml}</div>
|
||||
<div class="pt-5 border-t border-slate-100">
|
||||
|
||||
<div class="mb-5">${statusHtml}</div>
|
||||
|
||||
${contactHtml}
|
||||
|
||||
${clientDataHtml}
|
||||
|
||||
<div class="pt-5 mt-5 border-t border-slate-100">
|
||||
<p class="text-[10px] font-black text-slate-400 uppercase tracking-widest mb-1.5">Motivo de la Visita</p>
|
||||
<h3 class="font-black text-slate-800 text-sm leading-snug">${descLimpia}</h3>
|
||||
<h3 class="font-black text-slate-800 text-sm leading-relaxed">${descLimpia}</h3>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -259,18 +321,11 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Lógica para mostrar/ocultar secciones
|
||||
if (!hasActive) {
|
||||
document.getElementById('noActiveServices').classList.remove('hidden');
|
||||
} else {
|
||||
document.getElementById('noActiveServices').classList.add('hidden');
|
||||
}
|
||||
if (!hasActive) document.getElementById('noActiveServices').classList.remove('hidden');
|
||||
else document.getElementById('noActiveServices').classList.add('hidden');
|
||||
|
||||
if (hasHistory) {
|
||||
historyContainerWrapper.classList.remove('hidden');
|
||||
} else {
|
||||
historyContainerWrapper.classList.add('hidden');
|
||||
}
|
||||
if (hasHistory) document.getElementById('historyContainerWrapper').classList.remove('hidden');
|
||||
else document.getElementById('historyContainerWrapper').classList.add('hidden');
|
||||
|
||||
lucide.createIcons();
|
||||
|
||||
@@ -279,7 +334,6 @@
|
||||
document.getElementById('loader').classList.add('hidden');
|
||||
document.getElementById('mainContent').classList.remove('hidden');
|
||||
|
||||
// Disparamos el cálculo de ETA para los que estén De Camino
|
||||
etasToInit.forEach(item => calculateClientETA(item.id, item.address));
|
||||
}, 300);
|
||||
}
|
||||
@@ -291,7 +345,6 @@
|
||||
const container = document.getElementById(`eta-container-${serviceId}`);
|
||||
|
||||
try {
|
||||
// 1. Obtenemos la ubicación de donde salió el técnico
|
||||
const res = await fetch(`${API_URL}/public/portal/${urlToken}/location/${serviceId}`);
|
||||
const data = await res.json();
|
||||
|
||||
@@ -303,7 +356,6 @@
|
||||
const wLat = parseFloat(data.location.lat);
|
||||
const wLon = parseFloat(data.location.lng);
|
||||
|
||||
// 2. Buscamos las coordenadas del cliente
|
||||
let geoRes = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(destAddress + ', España')}`);
|
||||
let geoData = await geoRes.json();
|
||||
|
||||
@@ -318,7 +370,6 @@
|
||||
const cLat = parseFloat(geoData[0].lat);
|
||||
const cLon = parseFloat(geoData[0].lon);
|
||||
|
||||
// 3. Calculamos la distancia en línea recta (Fórmula de Haversine)
|
||||
const R = 6371;
|
||||
const dLat = (cLat - wLat) * Math.PI / 180;
|
||||
const dLon = (cLon - wLon) * Math.PI / 180;
|
||||
@@ -326,23 +377,19 @@
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||||
const km = R * c;
|
||||
|
||||
// 4. Estimamos los minutos totales (velocidad media ciudad 35km/h + 5min atascos/aparcar)
|
||||
const totalMins = Math.round((km/35)*60) + 5;
|
||||
|
||||
// 5. EL TRUCO MAGICO: Restar los minutos que ya han pasado desde que salió
|
||||
const startedAt = new Date(data.location.updated_at).getTime();
|
||||
const now = new Date().getTime();
|
||||
const diffMins = Math.floor((now - startedAt) / 60000);
|
||||
|
||||
let remainingMins = totalMins - diffMins;
|
||||
if (remainingMins < 1) remainingMins = 1; // Para que no ponga 0 o negativo
|
||||
if (remainingMins < 1) remainingMins = 1;
|
||||
|
||||
// Calculamos el % para la barra visual
|
||||
let progressPercent = (diffMins / totalMins) * 100;
|
||||
if (progressPercent > 95) progressPercent = 95;
|
||||
if (progressPercent < 5) progressPercent = 5;
|
||||
|
||||
// Dibujamos la barra visual
|
||||
container.innerHTML = `
|
||||
<p class="text-[10px] font-black text-indigo-500 uppercase tracking-widest mb-1.5 flex items-center gap-1.5">
|
||||
<i data-lucide="clock" class="w-3.5 h-3.5"></i> Llegada en aprox. <span class="text-indigo-700 text-sm ml-0.5">${remainingMins} min</span>
|
||||
|
||||
Reference in New Issue
Block a user