Files
2026-01-21 18:13:35 +01:00

237 lines
7.1 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { getCurrentUser } from '@/lib/auth';
// GET - Liste toutes les conversations de l'utilisateur
export async function GET(request: NextRequest) {
try {
const user = await getCurrentUser();
if (!user) {
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
}
const conversations = await prisma.conversation.findMany({
where: {
participants: {
some: {
userId: user.id,
},
},
},
include: {
participants: {
include: {
user: {
select: {
id: true,
email: true,
name: true,
},
},
},
},
messages: {
orderBy: {
createdAt: 'desc',
},
take: 1,
include: {
sender: {
select: {
id: true,
name: true,
email: true,
},
},
files: true,
},
},
},
orderBy: {
updatedAt: 'desc',
},
});
// Formater les conversations avec les informations nécessaires
const formattedConversations = await Promise.all(
conversations.map(async (conv) => {
const lastMessage = conv.messages[0] || null;
const otherParticipants = conv.participants
.filter((p) => p.userId !== user.id)
.map((p) => p.user);
// Pour les conversations directes, utiliser le nom de l'autre participant
const displayName =
conv.type === 'group'
? conv.name || 'Groupe sans nom'
: otherParticipants[0]?.name || otherParticipants[0]?.email || 'Utilisateur';
// Récupérer lastReadAt pour l'utilisateur actuel
const userParticipant = conv.participants.find((p) => p.userId === user.id);
const lastReadAt = userParticipant?.lastReadAt || null;
// Compter les messages non lus
let unreadCount = 0;
if (lastMessage && lastReadAt) {
const unreadMessages = await prisma.message.count({
where: {
conversationId: conv.id,
senderId: { not: user.id }, // Exclure les messages de l'utilisateur
createdAt: { gt: lastReadAt },
},
});
unreadCount = unreadMessages;
} else if (lastMessage && !lastReadAt) {
// Si jamais lu, compter tous les messages qui ne sont pas de l'utilisateur
const totalUnread = await prisma.message.count({
where: {
conversationId: conv.id,
senderId: { not: user.id },
},
});
unreadCount = totalUnread;
}
return {
id: conv.id,
name: conv.name,
type: conv.type,
displayName,
participants: conv.participants.map((p) => ({
id: p.user.id,
email: p.user.email,
name: p.user.name,
})),
lastMessage: lastMessage
? {
id: lastMessage.id,
content: lastMessage.content,
senderId: lastMessage.senderId,
senderName: lastMessage.sender.name || lastMessage.sender.email,
createdAt: lastMessage.createdAt,
hasFiles: lastMessage.files.length > 0,
}
: null,
unreadCount,
updatedAt: conv.updatedAt,
createdAt: conv.createdAt,
};
})
);
return NextResponse.json(formattedConversations);
} catch (error) {
console.error('Erreur lors de la récupération des conversations:', error);
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
}
}
// POST - Créer une nouvelle conversation
export async function POST(request: NextRequest) {
try {
const user = await getCurrentUser();
if (!user) {
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
}
const body = await request.json();
const { participantIds, name, type } = body;
if (!participantIds || !Array.isArray(participantIds) || participantIds.length === 0) {
return NextResponse.json(
{ error: 'Au moins un participant est requis' },
{ status: 400 }
);
}
// Filtrer l'utilisateur actuel de la liste des participants (on ne peut pas créer une conversation avec soi-même)
const filteredParticipantIds = participantIds.filter((id: string) => id !== user.id);
if (filteredParticipantIds.length === 0) {
return NextResponse.json(
{ error: 'Vous ne pouvez pas créer une conversation avec vous-même' },
{ status: 400 }
);
}
// Vérifier que tous les participants existent
const participants = await prisma.user.findMany({
where: {
id: {
in: filteredParticipantIds,
},
},
});
if (participants.length !== filteredParticipantIds.length) {
return NextResponse.json(
{ error: 'Un ou plusieurs participants sont invalides' },
{ status: 400 }
);
}
// Pour les conversations directes, vérifier si une conversation existe déjà
if (type === 'direct' && filteredParticipantIds.length === 1) {
const existingConversation = await prisma.conversation.findFirst({
where: {
type: 'direct',
participants: {
every: {
userId: {
in: [user.id, filteredParticipantIds[0]],
},
},
},
},
include: {
participants: true,
},
});
if (existingConversation) {
// Vérifier que les deux participants sont bien dans cette conversation
const participantUserIds = existingConversation.participants.map((p) => p.userId);
if (
participantUserIds.includes(user.id) &&
participantUserIds.includes(filteredParticipantIds[0]) &&
participantUserIds.length === 2
) {
return NextResponse.json(existingConversation);
}
}
}
// Créer la conversation avec tous les participants (y compris l'utilisateur actuel)
const conversation = await prisma.conversation.create({
data: {
name: type === 'group' ? name : null,
type: type || 'direct',
participants: {
create: [
{ userId: user.id },
...filteredParticipantIds.map((id: string) => ({ userId: id })),
],
},
},
include: {
participants: {
include: {
user: {
select: {
id: true,
email: true,
name: true,
},
},
},
},
},
});
return NextResponse.json(conversation, { status: 201 });
} catch (error) {
console.error('Erreur lors de la création de la conversation:', error);
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
}
}