feat(chat): botón Nuevo mensaje con búsqueda de paciente y picker de plantilla
- chat_buscar_paciente.php: GET ?q= busca en lab_pacientes por nombre,
documento o teléfono (mín. 2 chars, máx. 20 resultados)
- chat_start_conversation.php: POST {phone, template_name, lang, params}
— normaliza teléfono, busca/crea usuario en users, envía plantilla
vía WhatsAppService('turnero'), devuelve {ok, user_id}
- chat.php: botón "+ Nuevo" en sidebar header; modal 3 pasos:
1) buscar paciente (debounce 350ms) o ingresar número libre
2) lista de plantillas habilitadas
3) variables de la plantilla + Enviar
Al enviar recarga el sidebar y abre la conversación automáticamente
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
67efd470de
commit
ab72750410
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* GET ?q= — Busca pacientes en lab_pacientes por nombre o documento.
|
||||
* Usado por el modal "Nuevo mensaje" del chat turnero.
|
||||
*/
|
||||
require_once __DIR__ . '/../../../config/config.php';
|
||||
requireAuthentication();
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$q = trim($_GET['q'] ?? '');
|
||||
if (strlen($q) < 2) { echo json_encode(['ok' => true, 'data' => []]); exit; }
|
||||
|
||||
try {
|
||||
$pdo = Database::getInstance()->getConnection();
|
||||
$like = '%' . $q . '%';
|
||||
$rows = $pdo->prepare(
|
||||
"SELECT id, nombre_completo, telefono, numero_documento
|
||||
FROM lab_pacientes
|
||||
WHERE is_active = 1
|
||||
AND (nombre_completo LIKE ? OR numero_documento LIKE ? OR telefono LIKE ?)
|
||||
ORDER BY nombre_completo ASC
|
||||
LIMIT 20"
|
||||
);
|
||||
$rows->execute([$like, $like, $like]);
|
||||
echo json_encode(['ok' => true, 'data' => $rows->fetchAll(PDO::FETCH_ASSOC)]);
|
||||
} catch (Throwable $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* POST — Inicia una conversación nueva desde el chat turnero.
|
||||
* Body: { phone, template_name, lang, params }
|
||||
* Busca o crea el usuario en `users`, envía la plantilla y devuelve user_id.
|
||||
*/
|
||||
require_once __DIR__ . '/../../../config/config.php';
|
||||
require_once __DIR__ . '/../../../services/WhatsAppService.php';
|
||||
requireAuthentication();
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405); echo json_encode(['ok' => false, 'error' => 'Método no permitido']); exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: [];
|
||||
$phone = trim($input['phone'] ?? '');
|
||||
$templateName = trim($input['template_name'] ?? '');
|
||||
$lang = trim($input['lang'] ?? 'es_CO');
|
||||
$params = $input['params'] ?? [];
|
||||
|
||||
if (!$phone || !$templateName) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['ok' => false, 'error' => 'phone y template_name son requeridos']); exit;
|
||||
}
|
||||
|
||||
// Normalizar teléfono: solo dígitos, agregar 57 si es colombiano de 10 dígitos
|
||||
$phoneClean = preg_replace('/\D/', '', $phone);
|
||||
if (strlen($phoneClean) === 10 && $phoneClean[0] === '3') {
|
||||
$phoneClean = '57' . $phoneClean;
|
||||
}
|
||||
if (strlen($phoneClean) < 10) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['ok' => false, 'error' => 'Número de teléfono inválido']); exit;
|
||||
}
|
||||
|
||||
$db = Database::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
|
||||
// Buscar usuario existente (puede estar guardado con o sin prefijo 57)
|
||||
$user = $pdo->prepare(
|
||||
"SELECT id, name FROM users WHERE phone_number = ? OR phone_number = ? LIMIT 1"
|
||||
);
|
||||
$user->execute([$phoneClean, ltrim($phoneClean, '57')]);
|
||||
$userRow = $user->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$userRow) {
|
||||
// Buscar nombre en lab_pacientes por teléfono
|
||||
$pac = $pdo->prepare(
|
||||
"SELECT nombre_completo FROM lab_pacientes WHERE telefono LIKE ? AND is_active=1 LIMIT 1"
|
||||
);
|
||||
$pac->execute(['%' . substr($phoneClean, -10) . '%']);
|
||||
$pacRow = $pac->fetch(PDO::FETCH_ASSOC);
|
||||
$nombre = $pacRow['nombre_completo'] ?? $phoneClean;
|
||||
|
||||
// Crear usuario mínimo
|
||||
$ins = $pdo->prepare(
|
||||
"INSERT INTO users (name, phone_number, created_at) VALUES (?, ?, NOW())"
|
||||
);
|
||||
$ins->execute([$nombre, $phoneClean]);
|
||||
$userId = (int)$pdo->lastInsertId();
|
||||
} else {
|
||||
$userId = (int)$userRow['id'];
|
||||
}
|
||||
|
||||
// Enviar plantilla
|
||||
$operatorId = $_SESSION['admin_id'] ?? $_SESSION['user_id'] ?? null;
|
||||
$meta = ['canal' => 'turnero'];
|
||||
if ($operatorId) $meta['operator_id'] = $operatorId;
|
||||
|
||||
$wa = new WhatsAppService('turnero');
|
||||
$wa->sendTemplateMessage($phoneClean, $templateName, $lang, $params, [], null, $meta);
|
||||
|
||||
echo json_encode(['ok' => true, 'user_id' => $userId]);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
error_log('chat_start_conversation: ' . $e->getMessage());
|
||||
http_response_code(500);
|
||||
echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
Reference in New Issue
Block a user