diff --git a/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx b/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx index eaabb15..c87378e 100644 --- a/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx +++ b/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx @@ -1,9 +1,9 @@ -import React, { useState, useCallback } from 'react'; -import { FiUsers, FiXSquare } from 'react-icons/fi'; +import React, { useState, useCallback, useRef, useEffect } from 'react'; +import { FiPlusSquare, FiUsers, FiXSquare } from 'react-icons/fi'; import { useAsyncFn, useDebounce } from 'react-use'; import { userSearch } from '../../../../api/NirvanaApi'; import toast from 'react-hot-toast'; -import { Avatar, Skeleton } from 'antd'; +import { Avatar, Skeleton, Spin } from 'antd'; import { User } from '@nirvana/core/models/user.model'; export default function NewChannelForm() { @@ -11,52 +11,74 @@ export default function NewChannelForm() { const [userSearchRes, fetchUsers] = useAsyncFn(userSearch); - const [isReady, cancel] = useDebounce( + const [isSearchingUsers, setSearchingUsers] = useState(false); + + const searchInputRef = useRef(null); + + useEffect(() => { + if (searchInputRef) searchInputRef.current.focus(); + }, [searchInputRef]); + + const [_, cancel] = useDebounce( async () => { try { await fetchUsers(peopleSearchQuery); + + setSearchingUsers(false); } catch (error) { toast.error('Problem in searching users!'); console.error(error); } }, - 2000, - [peopleSearchQuery], + 1000, + [peopleSearchQuery, setSearchingUsers, fetchUsers], + ); + + const handleSearchChange = useCallback( + async (e) => { + setSearchingUsers(true); + setPeopleSearchQuery(e.target.value); + }, + [setPeopleSearchQuery, setSearchingUsers], ); const [selectedUsers, setSelectedUsers] = useState([]); + // ensuring that we haven't already selected this user + // changing search results so that we don't see the selected user in the search results anymore const addUser = useCallback( (newUser: User) => { - setSelectedUsers((prevUsers) => [...prevUsers, newUser]); + setSelectedUsers((prevUsers) => { + if (prevUsers.find((currUser) => currUser.email === newUser.email)) { + return [...prevUsers, newUser]; + } + return prevUsers; + }); + + if (userSearchRes.value?.users) { + userSearchRes.value.users = userSearchRes.value.users.filter( + (currUser) => currUser._id !== newUser._id, + ); + } }, - [setSelectedUsers], + [setSelectedUsers, userSearchRes.value], ); const removeUser = useCallback((userIdToRemove: string) => { setSelectedUsers((prevUsers) => - prevUsers.filter((currentUser) => !currentUser._id.equals(userIdToRemove)), + prevUsers.filter((currentUser) => currentUser._id.toString() !== userIdToRemove), ); }, []); - const handleSearchChange = useCallback( - async (e) => { - setPeopleSearchQuery(e.target.value); - }, - [setPeopleSearchQuery], - ); - return (
{/* people search */} People -
+
- {(userSearchRes.loading || !isReady) && } - + {(userSearchRes.loading || isSearchingUsers) && } + {(!userSearchRes.value || userSearchRes.value?.users.length === 0) && ( + {`Can't find someone? Invite them and tell them the secret passcode!`} + )} {userSearchRes.value?.users.map((searchedUser) => { return (
{searchedUser.name} {searchedUser.email} + +
); })} @@ -101,7 +127,7 @@ bg-gray-200 p-3 rounded" role={'presentation'} key={selectedUser.email} className="flex flex-row gap-2 items-center p-2 border border-gray-200 - hover:bg-gray-200 cursor-pointer group" + hover:bg-gray-100 cursor-pointer group" > @@ -109,7 +135,7 @@ bg-gray-200 p-3 rounded" {selectedUser.email} - +
); })}