feat: add message meta component

This commit is contained in:
Shivam Mishra
2024-11-27 17:05:13 +05:30
parent 71e706a0bf
commit 4da133fe12
2 changed files with 95 additions and 17 deletions
@@ -10,12 +10,11 @@ import {
} from './constants';
import Avatar from 'next/avatar/Avatar.vue';
import Icon from 'next/icon/Icon.vue';
import TextBubble from './bubbles/Text.vue';
import MessageError from './MessageError.vue';
import MessageStatus from './MessageStatus.vue';
import MessageMeta from './MessageMeta.vue';
/**
* @typedef {Object} Sender
@@ -119,15 +118,20 @@ const variant = computed(() => {
return variants[props.messageType] || MESSAGE_VARIANTS.USER;
});
const isMyMessage = computed(() => {
const senderId = props.senderId ?? props.sender?.id;
return (
props.senderType === SENDER_TYPES.USER && props.currentUserId === senderId
);
});
/**
* Computes the message orientation based on sender type and message type
* @returns {import('vue').ComputedRef<'left'|'right'|'center'>} The computed orientation
*/
const orientation = computed(() => {
if (
props.senderType === SENDER_TYPES.USER &&
props.currentUserId === props.senderId
) {
if (isMyMessage.value) {
return ORIENTATION.RIGHT;
}
@@ -218,19 +222,16 @@ const shouldShowAvatar = computed(() => {
:class="flexOrientationClass"
:error="contentAttributes.externalError"
/>
<div
<MessageMeta
v-else-if="!shouldGroupWithNext"
class="[grid-area:meta] text-xs text-n-slate-11 flex items-center gap-1.5"
class="[grid-area:meta]"
:class="flexOrientationClass"
>
<span>{{ sender ? sender.name + ' •' : '' }} {{ '1m ago' }}</span>
<Icon
v-if="variant === MESSAGE_VARIANTS.PRIVATE"
icon="i-lucide-lock-keyhole"
class="text-n-slate-10 size-3"
/>
<MessageStatus v-if="messageType === MESSAGE_TYPES.OUTGOING" :status />
</div>
:sender="props.sender"
:status="props.status"
:private="props.private"
:is-my-message="isMyMessage"
:created-at="props.createdAt"
/>
</div>
</div>
</template>
@@ -0,0 +1,77 @@
<script setup>
import { computed } from 'vue';
import { messageTimestamp } from 'shared/helpers/timeHelper';
import MessageStatus from './MessageStatus.vue';
import Icon from 'next/icon/Icon.vue';
import { MESSAGE_TYPES, MESSAGE_STATUS } from './constants';
/**
* @typedef {Object} Sender
* @property {Object} additional_attributes - Additional attributes of the sender
* @property {Object} custom_attributes - Custom attributes of the sender
* @property {string} email - Email of the sender
* @property {number} id - ID of the sender
* @property {string|null} identifier - Identifier of the sender
* @property {string} name - Name of the sender
* @property {string|null} phone_number - Phone number of the sender
* @property {string} thumbnail - Thumbnail URL of the sender
* @property {string} type - Type of sender
*/
/**
* @typedef {Object} Props
* @property {('sent'|'delivered'|'read'|'failed')} status - The delivery status of the message
* @property {boolean} [private=false] - Whether the message is private
* @property {isMyMessage} [private=false] - Whether the message is sent by the current user or not
* @property {number} createdAt - Timestamp when the message was created
* @property {Sender|null} [sender=null] - The sender information
*/
const props = defineProps({
sender: {
type: Object,
required: true,
},
status: {
type: String,
required: true,
validator: value => Object.values(MESSAGE_STATUS).includes(value),
},
private: {
type: Boolean,
default: false,
},
isMyMessage: {
type: Boolean,
default: false,
},
createdAt: {
type: Number,
required: true,
},
});
const readableTime = computed(() =>
messageTimestamp(props.createdAt, 'LLL d, h:mm a')
);
const showSender = computed(() => !props.isMyMessage && props.sender);
</script>
<template>
<div class="text-xs text-n-slate-11 flex items-center gap-1.5">
<div class="inline">
<span v-if="showSender" class="inline">{{ sender.name }}</span>
<span v-if="showSender && readableTime" class="inline"> </span>
<span class="inline">{{ readableTime }}</span>
</div>
<Icon
v-if="props.private"
icon="i-lucide-lock-keyhole"
class="text-n-slate-10 size-3"
/>
<MessageStatus v-if="props.isMyMessage" :status />
</div>
</template>