mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-26 16:30:57 +01:00
feat: add login and logout (#436)
This commit is contained in:
@@ -1,16 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import Link from "next/link";
|
||||
import { Menu, useMantineColorScheme } from "@mantine/core";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
Center,
|
||||
Menu,
|
||||
Stack,
|
||||
Text,
|
||||
useMantineColorScheme,
|
||||
} from "@mantine/core";
|
||||
import { useTimeout } from "@mantine/hooks";
|
||||
import {
|
||||
IconCheck,
|
||||
IconDashboard,
|
||||
IconLogin,
|
||||
IconLogout,
|
||||
IconMoon,
|
||||
IconSun,
|
||||
IconTool,
|
||||
} from "@tabler/icons-react";
|
||||
|
||||
import { signOut, useSession } from "@homarr/auth/client";
|
||||
import { createModal, useModalAction } from "@homarr/modals";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
|
||||
interface UserAvatarMenuProps {
|
||||
@@ -26,6 +39,22 @@ export const UserAvatarMenu = ({ children }: UserAvatarMenuProps) => {
|
||||
const colorSchemeText =
|
||||
colorScheme === "dark" ? t("switchToLightMode") : t("switchToDarkMode");
|
||||
|
||||
const session = useSession();
|
||||
const router = useRouter();
|
||||
|
||||
const { openModal } = useModalAction(LogoutModal);
|
||||
|
||||
const handleSignout = useCallback(async () => {
|
||||
await signOut({
|
||||
redirect: false,
|
||||
});
|
||||
openModal({
|
||||
onTimeout: () => {
|
||||
router.refresh();
|
||||
},
|
||||
});
|
||||
}, [openModal, router]);
|
||||
|
||||
return (
|
||||
<Menu width={200} withArrow withinPortal>
|
||||
<Menu.Dropdown>
|
||||
@@ -50,11 +79,58 @@ export const UserAvatarMenu = ({ children }: UserAvatarMenuProps) => {
|
||||
{t("management")}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item leftSection={<IconLogout size="1rem" />} color="red">
|
||||
{t("logout")}
|
||||
</Menu.Item>
|
||||
{session.status === "authenticated" ? (
|
||||
<Menu.Item
|
||||
onClick={handleSignout}
|
||||
leftSection={<IconLogout size="1rem" />}
|
||||
color="red"
|
||||
>
|
||||
{t("logout")}
|
||||
</Menu.Item>
|
||||
) : (
|
||||
<Menu.Item
|
||||
onClick={() => router.push("/auth/login")}
|
||||
leftSection={<IconLogin size="1rem" />}
|
||||
>
|
||||
{t("login")}
|
||||
</Menu.Item>
|
||||
)}
|
||||
</Menu.Dropdown>
|
||||
<Menu.Target>{children}</Menu.Target>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
const LogoutModal = createModal<{ onTimeout: () => void }>(
|
||||
({ actions, innerProps }) => {
|
||||
const t = useScopedI18n("common.userAvatar.menu");
|
||||
const { start } = useTimeout(() => {
|
||||
actions.closeModal();
|
||||
innerProps.onTimeout();
|
||||
}, 1500);
|
||||
|
||||
useEffect(() => {
|
||||
start();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Center h={200 - 2 * 16}>
|
||||
<Stack align="center" c="green">
|
||||
<IconCheck size={50} />
|
||||
<Text ta="center" fw="bold">
|
||||
{t("loggedOut")}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Center>
|
||||
);
|
||||
},
|
||||
).withOptions({
|
||||
centered: true,
|
||||
withCloseButton: false,
|
||||
transitionProps: {
|
||||
transition: "pop",
|
||||
},
|
||||
size: 200,
|
||||
closeOnClickOutside: false,
|
||||
closeOnEscape: false,
|
||||
});
|
||||
|
||||
@@ -18,6 +18,9 @@ export type CreateModalOptions = Pick<
|
||||
| "zIndex"
|
||||
| "scrollAreaComponent"
|
||||
| "yOffset"
|
||||
| "transitionProps"
|
||||
| "closeOnClickOutside"
|
||||
| "closeOnEscape"
|
||||
> & {
|
||||
defaultTitle: stringOrTranslation;
|
||||
};
|
||||
|
||||
@@ -403,7 +403,9 @@ export default {
|
||||
switchToLightMode: "Switch to light mode",
|
||||
management: "Management",
|
||||
logout: "Logout",
|
||||
login: "Login",
|
||||
navigateDefaultBoard: "Navigate to default board",
|
||||
loggedOut: "Logged out",
|
||||
},
|
||||
},
|
||||
menu: {
|
||||
|
||||
Reference in New Issue
Block a user