🚸(app-desk) cannot select user or email already selected
- Add the teamid to the useUsers query, to not get the users that are already in the team - Add a check to not select a user or email that is already selected
This commit is contained in:
@@ -2,18 +2,25 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query';
|
|||||||
|
|
||||||
import { APIError, APIList, errorCauses, fetchAPI } from '@/api';
|
import { APIError, APIList, errorCauses, fetchAPI } from '@/api';
|
||||||
import { User } from '@/core/auth';
|
import { User } from '@/core/auth';
|
||||||
|
import { Team } from '@/features/teams';
|
||||||
|
|
||||||
export type UsersParams = {
|
export type UsersParams = {
|
||||||
query: string;
|
query: string;
|
||||||
|
teamId: Team['id'];
|
||||||
};
|
};
|
||||||
|
|
||||||
type UsersResponse = APIList<User>;
|
type UsersResponse = APIList<User>;
|
||||||
|
|
||||||
export const getUsers = async ({
|
export const getUsers = async ({
|
||||||
query,
|
query,
|
||||||
|
teamId,
|
||||||
}: UsersParams): Promise<UsersResponse> => {
|
}: UsersParams): Promise<UsersResponse> => {
|
||||||
const queryParam = query ? `q=${query}` : '';
|
const queriesParams = [];
|
||||||
const response = await fetchAPI(`users/?${queryParam}`);
|
queriesParams.push(query ? `q=${query}` : '');
|
||||||
|
queriesParams.push(teamId ? `team_id=${teamId}` : '');
|
||||||
|
const queryParams = queriesParams.filter(Boolean).join('&');
|
||||||
|
|
||||||
|
const response = await fetchAPI(`users/?${queryParams}`);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new APIError('Failed to get the users', await errorCauses(response));
|
throw new APIError('Failed to get the users', await errorCauses(response));
|
||||||
|
|||||||
@@ -162,7 +162,11 @@ export const ModalAddMembers = ({
|
|||||||
>
|
>
|
||||||
<GlobalStyle />
|
<GlobalStyle />
|
||||||
<Box className="mb-xl mt-l">
|
<Box className="mb-xl mt-l">
|
||||||
<SearchMembers team={team} setSelectedMembers={setSelectedMembers} />
|
<SearchMembers
|
||||||
|
team={team}
|
||||||
|
setSelectedMembers={setSelectedMembers}
|
||||||
|
selectedMembers={selectedMembers}
|
||||||
|
/>
|
||||||
{selectedMembers.length > 0 && (
|
{selectedMembers.length > 0 && (
|
||||||
<Box className="mt-s">
|
<Box className="mt-s">
|
||||||
<Text as="h4" $textAlign="left" className="mb-t">
|
<Text as="h4" $textAlign="left" className="mb-t">
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ export type OptionsSelect = Options<OptionSelect>;
|
|||||||
|
|
||||||
interface SearchMembersProps {
|
interface SearchMembersProps {
|
||||||
team: Team;
|
team: Team;
|
||||||
|
selectedMembers: OptionsSelect;
|
||||||
setSelectedMembers: (value: OptionsSelect) => void;
|
setSelectedMembers: (value: OptionsSelect) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SearchMembers = ({
|
export const SearchMembers = ({
|
||||||
team,
|
team,
|
||||||
|
selectedMembers,
|
||||||
setSelectedMembers,
|
setSelectedMembers,
|
||||||
}: SearchMembersProps) => {
|
}: SearchMembersProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -27,7 +29,7 @@ export const SearchMembers = ({
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
const { data } = useUsers(
|
const { data } = useUsers(
|
||||||
{ query: userQuery },
|
{ query: userQuery, teamId: team.id },
|
||||||
{
|
{
|
||||||
enabled: !!userQuery,
|
enabled: !!userQuery,
|
||||||
queryKey: [KEY_LIST_USER, { query: userQuery }],
|
queryKey: [KEY_LIST_USER, { query: userQuery }],
|
||||||
@@ -41,16 +43,28 @@ export const SearchMembers = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let users: OptionsSelect = options.map((user) => ({
|
const optionsFiltered = options.filter(
|
||||||
|
(user) =>
|
||||||
|
!selectedMembers?.find(
|
||||||
|
(selectedUser) => selectedUser.value.email === user.email,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
let users: OptionsSelect = optionsFiltered.map((user) => ({
|
||||||
value: user,
|
value: user,
|
||||||
label: user.name || user.email,
|
label: user.name || user.email,
|
||||||
type: OptionType.NEW_MEMBER,
|
type: OptionType.NEW_MEMBER,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (userQuery && isValidEmail(userQuery)) {
|
if (userQuery && isValidEmail(userQuery)) {
|
||||||
const isFound = !!options.find((user) => user.email === userQuery);
|
const isFoundUser = !!optionsFiltered.find(
|
||||||
|
(user) => user.email === userQuery,
|
||||||
|
);
|
||||||
|
const isFoundEmail = !!selectedMembers.find(
|
||||||
|
(selectedMember) => selectedMember.value.email === userQuery,
|
||||||
|
);
|
||||||
|
|
||||||
if (!isFound) {
|
if (!isFoundUser && !isFoundEmail) {
|
||||||
users = [
|
users = [
|
||||||
{
|
{
|
||||||
value: { email: userQuery },
|
value: { email: userQuery },
|
||||||
@@ -64,7 +78,7 @@ export const SearchMembers = ({
|
|||||||
resolveOptionsRef.current(users);
|
resolveOptionsRef.current(users);
|
||||||
resolveOptionsRef.current = null;
|
resolveOptionsRef.current = null;
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [options]);
|
}, [options, selectedMembers]);
|
||||||
|
|
||||||
const loadOptions = (): Promise<OptionsSelect> => {
|
const loadOptions = (): Promise<OptionsSelect> => {
|
||||||
return new Promise<OptionsSelect>((resolve) => {
|
return new Promise<OptionsSelect>((resolve) => {
|
||||||
|
|||||||
@@ -176,14 +176,9 @@ test.describe('Members Create', () => {
|
|||||||
await page.getByLabel('Add members to the team').click();
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
await inputSearch.fill('test');
|
await inputSearch.fill('test');
|
||||||
await page.getByRole('option', { name: users[0].name }).click();
|
|
||||||
await page.getByRole('radio', { name: 'Owner' }).click();
|
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Validate' }).click();
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText(`Failed to add ${users[0].name} in the team`),
|
page.getByRole('option', { name: users[0].name }),
|
||||||
).toBeVisible();
|
).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it try to add twice the same invitation', async ({
|
test('it try to add twice the same invitation', async ({
|
||||||
@@ -218,12 +213,6 @@ test.describe('Members Create', () => {
|
|||||||
await page.getByLabel('Add members to the team').click();
|
await page.getByLabel('Add members to the team').click();
|
||||||
|
|
||||||
await inputSearch.fill(email);
|
await inputSearch.fill(email);
|
||||||
await page.getByRole('option', { name: email }).click();
|
await expect(page.getByRole('option', { name: email })).toBeHidden();
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Validate' }).click();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByText(`Failed to create the invitation for ${email}`),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user