Add CardMessageHistory component for chat-style message display
Some checks failed
/ golint (push) Failing after 9s
Some checks failed
/ golint (push) Failing after 9s
This commit is contained in:
parent
984223c287
commit
a1aee10412
1 changed files with 158 additions and 0 deletions
158
ts/components/CardMessageHistory.vue
Normal file
158
ts/components/CardMessageHistory.vue
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
<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"
|
||||
>
|
||||
·
|
||||
{{ 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, b) => a.created.getTime() - b.created.getTime(),
|
||||
);
|
||||
});
|
||||
|
||||
function isOwn(msg: Message): boolean {
|
||||
if (!props.ownIdentifier) {
|
||||
return false;
|
||||
}
|
||||
return msg.source === props.ownIdentifier;
|
||||
}
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue