281 lines
12 KiB
PHP

<?php
/**
* lista.php — Tabla dinámica de oficios con filtros
*/
require_once __DIR__ . '/../../config/config.php';
require_once __DIR__ . '/../../controllers/AuthController.php';
require_once __DIR__ . '/../../models/Oficio.php';
AuthController::requerirAuth();
$oficio = new OficioModel();
$esAdmin = AuthController::esAdmin();
$soloPropio = !$esAdmin && !AuthController::tienePermiso('oficios') !== 'CRUD';
// Filtros desde GET
$filtros = [
'tipo' => $_GET['tipo'] ?? '',
'estado' => $_GET['estado'] ?? '',
'prioridad' => $_GET['prioridad'] ?? '',
'responsable_id'=> $_GET['responsable_id']?? '',
'fecha_desde' => $_GET['fecha_desde'] ?? '',
'fecha_hasta' => $_GET['fecha_hasta'] ?? '',
'semaforo' => $_GET['semaforo'] ?? '',
'etiqueta_id' => $_GET['etiqueta_id'] ?? '',
'busqueda' => $_GET['busqueda'] ?? '',
];
$oficios = $oficio->listar($filtros, $soloPropio, $_SESSION['usuario_id']);
$etiquetas = $oficio->etiquetas();
// Título dinámico según tipo
$titulos = [
'recibido' => 'Bandeja de Entrada',
'enviado' => 'Bandeja de Salida',
'' => 'Todos los Oficios',
];
$pageTitle = $titulos[$filtros['tipo']] ?? 'Oficios';
$activeNav = $filtros['tipo'] === 'recibido' ? 'entrada' : ($filtros['tipo'] === 'enviado' ? 'salida' : 'lista');
$badgeEstado = [
'recibido' => 'badge-primary',
'en_proceso' => 'badge-warning',
'respondido' => 'badge-success',
'vencido' => 'badge-danger',
'archivado' => 'badge-secondary',
];
$badgePrioridad = [
'alta' => 'badge-danger',
'media' => 'badge-warning',
'baja' => 'badge-success',
];
include __DIR__ . '/../../views/layout/header.php';
include __DIR__ . '/../../views/layout/sidebar.php';
include __DIR__ . '/../../views/layout/topbar.php';
?>
<div class="page-content">
<!-- Breadcrumb -->
<div class="breadcrumb">
<a href="<?= APP_URL ?>/dashboard.php"><i class="fa-solid fa-house"></i></a>
<i class="fa-solid fa-chevron-right sep"></i>
<span><?= htmlspecialchars($pageTitle) ?></span>
</div>
<!-- Page Header -->
<div class="page-header">
<div class="page-header-content">
<h1><?= htmlspecialchars($pageTitle) ?></h1>
<p><?= count($oficios) ?> oficio(s) encontrado(s) con los filtros actuales</p>
</div>
<div class="d-flex gap-2 flex-wrap">
<?php if ($esAdmin): ?>
<a href="<?= APP_URL ?>/views/reportes/index.php" class="btn btn-secondary">
<i class="fa-solid fa-file-pdf"></i> Reporte PDF
</a>
<a href="<?= APP_URL ?>/views/reportes/carga_masiva.php" class="btn btn-secondary">
<i class="fa-solid fa-file-excel"></i> Carga Masiva
</a>
<?php endif; ?>
<a href="<?= APP_URL ?>/views/oficios/crear.php" class="btn btn-primary">
<i class="fa-solid fa-plus"></i> Nuevo Oficio
</a>
</div>
</div>
<!-- Filtros -->
<form method="GET" action="" id="filtrosForm">
<div class="filter-strip mb-3">
<div class="search-bar" style="max-width:280px;flex:2">
<i class="fa-solid fa-search"></i>
<input type="text" class="form-control" name="busqueda" placeholder="Buscar por asunto, número, remitente…" value="<?= htmlspecialchars($filtros['busqueda']) ?>">
</div>
<select name="tipo" class="form-control" onchange="this.form.submit()">
<option value="">Todos los tipos</option>
<option value="recibido" <?= $filtros['tipo']==='recibido' ? 'selected':'' ?>>Recibidos</option>
<option value="enviado" <?= $filtros['tipo']==='enviado' ? 'selected':'' ?>>Enviados</option>
</select>
<select name="estado" class="form-control" onchange="this.form.submit()">
<option value="">Todos los estados</option>
<option value="recibido" <?= $filtros['estado']==='recibido' ? 'selected':'' ?>>Recibido</option>
<option value="en_proceso" <?= $filtros['estado']==='en_proceso' ? 'selected':'' ?>>En Proceso</option>
<option value="respondido" <?= $filtros['estado']==='respondido' ? 'selected':'' ?>>Respondido</option>
<option value="vencido" <?= $filtros['estado']==='vencido' ? 'selected':'' ?>>Vencido</option>
<option value="archivado" <?= $filtros['estado']==='archivado' ? 'selected':'' ?>>Archivado</option>
</select>
<select name="prioridad" class="form-control" onchange="this.form.submit()">
<option value="">Todas las prioridades</option>
<option value="alta" <?= $filtros['prioridad']==='alta' ? 'selected':'' ?>>🔴 Alta</option>
<option value="media" <?= $filtros['prioridad']==='media' ? 'selected':'' ?>>🟡 Media</option>
<option value="baja" <?= $filtros['prioridad']==='baja' ? 'selected':'' ?>>🟢 Baja</option>
</select>
<select name="semaforo" class="form-control" onchange="this.form.submit()">
<option value="">Semáforo</option>
<option value="vencido" <?= $filtros['semaforo']==='vencido' ? 'selected':'' ?>>🔴 Vencido</option>
<option value="proximo" <?= $filtros['semaforo']==='proximo' ? 'selected':'' ?>>🟡 Próximo</option>
<option value="vigente" <?= $filtros['semaforo']==='vigente' ? 'selected':'' ?>>🟢 Vigente</option>
<option value="completado"<?= $filtros['semaforo']==='completado'? 'selected':'' ?>>🔵 Completado</option>
</select>
<input type="date" class="form-control" name="fecha_desde" value="<?= $filtros['fecha_desde'] ?>" title="Desde">
<input type="date" class="form-control" name="fecha_hasta" value="<?= $filtros['fecha_hasta'] ?>" title="Hasta">
<select name="etiqueta_id" class="form-control" onchange="this.form.submit()">
<option value="">Todas las etiquetas</option>
<?php foreach ($etiquetas as $et): ?>
<option value="<?= $et['id'] ?>" <?= $filtros['etiqueta_id']==$et['id']?'selected':'' ?>>
<?= htmlspecialchars($et['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
<button type="submit" class="btn btn-primary btn-sm"><i class="fa-solid fa-filter"></i> Filtrar</button>
<a href="?" class="btn btn-secondary btn-sm"><i class="fa-solid fa-rotate"></i> Limpiar</a>
</div>
</form>
<!-- Tabla de oficios -->
<div class="card">
<div class="card-body" style="padding:0">
<div class="table-responsive">
<table class="table" id="tablaOficios">
<thead>
<tr>
<th>Nº Oficio</th>
<th>Tipo</th>
<th>Asunto</th>
<th>Remitente / Destinatario</th>
<th>Responsable</th>
<th>Vence</th>
<th>Prioridad</th>
<th>Estado</th>
<th>Semáforo</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php if (empty($oficios)): ?>
<tr>
<td colspan="10" class="text-center" style="padding:2rem;color:var(--text-muted)">
<i class="fa-solid fa-folder-open" style="font-size:2rem;display:block;margin-bottom:.5rem;opacity:.3"></i>
No se encontraron oficios con los filtros aplicados
</td>
</tr>
<?php else: ?>
<?php foreach ($oficios as $o):
$semaforoClass = 'badge semaforo-' . ($o['semaforo'] ?? 'vigente');
$semaforoLabel = [
'vigente'=>'Vigente','proximo'=>'Próximo','vencido'=>'Vencido',
'completado'=>'Completado','sin_vencimiento'=>'Sin fecha'
][$o['semaforo'] ?? ''] ?? ($o['semaforo'] ?? '');
$diasLabel = '';
if ($o['fecha_vencimiento']) {
$d = (int)$o['dias_para_vencer'];
$diasLabel = $d < 0 ? abs($d).' días vencido' : ($d === 0 ? 'Hoy' : $d.' días');
}
?>
<tr>
<td>
<a href="<?= APP_URL ?>/views/oficios/detalle.php?id=<?= $o['id'] ?>" class="fw-600" style="color:var(--primary);text-decoration:none;">
<?= htmlspecialchars($o['numero_oficio']) ?>
</a>
<?php if ($o['total_adjuntos'] > 0): ?>
<span title="<?= $o['total_adjuntos'] ?> adjunto(s)" style="color:var(--text-muted);font-size:.75rem;margin-left:.3rem">
<i class="fa-solid fa-paperclip"></i>
</span>
<?php endif; ?>
</td>
<td>
<?php if ($o['tipo'] === 'recibido'): ?>
<span class="badge badge-info"><i class="fa-solid fa-inbox"></i> Entrada</span>
<?php else: ?>
<span class="badge badge-secondary"><i class="fa-solid fa-paper-plane"></i> Salida</span>
<?php endif; ?>
</td>
<td style="max-width:220px">
<div style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px" title="<?= htmlspecialchars($o['asunto']) ?>">
<?= htmlspecialchars(mb_strimwidth($o['asunto'], 0, 60, '…')) ?>
</div>
<?php if ($o['etiquetas']): ?>
<div style="margin-top:.2rem;font-size:.7rem;color:var(--text-muted)">
<i class="fa-solid fa-tag"></i> <?= htmlspecialchars($o['etiquetas']) ?>
</div>
<?php endif; ?>
</td>
<td style="font-size:.8rem">
<div><?= htmlspecialchars(mb_strimwidth($o['tipo']==='recibido' ? $o['remitente'] : $o['destinatario'], 0, 35, '…')) ?></div>
</td>
<td style="font-size:.8rem">
<?= htmlspecialchars($o['responsable_nombre'] ?? '—') ?>
</td>
<td style="font-size:.8rem;white-space:nowrap">
<?php if ($o['fecha_vencimiento']): ?>
<div><?= date('d/m/Y', strtotime($o['fecha_vencimiento'])) ?></div>
<div class="fs-sm text-muted"><?= $diasLabel ?></div>
<?php else: ?>
<span class="text-muted">—</span>
<?php endif; ?>
</td>
<td>
<span class="badge <?= $badgePrioridad[$o['prioridad']] ?? 'badge-secondary' ?>">
<?= ucfirst($o['prioridad']) ?>
</span>
</td>
<td>
<span class="badge <?= $badgeEstado[$o['estado']] ?? 'badge-secondary' ?>">
<?= ucfirst(str_replace('_',' ', $o['estado'])) ?>
</span>
</td>
<td>
<span class="badge <?= $semaforoClass ?>">
<?= $semaforoLabel ?>
</span>
</td>
<td>
<div class="d-flex gap-1">
<a href="<?= APP_URL ?>/views/oficios/detalle.php?id=<?= $o['id'] ?>" class="btn btn-sm btn-secondary" title="Ver detalle">
<i class="fa-solid fa-eye"></i>
</a>
<a href="<?= APP_URL ?>/views/oficios/editar.php?id=<?= $o['id'] ?>" class="btn btn-sm btn-warning" title="Editar">
<i class="fa-solid fa-pen"></i>
</a>
<a href="<?= APP_URL ?>/controllers/OficioController.php?action=pdf&id=<?= $o['id'] ?>" class="btn btn-sm btn-info" title="Exportar PDF" target="_blank">
<i class="fa-solid fa-file-pdf"></i>
</a>
<a href="<?= APP_URL ?>/controllers/OficioController.php?action=eliminar&id=<?= $o['id'] ?>"
class="btn btn-sm btn-danger"
title="Eliminar"
data-confirm="¿Mover este oficio a la papelera?">
<i class="fa-solid fa-trash"></i>
</a>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div><!-- /.page-content -->
<script>
$(document).ready(function() {
initDataTable('#tablaOficios', {
searching: false, // búsqueda ya manejada por el form
columnDefs: [{ orderable: false, targets: [9] }],
order: [[5, 'asc']], // ordenar por vencimiento
});
});
</script>
<?php include __DIR__ . '/../../views/layout/footer.php'; ?>