Files
whatsappNucleo/app/components/messages/MessageBubble.vue
josedario87 371b5676fb
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m2s
UI: Agregar botones de copiar en paneles de debug de ChatItem y MessageBubble
2025-12-02 21:06:51 -06:00

122 lines
3.3 KiB
Vue

<template>
<div
class="flex flex-col"
:class="message.fromMe ? 'items-end' : 'items-start'"
>
<div
class="max-w-[70%] rounded-lg px-3 py-2"
:class="message.fromMe ? 'bubble-out' : 'bubble-in'"
>
<!-- Message content -->
<p class="text-[var(--wa-text)] whitespace-pre-wrap break-words">{{ message.content }}</p>
<!-- Image -->
<img
v-if="message.mediaUrl && message.type === 'image'"
:src="message.mediaUrl"
class="rounded-lg max-w-full mt-2"
/>
<!-- Caption for media -->
<p
v-if="message.caption"
class="text-[var(--wa-text)] mt-2"
>
{{ message.caption }}
</p>
<!-- Footer -->
<div class="flex items-center justify-end gap-1 mt-1">
<span class="text-xs text-[var(--wa-text-muted)]">
{{ formatTime(message.timestamp) }}
</span>
<UIcon
v-if="message.fromMe"
:name="statusIcon"
class="w-4 h-4"
:class="statusColor"
/>
<!-- Debug button -->
<button
@click="showDebug = !showDebug"
class="ml-1 text-xs text-[var(--wa-text-muted)] hover:text-[var(--wa-blue)] opacity-50 hover:opacity-100"
title="Debug info"
>
<UIcon name="i-lucide-bug" class="w-3 h-3" />
</button>
</div>
</div>
<!-- Debug panel -->
<div
v-if="showDebug"
class="max-w-[90%] mt-1 p-2 rounded bg-gray-900 border border-gray-700 text-xs font-mono overflow-x-auto"
>
<div class="flex items-center justify-between mb-1">
<span class="text-gray-400">Message:</span>
<button
@click="copyToClipboard(JSON.stringify(message, null, 2))"
class="px-2 py-1 rounded bg-gray-700 hover:bg-gray-600 text-gray-300"
title="Copiar al portapapeles"
>
<UIcon name="i-lucide-copy" class="w-3 h-3" />
</button>
</div>
<pre class="text-green-400 whitespace-pre-wrap">{{ JSON.stringify(message, null, 2) }}</pre>
</div>
</div>
</template>
<script setup lang="ts">
interface Message {
id: string
content: string
type: 'text' | 'image' | 'video' | 'document' | 'audio'
mediaUrl?: string
caption?: string
fromMe: boolean
timestamp: Date
status: 'pending' | 'sent' | 'delivered' | 'read' | 'failed'
}
interface Props {
message: Message
}
const props = defineProps<Props>()
const showDebug = ref(false)
const copyToClipboard = async (text: string) => {
try {
await navigator.clipboard.writeText(text)
} catch (err) {
console.error('Failed to copy:', err)
}
}
const formatTime = (date: Date) => {
return new Date(date).toLocaleTimeString('es-AR', {
hour: '2-digit',
minute: '2-digit'
})
}
const statusIcon = computed(() => {
const icons: Record<string, string> = {
pending: 'i-lucide-clock',
sent: 'i-lucide-check',
delivered: 'i-lucide-check-check',
read: 'i-lucide-check-check',
failed: 'i-lucide-alert-circle'
}
return icons[props.message.status] || 'i-lucide-check'
})
const statusColor = computed(() => {
if (props.message.status === 'read') return 'text-[var(--wa-blue)]'
if (props.message.status === 'failed') return 'text-red-500'
return 'text-[var(--wa-text-muted)]'
})
</script>