WebAgent/src/components/ChatBubble.vue

79 lines
2.5 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import type { ChatBubbleProps } from '@/types/chat'
const props = defineProps<ChatBubbleProps>()
const messageClasses = computed(() => {
const base = 'rounded-2xl p-3 max-w-80 break-words'
const sender = props.message.sender === 'user'
? 'bg-blue-100 dark:bg-blue-800'
: 'bg-gray-100 dark:bg-gray-700'
return `${base} ${sender}`
})
const formattedTime = computed(() => {
if (!props.message.timestamp)
return ''
const date = typeof props.message.timestamp === 'string'
? new Date(props.message.timestamp)
: props.message.timestamp
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
})
</script>
<template>
<div class="mb-4 flex gap-2" :class="message.sender === 'user' ? 'justify-end' : 'justify-start'">
<!-- Avatar for AI messages (left side) -->
<div v-if="message.sender === 'ai'">
<van-image
v-if="avatar"
:src="avatar"
class="rounded-full flex-shrink-0 h-8 w-8"
round
/>
<div v-else class="text-gray-600 rounded-full bg-gray-100 flex flex-shrink-0 h-8 w-8 items-center justify-center dark:text-gray-300 dark:bg-gray-700">
<van-icon name="robot-o" class="text-lg" />
</div>
</div>
<!-- Message bubble and timestamp -->
<div class="flex flex-col max-w-[80%]">
<div :class="messageClasses">
<p class="text-sm">
{{ message.content }}
</p>
<!-- Status indicator -->
<div v-if="message.status === 'sending'" class="mt-1">
<van-icon name="clock-o" class="animate-pulse" />
</div>
<div v-else-if="message.status === 'error'" class="text-red-500 mt-1">
<van-icon name="warning-o" />
</div>
</div>
<!-- Timestamp -->
<div
v-if="showTimestamp && formattedTime"
class="text-xs text-gray-500 mt-1 dark:text-gray-400"
:class="message.sender === 'user' ? 'text-right' : 'text-left'"
>
{{ formattedTime }}
</div>
</div>
<!-- Avatar for user messages (right side) -->
<div v-if="message.sender === 'user'">
<van-image
v-if="avatar"
:src="avatar"
class="rounded-full flex-shrink-0 h-8 w-8"
round
/>
<div v-else class="text-blue-600 rounded-full bg-blue-100 flex flex-shrink-0 h-8 w-8 items-center justify-center dark:text-blue-300 dark:bg-blue-800">
<van-icon name="user-circle-o" class="text-lg" />
</div>
</div>
</div>
</template>