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:
pradeepkumar
2026-03-15 00:28:14 +05:30
parent 2c0d0f0aeb
commit 960cdd8d48
4 changed files with 120 additions and 89 deletions

View File

@@ -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,
},
};
}
}
/**