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>