feat(export): UI unificada de Excel + PDF en los 4 módulos
- Nuevos assets compartidos /assets/donna-export.{css,js}: botón
"Exportar ▾" + menú dropdown Excel/PDF y helpers DonnaExport.toExcel
/ .toPDF / .attach / .buttonHtml
- escrituras: refactor de exportExcel/exportPDF para usar el módulo
compartido (sin cambio de comportamiento)
- tramites: nuevo botón en la toolbar de cada tab (adm/corp/mig/lit),
exporta los rows filtrados de ese tab; PDF excluye Involucrados
- calendario: nuevo botón al final de la toolbar, exporta visibleEvents()
(respeta chips de origen y búsqueda)
- horas: reemplaza CSV server-side por XLSX client-side + agrega PDF;
removida la acción ?action=export del api.php
This commit is contained in:
@@ -140,6 +140,7 @@ tr.expanded>td{background:#fffdf5;}
|
||||
.toast.show{transform:translateY(0);opacity:1;}
|
||||
.toast.error{border-left-color:#ef5350;}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/assets/donna-export.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -213,6 +214,8 @@ tr.expanded>td{background:#fffdf5;}
|
||||
|
||||
<div id="toast" class="toast"></div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
||||
<script src="/assets/donna-export.js"></script>
|
||||
<script>
|
||||
const ABOGADOS = (window.DONNA && window.DONNA.abogados) || ['Arias','Abrego','Lopez','Altafulla','Álvarez','Gutiérrez','Cedeño','Mariscal','Ávila','Agudo','Martínez','De Gracia','Góndola','González','Valdés'];
|
||||
const USERS = (window.DONNA && window.DONNA.users) || [];
|
||||
@@ -391,6 +394,8 @@ function renderPanel(dept){
|
||||
const activos=rows.filter(r=>r.estatus!=='Culminado'&&r.estatus!=='Facturado').length;
|
||||
const culminados=rows.filter(r=>r.estatus==='Culminado'||r.estatus==='Facturado').length;
|
||||
|
||||
window.__tramFiltered = window.__tramFiltered || {};
|
||||
window.__tramFiltered[dept] = filtered;
|
||||
panel.innerHTML=`
|
||||
<div class="counts">
|
||||
<div class="count-card"><b>${total}</b>Total</div>
|
||||
@@ -412,6 +417,7 @@ function renderPanel(dept){
|
||||
<option${fEsfera==='Civil'?' selected':''}>Civil</option><option${fEsfera==='Penal'?' selected':''}>Penal</option>
|
||||
</select>`:''}
|
||||
${CAN_CREATE ? `<button class="btn btn-primary" onclick="openModal('${dept}',null)">+ Nuevo</button>` : ''}
|
||||
${DonnaExport.buttonHtml('export-wrap-'+dept)}
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table>
|
||||
@@ -421,6 +427,50 @@ function renderPanel(dept){
|
||||
</tbody>
|
||||
</table>
|
||||
</div>`;
|
||||
DonnaExport.attach('export-wrap-'+dept, {
|
||||
onExcel: () => tramExportExcel(dept),
|
||||
onPDF: () => tramExportPDF(dept),
|
||||
});
|
||||
}
|
||||
|
||||
// ── EXPORT (Trámites) ────────────────────────────────────────────────────
|
||||
const TRAM_HEADERS = {
|
||||
adm: ['Código','Institución','Nombre Trámite','Cliente','Abogado','Involucrados','Estatus','Fecha Solicitud','Horas'],
|
||||
corp: ['Código','Tipo Documento','Nombre Trámite','Cliente','Abogado','Involucrados','Estatus','Fecha Solicitud','Horas'],
|
||||
mig: ['Código','Tipo Trámite','Cliente','Abogado','Involucrados','Doc. Completa','Permiso Trabajo','Dependientes','Estatus','Fecha Solicitud','Vencimiento','Horas'],
|
||||
lit: ['Código','Proceso','Juzgado','Cliente','Abogado','Involucrados','Esfera','Instancia','Doc. Completa','Incidentes','Amparo','Estatus','Fecha Solicitud','Término','Horas'],
|
||||
};
|
||||
function fmtDateOnly(s){ return s ? String(s).substring(0,10) : ''; }
|
||||
function invsCSV(invs){ return (invs||[]).map(u => u.name || u.email).join(', '); }
|
||||
function tramRowToArray(dept, r){
|
||||
const inv = invsCSV(r.involucrados);
|
||||
if (dept === 'adm') return [r.codigo, r.institucion||'', r.nombre||'', r.cliente||'', r.abogado||'', inv, r.estatus||'', fmtDateOnly(r.fecha_solicitud), totalHours(r)];
|
||||
if (dept === 'corp')return [r.codigo, r.tipo_documento||'', r.nombre||'', r.cliente||'', r.abogado||'', inv, r.estatus||'', fmtDateOnly(r.fecha_solicitud), totalHours(r)];
|
||||
if (dept === 'mig') return [r.codigo, r.tipo_tramite||'', r.cliente||'', r.abogado||'', inv, r.doc_completa||'', r.permiso_trabajo||'', r.dependientes||'', r.estatus||'', fmtDateOnly(r.fecha_solicitud), fmtDateOnly(r.fecha_vencimiento), totalHours(r)];
|
||||
if (dept === 'lit') return [r.codigo, r.tipo_proceso||'', r.juzgado||'', r.cliente||'', r.abogado||'', inv, r.esfera||'', r.instancia||'', r.doc_completa||'', r.incidentes||'', r.amparo||'', r.estatus||'', fmtDateOnly(r.fecha_solicitud), fmtDateOnly(r.fecha_termino), totalHours(r)];
|
||||
}
|
||||
function tramExportExcel(dept){
|
||||
const rows = (window.__tramFiltered && window.__tramFiltered[dept]) || data[dept] || [];
|
||||
DonnaExport.toExcel({
|
||||
filename: 'Tramites_'+dept.toUpperCase()+'_AALN',
|
||||
sheetName: DEPT_LABELS[dept] || dept,
|
||||
headers: TRAM_HEADERS[dept],
|
||||
rows: rows.map(r => tramRowToArray(dept, r)),
|
||||
onEmpty: () => toast('No hay datos para exportar','error'),
|
||||
});
|
||||
}
|
||||
function tramExportPDF(dept){
|
||||
const rows = (window.__tramFiltered && window.__tramFiltered[dept]) || data[dept] || [];
|
||||
// En PDF excluye Involucrados (lista larga) para que quepa
|
||||
const cols = TRAM_HEADERS[dept].map((_,i) => i).filter(i => TRAM_HEADERS[dept][i] !== 'Involucrados');
|
||||
DonnaExport.toPDF({
|
||||
filename: 'Tramites_'+dept.toUpperCase()+'_AALN',
|
||||
title: 'Control de Trámites Legales · ' + (DEPT_LABELS[dept] || dept),
|
||||
headers: TRAM_HEADERS[dept],
|
||||
rows: rows.map(r => tramRowToArray(dept, r)),
|
||||
pdfCols: cols,
|
||||
onEmpty: () => toast('No hay datos para exportar','error'),
|
||||
});
|
||||
}
|
||||
|
||||
function buildHeaders(dept){
|
||||
|
||||
Reference in New Issue
Block a user