diff --git a/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx b/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx index c87378e..e66b128 100644 --- a/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx +++ b/packages/desktop/src/tree/protected/terminal/compose/NewChannelForm.tsx @@ -1,26 +1,34 @@ 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 { FiPlusSquare, FiUsers, FiX, FiXSquare } from 'react-icons/fi'; +import { useAsyncFn, useDebounce, useKeyPressEvent } from 'react-use'; +import { createLine, userSearch } from '../../../../api/NirvanaApi'; import toast from 'react-hot-toast'; -import { Avatar, Skeleton, Spin } from 'antd'; +import { Avatar, Divider, Skeleton, Spin } from 'antd'; import { User } from '@nirvana/core/models/user.model'; +import CreateLineRequest from '@nirvana/core/requests/createLine.request'; -export default function NewChannelForm() { +export default function NewChannelForm({ handleClose }: { handleClose: () => void }) { const [peopleSearchQuery, setPeopleSearchQuery] = useState(''); const [userSearchRes, fetchUsers] = useAsyncFn(userSearch); + const [selectedUsers, setSelectedUsers] = useState([]); const [isSearchingUsers, setSearchingUsers] = useState(false); const searchInputRef = useRef(null); + const [createChannelRes, triggerCreateChannel] = useAsyncFn(createLine); + useEffect(() => { if (searchInputRef) searchInputRef.current.focus(); }, [searchInputRef]); const [_, cancel] = useDebounce( async () => { + if (!peopleSearchQuery) { + return; + } + try { await fetchUsers(peopleSearchQuery); @@ -42,17 +50,15 @@ export default function NewChannelForm() { [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) => { if (prevUsers.find((currUser) => currUser.email === newUser.email)) { - return [...prevUsers, newUser]; + return prevUsers; } - return prevUsers; + return [...prevUsers, newUser]; }); if (userSearchRes.value?.users) { @@ -70,8 +76,49 @@ export default function NewChannelForm() { ); }, []); + // TODO: prevent creating one-on-one line if already exists with x person? + // ensure that we don't have a one on one chat already with x person if it's one person selected + + // upon success, + // make sure that the list of lines updates for this client and others so that it shows this new line + // select the line so that it shows up in the line details for this client + const handleCreateChannel = useCallback(async () => { + console.log('trying to create line now!'); + + try { + if (!selectedUsers?.length) { + toast.error('you must select at least one person'); + return; + } + + const selectedMemberIds = selectedUsers.map((selectedPerson) => + selectedPerson._id.toString(), + ); + + await triggerCreateChannel(new CreateLineRequest(selectedMemberIds)); + + toast.success('created channel!'); + + // handle close once the new line is created + handleClose(); + } catch (error) { + toast.error(error); + console.error(error); + } finally { + console.log('done'); + } + }, [handleClose, selectedUsers, triggerCreateChannel]); + + useKeyPressEvent('Enter', handleCreateChannel); + useKeyPressEvent('Escape', handleClose); + return ( -
+
+ + + `esc` + +
{/* people search */} People @@ -89,9 +136,10 @@ export default function NewChannelForm() { {/* dropdown search results */}
{(userSearchRes.loading || isSearchingUsers) && } - {(!userSearchRes.value || userSearchRes.value?.users.length === 0) && ( - {`Can't find someone? Invite them and tell them the secret passcode!`} - )} + {(!userSearchRes.value || userSearchRes.value?.users.length === 0) && + selectedUsers?.length === 0 && ( + {`Can't find someone? Invite them and tell them the secret passcode!`} + )} {userSearchRes.value?.users.map((searchedUser) => { return (
); })} + + + +
+ + + + + `enter` + +
); diff --git a/packages/desktop/src/tree/protected/terminal/panels/MainPanel.tsx b/packages/desktop/src/tree/protected/terminal/panels/MainPanel.tsx index 65a56c3..436fbf1 100644 --- a/packages/desktop/src/tree/protected/terminal/panels/MainPanel.tsx +++ b/packages/desktop/src/tree/protected/terminal/panels/MainPanel.tsx @@ -23,13 +23,14 @@ import NewChannelForm from '../compose/NewChannelForm'; export default function MainPanel() { const { user } = useAuth(); - const { selectedLineId, showNewChannelForm } = useRealTimeRooms(); + const { selectedLineId, showNewChannelForm, handleShowNewChannelForm } = useRealTimeRooms(); // already won't see stuff for overlay only mode as per parent configuration // TODO: if there is stuff in search, show that first - if (showNewChannelForm) return ; + if (showNewChannelForm) + return handleShowNewChannelForm('hide')} />; // if selected line, show line details if (selectedLineId) return ;