Actualizar servicios.html
This commit is contained in:
142
servicios.html
142
servicios.html
@@ -16,47 +16,67 @@
|
||||
<body class="bg-slate-50 text-slate-800 font-sans antialiased text-left">
|
||||
|
||||
<div class="flex h-screen overflow-hidden">
|
||||
<div id="sidebar-container" class="h-full"></div>
|
||||
<div class="flex-1 flex flex-col overflow-hidden">
|
||||
<div id="sidebar-container" class="h-full shrink-0"></div>
|
||||
|
||||
<div class="flex-1 flex flex-col overflow-hidden relative">
|
||||
<div id="header-container"></div>
|
||||
|
||||
<main class="flex-1 overflow-y-auto p-6 no-scrollbar text-left">
|
||||
<div class="flex justify-between items-center mb-8">
|
||||
<div>
|
||||
<h2 class="text-2xl font-black text-slate-800 tracking-tight">PANEL OPERATIVO</h2>
|
||||
<p class="text-sm text-slate-500 font-medium">Tablero Kanban de gestión de expedientes.</p>
|
||||
</div>
|
||||
<button onclick="openCreateModal()" class="bg-slate-900 hover:bg-blue-600 text-white px-6 py-3 rounded-2xl shadow-xl flex items-center gap-3 font-black text-xs uppercase tracking-widest transition-all active:scale-95">
|
||||
<i data-lucide="plus-circle" class="w-5 h-5"></i> Nuevo Servicio
|
||||
</button>
|
||||
</div>
|
||||
<main class="flex-1 overflow-x-hidden overflow-y-auto bg-slate-50 p-6 no-scrollbar text-left relative">
|
||||
<div class="fade-in max-w-full mx-auto space-y-6">
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
||||
|
||||
<div class="space-y-4 bg-slate-100/50 p-4 rounded-[2rem] border border-slate-200/60">
|
||||
<div class="flex items-center gap-2 px-2 pb-2 border-b border-slate-200">
|
||||
<div class="w-2.5 h-2.5 rounded-full bg-rose-500 shadow-[0_0_10px_rgba(244,63,94,0.5)]"></div>
|
||||
<h3 class="font-black text-slate-600 uppercase text-[10px] tracking-widest">Sin Asignar / En Pausa</h3>
|
||||
<div class="flex justify-between items-center bg-white p-6 rounded-[2rem] shadow-sm border border-slate-100">
|
||||
<div>
|
||||
<h2 class="text-2xl font-black text-slate-800 tracking-tight flex items-center gap-3">
|
||||
<span class="bg-blue-600 p-2.5 rounded-xl text-white shadow-lg shadow-blue-200"><i data-lucide="kanban"></i></span>
|
||||
PANEL OPERATIVO
|
||||
</h2>
|
||||
<p class="text-sm text-slate-500 mt-1 font-medium">Tablero Kanban de gestión de expedientes.</p>
|
||||
</div>
|
||||
<div id="unassigned-list" class="space-y-3"></div>
|
||||
<button onclick="openCreateModal()" class="bg-slate-900 hover:bg-blue-600 text-white px-6 py-3.5 rounded-2xl shadow-xl flex items-center gap-3 font-black text-xs uppercase tracking-widest transition-all active:scale-95">
|
||||
<i data-lucide="plus-circle" class="w-5 h-5"></i> Nuevo Servicio
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4 bg-slate-100/50 p-4 rounded-[2rem] border border-slate-200/60">
|
||||
<div class="flex items-center gap-2 px-2 pb-2 border-b border-slate-200">
|
||||
<div class="w-2.5 h-2.5 rounded-full bg-blue-500 shadow-[0_0_10px_rgba(59,130,246,0.5)]"></div>
|
||||
<h3 class="font-black text-slate-600 uppercase text-[10px] tracking-widest">Asignados (Falta Fecha)</h3>
|
||||
<div class="flex flex-wrap gap-4 items-center bg-white p-4 rounded-[1.5rem] shadow-sm border border-slate-100 mb-6">
|
||||
<div class="relative flex-1 min-w-[250px]">
|
||||
<i data-lucide="search" class="w-4 h-4 absolute left-4 top-1/2 -translate-y-1/2 text-slate-400"></i>
|
||||
<input type="text" id="searchFilter" oninput="renderLists()" placeholder="Buscar por cliente, REF, población, teléfono..." class="w-full pl-11 pr-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-xs font-bold focus:ring-2 focus:ring-blue-500 outline-none transition-all">
|
||||
</div>
|
||||
<div id="pending-list" class="space-y-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4 bg-slate-100/50 p-4 rounded-[2rem] border border-slate-200/60">
|
||||
<div class="flex items-center gap-2 px-2 pb-2 border-b border-slate-200">
|
||||
<div class="w-2.5 h-2.5 rounded-full bg-emerald-500 shadow-[0_0_10px_rgba(16,185,129,0.5)]"></div>
|
||||
<h3 class="font-black text-slate-600 uppercase text-[10px] tracking-widest">Citados / En Curso</h3>
|
||||
<div class="relative w-full md:w-64">
|
||||
<select id="opFilter" onchange="renderLists()" class="w-full bg-slate-50 border border-slate-200 text-xs font-black px-4 py-3 rounded-xl outline-none focus:ring-2 focus:ring-blue-500 uppercase tracking-widest text-slate-600 appearance-none pr-10 cursor-pointer">
|
||||
<option value="ALL">TODOS LOS OPERARIOS</option>
|
||||
</select>
|
||||
<i data-lucide="chevron-down" class="w-4 h-4 absolute right-4 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none"></i>
|
||||
</div>
|
||||
<div id="assigned-list" class="space-y-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
||||
|
||||
<div class="space-y-4 bg-slate-100/50 p-4 rounded-[2rem] border border-slate-200/60">
|
||||
<div class="flex items-center gap-2 px-2 pb-2 border-b border-slate-200">
|
||||
<div class="w-2.5 h-2.5 rounded-full bg-rose-500 shadow-[0_0_10px_rgba(244,63,94,0.5)]"></div>
|
||||
<h3 class="font-black text-slate-600 uppercase text-[10px] tracking-widest">Sin Asignar / En Pausa</h3>
|
||||
</div>
|
||||
<div id="unassigned-list" class="space-y-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4 bg-slate-100/50 p-4 rounded-[2rem] border border-slate-200/60">
|
||||
<div class="flex items-center gap-2 px-2 pb-2 border-b border-slate-200">
|
||||
<div class="w-2.5 h-2.5 rounded-full bg-blue-500 shadow-[0_0_10px_rgba(59,130,246,0.5)]"></div>
|
||||
<h3 class="font-black text-slate-600 uppercase text-[10px] tracking-widest">Asignados (Falta Fecha)</h3>
|
||||
</div>
|
||||
<div id="pending-list" class="space-y-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4 bg-slate-100/50 p-4 rounded-[2rem] border border-slate-200/60">
|
||||
<div class="flex items-center gap-2 px-2 pb-2 border-b border-slate-200">
|
||||
<div class="w-2.5 h-2.5 rounded-full bg-emerald-500 shadow-[0_0_10px_rgba(16,185,129,0.5)]"></div>
|
||||
<h3 class="font-black text-slate-600 uppercase text-[10px] tracking-widest">Citados / En Curso</h3>
|
||||
</div>
|
||||
<div id="assigned-list" class="space-y-3"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
@@ -212,15 +232,65 @@
|
||||
headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.ok) { localData = data.services; renderLists(); }
|
||||
if (data.ok) {
|
||||
localData = data.services;
|
||||
updateOperatorFilter(); // Actualiza el select de operarios
|
||||
renderLists();
|
||||
}
|
||||
} catch (e) { console.error(e); }
|
||||
}
|
||||
|
||||
function updateOperatorFilter() {
|
||||
const opSelect = document.getElementById('opFilter');
|
||||
const currentValue = opSelect.value;
|
||||
|
||||
// Extraer nombres únicos de operarios asignados en este panel
|
||||
const uniqueOps = [...new Set(localData.map(s => s.assigned_name).filter(Boolean))].sort();
|
||||
|
||||
let html = '<option value="ALL">TODOS LOS OPERARIOS</option>';
|
||||
uniqueOps.forEach(op => {
|
||||
html += `<option value="${op}">${op}</option>`;
|
||||
});
|
||||
|
||||
opSelect.innerHTML = html;
|
||||
// Restaurar la selección previa si sigue existiendo
|
||||
if (html.includes(`value="${currentValue}"`)) {
|
||||
opSelect.value = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
function renderLists() {
|
||||
const searchTerm = document.getElementById('searchFilter').value.toLowerCase();
|
||||
const selectedOp = document.getElementById('opFilter').value;
|
||||
|
||||
// FILTRO DE DATOS
|
||||
const filteredData = localData.filter(s => {
|
||||
const raw = s.raw_data;
|
||||
const name = (raw["Nombre Cliente"] || raw["CLIENTE"] || "").toLowerCase();
|
||||
const addr = (raw["Dirección"] || raw["DOMICILIO"] || "").toLowerCase();
|
||||
const pop = (raw["Población"] || raw["POBLACION-PROVINCIA"] || "").toLowerCase();
|
||||
const phone = (raw["Teléfono"] || raw["TELEFONO"] || "").toLowerCase();
|
||||
const ref = (s.service_ref || "").toLowerCase();
|
||||
const assigned = s.assigned_name || "";
|
||||
|
||||
// Buscar texto (Nombre, Ref, Dirección, Población, Teléfono)
|
||||
const matchesSearch = searchTerm === "" ||
|
||||
name.includes(searchTerm) ||
|
||||
ref.includes(searchTerm) ||
|
||||
addr.includes(searchTerm) ||
|
||||
pop.includes(searchTerm) ||
|
||||
phone.includes(searchTerm);
|
||||
|
||||
// Buscar Operario
|
||||
const matchesOp = selectedOp === "ALL" || assigned === selectedOp;
|
||||
|
||||
return matchesSearch && matchesOp;
|
||||
});
|
||||
|
||||
// Lógica inteligente de 3 columnas apoyada en el raw_data
|
||||
const unassigned = localData.filter(s => !s.assigned_name || s.raw_data.status_operativo === 'sin_asignar');
|
||||
const pending = localData.filter(s => s.assigned_name && (!s.raw_data.scheduled_date || s.raw_data.scheduled_date === "") && s.raw_data.status_operativo !== 'sin_asignar');
|
||||
const assigned = localData.filter(s => s.raw_data.scheduled_date && s.raw_data.scheduled_date !== "" && s.raw_data.status_operativo !== 'sin_asignar');
|
||||
const unassigned = filteredData.filter(s => !s.assigned_name || s.raw_data.status_operativo === 'sin_asignar');
|
||||
const pending = filteredData.filter(s => s.assigned_name && (!s.raw_data.scheduled_date || s.raw_data.scheduled_date === "") && s.raw_data.status_operativo !== 'sin_asignar');
|
||||
const assigned = filteredData.filter(s => s.raw_data.scheduled_date && s.raw_data.scheduled_date !== "" && s.raw_data.status_operativo !== 'sin_asignar');
|
||||
|
||||
document.getElementById('unassigned-list').innerHTML = unassigned.length > 0
|
||||
? unassigned.map(s => cardTemplate(s, 'rose', s.assigned_name ? 'Pausado' : 'Sin Asignar')).join('')
|
||||
@@ -281,7 +351,6 @@
|
||||
document.getElementById('detId').value = s.id;
|
||||
document.getElementById('detRef').innerText = s.service_ref;
|
||||
|
||||
// COMPAÑÍA ASEGURADORA
|
||||
const companyName = raw['Compañía'] || raw['COMPAÑIA'] || raw['Procedencia'] || "Particular";
|
||||
document.getElementById('detCompany').innerText = companyName;
|
||||
|
||||
@@ -301,7 +370,6 @@
|
||||
document.getElementById('dateInput').value = raw.scheduled_date || "";
|
||||
document.getElementById('timeInput').value = raw.scheduled_time || "";
|
||||
|
||||
// Si no tiene estado previo guardado, mostramos "citado" por defecto o "sin asignar" si procede.
|
||||
let defaultStatus = raw.status_operativo;
|
||||
if (!defaultStatus) {
|
||||
defaultStatus = (!s.assigned_name) ? 'sin_asignar' : 'citado';
|
||||
|
||||
Reference in New Issue
Block a user