getting things going although need some minor backend changes for creating line just name tables and such
This commit is contained in:
@@ -8,7 +8,7 @@ import express, { Application, Request, Response } from "express";
|
|||||||
|
|
||||||
import Content from "@nirvana/core/models/content.model";
|
import Content from "@nirvana/core/models/content.model";
|
||||||
import { ConversationService } from "../services/conversation.service";
|
import { ConversationService } from "../services/conversation.service";
|
||||||
import CreateConvoRequest from "../../core/requests/createConvo.request";
|
import CreateLineRequest from "../../core/requests/createLine.request";
|
||||||
import GetConversationDetailsResponse from "@nirvana/core/responses/getConversationDetails.response";
|
import GetConversationDetailsResponse from "@nirvana/core/responses/getConversationDetails.response";
|
||||||
import GetDmConversationByOtherUserIdResponse from "../../core/responses/getDmConversationByOtherUserId.response";
|
import GetDmConversationByOtherUserIdResponse from "../../core/responses/getDmConversationByOtherUserId.response";
|
||||||
import GetUserConversationsResponse from "../../core/responses/getUserConversations.response";
|
import GetUserConversationsResponse from "../../core/responses/getUserConversations.response";
|
||||||
@@ -60,7 +60,7 @@ async function getDmByOtherUserId(req: Request, res: Response) {
|
|||||||
|
|
||||||
async function createConversation(req: Request, res: Response) {
|
async function createConversation(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
const reqObj: CreateConvoRequest = req.body as CreateConvoRequest;
|
const reqObj: CreateLineRequest = req.body as CreateLineRequest;
|
||||||
console.log(req.body);
|
console.log(req.body);
|
||||||
|
|
||||||
if (!reqObj?.otherMemberIds.length) {
|
if (!reqObj?.otherMemberIds.length) {
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export default class CreateConvoRequest {
|
|
||||||
constructor(public otherMemberIds: string[]) {}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export default class CreateLineRequest {
|
||||||
|
constructor(public otherMemberIds: string[], public lineName?: string) {}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ export default function BasicUserRow({
|
|||||||
<span
|
<span
|
||||||
key={user._id.toString() + new Date().toDateString()}
|
key={user._id.toString() + new Date().toDateString()}
|
||||||
className="border-t border-t-gray-200 py-3 px-2 flex flex-row justify-start
|
className="border-t border-t-gray-200 py-3 px-2 flex flex-row justify-start
|
||||||
items-center w-full hover:bg-gray-300 cursor-pointer group"
|
items-center w-full hover:bg-gray-200 cursor-pointer group"
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
key={`searchUsers-${user._id.toString()}`}
|
key={`searchUsers-${user._id.toString()}`}
|
||||||
@@ -28,7 +28,7 @@ export default function BasicUserRow({
|
|||||||
<span className="flex flex-col items-start">
|
<span className="flex flex-col items-start">
|
||||||
<span className="text-gray-500 text-lg font-semibold">{user.name}</span>
|
<span className="text-gray-500 text-lg font-semibold">{user.name}</span>
|
||||||
|
|
||||||
<span className="text-zinc-300">{user.email}</span>
|
<span className="text-gray-300">{user.email}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className="ml-auto">{rightJsx}</div>
|
<div className="ml-auto">{rightJsx}</div>
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ import { ILineDetails } from "../../../pages/router/index";
|
|||||||
import LineIcon from "../lineIcon";
|
import LineIcon from "../lineIcon";
|
||||||
|
|
||||||
export default function LineRow({
|
export default function LineRow({
|
||||||
id,
|
|
||||||
lineDetails,
|
lineDetails,
|
||||||
onClick,
|
onClick,
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
|
||||||
lineDetails: ILineDetails;
|
lineDetails: ILineDetails;
|
||||||
onClick: (lineId: string) => void;
|
onClick: (lineId: string) => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -43,6 +41,7 @@ export default function LineRow({
|
|||||||
if (lineDetails.profilePicsLiveBroadcasters?.length)
|
if (lineDetails.profilePicsLiveBroadcasters?.length)
|
||||||
return (
|
return (
|
||||||
<Avatar.Group
|
<Avatar.Group
|
||||||
|
key={`lineRowRightActivityGroup-${lineDetails.lineId}`}
|
||||||
maxCount={2}
|
maxCount={2}
|
||||||
maxPopoverTrigger="click"
|
maxPopoverTrigger="click"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -87,7 +86,6 @@ export default function LineRow({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={handleSelectLine}
|
onClick={handleSelectLine}
|
||||||
id={id}
|
|
||||||
className="flex flex-row items-center justify-start gap-2 p-2 px-4 h-14 hover:bg-gray-200 cursor-pointer transition-all
|
className="flex flex-row items-center justify-start gap-2 p-2 px-4 h-14 hover:bg-gray-200 cursor-pointer transition-all
|
||||||
last:border-b-0 border-b border-b-gray-200"
|
last:border-b-0 border-b border-b-gray-200"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios";
|
import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios";
|
||||||
|
|
||||||
import { Conversation } from "../../../core/models/conversation.model";
|
import { Conversation } from "../../../core/models/conversation.model";
|
||||||
import CreateConvoRequest from "../../../core/requests/createConvo.request";
|
import CreateLineRequest from "@nirvana/core/requests/createLine.request";
|
||||||
import LoginResponse from "../../../core/responses/login.response";
|
import LoginResponse from "../../../core/responses/login.response";
|
||||||
import MasterConversation from "../../../core/models/masterConversation.model";
|
import MasterConversation from "../../../core/models/masterConversation.model";
|
||||||
import { User } from "@nirvana/core/models";
|
import { User } from "@nirvana/core/models";
|
||||||
@@ -93,13 +93,8 @@ async function getDmByUserId(otherUserId: string): Promise<Conversation> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createConversation(otherMemberIds: string[]): Promise<void> {
|
async function createConversation(request: CreateLineRequest): Promise<void> {
|
||||||
return await NirvanaApi.fetch(
|
return await NirvanaApi.fetch(`/conversations`, "POST", true, request);
|
||||||
`/conversations`,
|
|
||||||
"POST",
|
|
||||||
true,
|
|
||||||
new CreateConvoRequest(otherMemberIds)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ApiCalls = {
|
export const ApiCalls = {
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export default function NirvanaTerminal({
|
|||||||
<div className="flex flex-col mt-2">
|
<div className="flex flex-col mt-2">
|
||||||
{toggleTunedLines.map((line) => (
|
{toggleTunedLines.map((line) => (
|
||||||
<LineRow
|
<LineRow
|
||||||
id={line.lineId}
|
key={line.lineId}
|
||||||
lineDetails={line}
|
lineDetails={line}
|
||||||
onClick={handleSelectLine}
|
onClick={handleSelectLine}
|
||||||
/>
|
/>
|
||||||
@@ -90,7 +90,7 @@ export default function NirvanaTerminal({
|
|||||||
<div className={"flex flex-col"}>
|
<div className={"flex flex-col"}>
|
||||||
{restLines.map((line) => (
|
{restLines.map((line) => (
|
||||||
<LineRow
|
<LineRow
|
||||||
id={line.lineId}
|
key={line.lineId}
|
||||||
lineDetails={line}
|
lineDetails={line}
|
||||||
onClick={handleSelectLine}
|
onClick={handleSelectLine}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { Avatar, Modal } from "antd";
|
import { Avatar, Modal } from "antd";
|
||||||
import { HotKeys, KeyMap } from "react-hotkeys";
|
import { HotKeys, KeyMap } from "react-hotkeys";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { useCreateConvo, useUserSearch } from "../../../controller/index";
|
||||||
|
|
||||||
import BasicUserRow from "../../../components/User/basicUserDetailsRow";
|
import BasicUserRow from "../../../components/User/basicUserDetailsRow";
|
||||||
import { FiSearch } from "react-icons/fi";
|
import { FiSearch } from "react-icons/fi";
|
||||||
import { User } from "@nirvana/core/models";
|
import { User } from "@nirvana/core/models";
|
||||||
import { useUserSearch } from "../../../controller/index";
|
import toast from "react-hot-toast";
|
||||||
|
|
||||||
export default function NewLineModal({
|
export default function NewLineModal({
|
||||||
open,
|
open,
|
||||||
@@ -22,34 +23,38 @@ export default function NewLineModal({
|
|||||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||||
const { refetch, data: searchRes } = useUserSearch(searchQuery);
|
const { refetch, data: searchRes } = useUserSearch(searchQuery);
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const { mutateAsync, isError, isLoading } = useCreateConvo();
|
||||||
// ensure that we don't have a one on one chat already with x person if it's one person selected
|
|
||||||
|
|
||||||
// upon success,
|
const [lineName, setLineName] = useState<string>("");
|
||||||
// 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
|
|
||||||
|
|
||||||
// handle close once the new line is created
|
useEffect(() => {
|
||||||
handleClose();
|
if (searchQuery) refetch();
|
||||||
};
|
}, [searchQuery]);
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSearch = useCallback(() => {
|
const onSearch = useCallback(() => {
|
||||||
|
console.log("enter key pressed");
|
||||||
|
|
||||||
if (peopleSearchValue) {
|
if (peopleSearchValue) {
|
||||||
console.log("searching for people in database");
|
console.log("searching for people in database");
|
||||||
setSearchQuery(peopleSearchValue);
|
setSearchQuery(peopleSearchValue);
|
||||||
}
|
}
|
||||||
}, [setSearchQuery]);
|
}, [setSearchQuery, peopleSearchValue]);
|
||||||
|
|
||||||
const selectUser = useCallback(
|
const selectUser = useCallback(
|
||||||
(userToAdd: User) => {
|
(userToAdd: User) => {
|
||||||
setSelectedPeople((prevSelectedUsers) => [
|
setSelectedPeople((prevSelectedUsers) => {
|
||||||
...prevSelectedUsers,
|
// if user is not already in the selected user
|
||||||
userToAdd,
|
const foundUser = prevSelectedUsers.find(
|
||||||
]);
|
(currentUser) =>
|
||||||
|
currentUser._id.toString() === userToAdd._id.toString()
|
||||||
|
);
|
||||||
|
if (!foundUser) {
|
||||||
|
return [...prevSelectedUsers, userToAdd];
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.error("you already selected this person below!");
|
||||||
|
return prevSelectedUsers;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[setSelectedPeople]
|
[setSelectedPeople]
|
||||||
);
|
);
|
||||||
@@ -65,17 +70,48 @@ export default function NewLineModal({
|
|||||||
[setSelectedPeople]
|
[setSelectedPeople]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleSubmit = useCallback(async () => {
|
||||||
|
// 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
|
||||||
|
|
||||||
|
console.log("trying to create line now!");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!selectedPeople?.length) {
|
||||||
|
toast.error("you must select at least one person");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedMemberIds = selectedPeople.map((selectedPerson) =>
|
||||||
|
selectedPerson._id.toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
await mutateAsync({ lineName, otherMemberIds: selectedMemberIds });
|
||||||
|
|
||||||
|
// handle close once the new line is created
|
||||||
|
handleClose();
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(error);
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}, [lineName, selectedPeople]);
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
const keyMap: KeyMap = {
|
const keyMap: KeyMap = {
|
||||||
HANDLE_SEARCH: {
|
HANDLE_SEARCH: "enter",
|
||||||
name: "handle search on enter",
|
|
||||||
sequence: "enter",
|
|
||||||
action: "keypress",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
const handlers = {
|
const handlers = {
|
||||||
HANDLE_SEARCH: onSearch,
|
HANDLE_SEARCH: onSearch,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (isLoading) return <span>one second while we make magic</span>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
@@ -100,63 +136,73 @@ export default function NewLineModal({
|
|||||||
}
|
}
|
||||||
className={"flex flex-col gap-5"}
|
className={"flex flex-col gap-5"}
|
||||||
>
|
>
|
||||||
<HotKeys handlers={handlers} keyMap={keyMap} />
|
<HotKeys handlers={handlers} keyMap={keyMap} allowChanges={true}>
|
||||||
|
<div className="flex flex-col items-start gap-2 mb-5">
|
||||||
|
<p className="text-gray-300 text-sm">People</p>
|
||||||
|
|
||||||
<div className="flex flex-col items-start gap-2 mb-5">
|
<span className="flex flex-row gap-1 w-full items-center border border-gray-200 p-2 shadow">
|
||||||
<p className="text-gray-300 text-sm">People</p>
|
<FiSearch className="text-gray-300" />
|
||||||
|
|
||||||
<span className="flex flex-row gap-1 w-full items-center border border-gray-200 p-2 shadow">
|
<input
|
||||||
<FiSearch className="text-gray-300" />
|
className="placeholder:text-gray-300 outline-none placeholder:text-sm border-0 flex-1"
|
||||||
|
value={peopleSearchValue}
|
||||||
|
onChange={(e) => setPeopleSearchValue(e.target.value)}
|
||||||
|
placeholder="search by name or email"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<span className="text-xs text-gray-200 ml-auto">
|
||||||
|
enter to search
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{/* search results */}
|
||||||
|
<div className="flex flex-col border border-gray-200 shadow-md max-h-[500px] w-full overflow-y-auto">
|
||||||
|
{searchRes?.users?.map((searchedUser) => (
|
||||||
|
<BasicUserRow
|
||||||
|
key={`searchResUser-${searchedUser.googleId}`}
|
||||||
|
user={searchedUser}
|
||||||
|
rightJsx={
|
||||||
|
<button onClick={() => selectUser(searchedUser)}>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* selected people */}
|
||||||
|
<div className="flex flex-col gap-2 mb-5">
|
||||||
|
<p className="text-gray-300 text-sm">Selected People</p>
|
||||||
|
|
||||||
|
<div className="flex flex-col w-full">
|
||||||
|
{selectedPeople.map((selectedUser) => (
|
||||||
|
<BasicUserRow
|
||||||
|
key={`selectedUser-${selectedUser.googleId}`}
|
||||||
|
user={selectedUser}
|
||||||
|
rightJsx={
|
||||||
|
<button
|
||||||
|
onClick={() => unSelectUser(selectedUser._id.toString())}
|
||||||
|
>
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<p className="text-gray-300 text-sm">Line Name (optional)</p>
|
||||||
<input
|
<input
|
||||||
className="placeholder:text-gray-300 outline-none placeholder:text-sm border-0 flex-1"
|
value={lineName}
|
||||||
value={peopleSearchValue}
|
onChange={(e) => setLineName(e.target.value)}
|
||||||
onChange={(e) => setPeopleSearchValue(e.target.value)}
|
className="placeholder:text-gray-300 outline-none placeholder:text-sm flex-1
|
||||||
placeholder="search by name or email"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span className="text-xs text-gray-200">enter to search</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{/* search results */}
|
|
||||||
<div className="flex flex-col border border-gray-200 shadow-md max-h-[500px] w-full overflow-y-auto">
|
|
||||||
{searchRes?.users?.map((user) => (
|
|
||||||
<BasicUserRow
|
|
||||||
user={user}
|
|
||||||
rightJsx={<button onClick={() => selectUser(user)}>Add</button>}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* selected people */}
|
|
||||||
<div className="flex flex-col gap-2 mb-5">
|
|
||||||
<p className="text-gray-300 text-sm">Selected People</p>
|
|
||||||
|
|
||||||
<div className="flex flex-col w-full">
|
|
||||||
{selectedPeople.map((selectedUser) => (
|
|
||||||
<BasicUserRow
|
|
||||||
user={selectedUser}
|
|
||||||
rightJsx={
|
|
||||||
<button
|
|
||||||
onClick={() => unSelectUser(selectedUser._id.toString())}
|
|
||||||
>
|
|
||||||
Remove
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<p className="text-gray-300 text-sm">Line Name (optional)</p>
|
|
||||||
<input
|
|
||||||
className="placeholder:text-gray-300 outline-none placeholder:text-sm flex-1
|
|
||||||
border p-2 border-gray-200"
|
border p-2 border-gray-200"
|
||||||
placeholder={"ex. Engineering, Sprint 7, Follow up on present..."}
|
placeholder={"ex. Engineering, Sprint 7, Follow up on present..."}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</HotKeys>
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user