feat: use realworld like data

This commit is contained in:
Shivam Mishra
2024-11-21 19:44:30 +05:30
parent c3327502a1
commit d2634cb9a3
4 changed files with 858 additions and 71 deletions
@@ -1,69 +1,161 @@
<script setup>
import { computed } from 'vue';
import {
MESSAGE_TYPES,
MESSAGE_VARIANTS,
SENDER_TYPES,
ORIENTATION,
} from './constants';
import TextBubble from './bubbles/Text.vue';
import Avatar from 'next/avatar/Avatar.vue';
import Icon from 'next/icon/Icon.vue';
// id: 5272,
// content: 'Hey, how are ya, I had a few questions about Chatwoot?',
// inbox_id: 475,
// conversation_id: 43,
// message_type: 0,
// content_type: 'text',
// status: 'sent',
// content_attributes: {
// in_reply_to: null,
// },
// created_at: 1732195656,
// private: false,
// source_id: null,
// sender: {
// additional_attributes: {},
// custom_attributes: {},
// email: 'hey@example.com',
// id: 597,
// identifier: null,
// name: 'hey',
// phone_number: null,
// thumbnail: '',
// type: 'contact',
// },
//
const props = defineProps({
variant: {
id: { type: Number, required: true },
messageType: {
type: Number,
required: true,
validator: value => Object.values(MESSAGE_TYPES).includes(value),
},
status: {
type: String,
required: true,
validator: value => ['user', 'agent', 'system', 'private'].includes(value),
validator: value => ['sent', 'delivered', 'read', 'failed'].includes(value),
},
orientation: {
private: {
type: Boolean,
default: false,
},
createdAt: {
type: Number,
required: true,
},
sender: {
type: Object,
default: null,
},
senderId: {
type: Number,
default: null,
},
senderType: {
type: String,
default: 'left',
validator: value => ['left', 'right', 'center'].includes(value),
default: null,
},
text: {
content: {
type: String,
default: 'Hello World',
required: true,
},
user: {
type: String,
default: '',
currentUserId: {
type: Number,
required: true,
},
});
const variant = computed(() => {
if (props.private) {
return MESSAGE_VARIANTS.PRIVATE;
}
if (props.messageType === MESSAGE_TYPES.INCOMING) {
return MESSAGE_VARIANTS.USER;
}
if (props.messageType === MESSAGE_TYPES.ACTIVITY) {
return MESSAGE_VARIANTS.ACTIVITY;
}
if (props.messageType === MESSAGE_TYPES.OUTGOING) {
return MESSAGE_VARIANTS.AGENT;
}
if (props.messageType === MESSAGE_TYPES.TEMPLATE) {
return MESSAGE_VARIANTS.TEMPLATE;
}
return MESSAGE_VARIANTS.USER;
});
const orientation = computed(() => {
if (
props.senderType === SENDER_TYPES.USER &&
props.currentUserId === props.senderId
) {
return ORIENTATION.RIGHT;
}
if (props.messageType === MESSAGE_TYPES.ACTIVITY) return ORIENTATION.CENTER;
return ORIENTATION.LEFT;
});
const flexOrientationClass = computed(() => {
const map = {
left: 'justify-start',
right: 'justify-end',
center: 'justify-center',
[ORIENTATION.LEFT]: 'justify-start',
[ORIENTATION.RIGHT]: 'justify-end',
[ORIENTATION.CENTER]: 'justify-center',
};
return map[props.orientation];
return map[orientation.value];
});
const gridClass = computed(() => {
const map = {
left: 'grid grid-cols-[24px_1fr]',
right: 'grid grid-cols-[1fr_24px]',
[ORIENTATION.LEFT]: 'grid grid-cols-[24px_1fr]',
[ORIENTATION.RIGHT]: 'grid grid-cols-[1fr_24px]',
};
return map[props.orientation];
return map[orientation.value];
});
const gridTemplate = computed(() => {
const map = {
left: `
[ORIENTATION.LEFT]: `
"avatar bubble"
"spacer meta"
`,
right: `
[ORIENTATION.RIGHT]: `
"bubble avatar"
"meta spacer"
`,
};
return map[props.orientation];
return map[orientation.value];
});
</script>
<template>
<div class="flex w-full" :class="flexOrientationClass">
<div v-if="variant === 'system'">
<TextBubble v-bind="props" />
<div v-if="variant === MESSAGE_VARIANTS.ACTIVITY">
<TextBubble v-bind="props" :variant :orientation />
</div>
<div
v-else
@@ -71,21 +163,24 @@ const gridTemplate = computed(() => {
class="gap-x-3 gap-y-2 grid-area"
:style="{
gridTemplateAreas: gridTemplate,
gridTemplateColumns:
props.orientation === 'center' ? '1fr' : 'auto 1fr',
}"
>
<div class="[grid-area:avatar] flex items-end">
<Avatar :name="user" src="" size="24" />
<Avatar :name="sender ? sender.name : ''" src="" :size="24" />
</div>
<TextBubble v-bind="props" class="[grid-area:bubble]" />
<TextBubble
v-bind="props"
:variant
:orientation
class="[grid-area:bubble]"
/>
<div
class="[grid-area:meta] text-xs text-n-slate-11 flex items-center gap-1.5"
:class="flexOrientationClass"
>
<span>{{ user }} {{ '• 1m ago' }}</span>
<span>{{ sender ? sender.name : '' }} {{ '• 1m ago' }}</span>
<Icon
v-if="variant === 'private'"
v-if="variant === MESSAGE_VARIANTS.PRIVATE"
icon="i-lucide-lock-keyhole"
class="text-n-slate-10 size-3"
/>