Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | 7x 70x 68x 68x 68x 68x 2x 2x 70x 70x 7x 70x 70x 1059x 70x 70x 7x 70x 70x 70x 70x 70x 70x | /**
* UserAvatar Component
*
* Shared component for displaying user avatar with name and optional company.
* Used across UserManagement and EventManagement components.
*
* Features:
* - Avatar with initials fallback
* - Consistent color generation from name
* - Optional company display
* - Configurable sizes
* - Tooltip support
*/
import React from 'react';
import { Avatar, Box, Typography, Tooltip, Stack } from '@mui/material';
interface UserAvatarProps {
/** User's full name or firstName/lastName separately */
name?: string;
firstName?: string;
lastName?: string;
/** Company name (optional) */
company?: string;
/** Profile picture URL (optional) */
profilePictureUrl?: string;
/** Avatar size in pixels (default: 40) */
size?: number;
/** Show company below name (default: true if company provided) */
showCompany?: boolean;
/** Use horizontal layout (avatar + text side-by-side) (default: true) */
horizontal?: boolean;
/** Show tooltip with full name (default: false) */
showTooltip?: boolean;
/** Custom background color (optional - will generate from name if not provided) */
bgcolor?: string;
}
// Helper function to generate initials from name
const getInitials = (firstName?: string, lastName?: string, fullName?: string): string => {
if (fullName) {
const parts = fullName.trim().split(' ');
Iif (parts.length === 0) return '?';
Iif (parts.length === 1) return parts[0].charAt(0).toUpperCase();
return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
}
Iif (!firstName && !lastName) return '?';
const first = firstName?.charAt(0).toUpperCase() || '';
const last = lastName?.charAt(0).toUpperCase() || '';
return `${first}${last}`;
};
// Helper function to generate consistent avatar color from name
const stringToColor = (str: string): string => {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
const hue = hash % 360;
return `hsl(${hue}, 60%, 50%)`;
};
export const UserAvatar: React.FC<UserAvatarProps> = ({
name,
firstName,
lastName,
company,
profilePictureUrl,
size = 40,
showCompany = !!company,
horizontal = true,
showTooltip = false,
bgcolor,
}) => {
// Determine full name
const fullName =
name || (firstName && lastName ? `${firstName} ${lastName}` : firstName || lastName || '');
// Generate initials (fallback to '?' if no name)
const initials = getInitials(firstName, lastName, name);
// Generate background color if not provided (use '?' if no name for consistent color)
const avatarBgColor = bgcolor || stringToColor(fullName || '?');
const avatarElement = (
<Avatar
src={profilePictureUrl}
alt={fullName}
sx={{
bgcolor: avatarBgColor,
width: size,
height: size,
fontSize: size * 0.4,
}}
>
{initials}
</Avatar>
);
const content = horizontal ? (
<Stack direction="row" spacing={2} alignItems="center">
{showTooltip ? (
<Tooltip title={fullName} arrow>
{avatarElement}
</Tooltip>
) : (
avatarElement
)}
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="body2" fontWeight="medium">
{fullName}
</Typography>
{showCompany && company && (
<Typography variant="caption" color="text.secondary">
{company}
</Typography>
)}
</Box>
</Stack>
) : (
<Stack direction="column" spacing={1} alignItems="center">
{showTooltip ? (
<Tooltip title={fullName} arrow>
{avatarElement}
</Tooltip>
) : (
avatarElement
)}
<Box textAlign="center">
<Typography variant="body2" fontWeight="medium">
{fullName}
</Typography>
{showCompany && company && (
<Typography variant="caption" color="text.secondary">
{company}
</Typography>
)}
</Box>
</Stack>
);
return content;
};
export default UserAvatar;
|