2025-01-07 02:29:29 +08:00
|
|
|
import React, { useMemo } from 'react';
|
|
|
|
import { Avatar, AvatarProps } from 'antd';
|
2025-02-22 03:07:30 +08:00
|
|
|
import { getFirstTwoCapitalizedLetters } from '@/lib/text';
|
2025-01-07 02:29:29 +08:00
|
|
|
import { AppTooltip } from '../tooltip';
|
|
|
|
import type { GroupProps } from 'antd/es/avatar';
|
|
|
|
import BusterIconWhite from '@/assets/png/buster_icon_small_white.png';
|
|
|
|
import BusterIconBlack from '@/assets/png/buster_icon_small_black.png';
|
|
|
|
import { createStyles } from 'antd-style';
|
|
|
|
export interface BusterUserAvatarProps extends AvatarProps {
|
|
|
|
color?: string;
|
|
|
|
image?: string;
|
|
|
|
name?: string | null;
|
|
|
|
style?: React.CSSProperties;
|
|
|
|
useToolTip?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export const BusterUserAvatar = React.memo(
|
|
|
|
({ useToolTip = true, ...props }: BusterUserAvatarProps) => {
|
|
|
|
const { size = 38, ...restProps } = props;
|
|
|
|
if (!props.name && !props.image) return <BusterAvatar {...restProps} size={size as number} />;
|
|
|
|
|
|
|
|
const firstAndLastInitial = createNameLetters(props.name, props.image);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<AppTooltip
|
|
|
|
title={useToolTip ? props.name || '' : ''}
|
|
|
|
mouseEnterDelay={0.35}
|
|
|
|
performant={useToolTip}>
|
|
|
|
<Avatar
|
|
|
|
{...props}
|
2025-02-19 04:23:44 +08:00
|
|
|
className={`${props.className || ''} flex ${props.image ? 'bg-transparent!' : ''}`}
|
2025-01-07 02:29:29 +08:00
|
|
|
size={size}
|
|
|
|
style={{
|
|
|
|
minWidth: size as number,
|
|
|
|
minHeight: size as number
|
|
|
|
}}
|
|
|
|
src={createAvatarImage(props.image, firstAndLastInitial, props.name)}>
|
|
|
|
{firstAndLastInitial}
|
|
|
|
</Avatar>
|
|
|
|
</AppTooltip>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
BusterUserAvatar.displayName = 'BusterUserAvatar';
|
|
|
|
|
|
|
|
const useStyles = createStyles(({ css, token, isDarkMode }) => {
|
|
|
|
return {
|
|
|
|
groupAvatar: css`
|
|
|
|
.busterv2-avatar {
|
|
|
|
font-size: ${token.fontSizeSM} !important;
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
avatar: {
|
|
|
|
background: isDarkMode ? token.colorBgSpotlight : token.colorFillContentHover
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
export const BusterUserAvatarGroup: React.FC<
|
|
|
|
{
|
|
|
|
avatars: BusterUserAvatarProps[];
|
|
|
|
} & GroupProps
|
|
|
|
> = React.memo(({ avatars, ...props }) => {
|
|
|
|
const { styles, cx } = useStyles();
|
|
|
|
|
|
|
|
const renderedAvatars = useMemo(
|
|
|
|
() =>
|
|
|
|
avatars.map((avatar, index) => (
|
|
|
|
<BusterUserAvatar size={props.size} key={index} {...avatar} />
|
|
|
|
)),
|
|
|
|
[avatars, props.size]
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Avatar.Group {...props} className={cx(styles.groupAvatar, props.className)}>
|
|
|
|
{renderedAvatars}
|
|
|
|
</Avatar.Group>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
BusterUserAvatarGroup.displayName = 'BusterUserAvatarGroup';
|
|
|
|
|
|
|
|
const createNameLetters = (name?: string | null, image?: string | null | React.ReactNode) => {
|
|
|
|
if (name && !image) {
|
|
|
|
const firstTwoLetters = getFirstTwoCapitalizedLetters(name);
|
|
|
|
if (firstTwoLetters.length == 2) return firstTwoLetters;
|
|
|
|
|
|
|
|
//Get First Name Initial
|
|
|
|
const _name = name.split(' ') as [string, string];
|
|
|
|
const returnName = `${_name[0][0]}`.toUpperCase().replace('@', '');
|
|
|
|
|
|
|
|
return returnName;
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
};
|
|
|
|
|
|
|
|
const createAvatarImage = (
|
|
|
|
image: string | null | React.ReactNode,
|
|
|
|
initialNames?: null | string,
|
|
|
|
fullname?: string | null
|
|
|
|
) => {
|
|
|
|
if (image) return image;
|
|
|
|
if (!initialNames) return;
|
|
|
|
//USER AVATARS
|
|
|
|
|
|
|
|
// const removeHash = hex.replace('#', '');
|
|
|
|
// const baseUrl = `https://ui-avatars.com/api/?background=${removeHash}&color=fff&name=${name}`;
|
|
|
|
// return baseUrl;
|
|
|
|
|
|
|
|
//VERCEL
|
|
|
|
// const baseUrl = `https://avatar.vercel.sh/${fullname}.svg?text=${initialNames}`;
|
|
|
|
// return baseUrl;
|
|
|
|
|
|
|
|
//DICE BEAR INDENTICON
|
|
|
|
const baseUrl = `https://api.dicebear.com/9.x/initials/svg?seed=${fullname || initialNames}`;
|
|
|
|
return baseUrl;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const BusterAvatar: React.FC<{
|
|
|
|
size?: number;
|
|
|
|
shape?: 'circle' | 'square';
|
|
|
|
}> = React.memo(({ size = 24, shape = 'circle' }) => {
|
|
|
|
const { styles, cx } = useStyles();
|
|
|
|
|
|
|
|
const memoizedStyles = useMemo(
|
|
|
|
() => ({
|
|
|
|
minWidth: size,
|
|
|
|
minHeight: size
|
|
|
|
}),
|
|
|
|
[size]
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<AppTooltip title={'Buster'}>
|
|
|
|
<Avatar
|
|
|
|
size={size}
|
|
|
|
shape={shape}
|
|
|
|
icon={<BusterImage />}
|
|
|
|
className={cx(styles.avatar)}
|
|
|
|
style={memoizedStyles}
|
|
|
|
/>
|
|
|
|
</AppTooltip>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
BusterAvatar.displayName = 'BusterAvatar';
|
|
|
|
|
|
|
|
const BusterImage: React.FC = () => {
|
2025-02-27 11:11:41 +08:00
|
|
|
const isDarkMode = false;
|
2025-01-07 02:29:29 +08:00
|
|
|
const image = isDarkMode ? BusterIconBlack.src : BusterIconWhite.src;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={`flex h-full w-full items-center justify-center ${
|
|
|
|
isDarkMode ? 'bg-gray-900' : 'bg-white'
|
|
|
|
}`}>
|
|
|
|
<img
|
|
|
|
className="flex items-center justify-center"
|
|
|
|
style={{
|
|
|
|
height: '100%',
|
|
|
|
width: 'auto',
|
|
|
|
objectFit: 'contain'
|
|
|
|
}}
|
|
|
|
src={image}
|
|
|
|
alt="Company Logo"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|