nidus-sync/ts/components/CardMessageHistory.vue
Eli Ribble 7eb0ad1221
Some checks failed
/ golint (push) Failing after 9s
Show message history in contact review page.
2026-05-23 01:33:25 +00:00

144 lines
2.8 KiB
Vue

<style scoped>
.message-list {
max-height: 500px;
overflow-y: auto;
padding: 0.5rem;
}
.message-item {
display: flex;
margin-bottom: 0.75rem;
}
.message-item-incoming {
justify-content: flex-start;
}
.message-item-outgoing {
justify-content: flex-end;
}
.message-bubble {
max-width: 80%;
padding: 0.5rem 0.75rem;
border-radius: 0.75rem;
word-wrap: break-word;
}
.message-bubble-incoming {
background-color: #e9ecef;
border-bottom-left-radius: 0.25rem;
}
.message-bubble-outgoing {
background-color: #0d6efd;
color: #fff;
border-bottom-right-radius: 0.25rem;
}
.message-content {
font-size: 0.9rem;
line-height: 1.4;
white-space: pre-wrap;
}
.message-meta {
font-size: 0.7rem;
margin-top: 0.25rem;
opacity: 0.7;
}
.message-bubble-outgoing .message-meta {
text-align: right;
}
.message-phone {
font-weight: 500;
}
.empty-state {
text-align: center;
padding: 2rem;
color: #6c757d;
}
</style>
<template>
<div class="card mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<span>
<i class="bi bi-chat-dots"></i>
Message History
</span>
<span class="badge bg-secondary">
{{ sortedMessages.length }}
</span>
</div>
<div class="card-body p-0">
<div v-if="sortedMessages.length === 0" class="empty-state">
<i class="bi bi-chat-square-text fs-1"></i>
<p class="mb-0 mt-2">No messages</p>
</div>
<div v-else class="message-list">
<div
v-for="(msg, idx) in sortedMessages"
:key="idx"
class="message-item"
:class="
isOwn(msg) ? 'message-item-outgoing' : 'message-item-incoming'
"
>
<div
class="message-bubble"
:class="
isOwn(msg) ? 'message-bubble-outgoing' : 'message-bubble-incoming'
"
>
<div class="message-content">
{{ msg.content }}
</div>
<div class="message-meta">
<TimeRelative :time="msg.created" />
<span
v-if="ownIdentifier && msg.source && msg.destination"
class="message-phone"
>
&middot;
{{ isOwn(msg) ? "to" : "from" }}
{{ isOwn(msg) ? msg.destination : msg.source }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
import TimeRelative from "@/components/TimeRelative.vue";
import { Message } from "@/type/api";
interface Props {
messages: Message[];
ownIdentifier?: string;
}
const props = withDefaults(defineProps<Props>(), {
messages: () => [],
});
const sortedMessages = computed(() => {
return [...props.messages].sort(
(a: Message, b: Message) => a.created.getTime() - b.created.getTime(),
);
});
function isOwn(msg: Message): boolean {
if (!props.ownIdentifier) {
return false;
}
return msg.source === props.ownIdentifier;
}
</script>