Skip to content

Commit 1f054d9

Browse files
igor-francabrianchandotcom
authored andcommitted
LPD-91802 Add the four Daily Stats KPI cards
1 parent a6c1084 commit 1f054d9

10 files changed

Lines changed: 220 additions & 0 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import ClayIcon from '@clayui/icon';
7+
import React from 'react';
8+
9+
import MetricCard from './MetricCard';
10+
11+
export default function AgentsCard({value}: {value: number}) {
12+
return (
13+
<MetricCard
14+
icon={<ClayIcon symbol="organizations" />}
15+
title={Liferay.Language.get('agents')}
16+
value={value}
17+
/>
18+
);
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import ClayIcon from '@clayui/icon';
7+
import React from 'react';
8+
9+
import {formatMillisecondsAsSeconds} from '../utils/formatters';
10+
import MetricCard from './MetricCard';
11+
12+
export default function AverageResponseTimeCard({value}: {value: number}) {
13+
return (
14+
<MetricCard
15+
icon={<ClayIcon symbol="message-boards" />}
16+
title={Liferay.Language.get('average-response-time')}
17+
value={formatMillisecondsAsSeconds(value)}
18+
/>
19+
);
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import ClayIcon from '@clayui/icon';
7+
import React from 'react';
8+
9+
import MetricCard from './MetricCard';
10+
11+
export default function ChatbotsCard({value}: {value: number}) {
12+
return (
13+
<MetricCard
14+
icon={<ClayIcon symbol="chatbot" />}
15+
title={Liferay.Language.get('chatbots')}
16+
value={value}
17+
/>
18+
);
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import ClayIcon from '@clayui/icon';
7+
import React from 'react';
8+
9+
import MetricCard from './MetricCard';
10+
11+
export default function TotalInteractionsCard({value}: {value: number}) {
12+
return (
13+
<MetricCard
14+
icon={<ClayIcon symbol="message-boards" />}
15+
title={Liferay.Language.get('total-interactions')}
16+
value={value.toLocaleString()}
17+
/>
18+
);
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
export function formatMillisecondsAsSeconds(milliseconds: number): string {
7+
return `${(milliseconds / 1000).toFixed(1)}s`;
8+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import {render, screen} from '@testing-library/react';
7+
import React from 'react';
8+
9+
import '@testing-library/jest-dom';
10+
11+
import AgentsCard from '../../../../src/main/resources/META-INF/resources/js/activity_dashboard/components/AgentsCard';
12+
13+
(global as any).Liferay = {
14+
Language: {
15+
get: (key: string) => key,
16+
},
17+
};
18+
19+
describe('AgentsCard', () => {
20+
it('renders the agents heading and value', () => {
21+
render(<AgentsCard value={18} />);
22+
23+
expect(
24+
screen.getByRole('heading', {level: 2, name: 'agents'})
25+
).toBeInTheDocument();
26+
expect(screen.getByText('18')).toBeInTheDocument();
27+
});
28+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import {render, screen} from '@testing-library/react';
7+
import React from 'react';
8+
9+
import '@testing-library/jest-dom';
10+
11+
import AverageResponseTimeCard from '../../../../src/main/resources/META-INF/resources/js/activity_dashboard/components/AverageResponseTimeCard';
12+
13+
(global as any).Liferay = {
14+
Language: {
15+
get: (key: string) => key,
16+
},
17+
};
18+
19+
describe('AverageResponseTimeCard', () => {
20+
it('renders the average response time heading and the value in seconds', () => {
21+
render(<AverageResponseTimeCard value={2600} />);
22+
23+
expect(
24+
screen.getByRole('heading', {
25+
level: 2,
26+
name: 'average-response-time',
27+
})
28+
).toBeInTheDocument();
29+
expect(screen.getByText('2.6s')).toBeInTheDocument();
30+
});
31+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import {render, screen} from '@testing-library/react';
7+
import React from 'react';
8+
9+
import '@testing-library/jest-dom';
10+
11+
import ChatbotsCard from '../../../../src/main/resources/META-INF/resources/js/activity_dashboard/components/ChatbotsCard';
12+
13+
(global as any).Liferay = {
14+
Language: {
15+
get: (key: string) => key,
16+
},
17+
};
18+
19+
describe('ChatbotsCard', () => {
20+
it('renders the chatbots heading and value', () => {
21+
render(<ChatbotsCard value={4} />);
22+
23+
expect(
24+
screen.getByRole('heading', {level: 2, name: 'chatbots'})
25+
).toBeInTheDocument();
26+
expect(screen.getByText('4')).toBeInTheDocument();
27+
});
28+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import {render, screen} from '@testing-library/react';
7+
import React from 'react';
8+
9+
import '@testing-library/jest-dom';
10+
11+
import TotalInteractionsCard from '../../../../src/main/resources/META-INF/resources/js/activity_dashboard/components/TotalInteractionsCard';
12+
13+
(global as any).Liferay = {
14+
Language: {
15+
get: (key: string) => key,
16+
},
17+
};
18+
19+
describe('TotalInteractionsCard', () => {
20+
it('renders the total interactions heading and the value with a thousands separator', () => {
21+
render(<TotalInteractionsCard value={1245} />);
22+
23+
expect(
24+
screen.getByRole('heading', {level: 2, name: 'total-interactions'})
25+
).toBeInTheDocument();
26+
expect(screen.getByText('1,245')).toBeInTheDocument();
27+
});
28+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* SPDX-FileCopyrightText: (c) 2026 Liferay, Inc. https://liferay.com
3+
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
4+
*/
5+
6+
import {formatMillisecondsAsSeconds} from '../../../../src/main/resources/META-INF/resources/js/activity_dashboard/utils/formatters';
7+
8+
describe('formatMillisecondsAsSeconds', () => {
9+
it('converts whole seconds', () => {
10+
expect(formatMillisecondsAsSeconds(2000)).toBe('2.0s');
11+
});
12+
13+
it('formats fractional milliseconds to one decimal', () => {
14+
expect(formatMillisecondsAsSeconds(2600)).toBe('2.6s');
15+
});
16+
17+
it('formats zero as 0.0s', () => {
18+
expect(formatMillisecondsAsSeconds(0)).toBe('0.0s');
19+
});
20+
});

0 commit comments

Comments
 (0)