diff --git a/admin/solicitud-detalle.php b/admin/solicitud-detalle.php new file mode 100644 index 0000000..28ff6f7 --- /dev/null +++ b/admin/solicitud-detalle.php @@ -0,0 +1,404 @@ + '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', +]; + +// Must have an ID +$solicitudId = isset($_GET['id']) ? (int)$_GET['id'] : 0; +if ($solicitudId <= 0) { + header('Location: solicitudes.php'); + exit; +} + +$errors = []; +$success = ''; + +// ── Handle POST actions ───────────────────────────────────────── +if ($_SERVER['REQUEST_METHOD'] === 'POST' && csrfValidate()) { + $action = $_POST['action'] ?? ''; + + switch ($action) { + + // ── Update estado ──────────────────────────────────────── + case 'update_estado': + $nuevoEstado = trim($_POST['estado'] ?? ''); + if (!array_key_exists($nuevoEstado, $estadoSolicitudLabels)) { + $errors[] = 'El estado seleccionado no es válido.'; + } else { + $stmt = $db->prepare("UPDATE solicitudes SET estado = ? WHERE id = ?"); + $stmt->execute([$nuevoEstado, $solicitudId]); + header("Location: solicitud-detalle.php?id=$solicitudId&estado_saved=1"); + exit; + } + break; + + // ── Vincular a cliente existente ───────────────────────── + case 'vincular_cliente': + $clienteId = (int)($_POST['cliente_id'] ?? 0); + if ($clienteId <= 0) { + $errors[] = 'Debe seleccionar un cliente.'; + } else { + // Verify client exists + $stmtCheck = $db->prepare("SELECT id FROM clientes WHERE id = ?"); + $stmtCheck->execute([$clienteId]); + if (!$stmtCheck->fetch()) { + $errors[] = 'El cliente seleccionado no existe.'; + } else { + $stmt = $db->prepare("UPDATE solicitudes SET cliente_id = ?, estado = 'convertida' WHERE id = ?"); + $stmt->execute([$clienteId, $solicitudId]); + header("Location: solicitud-detalle.php?id=$solicitudId&vinculado=1"); + exit; + } + } + break; + } +} + +// ── Load solicitud data ────────────────────────────────────────── +$stmt = $db->prepare("SELECT s.*, c.nombre AS cliente_nombre + FROM solicitudes s + LEFT JOIN clientes c ON s.cliente_id = c.id + WHERE s.id = ?"); +$stmt->execute([$solicitudId]); +$solicitud = $stmt->fetch(); + +if (!$solicitud) { + header('Location: solicitudes.php'); + exit; +} + +// Decode form data +$datosFormulario = []; +if (!empty($solicitud['datos_formulario'])) { + $datosFormulario = json_decode($solicitud['datos_formulario'], true) ?: []; +} + +// Build human-readable labels for form fields from servicios-data +$campoLabels = []; +$servicio = $solicitud['servicio'] ?? ''; +if (isset($SERVICIOS[$servicio]['campos_formulario'])) { + foreach ($SERVICIOS[$servicio]['campos_formulario'] as $campo) { + $campoLabels[$campo['name']] = $campo['label']; + } +} + +// Load all clients for vincular dropdown (only if not already linked) +$allClientes = []; +if (empty($solicitud['cliente_id'])) { + $stmtClientes = $db->prepare("SELECT id, nombre FROM clientes ORDER BY nombre ASC"); + $stmtClientes->execute(); + $allClientes = $stmtClientes->fetchAll(); +} + +// Success messages from redirects +if (isset($_GET['estado_saved'])) $success = 'Estado actualizado correctamente.'; +if (isset($_GET['vinculado'])) $success = 'Solicitud vinculada al cliente y marcada como convertida.'; + +$pageTitle = 'Solicitud: ' . $solicitud['nombre']; +?> + +
+

+ + + + + +

+

+ + Volver a Solicitudes + +

+
+ + + +
+ + + +
+ + + +
+ +
+ +
+ +
+
+ + + +
+
+

Datos de la Solicitud

+
+
+
+
+ Nombre + +
+
+ Teléfono + + + + + - + + +
+
+ Email + + + + + - + + +
+
+ Servicio + +
+
+ Fecha de Solicitud + +
+
+ Estado Actual + + + + + +
+
+
+
+ + + +
+
+

Datos del Formulario

+
+
+
+ $value): ?> + +
+ + +
+ +
+
+
+ + + + +
+
+

Cliente Vinculado

+
+
+

+ Esta solicitud está vinculada al cliente: + + + +

+ + Crear Trámite + +
+
+ + + +
+
+

Acciones

+
+
+ + +
+

Cambiar Estado

+
+ + +
+ +
+ +
+
+ + + +
+

Crear Cliente Nuevo

+

+ Se creará un nuevo cliente con los datos de esta solicitud (nombre, teléfono, email). +

+ + Crear Cliente Nuevo + +
+ + +
+

Vincular a Cliente Existente

+

+ Vincule esta solicitud a un cliente ya registrado. El estado cambiará automáticamente a “Convertida”. +

+ +
+ + +
+ +
+ +
+ +

No hay clientes registrados. Crear uno nuevo.

+ +
+ + +
+
+ + + + + + + + diff --git a/admin/solicitudes.php b/admin/solicitudes.php new file mode 100644 index 0000000..5356895 --- /dev/null +++ b/admin/solicitudes.php @@ -0,0 +1,213 @@ + '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 !== ''); +?> + +
+

+ Solicitudes + 0): ?> + + nueva 1 ? 's' : '' ?> + + +

+

Solicitudes recibidas desde el sitio web

+
+ + +
+
+ + + + Limpiar + + +
+
+ + +
+
+ +
+ +

+ + Ver todas + +
+ +
+ + + + + + + + + + + + + + + > + + + + + + + + + + +
NombreServicioTeléfonoEmailEstadoFechaAcción
+ + + + + + + + + + + + Ver + +
+
+ + + 1): ?> + + + +
+
+ +