feat: Allow both users and agents to initiate conversations and dynamically display the other party based on the caller's role, while also enhancing user profile data in connection requests.
This commit is contained in:
@@ -33,17 +33,80 @@ export class MessagesService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create a conversation between user and agent
|
||||
* Get or create a conversation between user and agent.
|
||||
* Supports both user-initiated (provides agentProfileId) and agent-initiated (provides userId).
|
||||
*/
|
||||
async getOrCreateConversation(userId: string, agentProfileId: string) {
|
||||
async getOrCreateConversation(
|
||||
callerUserId: string,
|
||||
callerRole: UserRole,
|
||||
dto: { agentProfileId?: string; userId?: string },
|
||||
) {
|
||||
let userId: string;
|
||||
let agentProfileId: string;
|
||||
|
||||
if (callerRole === UserRole.AGENT) {
|
||||
// Agent is starting the conversation — they provide the target userId
|
||||
if (!dto.userId) {
|
||||
throw new BadRequestException('userId is required for agents to start a conversation');
|
||||
}
|
||||
const agentProfile = await this.prisma.agentProfile.findUnique({
|
||||
where: { userId: callerUserId },
|
||||
});
|
||||
if (!agentProfile) {
|
||||
throw new BadRequestException('Agent profile not found');
|
||||
}
|
||||
userId = dto.userId;
|
||||
agentProfileId = agentProfile.id;
|
||||
} else {
|
||||
// User is starting the conversation — they provide the target agentProfileId
|
||||
if (!dto.agentProfileId) {
|
||||
throw new BadRequestException('agentProfileId is required for users to start a conversation');
|
||||
}
|
||||
userId = callerUserId;
|
||||
agentProfileId = dto.agentProfileId;
|
||||
}
|
||||
|
||||
// Validate connection first
|
||||
const canMessage = await this.validateCanMessage(userId, agentProfileId);
|
||||
if (!canMessage) {
|
||||
throw new ForbiddenException(
|
||||
'You can only message agents with accepted connection requests',
|
||||
'You can only message users with accepted connection requests',
|
||||
);
|
||||
}
|
||||
|
||||
const conversationInclude = {
|
||||
agentProfile: {
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
avatar: true,
|
||||
headline: true,
|
||||
userId: true,
|
||||
user: {
|
||||
select: {
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
userProfile: {
|
||||
select: {
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
avatar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Check if conversation already exists
|
||||
let conversation = await this.prisma.conversation.findUnique({
|
||||
where: {
|
||||
@@ -52,38 +115,7 @@ export class MessagesService {
|
||||
agentProfileId,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
agentProfile: {
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
avatar: true,
|
||||
headline: true,
|
||||
userId: true,
|
||||
user: {
|
||||
select: {
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
userProfile: {
|
||||
select: {
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
avatar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: conversationInclude,
|
||||
});
|
||||
|
||||
// Create new conversation if it doesn't exist
|
||||
@@ -93,55 +125,40 @@ export class MessagesService {
|
||||
userId,
|
||||
agentProfileId,
|
||||
},
|
||||
include: {
|
||||
agentProfile: {
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
avatar: true,
|
||||
headline: true,
|
||||
userId: true,
|
||||
user: {
|
||||
select: {
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
isOnline: true,
|
||||
lastSeenAt: true,
|
||||
userProfile: {
|
||||
select: {
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
avatar: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: conversationInclude,
|
||||
});
|
||||
}
|
||||
|
||||
// Transform to include otherParty (for the user, other party is the agent)
|
||||
return {
|
||||
...conversation,
|
||||
unreadCount: conversation.userUnreadCount,
|
||||
otherParty: {
|
||||
id: conversation.agentProfile.id,
|
||||
userId: conversation.agentProfile.userId,
|
||||
name: `${conversation.agentProfile.firstName || ''} ${conversation.agentProfile.lastName || ''}`.trim() || 'Agent',
|
||||
avatar: conversation.agentProfile.avatar,
|
||||
headline: conversation.agentProfile.headline,
|
||||
isOnline: conversation.agentProfile.user?.isOnline || false,
|
||||
lastSeenAt: conversation.agentProfile.user?.lastSeenAt || null,
|
||||
},
|
||||
};
|
||||
// Transform to include otherParty based on caller role
|
||||
if (callerRole === UserRole.AGENT) {
|
||||
// Agent is viewing — other party is the user
|
||||
return {
|
||||
...conversation,
|
||||
unreadCount: conversation.agentUnreadCount,
|
||||
otherParty: {
|
||||
id: conversation.user.id,
|
||||
name: `${conversation.user.userProfile?.firstName || ''} ${conversation.user.userProfile?.lastName || ''}`.trim() || 'User',
|
||||
avatar: conversation.user.userProfile?.avatar,
|
||||
isOnline: conversation.user.isOnline,
|
||||
lastSeenAt: conversation.user.lastSeenAt,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
// User is viewing — other party is the agent
|
||||
return {
|
||||
...conversation,
|
||||
unreadCount: conversation.userUnreadCount,
|
||||
otherParty: {
|
||||
id: conversation.agentProfile.id,
|
||||
userId: conversation.agentProfile.userId,
|
||||
name: `${conversation.agentProfile.firstName || ''} ${conversation.agentProfile.lastName || ''}`.trim() || 'Agent',
|
||||
avatar: conversation.agentProfile.avatar,
|
||||
headline: conversation.agentProfile.headline,
|
||||
isOnline: conversation.agentProfile.user?.isOnline || false,
|
||||
lastSeenAt: conversation.agentProfile.user?.lastSeenAt || null,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user