434 lines
23 KiB
Vue
434 lines
23 KiB
Vue
<template>
|
||
<div class="flex-1 h-full overflow-y-auto overflow-x-clip overflow-hidden flex border border-surface rounded-2xl">
|
||
<div class="w-4/12 xl:w-3/12 min-w-40 overflow-auto flex flex-col gap-6">
|
||
<div class="flex flex-col gap-6 pt-3 pb-2 -mb-2 px-5 sticky top-0 bg-surface-0 dark:bg-surface-950 z-10">
|
||
<div class="flex items-center justify-between gap-6 text-color">
|
||
<div class="text-2xl font-medium lead">Chats</div>
|
||
<Button icon="pi pi-plus" text />
|
||
</div>
|
||
</div>
|
||
<div class="px-5">
|
||
<IconField iconPosition="left">
|
||
<InputIcon class="pi pi-search"> </InputIcon>
|
||
<InputText v-model="search" placeholder="Search" class="w-full" />
|
||
</IconField>
|
||
</div>
|
||
<div class="w-full px-5">
|
||
<SelectButton
|
||
v-model="value"
|
||
:options="options"
|
||
aria-labelledby="basic"
|
||
:pt="{
|
||
root: {
|
||
class: 'w-full'
|
||
},
|
||
pcbutton: {
|
||
root: {
|
||
class: 'flex-1'
|
||
}
|
||
}
|
||
}"
|
||
/>
|
||
</div>
|
||
<div class="flex-1 flex flex-col">
|
||
<div
|
||
v-for="chat in chats"
|
||
:key="chat.name"
|
||
class="flex items-center gap-2 p-4 cursor-pointer hover:bg-emphasis transition-all"
|
||
:class="{
|
||
'bg-emphasis': chat.name === activeChat
|
||
}"
|
||
>
|
||
<div class="relative">
|
||
<div v-if="chat.active !== undefined" class="absolute top-0 right-0 p-[1px] bg-surface-0 dark:bg-surface-950 rounded-full flex items-center justify-center">
|
||
<Badge :severity="chat.active ? 'success' : 'danger'" class="p-1.5"></Badge>
|
||
</div>
|
||
<Avatar
|
||
v-bind="chat.image ? { image: chat.image } : { label: chat.capName }"
|
||
:class="{
|
||
'bg-violet-100 text-violet-950': !chat.image
|
||
}"
|
||
class="text-base font-medium flex"
|
||
size="large"
|
||
shape="circle"
|
||
/>
|
||
</div>
|
||
<div class="flex-1">
|
||
<div class="flex items-start gap-1 justify-between">
|
||
<div class="text-color font-medium leading-6">{{ chat.name }}</div>
|
||
<div class="text-sm text-muted-color leading-5">{{ chat.time }}</div>
|
||
</div>
|
||
<div class="flex items-center gap-5 justify-between mt-1">
|
||
<div class="text-muted-color text-sm leading-5 line-clamp-1">{{ chat.lastMessage }}</div>
|
||
<Badge v-if="chat.unreadMessageCount > 0" :value="chat.unreadMessageCount" severity="contrast"></Badge>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="w-8/12 xl:w-6/12 border-x border-surface flex flex-col">
|
||
<div class="flex items-center p-4 gap-7 border-b border-surface">
|
||
<div class="flex items-center">
|
||
<Avatar image="https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar-primetek.png" class="mr-2 av" size="large" shape="circle" />
|
||
<div class="flex-1">
|
||
<div class="text-color leading-6 cursor-pointer hover:text-muted-color-emphasis transition-colors">PrimeTek</div>
|
||
<div class="text-muted-color leading-5 line-clamp-1 mt-1">Cody Fisher, Esther Howard, Jerome Bell, Kristin Watson, Ronald Richards, Darrell Steward</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<Button icon="pi pi-phone" text />
|
||
<Button icon="pi pi-search" text />
|
||
<Button type="button" icon="pi pi-ellipsis-h" text @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
|
||
<Menu ref="menu" id="overlay_menu" :model="menuItems" :popup="true" />
|
||
</div>
|
||
</div>
|
||
<div class="flex-1 overflow-y-auto flex flex-col gap-8 py-8 px-6">
|
||
<div v-for="message in chatMessages" :key="message.id" class="flex items-start min-w-64 w-fit max-w-[60%]" :class="{ 'ml-auto mr-0 flex-row-reverse': message.type === 'sent' }">
|
||
<div
|
||
class="flex items-center gap-2 sticky top-0 transition-all"
|
||
:class="{
|
||
'flex-row-reverse': message.type === 'sent'
|
||
}"
|
||
>
|
||
<Avatar
|
||
v-bind="message.image ? { image: message.image } : { label: message.capName }"
|
||
:class="{
|
||
'bg-blue-100 text-blue-950': !message.image
|
||
}"
|
||
class="w-10 h-10 text-sm font-medium"
|
||
shape="circle"
|
||
/>
|
||
<div>
|
||
<svg :class="message.type === 'received' ? 'fill-surface-100 dark:fill-surface-800' : 'fill-primary rotate-180'" class="" xmlns="http://www.w3.org/2000/svg" width="7" height="11" viewBox="0 0 7 11" fill="none">
|
||
<path d="M1.79256 7.09551C0.516424 6.31565 0.516426 4.46224 1.79256 3.68238L7 0.500055L7 10.2778L1.79256 7.09551Z" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
<div :class="message.type === 'received' ? 'flex-1 bg-surface-100 dark:bg-surface-800 px-2 py-1 rounded-lg' : 'flex-1 bg-primary px-2 py-1 rounded-lg'">
|
||
<p :class="message.type === 'received' ? 'text-color leading-6 mb-0' : 'text-primary-contrast leading-6 mb-0'">
|
||
{{ message.message }}
|
||
</p>
|
||
<div v-if="message.attachment" :class="message.type === 'received' ? 'bg-surface-200 dark:bg-surface-700' : 'bg-primary-emphasis'" class="mt-2 w-full rounded-lg mb-0.5 hover:opacity-75 transition-all">
|
||
<img class="w-full h-auto block cursor-pointer" :src="message.attachment" alt="Message Image" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="p-4 border-t border-surface flex items-end justify-between gap-2">
|
||
<div class="flex items-end gap-1 flex-1">
|
||
<Button icon="pi pi-face-smile" text />
|
||
<Button icon="pi pi-paperclip" text />
|
||
<Textarea class="ml-1 flex-1 border-0 shadow-none max-h-32 min-h-9 bg-emphasis overflow-auto" autoResize rows="1" placeholder="Write your message..." />
|
||
</div>
|
||
<Button icon="pi pi-send" />
|
||
</div>
|
||
</div>
|
||
<div class="w-3/12 xl:block hidden min-w-40 py-6 px-3 overflow-auto">
|
||
<div class="flex flex-col items-center justify-center">
|
||
<Avatar image="https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar-primetek.png" class="w-32 h-32" size="xlarge" shape="circle" />
|
||
<div class="leading-6 font-medium text-color mt-4 w-full text-center">PrimeTek</div>
|
||
<div class="leading-5 text-sm text-muted-color mt-1 w-full text-center">@primetek</div>
|
||
<div class="flex items-center justify-center flex-wrap gap-1 mt-4">
|
||
<Button icon="pi pi-phone text-muted-color" severity="secondary" text />
|
||
<Button icon="pi pi-video text-muted-color" severity="secondary" text />
|
||
<Button icon="pi pi-sign-in text-muted-color" severity="secondary" text />
|
||
<Button icon="pi pi-info-circle text-muted-color" severity="secondary" text />
|
||
<Button type="button" icon="pi pi-ellipsis-v text-muted-color" severity="secondary" text @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
|
||
<Menu ref="menu" id="overlay_menu" :model="menuItems" :popup="true" />
|
||
</div>
|
||
</div>
|
||
<div class="flex flex-col gap-4 mt-4">
|
||
<div class="flex items-center gap-2">
|
||
<i class="pi pi-bell text-color"></i>
|
||
<div class="leading-6 font-medium text-color flex-1">Notification</div>
|
||
<ToggleSwitch v-model="notification" />
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<i class="pi pi-volume-down text-color"></i>
|
||
<div class="leading-6 font-medium text-color flex-1">Sound</div>
|
||
<ToggleSwitch v-model="sound" />
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<i class="pi pi-download text-color"></i>
|
||
<div class="leading-6 font-medium text-color flex-1">Save to downloads</div>
|
||
<ToggleSwitch v-model="download" />
|
||
</div>
|
||
</div>
|
||
<div class="mt-6">
|
||
<div class="flex items-center gap-2">
|
||
<div class="flex-1 text-color leading-6 font-medium">Members</div>
|
||
<Button label="See All" class="text-sm py-0.5 px-2 text-muted-color" text />
|
||
</div>
|
||
<div class="mt-4 flex flex-col gap-4">
|
||
<div v-for="member in members" :key="member.name" class="flex items-center gap-2 cursor-pointer">
|
||
<Avatar
|
||
v-bind="member.image ? { image: member.image } : { label: member.capName }"
|
||
:class="{
|
||
'bg-orange-100 text-orange-950': !member.image
|
||
}"
|
||
class="font-medium text-xs"
|
||
shape="circle"
|
||
/>
|
||
<div class="text-sm text-color hover:text-muted-color-emphasis transition-colors font-medium leading-5 flex-1">
|
||
{{ member.name }}
|
||
</div>
|
||
<i class="pi pi-chevron-right text-xs text-muted-color"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="mt-5">
|
||
<SelectButton
|
||
v-model="media"
|
||
:options="mediaOptions"
|
||
:pt="{
|
||
root: {
|
||
class: 'w-full'
|
||
},
|
||
pcbutton: {
|
||
root: {
|
||
class: 'flex-1'
|
||
}
|
||
}
|
||
}"
|
||
/>
|
||
<div class="mt-3 mb-5 grid grid-cols-3 gap-2">
|
||
<div v-for="(media, index) in chatMedia" :key="index" class="bg-emphasis hover:opacity-70 transition-all flex-1 aspect-square rounded-lg border border-surface cursor-pointer">
|
||
<img class="w-full h-full object-cover block" :src="media" alt="Media Image" />
|
||
</div>
|
||
<div class="bg-emphasis hover:opacity-70 transition-all flex-1 aspect-square rounded-lg border border-surface cursor-pointer flex items-center justify-center">
|
||
<span class="text-muted-color font-medium">99+</span>
|
||
</div>
|
||
</div>
|
||
<Button
|
||
label="Show more"
|
||
icon="pi pi-arrow-right"
|
||
iconPos="right"
|
||
outlined
|
||
class="w-full text-left"
|
||
:pt="{
|
||
root: {
|
||
class: 'justify-between'
|
||
}
|
||
}"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'Chat',
|
||
redrawListener: null,
|
||
data() {
|
||
return {
|
||
search: '',
|
||
download: false,
|
||
notification: true,
|
||
sound: false,
|
||
value: 'Chat',
|
||
value2: '',
|
||
options: ['Chat', 'Call'],
|
||
media: 'Media',
|
||
mediaOptions: ['Media', 'Link', 'Docs'],
|
||
activeChat: 'PrimeTek Team',
|
||
menuItems: [
|
||
{
|
||
label: 'Group Info',
|
||
icon: 'pi pi-info-circle'
|
||
},
|
||
{
|
||
label: 'Leave group',
|
||
icon: 'pi pi-sign-out'
|
||
}
|
||
],
|
||
chats: [
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar11.jpg',
|
||
name: 'Cody Fisher',
|
||
capName: 'CF',
|
||
active: true,
|
||
unreadMessageCount: 8,
|
||
time: '12.30',
|
||
lastMessage: "Hey there! I've heard about PrimeVue. Any cool tips for getting started?"
|
||
},
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar-primetek.png',
|
||
name: 'PrimeTek Team',
|
||
capName: 'PT',
|
||
active: undefined,
|
||
unreadMessageCount: 0,
|
||
time: '11.15',
|
||
lastMessage: "Let's implement PrimeVue. Elevating our UI game! 🚀"
|
||
},
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar2.png',
|
||
name: 'Jerome Bell',
|
||
capName: 'JB',
|
||
active: true,
|
||
unreadMessageCount: 4,
|
||
time: '11.15',
|
||
lastMessage: "Absolutely! PrimeVue's documentation is gold—simplifies our UI work."
|
||
},
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar12.jpg',
|
||
name: 'Robert Fox',
|
||
capName: 'RF',
|
||
active: false,
|
||
unreadMessageCount: 0,
|
||
time: '11.15',
|
||
lastMessage: "Interesting! PrimeVue sounds amazing. What's your favorite feature?"
|
||
},
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar13.jpg',
|
||
name: 'Esther Howard',
|
||
capName: 'EH',
|
||
active: true,
|
||
unreadMessageCount: 9,
|
||
time: '11.15',
|
||
lastMessage: 'Quick one, team! Anyone using PrimeVue for mobile app development?'
|
||
},
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar9.jpg',
|
||
name: 'Darlene Robertson',
|
||
capName: 'DR',
|
||
active: false,
|
||
unreadMessageCount: 0,
|
||
time: '11.15',
|
||
lastMessage: "Just explored PrimeVue's themes. Can we talk about those stunning designs? 😍"
|
||
},
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar6.png',
|
||
name: 'Ralph Edwards',
|
||
capName: 'RE',
|
||
active: false,
|
||
unreadMessageCount: 0,
|
||
time: '11.15',
|
||
lastMessage: 'PrimeVue is a game-changer, right? What are your thoughts, folks?'
|
||
},
|
||
{ image: '', name: 'Ronald Richards', capName: 'RR', active: false, unreadMessageCount: 0, time: '11.15', lastMessage: "Jumping in! PrimeVue's community forum is buzzing. Any engaging discussions?" },
|
||
{ image: '', name: 'Kristin Watson', capName: 'KW', active: false, unreadMessageCount: 0, time: '11.15', lastMessage: 'Sharing a quick win-PrimeVue tutorials are leveling up my UI skills. 👩💻' },
|
||
{
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar7.png',
|
||
name: 'Darrell Steward',
|
||
capName: 'DS',
|
||
active: false,
|
||
unreadMessageCount: 0,
|
||
time: '11.15',
|
||
lastMessage: "Reflecting on PrimeVue's impact on our workflow. What's your take?"
|
||
}
|
||
],
|
||
chatMessages: [
|
||
{ id: 1, attachment: '', name: '', image: '', capName: 'OS', type: 'received', message: "Awesome! What's the standout feature?" },
|
||
{ id: 2, attachment: '', name: '', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar8.png', capName: 'A', type: 'received', message: 'PrimeVue rocks! Simplifies UI dev with versatile components.' },
|
||
{ id: 3, attachment: '', name: '', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar11.jpg', capName: 'A', type: 'received', message: 'Intriguing! Tell us more about its impact.' },
|
||
{
|
||
id: 4,
|
||
attachment: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/message-image.png',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar2.png',
|
||
capName: 'A',
|
||
type: 'received',
|
||
message: "It's design-neutral and compatible with Tailwind. Features accessible, high-grade components!"
|
||
},
|
||
{ id: 5, attachment: '', name: '', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar5.png', capName: 'A', type: 'sent', message: 'Customizable themes, responsive design – UI excellence!' },
|
||
{ id: 6, attachment: '', name: '', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar8.png', capName: 'A', type: 'received', message: 'Love it! Fast-tracking our development is key.' },
|
||
{ id: 7, attachment: '', name: '', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar6.png', capName: 'A', type: 'received', message: 'Documentation rocks too – smooth integration for all.' },
|
||
{
|
||
id: 8,
|
||
attachment: '',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar5.png',
|
||
capName: 'B',
|
||
type: 'sent',
|
||
message: 'The flexibility and ease of use are truly impressive. Have you explored the new components?'
|
||
},
|
||
{
|
||
id: 9,
|
||
attachment: '',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar12.jpg',
|
||
capName: 'C',
|
||
type: 'received',
|
||
message: 'Absolutely, the new calendar component has saved us a ton of development time!'
|
||
},
|
||
{
|
||
id: 10,
|
||
attachment: '',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar13.jpg',
|
||
capName: 'D',
|
||
type: 'received',
|
||
message: "And the accessibility features are top-notch. It's great to see a library focusing on inclusivity."
|
||
},
|
||
{
|
||
id: 11,
|
||
attachment: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/message-image.png',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar5.png',
|
||
capName: 'E',
|
||
type: 'sent',
|
||
message: "I couldn't agree more. Plus, the documentation is incredibly thorough, which makes onboarding new team members a breeze."
|
||
},
|
||
{
|
||
id: 12,
|
||
attachment: '',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar6.png',
|
||
capName: 'F',
|
||
type: 'received',
|
||
message: 'Do you have any tips for optimizing performance when using multiple complex components?'
|
||
},
|
||
{
|
||
id: 13,
|
||
attachment: '',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar11.jpg',
|
||
capName: 'G',
|
||
type: 'received',
|
||
message: 'Yes! Lazy loading and code splitting can make a huge difference, especially in larger applications.'
|
||
},
|
||
{
|
||
id: 14,
|
||
attachment: '',
|
||
name: '',
|
||
image: '',
|
||
capName: 'HS',
|
||
type: 'received',
|
||
message: "I've also found that leveraging the component's internal state management capabilities can help streamline data flow and improve performance."
|
||
},
|
||
{
|
||
id: 15,
|
||
attachment: '',
|
||
name: '',
|
||
image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar5.png',
|
||
capName: 'H',
|
||
type: 'sent',
|
||
message: "That's great advice. It's amazing how much detail and thought has gone into making PrimeVue such a powerful tool for developers."
|
||
}
|
||
],
|
||
chatMedia: [
|
||
'https://www.primefaces.org/cdn/primevue/images/landing/apps/chat-image1.png',
|
||
'https://www.primefaces.org/cdn/primevue/images/landing/apps/chat-image2.png',
|
||
'https://www.primefaces.org/cdn/primevue/images/landing/apps/chat-image3.png',
|
||
'https://www.primefaces.org/cdn/primevue/images/landing/apps/chat-image4.png',
|
||
'https://www.primefaces.org/cdn/primevue/images/landing/apps/chat-image5.png'
|
||
],
|
||
members: [
|
||
{ name: 'Robin Jonas', capName: 'RJ', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar2.png' },
|
||
{ name: 'Cameron Williamson', capName: 'CW', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar11.jpg' },
|
||
{ name: 'Eleanor Pena', capName: 'EP', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar5.png' },
|
||
{ name: 'Arlene McCoy', capName: 'AM', image: 'https://www.primefaces.org/cdn/primevue/images/landing/apps/avatar8.png' },
|
||
{ name: 'Dianne Russell', capName: 'DR', image: '' }
|
||
]
|
||
};
|
||
},
|
||
methods: {
|
||
toggle(event) {
|
||
this.$refs.menu.toggle(event);
|
||
}
|
||
},
|
||
components: {}
|
||
};
|
||
</script>
|