Actualizar calendario.html

This commit is contained in:
2026-02-22 16:56:48 +00:00
parent 27b6fe187f
commit e9d3ea3ae2

View File

@@ -85,6 +85,12 @@
<i data-lucide="map-pin" class="w-5 h-5 text-slate-400 shrink-0 mt-0.5"></i>
<p id="detAddress" class="font-bold text-slate-600 text-sm uppercase leading-snug"></p>
</div>
<div class="mt-5 pt-5 border-t border-slate-100">
<h4 class="text-[10px] font-black text-blue-500 uppercase tracking-widest mb-4 flex items-center gap-1.5"><i data-lucide="file-text" class="w-3.5 h-3.5"></i> Datos del Servicio</h4>
<div id="detExtraInfo" class="space-y-3 bg-slate-50 p-4 rounded-2xl border border-slate-200">
</div>
</div>
</div>
<div class="bg-gradient-to-br from-slate-800 to-slate-900 p-5 rounded-3xl shadow-lg text-white relative overflow-hidden">
@@ -140,16 +146,16 @@
let localServices = [];
let systemStatuses = [];
let systemGuilds = [];
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) {
try {
if (!dateObj || isNaN(dateObj)) return "";
@@ -167,7 +173,7 @@
return new Date(date.setDate(diff));
}
document.addEventListener("DOMContentLoaded", () => {
document.addEventListener("DOMContentLoaded", async () => {
if (!localStorage.getItem("token") || localStorage.getItem("role") !== 'operario') {
window.location.href = "index.html"; return;
}
@@ -179,13 +185,25 @@
currentWeekStart = getMonday(today);
selectedDateStr = toISODate(today);
buildWeekCalendar();
// Cargar datos paralelos
loadStatuses();
await loadGuilds();
refreshData();
} catch(error) {
alert("Error iniciando calendario: " + error.message);
}
});
// Cargar gremios para saber los nombres
async function loadGuilds() {
try {
const res = await fetch(`${API_URL}/guilds`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
const data = await res.json();
if(data.ok) systemGuilds = data.guilds;
} catch(e){}
}
function buildWeekCalendar() {
try {
const strip = document.getElementById('weekStrip');
@@ -296,7 +314,6 @@
return d === selectedDateStr;
});
// 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");
@@ -318,6 +335,7 @@
const raw = s.raw_data || {};
const time = raw.scheduled_time || "A convenir";
// BLOQUEOS
if (s.provider === 'SYSTEM_BLOCK') {
const desc = raw["Descripción"] || "Operario no disponible";
return `
@@ -333,21 +351,42 @@
</div>`;
}
// SERVICIOS NORMALES
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;
// Extracción Compañía y Gremio
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 `
<div onclick="openService(${s.id})" class="bg-white p-5 rounded-3xl border border-slate-200 shadow-sm active:scale-95 transition-transform flex gap-4 cursor-pointer fade-in">
<div class="flex flex-col items-center justify-center border-r border-slate-100 pr-4 shrink-0">
<i data-lucide="clock" class="w-4 h-4 text-blue-400 mb-1"></i>
<span class="font-black text-slate-800 text-sm">${time}</span>
<div onclick="openService(${s.id})" class="bg-white p-5 rounded-3xl border border-slate-200 shadow-sm active:scale-95 transition-transform flex gap-4 cursor-pointer fade-in relative overflow-hidden">
${isUrgent ? '<div class="absolute top-0 right-0 bg-red-500 text-white text-[8px] font-black px-3 py-1 rounded-bl-xl uppercase tracking-widest shadow-sm z-10">Urgente</div>' : ''}
<div class="flex flex-col items-center justify-center border-r border-slate-100 pr-4 shrink-0 min-w-[65px]">
<i data-lucide="clock" class="w-5 h-5 text-blue-500 mb-1"></i>
<span class="font-black text-slate-800 text-sm mt-1">${time}</span>
</div>
<div class="min-w-0 flex-1">
<h3 class="font-black text-slate-800 text-base uppercase leading-tight truncate">${name}</h3>
<p class="text-[10px] font-bold text-slate-500 mt-1 truncate uppercase">${addr}, ${pop}</p>
${isUrgent ? '<span class="inline-block mt-2 bg-red-100 text-red-700 text-[9px] font-black px-2 py-0.5 rounded uppercase tracking-widest">Urgente</span>' : ''}
<div class="flex flex-wrap gap-1.5 mb-2">
<span class="text-[8px] font-black bg-blue-50 text-blue-700 px-2 py-0.5 rounded uppercase tracking-widest truncate max-w-[120px]">${compShort}</span>
<span class="text-[8px] font-black bg-slate-100 text-slate-600 px-2 py-0.5 rounded uppercase tracking-widest truncate">${guildName}</span>
</div>
<h3 class="font-black text-slate-800 text-sm uppercase leading-tight line-clamp-2">${name}</h3>
<p class="text-[10px] font-bold text-slate-500 mt-1.5 truncate uppercase flex items-center gap-1.5">
<i data-lucide="map-pin" class="w-3 h-3 shrink-0 text-slate-400"></i> ${addr}, ${pop}
</p>
</div>
</div>`;
}).join('');
@@ -374,10 +413,37 @@
const fullAddress = `${raw["Dirección"] || ""}, ${raw["Código Postal"] || ""} ${raw["Población"] || ""}`;
document.getElementById('detAddress').innerText = fullAddress;
// VOLCAR TODOS LOS DATOS EXTRA
const detailsContainer = document.getElementById('detExtraInfo');
let detailsHtml = '';
// Ignoramos los campos que ya están enseñados arriba por defecto
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"];
for(let key in raw) {
if(skipKeys.includes(key)) continue;
let val = raw[key];
if(typeof val === 'object') val = JSON.stringify(val); // Por si es un JSON anidado
if(!val || val.trim() === "") continue;
detailsHtml += `
<div class="border-b border-slate-200 pb-2 mb-2 last:border-0 last:mb-0 last:pb-0">
<p class="text-[9px] font-black text-slate-400 uppercase tracking-widest mb-0.5">${key}</p>
<p class="text-xs font-bold text-slate-700 whitespace-pre-wrap leading-relaxed">${val}</p>
</div>
`;
}
if(detailsHtml === '') detailsHtml = '<p class="text-xs text-slate-400 font-medium">No hay más datos proporcionados.</p>';
detailsContainer.innerHTML = detailsHtml;
// 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);
}