all search stuff working just need to have the create work
This commit is contained in:
@@ -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<boolean>(false);
|
||||
|
||||
const searchInputRef = useRef<HTMLInputElement>(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<User[]>([]);
|
||||
|
||||
// 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 (
|
||||
<div className="flex flex-col flex-1 items-center pt-10 bg-white">
|
||||
<div className="flex flex-col gap-2 max-w-lg w-full">
|
||||
{/* people search */}
|
||||
<span className="text-gray-500">People</span>
|
||||
<div
|
||||
className="flex flex-row items-center space-x-2 bg-transparent
|
||||
bg-gray-200 p-3 rounded"
|
||||
>
|
||||
<div className="flex flex-row items-center space-x-2 bg-gray-100 p-3 rounded">
|
||||
<FiUsers className="text-lg text-gray-400" />
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
placeholder="Search by name or email"
|
||||
className="flex-1 text-lg bg-transparent placeholder-gray-300 focus:outline-none"
|
||||
onChange={handleSearchChange}
|
||||
@@ -66,8 +88,10 @@ bg-gray-200 p-3 rounded"
|
||||
|
||||
{/* dropdown search results */}
|
||||
<div className="flex flex-col shadow-lg max-h-[500px] overflow-auto">
|
||||
{(userSearchRes.loading || !isReady) && <Skeleton />}
|
||||
|
||||
{(userSearchRes.loading || isSearchingUsers) && <Spin />}
|
||||
{(!userSearchRes.value || userSearchRes.value?.users.length === 0) && (
|
||||
<span className="p-10 text-gray-300">{`Can't find someone? Invite them and tell them the secret passcode!`}</span>
|
||||
)}
|
||||
{userSearchRes.value?.users.map((searchedUser) => {
|
||||
return (
|
||||
<div
|
||||
@@ -75,13 +99,15 @@ bg-gray-200 p-3 rounded"
|
||||
role={'presentation'}
|
||||
key={searchedUser.email}
|
||||
className="flex flex-row gap-2 items-center p-2 border border-gray-200
|
||||
hover:bg-gray-200 cursor-pointer"
|
||||
hover:bg-gray-100 cursor-pointer"
|
||||
>
|
||||
<Avatar src={searchedUser.picture} size={'large'} shape={'square'} />
|
||||
<span className="flex flex-col gap-1">
|
||||
<span className="text-md font-semibold text-gray-600">{searchedUser.name}</span>
|
||||
<span className="text-sm text-gray-400">{searchedUser.email}</span>
|
||||
</span>
|
||||
|
||||
<FiPlusSquare className="ml-auto text-lg text-teal-500 cursor-pointer group-hover:scale-105" />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -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"
|
||||
>
|
||||
<Avatar src={selectedUser.picture} size={'large'} shape={'square'} />
|
||||
<span className="flex flex-col gap-1">
|
||||
@@ -109,7 +135,7 @@ bg-gray-200 p-3 rounded"
|
||||
<span className="text-sm text-gray-400">{selectedUser.email}</span>
|
||||
</span>
|
||||
|
||||
<FiXSquare className="ml-auto text-gray-400 cursor-pointer group-hover:scale-105" />
|
||||
<FiXSquare className="ml-auto text-lg text-pink-500 cursor-pointer group-hover:scale-105" />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user