Files
whatsappNucleo/app/pages/messages/index.vue
josedario87 91e152a4a3
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 51s
Feature: Conectar pagina de mensajes con API
2025-12-02 19:42:48 -06:00

184 lines
5.2 KiB
Vue

<template>
<div class="space-y-6">
<!-- Header -->
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-[var(--wa-text)]">Mensajes</h1>
<p class="text-[var(--wa-text-muted)]">Vista de conversaciones de todas las instancias</p>
</div>
</div>
<!-- Instance Selector -->
<div class="flex items-center gap-4">
<USelectMenu
v-model="selectedInstance"
:items="instanceOptions"
placeholder="Seleccionar instancia"
class="w-64"
/>
</div>
<!-- Chat Interface -->
<div class="grid grid-cols-12 gap-4 h-[calc(100vh-300px)]">
<!-- Chat List -->
<div class="col-span-4 instance-card overflow-hidden flex flex-col">
<div class="p-4 border-b border-[var(--wa-border)]">
<UInput
v-model="searchQuery"
placeholder="Buscar conversacion..."
icon="i-lucide-search"
/>
</div>
<div class="flex-1 overflow-y-auto">
<div v-if="chats.length === 0" class="p-8 text-center">
<UIcon name="i-lucide-message-square" class="w-12 h-12 text-[var(--wa-text-muted)] mx-auto mb-3" />
<p class="text-[var(--wa-text-muted)]">No hay conversaciones</p>
</div>
<div v-else>
<ChatItem
v-for="chat in filteredChats"
:key="chat.id"
:chat="chat"
:active="selectedChat?.id === chat.id"
@click="selectedChat = chat"
/>
</div>
</div>
</div>
<!-- Message View -->
<div class="col-span-8 instance-card overflow-hidden flex flex-col">
<div v-if="!selectedChat" class="flex-1 flex items-center justify-center">
<div class="text-center">
<UIcon name="i-lucide-message-circle" class="w-16 h-16 text-[var(--wa-text-muted)] mx-auto mb-4" />
<p class="text-[var(--wa-text-muted)]">Selecciona una conversacion</p>
</div>
</div>
<template v-else>
<!-- Chat Header -->
<div class="p-4 border-b border-[var(--wa-border)] flex items-center gap-3">
<UAvatar :alt="selectedChat.name" size="md" />
<div>
<p class="font-medium text-[var(--wa-text)]">{{ selectedChat.name }}</p>
<p class="text-sm text-[var(--wa-text-muted)]">{{ selectedChat.jid }}</p>
</div>
</div>
<!-- Messages -->
<div class="flex-1 overflow-y-auto p-4 space-y-2">
<MessageBubble
v-for="message in messages"
:key="message.id"
:message="message"
/>
</div>
<!-- Input -->
<div class="p-4 border-t border-[var(--wa-border)]">
<MessageInput @send="handleSendMessage" />
</div>
</template>
</div>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'dashboard',
title: 'Mensajes',
icon: 'i-lucide-message-square'
})
const { instances, fetchInstances } = useInstances()
const selectedInstance = ref<string | null>(null)
const searchQuery = ref('')
const selectedChat = ref<any>(null)
const chats = ref<any[]>([])
const messages = ref<any[]>([])
const loadingChats = ref(false)
const loadingMessages = ref(false)
// Instance options for selector
const instanceOptions = computed(() =>
instances.value
.filter(i => i.status === 'connected')
.map(i => ({ label: i.name, value: i.id }))
)
// Auto-select first connected instance
watch(instanceOptions, (opts) => {
if (opts.length > 0 && !selectedInstance.value) {
selectedInstance.value = opts[0].value
}
}, { immediate: true })
// Load chats when instance changes
watch(selectedInstance, async (instanceId) => {
if (!instanceId) {
chats.value = []
return
}
loadingChats.value = true
try {
chats.value = await $fetch(`/api/messages/${instanceId}/chats`)
} catch (e) {
console.error('Error loading chats:', e)
chats.value = []
} finally {
loadingChats.value = false
}
})
// Load messages when chat changes
watch(selectedChat, async (chat) => {
if (!chat || !selectedInstance.value) {
messages.value = []
return
}
loadingMessages.value = true
try {
messages.value = await $fetch(`/api/messages/${selectedInstance.value}/${chat.id}`)
} catch (e) {
console.error('Error loading messages:', e)
messages.value = []
} finally {
loadingMessages.value = false
}
})
const filteredChats = computed(() => {
if (!searchQuery.value) return chats.value
return chats.value.filter(chat =>
chat.name?.toLowerCase().includes(searchQuery.value.toLowerCase())
)
})
const handleSendMessage = async (content: string) => {
if (!selectedInstance.value || !selectedChat.value) return
try {
await $fetch(`/api/messages/${selectedInstance.value}/${selectedChat.value.id}/send`, {
method: 'POST',
body: { content }
})
// Reload messages
messages.value = await $fetch(`/api/messages/${selectedInstance.value}/${selectedChat.value.id}`)
} catch (e) {
console.error('Error sending message:', e)
}
}
// Load instances on mount
onMounted(() => {
fetchInstances()
})
</script>