Actualizar calendario.html
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user