feat(reporting): enhance overview reports with memoization and dark mode support

- Refactored components in the reporting section to utilize React.memo, useCallback, and useMemo for improved performance and reduced unnecessary re-renders.
- Updated the OverviewStatCard to support dark mode styling and added enhanced hover effects.
- Improved the Avatars component by memoizing rendering logic and preventing event propagation.
- Enhanced OverviewReportsTable with memoized columns and row props for better performance.
- Applied consistent styling adjustments across various components to ensure a cohesive user experience.
This commit is contained in:
chamikaJ
2025-06-13 16:04:32 +05:30
parent d0c231ee43
commit 4426b5f3ef
7 changed files with 423 additions and 155 deletions

View File

@@ -1,4 +1,5 @@
import { Avatar, Tooltip } from 'antd';
import React, { useCallback, useMemo } from 'react';
import { InlineMember } from '@/types/teamMembers/inlineMember.types';
interface AvatarsProps {
@@ -6,41 +7,54 @@ interface AvatarsProps {
maxCount?: number;
}
const renderAvatar = (member: InlineMember, index: number) => (
<Tooltip
key={member.team_member_id || index}
title={member.end && member.names ? member.names.join(', ') : member.name}
>
{member.avatar_url ? (
<span onClick={(e: React.MouseEvent) => e.stopPropagation()}>
<Avatar src={member.avatar_url} size={28} key={member.team_member_id || index} />
</span>
) : (
<span onClick={(e: React.MouseEvent) => e.stopPropagation()}>
<Avatar
size={28}
key={member.team_member_id || index}
style={{
backgroundColor: member.color_code || '#ececec',
fontSize: '14px',
}}
>
{member.end && member.names ? member.name : member.name?.charAt(0).toUpperCase()}
</Avatar>
</span>
)}
</Tooltip>
);
const Avatars: React.FC<AvatarsProps> = React.memo(({ members, maxCount }) => {
const stopPropagation = useCallback((e: React.MouseEvent) => {
e.stopPropagation();
}, []);
const renderAvatar = useCallback((member: InlineMember, index: number) => (
<Tooltip
key={member.team_member_id || index}
title={member.end && member.names ? member.names.join(', ') : member.name}
>
{member.avatar_url ? (
<span onClick={stopPropagation}>
<Avatar src={member.avatar_url} size={28} key={member.team_member_id || index} />
</span>
) : (
<span onClick={stopPropagation}>
<Avatar
size={28}
key={member.team_member_id || index}
style={{
backgroundColor: member.color_code || '#ececec',
fontSize: '14px',
}}
>
{member.end && member.names ? member.name : member.name?.charAt(0).toUpperCase()}
</Avatar>
</span>
)}
</Tooltip>
), [stopPropagation]);
const visibleMembers = useMemo(() => {
return maxCount ? members.slice(0, maxCount) : members;
}, [members, maxCount]);
const avatarElements = useMemo(() => {
return visibleMembers.map((member, index) => renderAvatar(member, index));
}, [visibleMembers, renderAvatar]);
const Avatars: React.FC<AvatarsProps> = ({ members, maxCount }) => {
const visibleMembers = maxCount ? members.slice(0, maxCount) : members;
return (
<div onClick={(e: React.MouseEvent) => e.stopPropagation()}>
<div onClick={stopPropagation}>
<Avatar.Group>
{visibleMembers.map((member, index) => renderAvatar(member, index))}
{avatarElements}
</Avatar.Group>
</div>
);
};
});
Avatars.displayName = 'Avatars';
export default Avatars;