mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
refs [AP-647](https://linear.app/ghost/issue/AP-648/refactor-profile-tab-to-use-account-and-follows) Updated the profile tab in `admin-x-activitypub` to use dedicated account endpoints. This is to remove coupling between the UI and the ActivityPub endpoints in preparation for the upcoming changes around storing `accounts` and `follows` in the database
107 lines
3 KiB
TypeScript
107 lines
3 KiB
TypeScript
import NiceModal from '@ebay/nice-modal-react';
|
|
import React, {useEffect, useState} from 'react';
|
|
import ViewProfileModal from '../modals/ViewProfileModal';
|
|
import clsx from 'clsx';
|
|
import getUsername from '../../utils/get-username';
|
|
import {ActorProperties} from '@tryghost/admin-x-framework/api/activitypub';
|
|
import {Icon} from '@tryghost/admin-x-design-system';
|
|
|
|
type AvatarSize = '2xs' | 'xs' | 'sm' | 'lg' | 'notification';
|
|
|
|
interface APAvatarProps {
|
|
author: {
|
|
icon: {
|
|
url: string;
|
|
};
|
|
name: string;
|
|
} | undefined;
|
|
size?: AvatarSize;
|
|
}
|
|
|
|
const APAvatar: React.FC<APAvatarProps> = ({author, size}) => {
|
|
let iconSize = 18;
|
|
let containerClass = `shrink-0 items-center justify-center relative cursor-pointer z-10 flex ${size === 'lg' ? '' : 'hover:opacity-80'}`;
|
|
let imageClass = 'z-10 rounded-md w-10 h-10 object-cover';
|
|
const [iconUrl, setIconUrl] = useState(author?.icon?.url);
|
|
|
|
useEffect(() => {
|
|
setIconUrl(author?.icon?.url);
|
|
}, [author?.icon?.url]);
|
|
|
|
if (!author) {
|
|
return null;
|
|
}
|
|
|
|
switch (size) {
|
|
case '2xs':
|
|
iconSize = 10;
|
|
containerClass = clsx('h-4 w-4 rounded-md ', containerClass);
|
|
imageClass = 'z-10 rounded-md w-4 h-4 object-cover';
|
|
break;
|
|
case 'xs':
|
|
iconSize = 12;
|
|
containerClass = clsx('h-6 w-6 rounded-md ', containerClass);
|
|
imageClass = 'z-10 rounded-md w-6 h-6 object-cover';
|
|
break;
|
|
case 'notification':
|
|
iconSize = 12;
|
|
containerClass = clsx('h-9 w-9 rounded-md', containerClass);
|
|
imageClass = 'z-10 rounded-xl w-9 h-9 object-cover';
|
|
break;
|
|
case 'sm':
|
|
containerClass = clsx('h-10 w-10 rounded-md', containerClass);
|
|
break;
|
|
case 'lg':
|
|
containerClass = clsx('h-22 w-22 rounded-xl', containerClass);
|
|
imageClass = 'z-10 rounded-xl w-22 h-22 object-cover';
|
|
break;
|
|
default:
|
|
containerClass = clsx('h-10 w-10 rounded-md', containerClass);
|
|
break;
|
|
}
|
|
|
|
if (!iconUrl) {
|
|
containerClass = clsx(containerClass, 'bg-grey-100');
|
|
}
|
|
|
|
const onClick = (e: React.MouseEvent) => {
|
|
e.stopPropagation();
|
|
NiceModal.show(ViewProfileModal, {
|
|
profile: getUsername(author as ActorProperties)
|
|
});
|
|
};
|
|
|
|
const title = `${author?.name} ${getUsername(author as ActorProperties)}`;
|
|
|
|
if (iconUrl) {
|
|
return (
|
|
<div
|
|
className={containerClass}
|
|
title={title}
|
|
onClick={onClick}
|
|
>
|
|
<img
|
|
className={imageClass}
|
|
src={iconUrl}
|
|
onError={() => setIconUrl(undefined)}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={containerClass}
|
|
title={title}
|
|
onClick={onClick}
|
|
>
|
|
<Icon
|
|
colorClass='text-grey-600'
|
|
name='user'
|
|
size={iconSize}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default APAvatar;
|