4689 multi workspace i should be able to accept an invite if im already logged in (#5454)

- split signInUp to separate Invitation from signInUp
- update redirection logic
- add a resolver for userWorkspace
- add a mutation to add a user to a workspace
- authorize /invite/hash while loggedIn
- add a button to join a workspace

### Base functionnality

https://github.com/twentyhq/twenty/assets/29927851/a1075a4e-a2af-4184-aa3e-e163711277a1

### Error handling

https://github.com/twentyhq/twenty/assets/29927851/1bdd78ce-933a-4860-a87a-3f1f7bda389e
This commit is contained in:
martmull
2024-05-20 12:11:38 +02:00
committed by GitHub
parent 1ceeb68da8
commit 88f5eb669e
17 changed files with 340 additions and 101 deletions

View File

@ -0,0 +1,122 @@
import { useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { Logo } from '@/auth/components/Logo';
import { Title } from '@/auth/components/Title';
import { FooterNote } from '@/auth/sign-in-up/components/FooterNote';
import { SignInUpForm } from '@/auth/sign-in-up/components/SignInUpForm';
import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm';
import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { AppPath } from '@/types/AppPath';
import { Loader } from '@/ui/feedback/loader/components/Loader';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { MainButton } from '@/ui/input/button/components/MainButton';
import { useWorkspaceSwitching } from '@/ui/navigation/navigation-drawer/hooks/useWorkspaceSwitching';
import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn';
import { useAddUserToWorkspaceMutation } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
const StyledContentContainer = styled.div`
margin-bottom: ${({ theme }) => theme.spacing(8)};
margin-top: ${({ theme }) => theme.spacing(4)};
`;
export const Invite = () => {
const { enqueueSnackBar } = useSnackBar();
const navigate = useNavigate();
const {
workspace: workspaceFromInviteHash,
loading: workspaceFromInviteHashLoading,
workspaceInviteHash,
} = useWorkspaceFromInviteHash();
const { form } = useSignInUpForm();
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const [addUserToWorkspace] = useAddUserToWorkspaceMutation();
const { switchWorkspace } = useWorkspaceSwitching();
const title = useMemo(() => {
return `Join ${workspaceFromInviteHash?.displayName ?? ''} team`;
}, [workspaceFromInviteHash?.displayName]);
const handleUserJoinWorkspace = async () => {
if (
!(isDefined(workspaceInviteHash) && isDefined(workspaceFromInviteHash))
) {
return;
}
await addUserToWorkspace({
variables: {
inviteHash: workspaceInviteHash,
},
});
await switchWorkspace(workspaceFromInviteHash.id);
};
useEffect(() => {
if (
!isDefined(workspaceFromInviteHash) &&
!workspaceFromInviteHashLoading
) {
enqueueSnackBar('workspace does not exist', {
variant: 'error',
});
if (isDefined(currentWorkspace)) {
navigate(AppPath.Index);
} else {
navigate(AppPath.SignInUp);
}
}
if (
isDefined(currentWorkspace) &&
currentWorkspace.id === workspaceFromInviteHash?.id
) {
enqueueSnackBar(
`You already belong to ${workspaceFromInviteHash?.displayName} workspace`,
{
variant: 'info',
},
);
navigate(AppPath.Index);
}
}, [
navigate,
enqueueSnackBar,
currentWorkspace,
workspaceFromInviteHash,
workspaceFromInviteHashLoading,
]);
return (
!workspaceFromInviteHashLoading && (
<>
<AnimatedEaseIn>
<Logo workspaceLogo={workspaceFromInviteHash?.logo} />
</AnimatedEaseIn>
<Title animate>{title}</Title>
{isDefined(currentWorkspace) && workspaceFromInviteHash ? (
<>
<StyledContentContainer>
<MainButton
variant="secondary"
title="Continue"
type="submit"
onClick={handleUserJoinWorkspace}
Icon={() => form.formState.isSubmitting && <Loader />}
fullWidth
/>
</StyledContentContainer>
<FooterNote>
By using Twenty, you agree to the Terms of Service and Privacy
Policy.
</FooterNote>
</>
) : (
<SignInUpForm />
)}
</>
)
);
};