diff --git a/lab_formularios.php b/lab_formularios.php index bfe0e71..7222df3 100644 --- a/lab_formularios.php +++ b/lab_formularios.php @@ -118,6 +118,28 @@ $puedeEscribir = $esAdmin && hasModuleWrite('lab_formularios'); @@ -443,26 +473,71 @@ const ESTADO_ENV = { firmado: { cls:'badge-firmado', icon:'✍️' }, expirado: { cls:'badge-expirado', icon:'⏰' }, }; +const POR_PAGINA = 15; const envios = { - _data: [], + _data: [], + _filtrado: [], + _pagina: 1, + async cargar() { const r = await fetch('api/lab/get_formularios.php?envios=1'); const d = await r.json(); this._data = d.data || []; - this._render(); + this._pagina = 1; + this._aplicarFiltros(); }, - _render() { - const tb = $('tbody-envios'); + + filtrar() { + this._pagina = 1; + this._aplicarFiltros(); + }, + + limpiarFiltros() { + $('env-f-desde').value = ''; + $('env-f-hasta').value = ''; + $('env-f-paciente').value = ''; + this.filtrar(); + }, + + _aplicarFiltros() { + const desde = $('env-f-desde').value; + const hasta = $('env-f-hasta').value; + const paciente = $('env-f-paciente').value.trim().toLowerCase(); + + this._filtrado = this._data.filter(e => { + const fecha = (e.created_at || '').slice(0, 10); + if (desde && fecha < desde) return false; + if (hasta && fecha > hasta) return false; + if (paciente && !(e.paciente_nombre || '').toLowerCase().includes(paciente)) return false; + return true; + }); + + // badge de pendientes sobre el total sin filtrar const badgePend = $('badge-envios'); - const pend = this._data.filter(e => e.estado==='pendiente').length; + const pend = this._data.filter(e => e.estado === 'pendiente').length; if (pend) { badgePend.textContent = pend; badgePend.style.display = ''; } else badgePend.style.display = 'none'; - if (!this._data.length) { - tb.innerHTML = 'Sin envíos aún'; + this._render(); + }, + + _render() { + const tb = $('tbody-envios'); + const total = this._filtrado.length; + + if (!total) { + tb.innerHTML = 'Sin envíos para los filtros seleccionados'; + $('env-pag-info').textContent = ''; + $('env-paginacion').innerHTML = ''; return; } - tb.innerHTML = this._data.map(e => { + + const totalPag = Math.ceil(total / POR_PAGINA); + if (this._pagina > totalPag) this._pagina = totalPag; + const inicio = (this._pagina - 1) * POR_PAGINA; + const pagina = this._filtrado.slice(inicio, inicio + POR_PAGINA); + + tb.innerHTML = pagina.map(e => { const info = ESTADO_ENV[e.estado] || {}; return ` ${esc(e.form_nombre)} @@ -473,7 +548,7 @@ const envios = { ${esc((e.expira_en||'').slice(0,10))} ${['completado','firmado'].includes(e.estado) @@ -487,7 +562,41 @@ const envios = { `; }).join(''); + + // Info + $('env-pag-info').textContent = + `Mostrando ${inicio + 1}–${Math.min(inicio + POR_PAGINA, total)} de ${total} envíos`; + + // Paginación + const ul = $('env-paginacion'); + ul.innerHTML = ''; + const agregar = (label, pag, disabled, active) => { + const li = document.createElement('li'); + li.className = `page-item${disabled?' disabled':''}${active?' active':''}`; + li.innerHTML = `${label}`; + ul.appendChild(li); + }; + agregar('«', 1, this._pagina === 1, false); + agregar('‹', this._pagina-1, this._pagina === 1, false); + + // páginas con ventana deslizante ±2 + const rango = 2; + const pMin = Math.max(1, this._pagina - rango); + const pMax = Math.min(totalPag, this._pagina + rango); + if (pMin > 1) { agregar('1', 1, false, false); if (pMin > 2) agregar('…', null, true, false); } + for (let p = pMin; p <= pMax; p++) agregar(p, p, false, p === this._pagina); + if (pMax < totalPag) { if (pMax < totalPag-1) agregar('…', null, true, false); agregar(totalPag, totalPag, false, false); } + + agregar('›', this._pagina+1, this._pagina === totalPag, false); + agregar('»', totalPag, this._pagina === totalPag, false); }, + + irAPagina(p) { + this._pagina = p; + this._render(); + $('panel-envios').scrollIntoView({ behavior:'smooth', block:'start' }); + }, + copiarTokenLink(token) { const url = window.location.origin + window.location.pathname.replace(/\/[^/]+$/, '') + `/form_cliente.php?t=${token}`;