diff --git a/api/lab/get_pacientes.php b/api/lab/get_pacientes.php index 6104a38..6e6c8dd 100644 --- a/api/lab/get_pacientes.php +++ b/api/lab/get_pacientes.php @@ -13,11 +13,17 @@ try { jsonOk(['data' => [$row]]); } + if (isset($_GET['stats'])) { + jsonOk(['stats' => $pac->stats()]); + } + $busqueda = trim($_GET['busqueda'] ?? $_GET['search'] ?? ''); $pagina = max(1, (int)($_GET['page'] ?? $_GET['pagina'] ?? 1)); $por = max(1, min(100, (int)($_GET['limit'] ?? $_GET['por_pagina'] ?? 30))); + $origen = in_array($_GET['origen'] ?? '', ['manual', 'rips', 'whatsapp'], true) + ? $_GET['origen'] : ''; - jsonOk($pac->listar($busqueda, $pagina, $por)); + jsonOk($pac->listar($busqueda, $pagina, $por, $origen)); } catch (Exception $e) { jsonError($e->getMessage(), 500); } diff --git a/api/lab/ingest_paciente.php b/api/lab/ingest_paciente.php index 6ee1e78..bdd16c3 100644 --- a/api/lab/ingest_paciente.php +++ b/api/lab/ingest_paciente.php @@ -121,6 +121,9 @@ if (!empty($data['ciudad'])) { if (!empty($data['eps'])) { $campos['eps'] = trim($data['eps']); } +$origenValidos = ['manual', 'rips', 'whatsapp']; +$campos['origen'] = in_array($data['origen'] ?? '', $origenValidos, true) + ? $data['origen'] : 'rips'; // ── Modo: "insertar" (solo nuevos) | "upsert" (crea o actualiza) ───────────── $modo = trim($data['modo'] ?? 'upsert'); diff --git a/classes/lab/Paciente.php b/classes/lab/Paciente.php index 6352843..52ac9f4 100644 --- a/classes/lab/Paciente.php +++ b/classes/lab/Paciente.php @@ -27,20 +27,25 @@ class Paciente { public function listar( string $busqueda = '', int $pagina = 1, - int $porPagina = 30 + int $porPagina = 30, + string $origen = '' ): array { $offset = ($pagina - 1) * $porPagina; $like = "%$busqueda%"; - $params = $busqueda - ? [$like, $like, $like, $like] - : []; - $where = $busqueda - ? "WHERE p.nombre_completo LIKE ? - OR p.numero_documento LIKE ? - OR p.telefono LIKE ? - OR p.email LIKE ?" - : ''; + $conditions = []; + $params = []; + + if ($busqueda) { + $conditions[] = "(p.nombre_completo LIKE ? OR p.numero_documento LIKE ? OR p.telefono LIKE ? OR p.email LIKE ?)"; + $params = [$like, $like, $like, $like]; + } + if ($origen) { + $conditions[] = "p.origen = ?"; + $params[] = $origen; + } + + $where = $conditions ? 'WHERE ' . implode(' AND ', $conditions) : ''; $total = $this->db->fetch( "SELECT COUNT(*) AS n FROM lab_pacientes p $where", @@ -56,7 +61,7 @@ class Paciente { FROM lab_pacientes p LEFT JOIN users u ON u.id = p.user_id $where - ORDER BY p.nombre_completo ASC + ORDER BY p.created_at DESC, p.nombre_completo ASC LIMIT ? OFFSET ? ", array_merge($params, [$porPagina, $offset])); @@ -69,6 +74,19 @@ class Paciente { ]; } + public function stats(): array { + return $this->db->fetch(" + SELECT + COUNT(*) AS total, + SUM(origen = 'rips') AS importados, + SUM(origen = 'manual') AS manuales, + SUM(origen = 'whatsapp') AS whatsapp, + SUM(user_id IS NOT NULL) AS con_wa + FROM lab_pacientes + WHERE is_active = 1 + ") ?: ['total' => 0, 'importados' => 0, 'manuales' => 0, 'whatsapp' => 0, 'con_wa' => 0]; + } + /** * Un paciente por ID (con datos del usuario WhatsApp). */ @@ -238,7 +256,7 @@ class Paciente { 'user_id', 'numero_documento', 'tipo_documento', 'nombre_completo', 'telefono', 'email', 'fecha_nacimiento', 'genero', 'direccion', - 'ciudad', 'barrio', 'eps', 'notas_admin', 'is_active', + 'ciudad', 'barrio', 'eps', 'notas_admin', 'is_active', 'origen', ]; $campos = array_intersect_key($datos, array_flip($permitidos)); if (!empty($campos['telefono'])) { diff --git a/lab_pacientes.php b/lab_pacientes.php index a0e22ad..db0083c 100644 --- a/lab_pacientes.php +++ b/lab_pacientes.php @@ -155,8 +155,37 @@ require_once __DIR__ . '/shared/components/sidebar.php';
- -
+ + +
+
+
+
+
Total
+
+
+
+
+
+
Importados RIPS
+
+
+
+
+
+
Vinculados WA
+
+
+
+
+
+
Manuales
+
+
+
+ + +
@@ -165,6 +194,19 @@ require_once __DIR__ . '/shared/components/sidebar.php'; oninput="debounce(cargarLista, 380)()">
+
+ +
+
+ +
@@ -178,14 +220,15 @@ require_once __DIR__ . '/shared/components/sidebar.php'; Paciente Documento - Teléfono - EPS + Ciudad + Origen + Registro Órd. - + Cargando... @@ -367,16 +410,53 @@ require_once __DIR__ . '/shared/components/sidebar.php'; let paginaActual = 1; const modal = new bootstrap.Modal('#modalPaciente'); +// ── Stats ────────────────────────────────────────────────────────────────── +async function cargarStats() { + try { + const r = await fetch('api/lab/get_pacientes.php?stats=1'); + const d = await r.json(); + const s = d.stats || {}; + document.getElementById('stat-total').textContent = s.total ?? '—'; + document.getElementById('stat-rips').textContent = s.importados ?? '—'; + document.getElementById('stat-wa').textContent = s.con_wa ?? '—'; + document.getElementById('stat-manual').textContent = s.manuales ?? '—'; + } catch(_) {} +} + +function filtrarOrigen(origen) { + const sel = document.getElementById('filtro-origen'); + sel.value = sel.value === origen ? '' : origen; + cargarLista(1); +} + // ── Lista ────────────────────────────────────────────────────────────────── +const _origenBadge = { + rips: 'RIPS', + whatsapp: 'WA', + manual: 'Manual', +}; + +function origenBadge(origen) { + return _origenBadge[origen] || _origenBadge.manual; +} + +function fmtFecha(str) { + if (!str) return '—'; + return str.slice(0, 10).split('-').reverse().join('/'); +} + async function cargarLista(pag = 1) { paginaActual = pag; - const busq = document.getElementById('buscador').value.trim(); - const r = await fetch(`api/lab/get_pacientes.php?busqueda=${encodeURIComponent(busq)}&page=${pag}&limit=25`); + const busq = document.getElementById('buscador').value.trim(); + const origen = document.getElementById('filtro-origen').value; + const r = await fetch( + `api/lab/get_pacientes.php?busqueda=${encodeURIComponent(busq)}&page=${pag}&limit=25&origen=${encodeURIComponent(origen)}` + ); const d = await r.json(); const tbody = document.getElementById('tabla-body'); if (!d.data?.length) { - tbody.innerHTML = 'Sin resultados'; + tbody.innerHTML = 'Sin resultados'; document.getElementById('paginacion').innerHTML = ''; return; } @@ -385,11 +465,12 @@ async function cargarLista(pag = 1) {
${esc(p.nombre_completo)}
- ${p.phone_number ? ` ${esc(p.phone_number)}` : ''} + ${p.telefono ? `${esc(p.telefono)}` : ''} ${tipoDocLabel(p.tipo_documento)} ${esc(p.numero_documento||'—')} - ${esc(p.telefono||'—')} - ${esc(p.eps||'—')} + ${esc(p.ciudad||'—')} + ${origenBadge(p.origen)} + ${fmtFecha(p.created_at)} ${p.total_ordenes||0}