diff --git a/packages/react-components/src/components/InviteAgents/InviteAgents.module.scss b/packages/react-components/src/components/InviteAgents/InviteAgents.module.scss index 85201aa48..573a34ece 100644 --- a/packages/react-components/src/components/InviteAgents/InviteAgents.module.scss +++ b/packages/react-components/src/components/InviteAgents/InviteAgents.module.scss @@ -37,6 +37,7 @@ $base-class: 'invite-agents'; } &__tooltip { + box-shadow: 0 1px 10px 0 rgb(66 77 87 / 30%); max-width: 260px; > div { @@ -95,4 +96,16 @@ $base-class: 'invite-agents'; font-weight: 500; font-style: normal; } + + &__accepting-agents { + display: flex; + flex-direction: column; + gap: var(--spacing-2); + } + + &__accepting-agents-row { + display: flex; + gap: var(--spacing-2); + align-items: center; + } } diff --git a/packages/react-components/src/components/InviteAgents/InviteAgents.spec.tsx b/packages/react-components/src/components/InviteAgents/InviteAgents.spec.tsx index 4d0ea4866..4086daeb0 100644 --- a/packages/react-components/src/components/InviteAgents/InviteAgents.spec.tsx +++ b/packages/react-components/src/components/InviteAgents/InviteAgents.spec.tsx @@ -46,18 +46,21 @@ describe('InviteAgents Component', () => { email: 'alice@example.com', status: 'available', avatar: 'https://via.placeholder.com/150', + isBot: false, }, { name: 'Bob', email: 'bob@example.com', status: 'unavailable', avatar: 'https://via.placeholder.com/150', + isBot: false, }, { name: 'Charlie', email: 'charlie@example.com', status: 'unknown', avatar: 'https://via.placeholder.com/150', + isBot: true, }, ]; @@ -69,7 +72,7 @@ describe('InviteAgents Component', () => { userEvent.hover(avatars[0]); await waitFor(() => { - expect(screen.getByText(/1 accepting chats/i)).toBeInTheDocument(); + expect(screen.getByText(/1 agent/i)).toBeInTheDocument(); }); }); @@ -80,6 +83,7 @@ describe('InviteAgents Component', () => { email: 'bob@example.com', status: 'unavailable', avatar: 'https://via.placeholder.com/150', + isBot: false, }, ]; @@ -102,6 +106,7 @@ describe('InviteAgents Component', () => { email: 'alice@example.com', status: 'available', avatar: 'https://via.placeholder.com/150', + isBot: false, }, ]; @@ -127,17 +132,18 @@ describe('InviteAgents Component', () => { expect(mockOnAddAgentsClick).toHaveBeenCalledTimes(1); }); - it('displays additional agents count correctly', () => { + it('displays total accepting agents count correctly', () => { const agents: Agent[] = Array.from({ length: 5 }, (_, index) => ({ name: `Agent ${index + 1}`, email: `agent${index + 1}@example.com`, status: 'available', avatar: 'https://via.placeholder.com/150', + isBot: false, })); renderComponent(agents); - expect(screen.getByText('+2')).toBeInTheDocument(); + expect(screen.getByText('5')).toBeInTheDocument(); }); it('renders "Not accepting" when all agents are unavailable', async () => { @@ -147,12 +153,14 @@ describe('InviteAgents Component', () => { email: 'bob@example.com', status: 'unavailable', avatar: 'https://via.placeholder.com/150', + isBot: false, }, { name: 'Charlie', email: 'charlie@example.com', status: 'unavailable', avatar: 'https://via.placeholder.com/150', + isBot: false, }, ]; @@ -180,4 +188,34 @@ describe('InviteAgents Component', () => { userEvent.click(chatbotButton); expect(mockOnSetUpChatbotClick).toHaveBeenCalledTimes(1); }); + + it('displays only bots when all agents are bots', async () => { + const agents: Agent[] = [ + { + name: 'Alice', + email: 'alice@example.com', + status: 'available', + avatar: 'https://via.placeholder.com/150', + isBot: true, + }, + { + name: 'Bob', + email: 'bob@example.com', + status: 'available', + avatar: 'https://via.placeholder.com/150', + isBot: true, + }, + ]; + + renderComponent(agents); + + const avatars = screen.getAllByRole('img'); + expect(avatars).toHaveLength(2); + + userEvent.hover(avatars[0]); + + await waitFor(() => { + expect(screen.getByText('2 bots')).toBeInTheDocument(); + }); + }); }); diff --git a/packages/react-components/src/components/InviteAgents/InviteAgents.stories.tsx b/packages/react-components/src/components/InviteAgents/InviteAgents.stories.tsx index 028766dfd..ac1fc7cca 100644 --- a/packages/react-components/src/components/InviteAgents/InviteAgents.stories.tsx +++ b/packages/react-components/src/components/InviteAgents/InviteAgents.stories.tsx @@ -24,30 +24,35 @@ const mockAgents = [ email: 'bob@example.com', status: 'unknown' as const, avatar: '', + isBot: false, }, { name: 'Alice Johnson', email: 'alice@example.com', status: 'available' as const, avatar: undefined, + isBot: false, }, { name: 'Alice Johnson 2', email: 'alic2@example.com', status: 'available' as const, avatar: 'https://via.placeholder.com/150', + isBot: false, }, { name: 'Bob Smith', email: 'bob3@example.com', status: 'unavailable' as const, avatar: 'https://via.placeholder.com/150', + isBot: false, }, ...[...Array(10)].map((_, index) => ({ name: `Unknown Agent ${index}`, email: `unknown${index}@example.com`, status: 'available' as const, avatar: 'https://via.placeholder.com/150', + isBot: index % 2 === 0, })), ]; diff --git a/packages/react-components/src/components/InviteAgents/InviteAgents.tsx b/packages/react-components/src/components/InviteAgents/InviteAgents.tsx index b81ba131d..52cb55b78 100644 --- a/packages/react-components/src/components/InviteAgents/InviteAgents.tsx +++ b/packages/react-components/src/components/InviteAgents/InviteAgents.tsx @@ -1,9 +1,16 @@ import { FC, memo, useMemo, useState } from 'react'; -import { Add, ChatBotColored, PersonAdd } from '@livechat/design-system-icons'; +import { + Add, + Bot, + ChatBotColored, + People, + PersonAdd, +} from '@livechat/design-system-icons'; import cx from 'clsx'; import { ThemeClassName } from '../../providers'; +import { plural } from '../../utils/plural'; import { ActionMenu, ActionMenuItem } from '../ActionMenu'; import { Avatar } from '../Avatar'; import { Icon } from '../Icon'; @@ -11,7 +18,7 @@ import { Interactive, Tooltip } from '../Tooltip'; import { Text } from '../Typography'; import { AnimatedButton } from './components/AnimatedButton/AnimatedButton'; -import { getAvailableAgentsTooltipText, getSortedAgents } from './helpers'; +import { getSortedAgents } from './helpers'; import { InviteAgentsProps } from './types'; import styles from './InviteAgents.module.scss'; @@ -36,8 +43,9 @@ const InviteAgentsComponent: FC = ({ const { availableAgentsNumber, visibleAgents, - additionalAgentsNumber, hasOnlyUnavailableAgents, + onlyAgentsNumber, + onlyBotsNumber, } = useMemo(() => { const availableAgents = agents.filter( (agent) => agent.status === 'available' @@ -47,15 +55,19 @@ const InviteAgentsComponent: FC = ({ const visibleAgents = sortedAgents.length > 4 ? sortedAgents.slice(0, 3) : sortedAgents; - const additionalAgentsNumber = availableAgentsNumber - visibleAgents.length; const hasOnlyUnavailableAgents = agents.length > 0 && availableAgentsNumber === 0; + const onlyAgentsNumber = availableAgents.filter( + (agent) => !agent.isBot + ).length; + const onlyBotsNumber = availableAgentsNumber - onlyAgentsNumber; return { availableAgentsNumber, visibleAgents, - additionalAgentsNumber, hasOnlyUnavailableAgents, + onlyAgentsNumber, + onlyBotsNumber, }; }, [agents]); @@ -154,11 +166,11 @@ const InviteAgentsComponent: FC = ({ /> ))} - {additionalAgentsNumber > 0 && ( + {availableAgentsNumber > 0 && ( - +{additionalAgentsNumber} + {availableAgentsNumber} )} @@ -175,8 +187,33 @@ const InviteAgentsComponent: FC = ({ }} /> ) : ( - - {getAvailableAgentsTooltipText(availableAgentsNumber)} + + + Accepting chats: + + + + {plural( + onlyAgentsNumber, + '1 agent', + `${onlyAgentsNumber} agents` + )} + + + + {plural(onlyBotsNumber, '1 bot', `${onlyBotsNumber} bots`)} + )} diff --git a/packages/react-components/src/components/InviteAgents/helpers.ts b/packages/react-components/src/components/InviteAgents/helpers.ts index b1db0fae5..2b18e0fbd 100644 --- a/packages/react-components/src/components/InviteAgents/helpers.ts +++ b/packages/react-components/src/components/InviteAgents/helpers.ts @@ -11,13 +11,3 @@ export const getSortedAgents = (agents: Agent[]) => { return statusPriority[a.status] - statusPriority[b.status]; }); }; - -export const getAvailableAgentsTooltipText = ( - availableAgentsNumber: number -) => { - if (availableAgentsNumber === 0) { - return 'No one assist your customers'; - } - - return `${availableAgentsNumber} accepting chats`; -}; diff --git a/packages/react-components/src/components/InviteAgents/types.ts b/packages/react-components/src/components/InviteAgents/types.ts index cf0ad7393..2aed53cbf 100644 --- a/packages/react-components/src/components/InviteAgents/types.ts +++ b/packages/react-components/src/components/InviteAgents/types.ts @@ -5,6 +5,7 @@ export interface Agent { email: string; status: 'available' | 'unavailable' | 'unknown'; avatar?: string; + isBot: boolean; } export interface InviteAgentsProps extends ComponentCoreProps {