2023-07-29 21:15:55 +02:00
|
|
|
import { Avatar, Badge, Menu, UnstyledButton, useMantineTheme } from '@mantine/core';
|
|
|
|
|
import { useDisclosure } from '@mantine/hooks';
|
|
|
|
|
import {
|
|
|
|
|
IconDashboard,
|
|
|
|
|
IconInfoCircle,
|
|
|
|
|
IconLogin,
|
|
|
|
|
IconLogout,
|
2023-07-29 22:06:21 +02:00
|
|
|
IconMoonStars,
|
2023-07-29 21:15:55 +02:00
|
|
|
IconSun,
|
2023-07-29 23:03:40 +02:00
|
|
|
IconUserCog,
|
2023-07-29 21:15:55 +02:00
|
|
|
} from '@tabler/icons-react';
|
2023-07-30 01:09:10 +02:00
|
|
|
import { useQuery } from '@tanstack/react-query';
|
2023-07-29 21:15:55 +02:00
|
|
|
import { User } from 'next-auth';
|
|
|
|
|
import { signOut, useSession } from 'next-auth/react';
|
|
|
|
|
import Link from 'next/link';
|
|
|
|
|
import { forwardRef } from 'react';
|
2023-08-01 15:23:31 +02:00
|
|
|
import { AboutModal } from '~/components/layout/Header/About/AboutModal';
|
2023-07-29 22:06:21 +02:00
|
|
|
import { useColorScheme } from '~/hooks/use-colorscheme';
|
2023-07-30 01:09:10 +02:00
|
|
|
import { usePackageAttributesStore } from '~/tools/client/zustands/usePackageAttributesStore';
|
|
|
|
|
|
|
|
|
|
import { REPO_URL } from '../../../../data/constants';
|
2023-07-29 21:15:55 +02:00
|
|
|
|
|
|
|
|
export const AvatarMenu = () => {
|
|
|
|
|
const [aboutModalOpened, aboutModal] = useDisclosure(false);
|
|
|
|
|
const { data: sessionData } = useSession();
|
2023-07-29 22:06:21 +02:00
|
|
|
const { colorScheme, toggleColorScheme } = useColorScheme();
|
2023-07-30 01:09:10 +02:00
|
|
|
const newVersionAvailable = useNewVersionAvailable();
|
2023-07-29 22:06:21 +02:00
|
|
|
|
|
|
|
|
const Icon = colorScheme === 'dark' ? IconSun : IconMoonStars;
|
2023-07-29 21:15:55 +02:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<UnstyledButton>
|
2023-08-01 12:06:39 +02:00
|
|
|
<Menu width={256}>
|
2023-07-29 21:15:55 +02:00
|
|
|
<Menu.Target>
|
|
|
|
|
<CurrentUserAvatar user={sessionData?.user ?? null} />
|
|
|
|
|
</Menu.Target>
|
|
|
|
|
<Menu.Dropdown>
|
2023-07-29 22:06:21 +02:00
|
|
|
<Menu.Item icon={<Icon size="1rem" />} onClick={toggleColorScheme}>
|
|
|
|
|
Switch theme
|
|
|
|
|
</Menu.Item>
|
2023-07-29 21:18:41 +02:00
|
|
|
{sessionData?.user && (
|
|
|
|
|
<>
|
2023-07-29 23:03:40 +02:00
|
|
|
<Menu.Item
|
|
|
|
|
component={Link}
|
2023-07-30 22:57:14 +02:00
|
|
|
href="/user/preferences"
|
2023-07-29 23:03:40 +02:00
|
|
|
icon={<IconUserCog size="1rem" />}
|
|
|
|
|
>
|
2023-07-30 22:57:14 +02:00
|
|
|
User preferences
|
2023-07-29 23:03:40 +02:00
|
|
|
</Menu.Item>
|
|
|
|
|
<Menu.Item component={Link} href="/board" icon={<IconDashboard size="1rem" />}>
|
|
|
|
|
Default Dashboard
|
|
|
|
|
</Menu.Item>
|
2023-07-29 21:18:41 +02:00
|
|
|
<Menu.Divider />
|
|
|
|
|
</>
|
|
|
|
|
)}
|
2023-07-29 21:15:55 +02:00
|
|
|
<Menu.Item
|
|
|
|
|
icon={<IconInfoCircle size="1rem" />}
|
|
|
|
|
rightSection={
|
|
|
|
|
newVersionAvailable && (
|
|
|
|
|
<Badge variant="light" color="blue">
|
|
|
|
|
New
|
|
|
|
|
</Badge>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
onClick={() => aboutModal.open()}
|
|
|
|
|
>
|
|
|
|
|
About
|
|
|
|
|
</Menu.Item>
|
|
|
|
|
{sessionData?.user ? (
|
2023-08-05 11:42:49 +02:00
|
|
|
<Menu.Item
|
|
|
|
|
icon={<IconLogout size="1rem" />}
|
|
|
|
|
color="red"
|
|
|
|
|
onClick={() =>
|
|
|
|
|
signOut({
|
2023-08-05 11:49:37 +02:00
|
|
|
redirect: false,
|
|
|
|
|
}).then(() => window.location.reload())
|
2023-08-05 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
>
|
2023-08-01 12:06:39 +02:00
|
|
|
Logout from {sessionData.user.name}
|
2023-07-29 21:15:55 +02:00
|
|
|
</Menu.Item>
|
|
|
|
|
) : (
|
|
|
|
|
<Menu.Item icon={<IconLogin size="1rem" />} component={Link} href="/auth/login">
|
|
|
|
|
Login
|
|
|
|
|
</Menu.Item>
|
|
|
|
|
)}
|
|
|
|
|
</Menu.Dropdown>
|
|
|
|
|
</Menu>
|
|
|
|
|
</UnstyledButton>
|
|
|
|
|
|
|
|
|
|
<AboutModal
|
|
|
|
|
opened={aboutModalOpened}
|
|
|
|
|
closeModal={aboutModal.close}
|
|
|
|
|
newVersionAvailable={newVersionAvailable}
|
|
|
|
|
/>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type CurrentUserAvatarProps = {
|
|
|
|
|
user: User | null;
|
|
|
|
|
};
|
2023-07-30 01:09:10 +02:00
|
|
|
|
2023-07-29 21:15:55 +02:00
|
|
|
const CurrentUserAvatar = forwardRef<HTMLDivElement, CurrentUserAvatarProps>(
|
|
|
|
|
({ user, ...others }, ref) => {
|
|
|
|
|
const { primaryColor } = useMantineTheme();
|
|
|
|
|
if (!user) return <Avatar ref={ref} {...others} />;
|
|
|
|
|
return (
|
|
|
|
|
<Avatar ref={ref} color={primaryColor} {...others}>
|
|
|
|
|
{user.name?.slice(0, 2).toUpperCase()}
|
|
|
|
|
</Avatar>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-07-30 01:09:10 +02:00
|
|
|
|
|
|
|
|
const useNewVersionAvailable = () => {
|
|
|
|
|
const { attributes } = usePackageAttributesStore();
|
|
|
|
|
const { data } = useQuery({
|
|
|
|
|
queryKey: ['github/latest'],
|
|
|
|
|
cacheTime: 1000 * 60 * 60 * 24,
|
|
|
|
|
staleTime: 1000 * 60 * 60 * 5,
|
|
|
|
|
queryFn: () =>
|
|
|
|
|
fetch(`https://api.github.com/repos/${REPO_URL}/releases/latest`).then((res) => res.json()),
|
|
|
|
|
});
|
|
|
|
|
return data?.tag_name > `v${attributes.packageVersion}` ? data?.tag_name : undefined;
|
|
|
|
|
};
|