You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
overseerr/src/components/Layout/UserDropdown/index.tsx

164 lines
6.0 KiB

import MiniQuotaDisplay from '@app/components/Layout/UserDropdown/MiniQuotaDisplay';
import { useUser } from '@app/hooks/useUser';
import { Menu, Transition } from '@headlessui/react';
import { ClockIcon, LogoutIcon } from '@heroicons/react/outline';
import { CogIcon, UserIcon } from '@heroicons/react/solid';
import axios from 'axios';
import type { LinkProps } from 'next/link';
import Link from 'next/link';
import { forwardRef, Fragment } from 'react';
import { defineMessages, useIntl } from 'react-intl';
const messages = defineMessages({
myprofile: 'Profile',
settings: 'Settings',
requests: 'Requests',
signout: 'Sign Out',
});
const ForwardedLink = forwardRef<
HTMLAnchorElement,
LinkProps & React.ComponentPropsWithoutRef<'a'>
>(({ href, children, ...rest }, ref) => {
return (
<Link href={href}>
<a ref={ref} {...rest}>
{children}
</a>
</Link>
);
});
ForwardedLink.displayName = 'ForwardedLink';
const UserDropdown = () => {
const intl = useIntl();
const { user, revalidate } = useUser();
const logout = async () => {
const response = await axios.post('/api/v1/auth/logout');
if (response.data?.status === 'ok') {
revalidate();
}
};
return (
<Menu as="div" className="relative ml-3">
<div>
<Menu.Button
className="flex max-w-xs items-center rounded-full text-sm ring-1 ring-gray-700 hover:ring-gray-500 focus:outline-none focus:ring-gray-500"
data-testid="user-menu"
>
<img
className="h-8 w-8 rounded-full object-cover sm:h-10 sm:w-10"
src={user?.avatar}
alt=""
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
appear
>
<Menu.Items className="absolute right-0 mt-2 w-72 origin-top-right rounded-md shadow-lg">
<div className="divide-y divide-gray-700 rounded-md bg-gray-800 bg-opacity-80 ring-1 ring-gray-700 backdrop-blur">
<div className="flex flex-col space-y-4 px-4 py-4">
<div className="flex items-center space-x-2">
<img
className="h-8 w-8 rounded-full object-cover sm:h-10 sm:w-10"
src={user?.avatar}
alt=""
/>
<div className="flex min-w-0 flex-col">
<span className="truncate text-xl font-semibold text-gray-200">
{user?.displayName}
</span>
<span className="truncate text-sm text-gray-400">
{user?.email}
</span>
</div>
</div>
{user && <MiniQuotaDisplay userId={user?.id} />}
</div>
<div className="p-1">
<Menu.Item>
{({ active }) => (
<ForwardedLink
href={`/profile`}
className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
active
? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
: ''
}`}
data-testid="user-menu-profile"
>
<UserIcon className="mr-2 inline h-5 w-5" />
<span>{intl.formatMessage(messages.myprofile)}</span>
</ForwardedLink>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<ForwardedLink
href={`/users/${user?.id}/requests?filter=all`}
className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
active
? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
: ''
}`}
data-testid="user-menu-settings"
>
<ClockIcon className="mr-2 inline h-5 w-5" />
<span>{intl.formatMessage(messages.requests)}</span>
</ForwardedLink>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<ForwardedLink
href={`/profile/settings`}
className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
active
? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
: ''
}`}
data-testid="user-menu-settings"
>
<CogIcon className="mr-2 inline h-5 w-5" />
<span>{intl.formatMessage(messages.settings)}</span>
</ForwardedLink>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<a
href="#"
className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
active
? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
: ''
}`}
onClick={() => logout()}
>
<LogoutIcon className="mr-2 inline h-5 w-5" />
<span>{intl.formatMessage(messages.signout)}</span>
</a>
)}
</Menu.Item>
</div>
</div>
</Menu.Items>
</Transition>
</Menu>
);
};
export default UserDropdown;