feat: add channel icon component (#10471)

This pull request introduces a new `ChannelIcon` component and refactors the existing code to use this component, which simplifies the icon management for different channel types and providers.
This commit is contained in:
Shivam Mishra
2024-11-21 09:53:12 +05:30
committed by GitHub
parent 515778eabb
commit 3a334be582
4 changed files with 114 additions and 32 deletions

View File

@@ -0,0 +1,17 @@
<script setup>
import { useChannelIcon } from './provider';
import Icon from 'next/icon/Icon.vue';
const props = defineProps({
inbox: {
type: Object,
required: true,
},
});
const channelIcon = useChannelIcon(props.inbox);
</script>
<template>
<Icon :icon="channelIcon" />
</template>

View File

@@ -0,0 +1,36 @@
import { computed } from 'vue';
export function useChannelIcon(inbox) {
const channelTypeIconMap = {
'Channel::Api': 'i-ri-cloudy-fill',
'Channel::Email': 'i-ri-mail-fill',
'Channel::FacebookPage': 'i-ri-messenger-fill',
'Channel::Line': 'i-ri-line-fill',
'Channel::Sms': 'i-ri-chat-1-fill',
'Channel::Telegram': 'i-ri-telegram-fill',
'Channel::TwilioSms': 'i-ri-chat-1-fill',
'Channel::TwitterProfile': 'i-ri-twitter-x-fill',
'Channel::WebWidget': 'i-ri-global-fill',
'Channel::Whatsapp': 'i-ri-whatsapp-fill',
};
const providerIconMap = {
microsoft: 'i-ri-microsoft-fill',
google: 'i-ri-google-fill',
};
const channelIcon = computed(() => {
const type = inbox.channel_type;
let icon = channelTypeIconMap[type];
if (type === 'Channel::Email' && inbox.provider) {
if (Object.keys(providerIconMap).includes(inbox.provider)) {
icon = providerIconMap[inbox.provider];
}
}
return icon ?? 'i-ri-global-fill';
});
return channelIcon;
}

View File

@@ -0,0 +1,59 @@
import { useChannelIcon } from '../provider';
describe('useChannelIcon', () => {
it('returns correct icon for API channel', () => {
const inbox = { channel_type: 'Channel::Api' };
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-cloudy-fill');
});
it('returns correct icon for Facebook channel', () => {
const inbox = { channel_type: 'Channel::FacebookPage' };
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-messenger-fill');
});
it('returns correct icon for WhatsApp channel', () => {
const inbox = { channel_type: 'Channel::Whatsapp' };
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-whatsapp-fill');
});
describe('Email channel', () => {
it('returns mail icon for generic email channel', () => {
const inbox = { channel_type: 'Channel::Email' };
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-mail-fill');
});
it('returns Microsoft icon for Microsoft email provider', () => {
const inbox = {
channel_type: 'Channel::Email',
provider: 'microsoft',
};
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-microsoft-fill');
});
it('returns Google icon for Google email provider', () => {
const inbox = {
channel_type: 'Channel::Email',
provider: 'google',
};
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-google-fill');
});
});
it('returns default icon for unknown channel type', () => {
const inbox = { channel_type: 'Channel::Unknown' };
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-global-fill');
});
it('returns default icon when channel type is undefined', () => {
const inbox = {};
const { value: icon } = useChannelIcon(inbox);
expect(icon).toBe('i-ri-global-fill');
});
});

View File

@@ -1,6 +1,7 @@
<script setup>
import { computed } from 'vue';
import Icon from 'next/icon/Icon.vue';
import ChannelIcon from 'next/icon/ChannelIcon.vue';
const props = defineProps({
label: {
@@ -17,37 +18,6 @@ const props = defineProps({
},
});
const channelTypeIconMap = {
'Channel::Api': 'i-ri-cloudy-fill',
'Channel::Email': 'i-ri-mail-fill',
'Channel::FacebookPage': 'i-ri-messenger-fill',
'Channel::Line': 'i-ri-line-fill',
'Channel::Sms': 'i-ri-chat-1-fill',
'Channel::Telegram': 'i-ri-telegram-fill',
'Channel::TwilioSms': 'i-ri-chat-1-fill',
'Channel::TwitterProfile': 'i-ri-twitter-x-fill',
'Channel::WebWidget': 'i-ri-global-fill',
'Channel::Whatsapp': 'i-ri-whatsapp-fill',
};
const providerIconMap = {
microsoft: 'i-ri-microsoft-fill',
google: 'i-ri-google-fill',
};
const channelIcon = computed(() => {
const type = props.inbox.channel_type;
let icon = channelTypeIconMap[type];
if (type === 'Channel::Email' && props.inbox.provider) {
if (Object.keys(providerIconMap).includes(props.inbox.provider)) {
icon = providerIconMap[props.inbox.provider];
}
}
return icon ?? 'i-ri-global-fill';
});
const reauthorizationRequired = computed(() => {
return props.inbox.reauthorization_required;
});
@@ -58,7 +28,7 @@ const reauthorizationRequired = computed(() => {
class="size-4 grid place-content-center rounded-full bg-n-alpha-2"
:class="{ 'bg-n-solid-blue': active }"
>
<Icon :icon="channelIcon" class="size-3" />
<ChannelIcon :inbox="inbox" class="size-3" />
</span>
<div class="flex-1 truncate min-w-0">{{ label }}</div>
<div