Files
myeasycms-v2/packages/features/accounts/src/components/personal-account-dropdown.tsx
giancarlo d7cf271e8a Refactor personal account components for data fetching efficiency
Refactored personal account components to centralize user data fetching and subsequently reduce and distribute calls. Instead of fetching user data individually in `UpdateAccountImageContainer`, `UpdateAccountDetailsFormContainer` and `UpdateAccountNameFormContainer`, data fetching is now performed in the parent component, `AccountSettingsContainer`. Also, implemented partial loading state.
2024-04-16 22:30:41 +08:00

210 lines
5.2 KiB
TypeScript

'use client';
import { useMemo } from 'react';
import Link from 'next/link';
import type { User } from '@supabase/supabase-js';
import {
EllipsisVertical,
Home,
LogOut,
MessageCircleQuestion,
Shield,
} from 'lucide-react';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@kit/ui/dropdown-menu';
import { If } from '@kit/ui/if';
import { SubMenuModeToggle } from '@kit/ui/mode-toggle';
import { ProfileAvatar } from '@kit/ui/profile-avatar';
import { Trans } from '@kit/ui/trans';
import { cn } from '@kit/ui/utils';
import { usePersonalAccountData } from '../hooks/use-personal-account-data';
export function PersonalAccountDropdown({
className,
user,
signOutRequested,
showProfileName,
paths,
features,
account,
}: {
className?: string;
user: User | null;
account?: {
id: string | null;
name: string | null;
picture_url: string | null;
};
signOutRequested: () => unknown;
showProfileName?: boolean;
paths: {
home: string;
};
features: {
enableThemeToggle: boolean;
};
}) {
const { data: personalAccountData } = usePersonalAccountData(account);
const signedInAsLabel = useMemo(() => {
const email = user?.email ?? undefined;
const phone = user?.phone ?? undefined;
return email ?? phone;
}, [user?.email, user?.phone]);
const displayName =
personalAccountData?.name ?? account?.name ?? user?.email ?? '';
const isSuperAdmin = useMemo(() => {
return user?.app_metadata.role === 'super-admin';
}, [user]);
return (
<DropdownMenu>
<DropdownMenuTrigger
aria-label="Open your profile menu"
data-test={'account-dropdown-trigger'}
className={cn(
'animate-in fade-in group flex cursor-pointer items-center focus:outline-none',
className ?? '',
{
['active:bg-muted/50 items-center space-x-2.5 rounded-md' +
' hover:bg-muted p-2 transition-colors']: showProfileName,
},
)}
>
<ProfileAvatar
displayName={displayName ?? user?.email ?? ''}
pictureUrl={personalAccountData?.picture_url}
/>
<If condition={showProfileName}>
<div
className={
'fade-in animate-in flex w-full flex-col truncate text-left'
}
>
<span
data-test={'account-dropdown-display-name'}
className={'truncate text-sm'}
>
{displayName}
</span>
<span
data-test={'account-dropdown-email'}
className={'text-muted-foreground truncate text-xs'}
>
{signedInAsLabel}
</span>
</div>
<EllipsisVertical
className={'text-muted-foreground hidden h-8 group-hover:flex'}
/>
</If>
</DropdownMenuTrigger>
<DropdownMenuContent
className={'!min-w-[15rem]'}
collisionPadding={{ right: 20, left: 20 }}
sideOffset={20}
>
<DropdownMenuItem className={'!h-10 rounded-none'}>
<div
className={'flex flex-col justify-start truncate text-left text-xs'}
>
<div className={'text-muted-foreground'}>
<Trans i18nKey={'common:signedInAs'} />
</div>
<div>
<span className={'block truncate'}>{signedInAsLabel}</span>
</div>
</div>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
className={'s-full flex items-center space-x-2'}
href={paths.home}
>
<Home className={'h-5'} />
<span>
<Trans i18nKey={'common:homeTabLabel'} />
</span>
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link className={'s-full flex items-center space-x-2'} href={'/docs'}>
<MessageCircleQuestion className={'h-5'} />
<span>
<Trans i18nKey={'common:documentation'} />
</span>
</Link>
</DropdownMenuItem>
<If condition={isSuperAdmin}>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
className={'s-full flex items-center space-x-2'}
href={'/admin'}
>
<Shield className={'h-5'} />
<span>Admin</span>
</Link>
</DropdownMenuItem>
</If>
<DropdownMenuSeparator />
<If condition={features.enableThemeToggle}>
<SubMenuModeToggle />
</If>
<DropdownMenuSeparator />
<DropdownMenuItem
data-test={'account-dropdown-sign-out'}
role={'button'}
className={'cursor-pointer'}
onClick={signOutRequested}
>
<span className={'flex w-full items-center space-x-2'}>
<LogOut className={'h-5'} />
<span>
<Trans i18nKey={'auth:signOut'} />
</span>
</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}