(app-desk) add new member to team

We integrate the endpoint to add a new member
to the team with the multi select seach user.
- If it is a unknown email, it will send an invitation,
- If it is a known user, it will add it to the team.
This commit is contained in:
Anthony LC
2024-03-15 17:29:15 +01:00
parent dffbcd2099
commit 3a08c0595b
2 changed files with 61 additions and 24 deletions
@@ -14,11 +14,16 @@ import { APIError } from '@/api';
import { Box, StyledLink, Text } from '@/components';
import { Team } from '@/features/teams';
import { useCreateInvitation } from '../api';
import { Invitation, Role } from '../types';
import { useCreateInvitation, useCreateTeamAccess } from '../api';
import { Role } from '../types';
import { ChooseRole } from './ChooseRole';
import { OptionSelect, SearchMembers } from './SearchMembers';
import {
OptionInvitation,
OptionNewMember,
OptionSelect,
SearchMembers,
} from './SearchMembers';
const GlobalStyle = createGlobalStyle`
.c__modal {
@@ -41,20 +46,37 @@ export const ModalAddMembers = ({
const [selectedRole, setSelectedRole] = useState<Role>(Role.MEMBER);
const { toast } = useToastProvider();
const { mutateAsync: createInvitation } = useCreateInvitation();
const { mutateAsync: createTeamAccess } = useCreateTeamAccess();
const handleValidate = useCallback(
() =>
void Promise.allSettled<Invitation>(
void Promise.allSettled<OptionInvitation | OptionNewMember>(
selectedMembers.map((selectedMember) => {
return new Promise<Invitation>((resolve, reject) => {
createInvitation({
email: selectedMember.value.email,
if (selectedMember.type === 'invitation') {
return new Promise<OptionInvitation>((resolve, reject) => {
createInvitation({
email: selectedMember.value.email,
role: selectedRole,
teamId: team.id,
})
.then(() => {
resolve(selectedMember);
})
.catch((error) => {
reject(error);
});
});
}
return new Promise<OptionNewMember>((resolve, reject) => {
createTeamAccess({
name: selectedMember.value.name,
role: selectedRole,
teamId: team.id,
userId: selectedMember.value.id,
})
.then((data) => {
resolve(data);
.then(() => {
resolve(selectedMember);
})
.catch((error) => {
reject(error);
@@ -64,28 +86,32 @@ export const ModalAddMembers = ({
).then((results) => {
void router.push(`/teams/${team.id}/`);
results.forEach((result) => {
const toastOptions = {
duration: 4000,
};
if (result.status === 'rejected') {
const apiError = result.reason as APIError;
toast(apiError.message, VariantType.ERROR, {
duration: 4000,
});
toast(apiError.message, VariantType.ERROR, toastOptions);
}
if (result.status === 'fulfilled') {
toast(
t('Invitations sent to {{email}}', {
email: result.value.email,
}),
VariantType.SUCCESS,
{
duration: 4000,
},
);
const message =
result.value.type === 'invitation'
? t('Invitations sent to {{email}}', {
email: result.value.value.email,
})
: t('Member {{name}} added to the team', {
name: result.value.value.name,
});
toast(message, VariantType.SUCCESS, toastOptions);
}
});
}),
[
createInvitation,
createTeamAccess,
router,
selectedMembers,
selectedRole,
@@ -14,10 +14,19 @@ const isValidEmail = (email: string) => {
);
};
export type OptionSelect = Options<{
value: Partial<User> & { email: User['email'] };
export interface OptionInvitation {
value: { email: string };
label: string;
}>;
type: 'invitation';
}
export interface OptionNewMember {
value: User;
label: string;
type: 'new_member';
}
export type OptionSelect = Options<OptionNewMember | OptionInvitation>;
interface SearchMembersProps {
team: Team;
@@ -49,6 +58,7 @@ export const SearchMembers = ({
let users: OptionSelect = options.map((user) => ({
value: user,
label: user.name || '',
type: 'new_member',
}));
if (userQuery && isValidEmail(userQuery)) {
@@ -61,6 +71,7 @@ export const SearchMembers = ({
{
value: { email: userQuery },
label: userQuery,
type: 'invitation',
},
];
}