```
add Implement custom sign-out functionality with loading state and error handling ```
This commit is contained in:
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { Button } from '@mui/material';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
|
import { SignOut as SignOutIcon } from '@phosphor-icons/react/dist/ssr/SignOut';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { authClient } from '@/lib/auth/custom/client';
|
import { authClient } from '@/lib/auth/custom/client';
|
||||||
import { logger } from '@/lib/default-logger';
|
import { logger } from '@/lib/default-logger';
|
||||||
@@ -10,39 +14,44 @@ import { useUser } from '@/hooks/use-user';
|
|||||||
import { toast } from '@/components/core/toaster';
|
import { toast } from '@/components/core/toaster';
|
||||||
|
|
||||||
export function CustomSignOut(): React.JSX.Element {
|
export function CustomSignOut(): React.JSX.Element {
|
||||||
|
const { t } = useTranslation('sign_in');
|
||||||
|
|
||||||
const { checkSession } = useUser();
|
const { checkSession } = useUser();
|
||||||
|
const [buttonShowLoading, setButtonShowLoading] = React.useState<boolean>(false);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const handleSignOut = React.useCallback(async (): Promise<void> => {
|
const handleSignOut = React.useCallback(async (): Promise<void> => {
|
||||||
|
setButtonShowLoading(true);
|
||||||
try {
|
try {
|
||||||
const { error } = await authClient.signOut();
|
const { error } = await authClient.signOut();
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Sign out error', error);
|
logger.error('Sign out error', error);
|
||||||
toast.error('Something went wrong, unable to sign out');
|
toast.error(t('something-went-wrong-unable-to-sign-out'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh the auth state
|
// Refresh the auth state
|
||||||
await checkSession?.();
|
await checkSession?.();
|
||||||
|
|
||||||
// UserProvider, for this case, will not refresh the router and we need to do it manually
|
// UserProvider, for this case, will not refresh the router and we need to do it manually
|
||||||
router.refresh();
|
router.refresh();
|
||||||
// After refresh, AuthGuard will handle the redirect
|
// After refresh, AuthGuard will handle the redirect
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Sign out error', err);
|
logger.error('Sign out error', err);
|
||||||
toast.error('Something went wrong, unable to sign out');
|
toast.error(t('something-went-wrong-unable-to-sign-out'));
|
||||||
}
|
}
|
||||||
}, [checkSession, router]);
|
}, [checkSession, router, t]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<LoadingButton
|
||||||
component="div"
|
|
||||||
onClick={handleSignOut}
|
onClick={handleSignOut}
|
||||||
sx={{ justifyContent: 'center' }}
|
sx={{ width: '100%' }}
|
||||||
|
variant="text"
|
||||||
|
disabled={buttonShowLoading}
|
||||||
|
loading={buttonShowLoading}
|
||||||
|
startIcon={<SignOutIcon />}
|
||||||
|
color="secondary"
|
||||||
>
|
>
|
||||||
Sign out
|
{t('sign-out')}
|
||||||
</MenuItem>
|
</LoadingButton>
|
||||||
);
|
);
|
||||||
}
|
}
|
@@ -16,15 +16,15 @@ import { User as UserIcon } from '@phosphor-icons/react/dist/ssr/User';
|
|||||||
import type { User } from '@/types/user';
|
import type { User } from '@/types/user';
|
||||||
import { config } from '@/config';
|
import { config } from '@/config';
|
||||||
import { paths } from '@/paths';
|
import { paths } from '@/paths';
|
||||||
|
import { authClient } from '@/lib/auth/custom/client';
|
||||||
import { AuthStrategy } from '@/lib/auth/strategy';
|
import { AuthStrategy } from '@/lib/auth/strategy';
|
||||||
|
import { logger } from '@/lib/default-logger';
|
||||||
|
|
||||||
import { Auth0SignOut } from './auth0-sign-out';
|
import { Auth0SignOut } from './auth0-sign-out';
|
||||||
import { CognitoSignOut } from './cognito-sign-out';
|
import { CognitoSignOut } from './cognito-sign-out';
|
||||||
import { CustomSignOut } from './custom-sign-out';
|
import { CustomSignOut } from './custom-sign-out';
|
||||||
import { FirebaseSignOut } from './firebase-sign-out';
|
import { FirebaseSignOut } from './firebase-sign-out';
|
||||||
import { SupabaseSignOut } from './supabase-sign-out';
|
import { SupabaseSignOut } from './supabase-sign-out';
|
||||||
import { authClient } from '@/lib/auth/custom/client';
|
|
||||||
import { logger } from '@/lib/default-logger';
|
|
||||||
|
|
||||||
const defaultUser = {
|
const defaultUser = {
|
||||||
id: 'USR-000',
|
id: 'USR-000',
|
||||||
@@ -55,7 +55,8 @@ export function UserPopover({ anchorEl, onClose, open }: UserPopoverProps): Reac
|
|||||||
void loadUserMeta();
|
void loadUserMeta();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!userMeta) return <>loading</>;
|
// NOTE: delay when userMeta is null, used for sign-out
|
||||||
|
if (!userMeta) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
|
@@ -66,6 +66,7 @@ export function SideNav({ color = 'evident', items = [] }: SideNavProps): React.
|
|||||||
spacing={2}
|
spacing={2}
|
||||||
sx={{ p: 2 }}
|
sx={{ p: 2 }}
|
||||||
>
|
>
|
||||||
|
{/* NOTE: hide logo
|
||||||
<div>
|
<div>
|
||||||
<Box
|
<Box
|
||||||
component={RouterLink}
|
component={RouterLink}
|
||||||
@@ -79,6 +80,7 @@ export function SideNav({ color = 'evident', items = [] }: SideNavProps): React.
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
|
*/}
|
||||||
<WorkspacesSwitch />
|
<WorkspacesSwitch />
|
||||||
</Stack>
|
</Stack>
|
||||||
<Box
|
<Box
|
||||||
|
Reference in New Issue
Block a user