Files
sirpremiumv2/app/Http/Livewire/Chat/ShowConversaciones.php
T
Lizandro GuarnizoandClaude Opus 5 5bc1ec14ca feat(whatsapp): mismo motor, menú y configuración que Telegram y el chat web
WhatsApp dejaba de usar su bot propio (árbol de menús sin login ni compras) y
pasa al motor compartido, así los tres canales quedan iguales.

- TelegramBotService recibe el canal por constructor; flujos, menús, Gemini,
  OCR, validación de pagos y datos bancarios salen de ChatConfig sin duplicar
- WhatsApp no tiene teclados inline: las opciones se envían numeradas y la
  respuesta numérica se traduce al callback equivalente
- estado en caché con prefijo por canal (Telegram conserva el suyo para no
  cerrar las sesiones abiertas)
- descarga de comprobantes y audios por la Graph API de Meta
- respuesta manual del asesor y aviso de vencimiento salen también por WhatsApp
- la pantalla de WhatsApp queda sólo con credenciales; el resto se administra
  en Chat / Bot

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 23:24:21 -05:00

153 lines
4.4 KiB
PHP
Executable File

<?php
namespace App\Http\Livewire\Chat;
use App\Models\ChatConversation;
use App\Models\ChatMessage;
use App\Services\ChatBotEngine;
use Livewire\Component;
class ShowConversaciones extends Component
{
public string $busqueda = '';
public string $filtroEstado = '';
public ?int $convSelecId = null;
public string $replyText = '';
public array $mensajes = [];
protected $queryString = ['convSelecId' => ['except' => null, 'as' => 'conv']];
public function mount(): void
{
if ($this->convSelecId) {
$this->cargarMensajes();
}
}
public function selectConv(int $convId): void
{
$this->convSelecId = $convId;
$this->replyText = '';
$this->cargarMensajes();
// Marcar mensajes entrantes como leídos
ChatMessage::where('conversation_id', $convId)
->where('tipo', 'usuario')
->where('leido', false)
->update(['leido' => true]);
ChatConversation::where('id', $convId)
->update(['mensajes_no_leidos' => 0]);
}
public function cargarMensajes(): void
{
if (! $this->convSelecId) {
$this->mensajes = [];
return;
}
$this->mensajes = ChatMessage::where('conversation_id', $this->convSelecId)
->orderBy('id')
->get()
->map(fn($m) => [
'id' => $m->id,
'tipo' => $m->tipo,
'contenido' => $m->contenido,
'created_at' => $m->created_at->format('d/m H:i'),
])
->toArray();
$this->dispatchBrowserEvent('scroll-admin');
}
public function sendReply(): void
{
$this->validate(['replyText' => 'required|string|max:4096']);
if (! $this->convSelecId) {
return;
}
$conv = ChatConversation::with('contact')->find($this->convSelecId);
if (! $conv) {
return;
}
ChatMessage::create([
'conversation_id' => $this->convSelecId,
'tipo' => 'agente',
'contenido' => $this->replyText,
'leido' => true,
]);
$conv->update(['ultimo_mensaje_at' => now()]);
// Entregar por el canal del cliente
if ($conv->canal === 'telegram') {
$engine = new ChatBotEngine();
$engine->enviarTelegram($conv->contact->canal_id, $this->replyText);
} elseif ($conv->canal === 'whatsapp') {
(new \App\Services\TelegramBotService('whatsapp'))
->send($conv->contact->canal_id, $this->replyText);
}
$this->replyText = '';
$this->cargarMensajes();
}
public function cerrarConv(): void
{
if (! $this->convSelecId) {
return;
}
ChatConversation::where('id', $this->convSelecId)
->update(['estado' => 'cerrada']);
$this->cargarMensajes();
}
public function devolverAlBot(): void
{
if (! $this->convSelecId) {
return;
}
ChatConversation::where('id', $this->convSelecId)
->update(['estado' => 'bot', 'menu_actual_id' => null]);
}
public function tomarControl(): void
{
if (! $this->convSelecId) {
return;
}
ChatConversation::where('id', $this->convSelecId)
->update(['estado' => 'agente']);
}
public function render()
{
$conversaciones = ChatConversation::with('contact')
->when($this->filtroEstado, fn($q) => $q->where('estado', $this->filtroEstado))
->when($this->busqueda, function ($q) {
$q->whereHas('contact', function ($s) {
$s->where('nombre', 'like', "%{$this->busqueda}%")
->orWhere('telefono', 'like', "%{$this->busqueda}%")
->orWhere('canal_id', 'like', "%{$this->busqueda}%")
->orWhereHas('user', fn($u) => $u->where('email', 'like', "%{$this->busqueda}%"));
});
})
->orderByDesc('ultimo_mensaje_at')
->get();
$convSelec = $this->convSelecId
? ChatConversation::with('contact')->find($this->convSelecId)
: null;
return view('livewire.chat.show-conversaciones', compact('conversaciones', 'convSelec'));
}
}