281 lines
12 KiB
PHP
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'; ?>
|