File "visualizar.php"
Full Path: C:/wamp64/www/AVIDOTAPP/views/anexos/visualizar.php
File size: 13.77 KB
MIME-type: text/html
Charset: utf-8
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Visualizador de Documentos Anexados</title>
<link rel="icon" type="image/png" href="assets/img/icono.png">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body { background:linear-gradient(225deg,#d0101d,#752b2a); min-height:100vh; padding:20px; }
.doc-container {
background:#fff; border-radius:20px; max-width:960px; width:100%;
padding:40px; box-shadow:10px 10px 20px 0 rgba(0,0,0,.3); margin:0 auto;
}
.document-card {
border:2px solid #d9534f; border-radius:10px; padding:14px;
margin-bottom:12px; transition:all .25s ease; animation:fadeIn .3s ease;
}
.document-card:hover { transform:translateY(-3px); box-shadow:0 8px 20px rgba(0,0,0,.1); }
.document-card.selected { background:#e3f2fd; border-color:#2196f3; }
.btn-view { background:#5bc0de; color:#fff; border:none; }
.btn-download { background:#d0101d; color:#fff; border:none; }
.btn-delete { background:#6c757d; color:#fff; border:none; }
.btn-view:hover,.btn-download:hover,.btn-delete:hover { opacity:.8; }
.stats-badge { background:#979393; color:#fff; padding:5px 12px; border-radius:15px; font-size:.85em; margin-left:8px; }
.search-stats { background:#f8f9fa; padding:10px 15px; border-radius:8px; margin-bottom:15px; border-left:4px solid #007bff; }
.date-filter { background:#f8f9fa; padding:15px; border-radius:10px; margin-bottom:20px; border-left:4px solid #28a745; }
.no-results { display:none; text-align:center; padding:40px; color:#666; background:#f8f9fa; border-radius:10px; }
.highlight { background:#ffeb3b; font-weight:bold; padding:2px 4px; border-radius:3px; }
.pagination-wrap { display:flex; justify-content:center; gap:15px; margin-top:25px; align-items:center; }
.pag-info { background:#f8f9fa; padding:7px 14px; border-radius:20px; font-size:.9em; color:#666; }
@keyframes fadeIn { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }
</style>
</head>
<body>
<div class="container">
<div class="doc-container">
<img src="assets/img/LOGO.png" alt="" style="max-width:220px;display:block;margin:0 auto 1.5rem;" onerror="this.style.display='none'">
<?php
// Helper de iconos
function iconForExt($archivo) {
$ext = strtolower(pathinfo($archivo, PATHINFO_EXTENSION));
$map = ['pdf'=>'fa-file-pdf text-danger','jpg'=>'fa-file-image text-success',
'jpeg'=>'fa-file-image text-success','png'=>'fa-file-image text-success',
'gif'=>'fa-file-image text-success','txt'=>'fa-file-alt text-info',
'doc'=>'fa-file-word text-primary','docx'=>'fa-file-word text-primary',
'xls'=>'fa-file-excel text-success','xlsx'=>'fa-file-excel text-success'];
return 'fas ' . ($map[$ext] ?? 'fa-file text-secondary');
}
function puedeVisualizar($archivo) {
$ext = strtolower(pathinfo($archivo, PATHINFO_EXTENSION));
return in_array($ext, ['pdf','jpg','jpeg','png','gif','txt']);
}
?>
<h2 class="text-center">
Documentos Anexados
<span class="stats-badge" id="totalStats">
<i class="fas fa-file-alt"></i> <?= $totalDocuments ?> documentos
</span>
</h2>
<hr>
<!-- Alertas flash -->
<?php if (!empty($_SESSION['anexo_ok'])): ?>
<div class="alert alert-success"><i class="fas fa-check-circle me-2"></i><?= $_SESSION['anexo_ok'] ?></div>
<?php unset($_SESSION['anexo_ok']); ?>
<?php endif; ?>
<!-- Botones superiores -->
<div class="mb-4 d-flex gap-2 flex-wrap">
<a href="index.php?controller=Anexo&action=index" class="btn btn-danger">
<i class="fas fa-upload me-1"></i>Subir Documento
</a>
<a href="javascript:history.back()" class="btn btn-warning">
<i class="fas fa-undo me-1"></i>Regresar
</a>
<a href="index.php?controller=Dashboard&action=index" class="btn btn-secondary">
<i class="fas fa-house me-1"></i>Menú
</a>
</div>
<!-- Filtro por fecha y búsqueda -->
<form method="GET" action="index.php" class="date-filter">
<input type="hidden" name="controller" value="Anexo">
<input type="hidden" name="action" value="visualizar">
<div class="row align-items-end g-3">
<div class="col-md-4">
<label class="form-label"><i class="fas fa-calendar-alt me-1"></i>Filtrar por fecha:</label>
<input type="date" name="date" class="form-control" value="<?= htmlspecialchars($dateFilter) ?>">
</div>
<div class="col-md-4">
<label class="form-label"><i class="fas fa-search me-1"></i>Buscar por nombre:</label>
<input type="text" name="search" class="form-control" placeholder="Nombre del archivo..."
value="<?= htmlspecialchars($searchTerm) ?>">
</div>
<div class="col-md-4 d-flex gap-2 align-items-end">
<button type="submit" class="btn btn-primary flex-grow-1">
<i class="fas fa-filter me-1"></i>Filtrar
</button>
<a href="index.php?controller=Anexo&action=visualizar" class="btn btn-outline-secondary">
<i class="fas fa-times"></i>
</a>
</div>
</div>
<?php if ($dateFilter || $searchTerm): ?>
<div class="mt-2">
<small class="text-muted">Filtros activos:
<?php if ($dateFilter): ?><span class="badge bg-info">Fecha: <?= htmlspecialchars($dateFilter) ?></span><?php endif; ?>
<?php if ($searchTerm): ?><span class="badge bg-info">Búsqueda: "<?= htmlspecialchars($searchTerm) ?>"</span><?php endif; ?>
</small>
</div>
<?php endif; ?>
</form>
<!-- Búsqueda en tiempo real (cliente) -->
<div class="mb-3">
<div class="input-group">
<input type="text" id="searchInput" class="form-control"
placeholder="Buscar en tiempo real..." autocomplete="off">
<button class="btn btn-outline-secondary" id="clearSearch" style="display:none">
<i class="fas fa-times"></i>
</button>
<button class="btn btn-outline-secondary" id="searchButton">
<i class="fas fa-search"></i>
</button>
</div>
<small class="text-muted mt-1 d-block"><i class="fas fa-keyboard me-1"></i><strong>Escape</strong> para limpiar</small>
</div>
<div class="search-stats" id="searchStats">
<i class="fas fa-chart-bar me-1"></i>
Mostrando <span id="resultsCount"><?= count($currentPageFiles) ?></span>
de <span id="totalDocuments"><?= $totalDocuments ?></span> documentos
<?php if ($totalPages > 1): ?> — Página <?= $page ?> de <?= $totalPages ?><?php endif; ?>
</div>
<div id="noResults" class="no-results">
<i class="fas fa-search fa-3x mb-3" style="color:#ddd"></i>
<h5>No se encontraron resultados</h5>
</div>
<!-- Tarjetas de documentos -->
<div class="row" id="documentsContainer">
<?php if (!empty($currentPageFiles)): ?>
<?php foreach ($currentPageFiles as $fi):
$archivo = $fi['name'];
$ruta = $fi['path'];
$icono = iconForExt($archivo);
$ver = puedeVisualizar($archivo);
?>
<div class="col-md-6 document-item"
data-filename="<?= strtolower(htmlspecialchars($archivo)) ?>"
data-date="<?= htmlspecialchars($fi['date']) ?>">
<div class="document-card" onclick="selectDoc(this)">
<div class="d-flex justify-content-between align-items-center gap-2">
<div class="text-truncate flex-grow-1">
<i class="<?= $icono ?> me-1"></i>
<span class="fw-bold document-name" title="<?= htmlspecialchars($archivo) ?>">
<?= htmlspecialchars($archivo) ?>
</span>
<br>
<small class="text-muted"><i class="fas fa-clock me-1"></i><?= $fi['date'] ?></small>
</div>
<div class="btn-group btn-group-sm flex-shrink-0">
<?php if ($ver): ?>
<a href="<?= htmlspecialchars($ruta) ?>" target="_blank" class="btn btn-view" title="Ver">
<i class="fas fa-eye"></i>
</a>
<?php endif; ?>
<a href="<?= htmlspecialchars($ruta) ?>" download class="btn btn-download" title="Descargar">
<i class="fas fa-download"></i>
</a>
<a href="index.php?controller=Anexo&action=eliminar&archivo=<?= urlencode($archivo) ?>"
class="btn btn-delete btn-eliminar" title="Eliminar"
data-nombre="<?= htmlspecialchars($archivo) ?>">
<i class="fas fa-trash-can"></i>
</a>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<?php elseif ($dateFilter || $searchTerm): ?>
<div class="col-12">
<div class="alert alert-warning">
<i class="fas fa-filter me-2"></i>No se encontraron documentos con los filtros aplicados.
</div>
</div>
<?php else: ?>
<div class="col-12">
<div class="alert alert-info">
<i class="fas fa-info-circle me-2"></i>No hay documentos en la carpeta de anexos.
<a href="index.php?controller=Anexo&action=index" class="btn btn-danger btn-sm ms-2">
<i class="fas fa-upload me-1"></i>Subir ahora
</a>
</div>
</div>
<?php endif; ?>
</div>
<!-- Paginación -->
<?php if ($totalPages > 1):
$qBase = '&date=' . urlencode($dateFilter) . '&search=' . urlencode($searchTerm);
?>
<div class="pagination-wrap">
<span class="pag-info">
Mostrando <?= $offset + 1 ?>–<?= min($offset + $itemsPerPage, $totalDocuments) ?>
de <?= $totalDocuments ?>
</span>
<nav><ul class="pagination mb-0">
<?php if ($page > 1): ?>
<li class="page-item">
<a class="page-link" href="index.php?controller=Anexo&action=visualizar&page=<?= $page-1 . $qBase ?>">
<i class="fas fa-chevron-left"></i>
</a>
</li>
<?php endif; ?>
<?php for ($i = max(1,$page-2); $i <= min($totalPages,$page+2); $i++): ?>
<li class="page-item <?= $i==$page?'active':'' ?>">
<a class="page-link" href="index.php?controller=Anexo&action=visualizar&page=<?= $i . $qBase ?>">
<?= $i ?>
</a>
</li>
<?php endfor; ?>
<?php if ($page < $totalPages): ?>
<li class="page-item">
<a class="page-link" href="index.php?controller=Anexo&action=visualizar&page=<?= $page+1 . $qBase ?>">
<i class="fas fa-chevron-right"></i>
</a>
</li>
<?php endif; ?>
</ul></nav>
</div>
<?php endif; ?>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.7.5/sweetalert2.all.min.js"></script>
<script>
// Confirmar eliminación
document.querySelectorAll('.btn-eliminar').forEach(btn => {
btn.addEventListener('click', function(e) {
e.preventDefault();
const nombre = this.dataset.nombre;
const href = this.href;
Swal.fire({
title: '¿Eliminar archivo?',
text: nombre,
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d0101d',
cancelButtonText: 'Cancelar',
confirmButtonText: 'Sí, eliminar'
}).then(r => { if (r.isConfirmed) window.location = href; });
});
});
// Búsqueda en tiempo real
const searchInput = document.getElementById('searchInput');
const clearBtn = document.getElementById('clearSearch');
const items = document.querySelectorAll('.document-item');
const noResults = document.getElementById('noResults');
const stats = document.getElementById('searchStats');
const count = document.getElementById('resultsCount');
const total = items.length;
function selectDoc(card) {
document.querySelectorAll('.document-card').forEach(c => c.classList.remove('selected'));
card.classList.add('selected');
}
function filterDocs() {
const term = searchInput.value.toLowerCase().trim();
let visible = 0;
clearBtn.style.display = term ? 'block' : 'none';
items.forEach(item => {
const name = item.getAttribute('data-filename');
const show = !term || name.includes(term);
item.style.display = show ? '' : 'none';
if (show) visible++;
});
count.textContent = visible;
noResults.style.display = (term && visible === 0) ? 'block' : 'none';
stats.style.display = (term && visible === 0) ? 'none' : 'block';
}
function clearSearch() {
searchInput.value = '';
clearBtn.style.display = 'none';
items.forEach(i => i.style.display = '');
count.textContent = total;
noResults.style.display = 'none';
stats.style.display = 'block';
searchInput.focus();
}
searchInput.addEventListener('input', () => { clearTimeout(window._st); window._st = setTimeout(filterDocs, 250); });
clearBtn.addEventListener('click', clearSearch);
document.addEventListener('keydown', e => { if (e.key === 'Escape') clearSearch(); });
searchInput.focus();
window.selectDoc = selectDoc;
</script>
</body>
</html>