diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue b/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue
index 0932a79c7..0e893b767 100644
--- a/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsCard/ContactsCard.vue
@@ -98,6 +98,7 @@ const onClickViewDetails = () => emit('showContact', props.id);
:src="thumbnail"
:size="48"
:status="availabilityStatus"
+ hide-offline-status
rounded-full
/>
diff --git a/app/javascript/dashboard/components-next/avatar/Avatar.vue b/app/javascript/dashboard/components-next/avatar/Avatar.vue
index 65859b1c7..08224995c 100644
--- a/app/javascript/dashboard/components-next/avatar/Avatar.vue
+++ b/app/javascript/dashboard/components-next/avatar/Avatar.vue
@@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n';
import { removeEmoji } from 'shared/helpers/emoji';
import Icon from 'dashboard/components-next/icon/Icon.vue';
+import ChannelIcon from 'dashboard/components-next/icon/ChannelIcon.vue';
import wootConstants from 'dashboard/constants/globals';
const props = defineProps({
@@ -33,10 +34,18 @@ const props = defineProps({
validator: value =>
!value || wootConstants.AVAILABILITY_STATUS_KEYS.includes(value),
},
+ inbox: {
+ type: Object,
+ default: null,
+ },
iconName: {
type: String,
default: null,
},
+ hideOfflineStatus: {
+ type: Boolean,
+ default: false,
+ },
});
const emit = defineEmits(['upload', 'delete']);
@@ -66,11 +75,11 @@ const AVATAR_COLORS = {
default: { bg: '#E8E8E8', text: '#60646C' },
};
-const STATUS_CLASSES = {
+const STATUS_CLASSES = computed(() => ({
online: 'bg-n-teal-10',
busy: 'bg-n-amber-10',
- offline: 'bg-n-slate-10',
-};
+ ...(props.hideOfflineStatus ? {} : { offline: 'bg-n-slate-10' }),
+}));
const showDefaultAvatar = computed(() => !props.src && !props.name);
@@ -178,11 +187,18 @@ watch(
+
+
+
@@ -239,24 +255,33 @@ watch(
-
-
-
-
+
+
+
+
+
diff --git a/app/javascript/dashboard/components-next/icon/ChannelIcon.vue b/app/javascript/dashboard/components-next/icon/ChannelIcon.vue
index 11117cc18..68102dbd3 100644
--- a/app/javascript/dashboard/components-next/icon/ChannelIcon.vue
+++ b/app/javascript/dashboard/components-next/icon/ChannelIcon.vue
@@ -1,4 +1,5 @@
diff --git a/app/javascript/dashboard/components-next/icon/provider.js b/app/javascript/dashboard/components-next/icon/provider.js
index 36dd6216e..887368438 100644
--- a/app/javascript/dashboard/components-next/icon/provider.js
+++ b/app/javascript/dashboard/components-next/icon/provider.js
@@ -22,15 +22,21 @@ export function useChannelIcon(inbox) {
};
const channelIcon = computed(() => {
- const type = inbox.channel_type;
+ const inboxDetails = inbox.value || inbox;
+ const type = inboxDetails.channel_type;
let icon = channelTypeIconMap[type];
- if (type === 'Channel::Email' && inbox.provider) {
- if (Object.keys(providerIconMap).includes(inbox.provider)) {
- icon = providerIconMap[inbox.provider];
+ if (type === 'Channel::Email' && inboxDetails.provider) {
+ if (Object.keys(providerIconMap).includes(inboxDetails.provider)) {
+ icon = providerIconMap[inboxDetails.provider];
}
}
+ // Special case for Twilio whatsapp
+ if (type === 'Channel::TwilioSms' && inboxDetails.medium === 'whatsapp') {
+ icon = 'i-ri-whatsapp-fill';
+ }
+
return icon ?? 'i-ri-global-fill';
});
diff --git a/app/javascript/dashboard/components-next/icon/specs/provider.spec.js b/app/javascript/dashboard/components-next/icon/specs/provider.spec.js
index 5860e30ea..b0b820f25 100644
--- a/app/javascript/dashboard/components-next/icon/specs/provider.spec.js
+++ b/app/javascript/dashboard/components-next/icon/specs/provider.spec.js
@@ -25,6 +25,77 @@ describe('useChannelIcon', () => {
expect(icon).toBe('i-ri-phone-fill');
});
+ it('returns correct icon for Line channel', () => {
+ const inbox = { channel_type: 'Channel::Line' };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-line-fill');
+ });
+
+ it('returns correct icon for SMS channel', () => {
+ const inbox = { channel_type: 'Channel::Sms' };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-chat-1-fill');
+ });
+
+ it('returns correct icon for Telegram channel', () => {
+ const inbox = { channel_type: 'Channel::Telegram' };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-telegram-fill');
+ });
+
+ it('returns correct icon for Twitter channel', () => {
+ const inbox = { channel_type: 'Channel::TwitterProfile' };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-twitter-x-fill');
+ });
+
+ it('returns correct icon for WebWidget channel', () => {
+ const inbox = { channel_type: 'Channel::WebWidget' };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-global-fill');
+ });
+
+ it('returns correct icon for Instagram channel', () => {
+ const inbox = { channel_type: 'Channel::Instagram' };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-instagram-fill');
+ });
+
+ describe('TwilioSms channel', () => {
+ it('returns chat icon for regular Twilio SMS channel', () => {
+ const inbox = { channel_type: 'Channel::TwilioSms' };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-chat-1-fill');
+ });
+
+ it('returns WhatsApp icon for Twilio SMS with WhatsApp medium', () => {
+ const inbox = {
+ channel_type: 'Channel::TwilioSms',
+ medium: 'whatsapp',
+ };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-whatsapp-fill');
+ });
+
+ it('returns chat icon for Twilio SMS with non-WhatsApp medium', () => {
+ const inbox = {
+ channel_type: 'Channel::TwilioSms',
+ medium: 'sms',
+ };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-chat-1-fill');
+ });
+
+ it('returns chat icon for Twilio SMS with undefined medium', () => {
+ const inbox = {
+ channel_type: 'Channel::TwilioSms',
+ medium: undefined,
+ };
+ const { value: icon } = useChannelIcon(inbox);
+ expect(icon).toBe('i-ri-chat-1-fill');
+ });
+ });
+
describe('Email channel', () => {
it('returns mail icon for generic email channel', () => {
const inbox = { channel_type: 'Channel::Email' };
diff --git a/app/javascript/dashboard/components/widgets/InboxName.vue b/app/javascript/dashboard/components/widgets/InboxName.vue
index cf48b0837..66b80f69b 100644
--- a/app/javascript/dashboard/components/widgets/InboxName.vue
+++ b/app/javascript/dashboard/components/widgets/InboxName.vue
@@ -1,29 +1,19 @@
-
-
{{ inbox.name }}
diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue
index 9214a8234..cfac915bf 100644
--- a/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue
@@ -1,10 +1,10 @@