fetching convos with current state for user and combining to master convos
This commit is contained in:
@@ -11,6 +11,7 @@ import { ConversationService } from "../services/conversation.service";
|
|||||||
import CreateConvoRequest from "../../core/requests/createConvo.request";
|
import CreateConvoRequest from "../../core/requests/createConvo.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 MasterConversation from "../../core/models/masterConversation.model";
|
import MasterConversation from "../../core/models/masterConversation.model";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
import Relationship from "@nirvana/core/models/relationship.model";
|
import Relationship from "@nirvana/core/models/relationship.model";
|
||||||
@@ -28,6 +29,9 @@ export default function getConversationRoutes() {
|
|||||||
// create a convo
|
// create a convo
|
||||||
router.post("/", authCheck, createConversation);
|
router.post("/", authCheck, createConversation);
|
||||||
|
|
||||||
|
// get all of user's convos
|
||||||
|
router.get("/", authCheck, getUserConvos);
|
||||||
|
|
||||||
// get conversation between user and other user
|
// get conversation between user and other user
|
||||||
router.get("/dm/:otherUserId", authCheck, getDmByOtherUserId);
|
router.get("/dm/:otherUserId", authCheck, getDmByOtherUserId);
|
||||||
|
|
||||||
@@ -99,3 +103,48 @@ async function createConversation(req: Request, res: Response) {
|
|||||||
res.status(500).json(error);
|
res.status(500).json(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getUserConvos(req: Request, res: Response) {
|
||||||
|
try {
|
||||||
|
const userInfo = res.locals.userInfo as JwtClaims;
|
||||||
|
|
||||||
|
// get all of user's convoMember entries
|
||||||
|
const convoMembers =
|
||||||
|
await ConversationService.getConversationsMembersByUserId(
|
||||||
|
userInfo.userId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!convoMembers?.length) {
|
||||||
|
res.status(400).json();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const convoIds =
|
||||||
|
convoMembers?.map((convoMem) => convoMem.conversationId) ?? [];
|
||||||
|
|
||||||
|
// get all convos from the list of relevant convos
|
||||||
|
const convos =
|
||||||
|
(await ConversationService.getConversationsByIds(convoIds)) ?? [];
|
||||||
|
|
||||||
|
const masterConvos =
|
||||||
|
convos.map((convo) => {
|
||||||
|
const assocConvoMember = convoMembers.find((convMem) =>
|
||||||
|
convMem.conversationId.equals(convo._id!)
|
||||||
|
);
|
||||||
|
|
||||||
|
return new MasterConversation(
|
||||||
|
convo._id!,
|
||||||
|
convo.createdDate,
|
||||||
|
convo.lastUpdatedDate,
|
||||||
|
assocConvoMember
|
||||||
|
);
|
||||||
|
}) ?? [];
|
||||||
|
|
||||||
|
const resObj = new GetUserConversationsResponse(convos);
|
||||||
|
|
||||||
|
res.json(masterConvos);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,34 @@ export class ConversationService {
|
|||||||
// return null;
|
// return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async getConversationsByIds(convoIds: ObjectId[]) {
|
||||||
|
const query = { _id: { $in: convoIds } };
|
||||||
|
|
||||||
|
const convosRes = await collections.conversations?.find(query).toArray();
|
||||||
|
|
||||||
|
// exists
|
||||||
|
if (convosRes?.length) {
|
||||||
|
return convosRes as Conversation[];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getConversationsMembersByUserId(userId: string) {
|
||||||
|
const query = { userId: new ObjectId(userId) };
|
||||||
|
|
||||||
|
const convoMembersRes = await collections.conversationMembers
|
||||||
|
?.find(query)
|
||||||
|
.toArray();
|
||||||
|
|
||||||
|
// exists
|
||||||
|
if (convoMembersRes?.length) {
|
||||||
|
return convoMembersRes as ConversationMember[];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static async createConversation(
|
static async createConversation(
|
||||||
convo: Conversation,
|
convo: Conversation,
|
||||||
convoMembers: ConversationMember[]
|
convoMembers: ConversationMember[]
|
||||||
|
|||||||
@@ -3,15 +3,20 @@ import { ConversationMember } from "./conversation.model";
|
|||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
export default class MasterConversation {
|
export default class MasterConversation {
|
||||||
// attributes of conversation
|
constructor(
|
||||||
id: ObjectId; // id of the conversation
|
// attributes of conversation
|
||||||
name?: string;
|
public id: ObjectId, // id of the conversation
|
||||||
createdDate: Date;
|
|
||||||
lastUpdatedDate: Date;
|
|
||||||
|
|
||||||
// compiled data for easy client read
|
public createdDate: Date,
|
||||||
currentUserMember: ConversationMember;
|
public lastUpdatedDate: Date,
|
||||||
otherMembers: ConversationMember[];
|
|
||||||
|
|
||||||
audioClips: AudioClip[];
|
// compiled data for easy client read
|
||||||
|
public currentUserMember?: ConversationMember,
|
||||||
|
|
||||||
|
public otherMembers?: ConversationMember[],
|
||||||
|
|
||||||
|
public audioClips: AudioClip[] = [],
|
||||||
|
|
||||||
|
public name?: string
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { Conversation } from "../models/conversation.model";
|
||||||
|
|
||||||
|
export default class GetUserConversationsResponse {
|
||||||
|
constructor(public convos: Conversation[]) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import MasterConversation from "../../../../core/models/masterConversation.model";
|
||||||
|
import UserStatusText from "../User/userStatusText";
|
||||||
|
export default function BasicConversationRow({
|
||||||
|
masterConvo,
|
||||||
|
}: {
|
||||||
|
masterConvo: MasterConversation;
|
||||||
|
}) {
|
||||||
|
const isSelected = false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={masterConvo.id.toString()}
|
||||||
|
className={`flex flex-row items-center hover:bg-zinc-600 group py-4 px-2 cursor-pointer ${
|
||||||
|
isSelected ? "bg-zinc-600" : ""
|
||||||
|
} rounded`}
|
||||||
|
>
|
||||||
|
{/* <UserAvatarWithStatus user={contactDetail.otherUser} /> */}
|
||||||
|
|
||||||
|
<span className="text-white font-semibold ml-2">{masterConvo.name}</span>
|
||||||
|
<span className="text-white font-semibold ml-2">
|
||||||
|
{masterConvo.id.toString()}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{/* <span className="ml-2">
|
||||||
|
<UserStatusText status={contactDetail.otherUser.status} />
|
||||||
|
</span> */}
|
||||||
|
|
||||||
|
{/* {speakingRooms.includes(contactDetail.relationship._id.toString()) ? (
|
||||||
|
<span className="ml-auto">speaking...</span>
|
||||||
|
) : null} */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -30,6 +30,12 @@ export function useUserSearch(searchQuery: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useUserConvos() {
|
||||||
|
// todo: merge with sockets + audio clip data + master data + convomember data
|
||||||
|
|
||||||
|
return useQuery("USER_CONVERSATIONS", ApiCalls.getUserConversations);
|
||||||
|
}
|
||||||
|
|
||||||
// =========== MUTATIONS
|
// =========== MUTATIONS
|
||||||
export function useGetDmByUserId() {
|
export function useGetDmByUserId() {
|
||||||
return useMutation(ApiCalls.getDmByUserId);
|
return useMutation(ApiCalls.getDmByUserId);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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 CreateConvoRequest from "../../../core/requests/createConvo.request";
|
||||||
import LoginResponse from "../../../core/responses/login.response";
|
import LoginResponse from "../../../core/responses/login.response";
|
||||||
|
import MasterConversation from "../../../core/models/masterConversation.model";
|
||||||
import { User } from "@nirvana/core/models";
|
import { User } from "@nirvana/core/models";
|
||||||
import UserDetailsResponse from "../../../core/responses/userDetails.response";
|
import UserDetailsResponse from "../../../core/responses/userDetails.response";
|
||||||
import UserSearchResponse from "../../../core/responses/userSearch.response";
|
import UserSearchResponse from "../../../core/responses/userSearch.response";
|
||||||
@@ -80,6 +81,10 @@ async function userSearch(searchQuery: string): Promise<UserSearchResponse> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getUserConversations(): Promise<MasterConversation[]> {
|
||||||
|
return await NirvanaApi.fetch(`/conversations`, "GET", true);
|
||||||
|
}
|
||||||
|
|
||||||
async function getDmByUserId(otherUserId: string): Promise<Conversation> {
|
async function getDmByUserId(otherUserId: string): Promise<Conversation> {
|
||||||
return await NirvanaApi.fetch(
|
return await NirvanaApi.fetch(
|
||||||
`/conversations/dm/${otherUserId}`,
|
`/conversations/dm/${otherUserId}`,
|
||||||
@@ -102,6 +107,7 @@ export const ApiCalls = {
|
|||||||
authCheck,
|
authCheck,
|
||||||
getUserDetails,
|
getUserDetails,
|
||||||
userSearch,
|
userSearch,
|
||||||
|
getUserConversations,
|
||||||
getDmByUserId,
|
getDmByUserId,
|
||||||
createConversation,
|
createConversation,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
} from "../../../../../core/models/conversation.model";
|
} from "../../../../../core/models/conversation.model";
|
||||||
import { useRecoilState, useSetRecoilState } from "recoil";
|
import { useRecoilState, useSetRecoilState } from "recoil";
|
||||||
|
|
||||||
|
import BasicConversationRow from "../../../components/conversation/basicRow";
|
||||||
import { ContactDetails } from "@nirvana/core/responses/getContacts.response";
|
import { ContactDetails } from "@nirvana/core/responses/getContacts.response";
|
||||||
import { FaVolumeUp } from "react-icons/fa";
|
import { FaVolumeUp } from "react-icons/fa";
|
||||||
import MasterConversation from "../../../../../core/models/masterConversation.model";
|
import MasterConversation from "../../../../../core/models/masterConversation.model";
|
||||||
@@ -19,6 +20,7 @@ import UserAvatarWithStatus from "../../../components/User/userAvatarWithStatus"
|
|||||||
import UserStatusText from "../../../components/User/userStatusText";
|
import UserStatusText from "../../../components/User/userStatusText";
|
||||||
import useSocketData from "../../../controller/sockets";
|
import useSocketData from "../../../controller/sockets";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { useUserConvos } from "../../../controller/index";
|
||||||
|
|
||||||
enum ConvoTab {
|
enum ConvoTab {
|
||||||
LIVE = "LIVE",
|
LIVE = "LIVE",
|
||||||
@@ -57,22 +59,21 @@ export default function Conversations() {
|
|||||||
setSelectedConvo(googleUserId);
|
setSelectedConvo(googleUserId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// fake data of conversations
|
const { data: userConverstionsData } = useUserConvos();
|
||||||
const allMasterConvos = [] as MasterConversation[];
|
|
||||||
|
|
||||||
// render right content based on selected tab
|
// render right content based on selected tab
|
||||||
const renderConversationContent = () => {
|
const renderConversationContent = () => {
|
||||||
// if no content for a tab, then show stale text
|
// if no content for a tab, then show stale text
|
||||||
|
|
||||||
const invitedConvos = allMasterConvos.filter(
|
const invitedConvos = userConverstionsData?.filter(
|
||||||
(masterConvo) =>
|
(masterConvo) =>
|
||||||
masterConvo.currentUserMember.state === ConversationMemberState.INVITED
|
masterConvo.currentUserMember.state === ConversationMemberState.INVITED
|
||||||
);
|
);
|
||||||
const inboxConvos = allMasterConvos.filter(
|
const inboxConvos = userConverstionsData?.filter(
|
||||||
(masterConvo) =>
|
(masterConvo) =>
|
||||||
masterConvo.currentUserMember.state === ConversationMemberState.INBOX
|
masterConvo.currentUserMember.state === ConversationMemberState.INBOX
|
||||||
);
|
);
|
||||||
const tunedConvos = allMasterConvos.filter(
|
const tunedConvos = userConverstionsData?.filter(
|
||||||
(masterConvo) =>
|
(masterConvo) =>
|
||||||
masterConvo.currentUserMember.state === ConversationMemberState.TUNED
|
masterConvo.currentUserMember.state === ConversationMemberState.TUNED
|
||||||
);
|
);
|
||||||
@@ -94,7 +95,13 @@ export default function Conversations() {
|
|||||||
return <span>Pin a channel to turn it into a walkie talkie.</span>;
|
return <span>Pin a channel to turn it into a walkie talkie.</span>;
|
||||||
case ConvoTab.INBOX:
|
case ConvoTab.INBOX:
|
||||||
if (inboxConvos?.length) {
|
if (inboxConvos?.length) {
|
||||||
return <span>displaying all inbox convos</span>;
|
return (
|
||||||
|
<>
|
||||||
|
{inboxConvos.map((convo) => (
|
||||||
|
<BasicConversationRow masterConvo={convo} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return <span>Connect with someone and start talking!</span>;
|
return <span>Connect with someone and start talking!</span>;
|
||||||
case ConvoTab.REQUESTS:
|
case ConvoTab.REQUESTS:
|
||||||
|
|||||||
Reference in New Issue
Block a user