Add solicitudes list page with estado filtering, pagination, and new request count badge. Add detail page showing all form data with actions to change status, create new client, link to existing client, and create tramite from linked client. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
214 lines
8.3 KiB
PHP
214 lines
8.3 KiB
PHP
<?php
|
|
$pageTitle = 'Solicitudes';
|
|
require_once __DIR__ . '/../includes/db.php';
|
|
require_once __DIR__ . '/includes/admin-header.php';
|
|
|
|
$db = getDB();
|
|
|
|
// Label maps
|
|
$servicioLabels = [
|
|
'visa' => 'Visa',
|
|
'sentri' => 'Sentri/Global',
|
|
'pasaporte' => 'Pasaporte',
|
|
'adelanto_cita' => 'Adelanto Cita',
|
|
'doble_nacionalidad' => 'Doble Nacionalidad',
|
|
];
|
|
$estadoSolicitudLabels = [
|
|
'nueva' => 'Nueva',
|
|
'contactada' => 'Contactada',
|
|
'convertida' => 'Convertida',
|
|
'descartada' => 'Descartada',
|
|
];
|
|
$estadoBadgeClass = [
|
|
'nueva' => 'primary',
|
|
'contactada' => 'warning',
|
|
'convertida' => 'success',
|
|
'descartada' => 'danger',
|
|
];
|
|
|
|
// Filters & Pagination
|
|
$fEstado = trim($_GET['estado'] ?? '');
|
|
$page = max(1, (int)($_GET['page'] ?? 1));
|
|
$perPage = 15;
|
|
$offset = ($page - 1) * $perPage;
|
|
|
|
// Validate filter
|
|
$validEstados = array_keys($estadoSolicitudLabels);
|
|
if ($fEstado !== '' && !in_array($fEstado, $validEstados, true)) $fEstado = '';
|
|
|
|
// Build WHERE clause
|
|
$conditions = [];
|
|
$params = [];
|
|
|
|
if ($fEstado !== '') {
|
|
$conditions[] = 's.estado = ?';
|
|
$params[] = $fEstado;
|
|
}
|
|
|
|
$where = '';
|
|
if (!empty($conditions)) {
|
|
$where = 'WHERE ' . implode(' AND ', $conditions);
|
|
}
|
|
|
|
// Count total
|
|
$countSql = "SELECT COUNT(*) FROM solicitudes s $where";
|
|
$countStmt = $db->prepare($countSql);
|
|
$countStmt->execute($params);
|
|
$totalSolicitudes = $countStmt->fetchColumn();
|
|
$totalPages = max(1, (int)ceil($totalSolicitudes / $perPage));
|
|
|
|
// Ensure page is within range
|
|
if ($page > $totalPages) $page = $totalPages;
|
|
|
|
// Count new requests for header badge
|
|
$stmtNew = $db->prepare("SELECT COUNT(*) FROM solicitudes WHERE estado = 'nueva'");
|
|
$stmtNew->execute();
|
|
$countNuevas = (int)$stmtNew->fetchColumn();
|
|
|
|
// Fetch solicitudes
|
|
$sql = "SELECT s.*
|
|
FROM solicitudes s
|
|
$where
|
|
ORDER BY s.created_at DESC
|
|
LIMIT $perPage OFFSET $offset";
|
|
$stmt = $db->prepare($sql);
|
|
$stmt->execute($params);
|
|
$solicitudes = $stmt->fetchAll();
|
|
|
|
// Check if any filters are active
|
|
$hasFilters = ($fEstado !== '');
|
|
?>
|
|
|
|
<div class="admin-content__header">
|
|
<h1>
|
|
<i class="fas fa-inbox"></i> Solicitudes
|
|
<?php if ($countNuevas > 0): ?>
|
|
<span class="badge badge--primary" style="font-size: 0.5em; vertical-align: middle;">
|
|
<?= $countNuevas ?> nueva<?= $countNuevas > 1 ? 's' : '' ?>
|
|
</span>
|
|
<?php endif; ?>
|
|
</h1>
|
|
<p>Solicitudes recibidas desde el sitio web</p>
|
|
</div>
|
|
|
|
<!-- Toolbar: Filters -->
|
|
<div class="toolbar">
|
|
<div class="toolbar__left">
|
|
<form method="GET" class="search-bar search-bar--wide" action="solicitudes.php" style="display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap;">
|
|
<select name="estado" class="form-control" style="width: auto; min-width: 160px;">
|
|
<option value="">-- Todos los estados --</option>
|
|
<?php foreach ($estadoSolicitudLabels as $val => $label): ?>
|
|
<option value="<?= htmlspecialchars($val) ?>" <?= $fEstado === $val ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($label) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<button type="submit" class="btn btn--sm btn--secondary">
|
|
<i class="fas fa-filter"></i> Filtrar
|
|
</button>
|
|
</form>
|
|
<?php if ($hasFilters): ?>
|
|
<a href="solicitudes.php" class="btn btn--sm btn--secondary" style="margin-left: 0.5rem;">
|
|
<i class="fas fa-times"></i> Limpiar
|
|
</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Solicitudes Table -->
|
|
<div class="card">
|
|
<div class="card__body">
|
|
<?php if (empty($solicitudes)): ?>
|
|
<div class="table-empty">
|
|
<i class="fas fa-inbox"></i>
|
|
<p><?= $hasFilters ? 'No se encontraron solicitudes con ese filtro.' : 'No hay solicitudes registradas aún.' ?></p>
|
|
<?php if ($hasFilters): ?>
|
|
<a href="solicitudes.php" class="btn btn--sm btn--outline">Ver todas</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="table-responsive">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Nombre</th>
|
|
<th>Servicio</th>
|
|
<th>Teléfono</th>
|
|
<th>Email</th>
|
|
<th>Estado</th>
|
|
<th>Fecha</th>
|
|
<th>Acción</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($solicitudes as $s): ?>
|
|
<tr<?= $s['estado'] === 'nueva' ? ' style="background: rgba(23, 162, 184, 0.06);"' : '' ?>>
|
|
<td>
|
|
<?php if ($s['estado'] === 'nueva'): ?>
|
|
<strong style="color: var(--admin-primary, #0C7C8C);"><?= htmlspecialchars($s['nombre']) ?></strong>
|
|
<?php else: ?>
|
|
<strong><?= htmlspecialchars($s['nombre']) ?></strong>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= htmlspecialchars($servicioLabels[$s['servicio']] ?? $s['servicio']) ?></td>
|
|
<td><?= htmlspecialchars($s['telefono'] ?: '-') ?></td>
|
|
<td><?= htmlspecialchars($s['email'] ?: '-') ?></td>
|
|
<td>
|
|
<span class="badge badge--<?= htmlspecialchars($estadoBadgeClass[$s['estado']] ?? 'secondary') ?>">
|
|
<?= htmlspecialchars($estadoSolicitudLabels[$s['estado']] ?? $s['estado']) ?>
|
|
</span>
|
|
</td>
|
|
<td><?= date('d/m/Y H:i', strtotime($s['created_at'])) ?></td>
|
|
<td>
|
|
<a href="solicitud-detalle.php?id=<?= (int)$s['id'] ?>" class="btn btn--sm btn--primary">
|
|
<i class="fas fa-eye"></i> Ver
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
<?php if ($totalPages > 1): ?>
|
|
<div class="pagination">
|
|
<?php
|
|
$queryParams = '';
|
|
if ($fEstado !== '') $queryParams .= '&estado=' . urlencode($fEstado);
|
|
?>
|
|
<a href="?page=1<?= $queryParams ?>" class="pagination__link <?= $page <= 1 ? 'pagination__link--disabled' : '' ?>">
|
|
<i class="fas fa-angle-double-left"></i>
|
|
</a>
|
|
<a href="?page=<?= $page - 1 ?><?= $queryParams ?>" class="pagination__link <?= $page <= 1 ? 'pagination__link--disabled' : '' ?>">
|
|
<i class="fas fa-angle-left"></i>
|
|
</a>
|
|
|
|
<?php
|
|
$start = max(1, $page - 2);
|
|
$end = min($totalPages, $page + 2);
|
|
for ($i = $start; $i <= $end; $i++):
|
|
?>
|
|
<a href="?page=<?= $i ?><?= $queryParams ?>" class="pagination__link <?= $i === $page ? 'pagination__link--active' : '' ?>">
|
|
<?= $i ?>
|
|
</a>
|
|
<?php endfor; ?>
|
|
|
|
<a href="?page=<?= $page + 1 ?><?= $queryParams ?>" class="pagination__link <?= $page >= $totalPages ? 'pagination__link--disabled' : '' ?>">
|
|
<i class="fas fa-angle-right"></i>
|
|
</a>
|
|
<a href="?page=<?= $totalPages ?><?= $queryParams ?>" class="pagination__link <?= $page >= $totalPages ? 'pagination__link--disabled' : '' ?>">
|
|
<i class="fas fa-angle-double-right"></i>
|
|
</a>
|
|
|
|
<span class="pagination__info">
|
|
Página <?= $page ?> de <?= $totalPages ?> (<?= $totalSolicitudes ?> solicitudes)
|
|
</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php require_once __DIR__ . '/includes/admin-footer.php'; ?>
|