feat: WhatsApp Nucleo con Nuxt 4 + Baileys v7
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 6m46s

Reemplazo completo de Evolution API por implementación directa con Baileys.

Características:
- Dashboard completo con Nuxt UI v4
- Soporte para múltiples instancias de WhatsApp
- Conexión via QR code o pairing code
- Persistencia de mensajes en PostgreSQL
- API REST para integraciones externas
- Webhooks con firma HMAC
- SSE para actualizaciones en tiempo real
- Autenticación con Authentik
This commit is contained in:
2025-12-02 17:54:31 -06:00
parent 327118440b
commit faedec47d7
62 changed files with 4489 additions and 92 deletions

View File

@@ -0,0 +1,117 @@
<template>
<div class="instance-card p-6">
<div class="flex items-start justify-between mb-4">
<div class="flex items-center gap-3">
<div class="w-12 h-12 rounded-full bg-[var(--wa-green-dark)] flex items-center justify-center">
<UIcon name="i-lucide-smartphone" class="w-6 h-6 text-white" />
</div>
<div>
<h3 class="font-semibold text-[var(--wa-text)]">{{ instance.name }}</h3>
<p class="text-sm text-[var(--wa-text-muted)]">
{{ instance.phoneNumber || 'Sin numero asignado' }}
</p>
</div>
</div>
<StatusBadge :status="instance.status" />
</div>
<!-- Connection info -->
<div v-if="instance.lastConnectedAt" class="text-xs text-[var(--wa-text-muted)] mb-4">
Ultima conexion: {{ formatDate(instance.lastConnectedAt) }}
</div>
<!-- Actions -->
<div class="flex items-center gap-2">
<template v-if="instance.status === 'disconnected'">
<UButton
size="sm"
icon="i-lucide-qr-code"
@click="$emit('connect', instance.id)"
>
Conectar
</UButton>
</template>
<template v-else-if="instance.status === 'connected'">
<UButton
size="sm"
variant="soft"
icon="i-lucide-message-square"
:to="`/messages?instance=${instance.id}`"
>
Mensajes
</UButton>
<UButton
size="sm"
variant="ghost"
color="red"
icon="i-lucide-unplug"
@click="$emit('disconnect', instance.id)"
>
Desconectar
</UButton>
</template>
<template v-else-if="instance.status === 'qr_ready'">
<UButton
size="sm"
icon="i-lucide-qr-code"
@click="$emit('connect', instance.id)"
>
Ver QR
</UButton>
</template>
<template v-else>
<UButton
size="sm"
variant="ghost"
loading
>
Procesando...
</UButton>
</template>
<!-- Delete button -->
<UButton
size="sm"
variant="ghost"
color="red"
icon="i-lucide-trash-2"
class="ml-auto"
@click="confirmDelete"
/>
</div>
</div>
</template>
<script setup lang="ts">
interface Instance {
id: string
name: string
phoneNumber: string | null
status: 'connected' | 'disconnected' | 'connecting' | 'qr_ready' | 'pairing'
lastConnectedAt: Date | null
}
interface Props {
instance: Instance
}
defineProps<Props>()
const emit = defineEmits<{
connect: [instanceId: string]
disconnect: [instanceId: string]
delete: [instanceId: string]
}>()
const formatDate = (date: Date) => {
return new Date(date).toLocaleString('es-AR')
}
const confirmDelete = () => {
// TODO: Show confirmation modal
emit('delete', props.instance.id)
}
</script>