Added Chat Page
This commit is contained in:
220
app/api/conversations/[id]/messages/route.ts
Normal file
220
app/api/conversations/[id]/messages/route.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { writeFile } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
|
||||
// GET - Récupérer les messages d'une conversation
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const limit = parseInt(searchParams.get('limit') || '50');
|
||||
const cursor = searchParams.get('cursor');
|
||||
|
||||
const conversation = await prisma.conversation.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
participants: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!conversation) {
|
||||
return NextResponse.json({ error: 'Conversation non trouvée' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Vérifier que l'utilisateur est participant
|
||||
const isParticipant = conversation.participants.some((p) => p.userId === user.id);
|
||||
if (!isParticipant) {
|
||||
return NextResponse.json({ error: 'Accès non autorisé' }, { status: 403 });
|
||||
}
|
||||
|
||||
// Mettre à jour lastReadAt pour l'utilisateur
|
||||
await prisma.conversationParticipant.updateMany({
|
||||
where: {
|
||||
conversationId: params.id,
|
||||
userId: user.id,
|
||||
},
|
||||
data: {
|
||||
lastReadAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
const where: any = {
|
||||
conversationId: params.id,
|
||||
};
|
||||
|
||||
if (cursor) {
|
||||
where.id = {
|
||||
lt: cursor,
|
||||
};
|
||||
}
|
||||
|
||||
const messages = await prisma.message.findMany({
|
||||
where,
|
||||
include: {
|
||||
sender: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
files: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
take: limit,
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
messages: messages.reverse(), // Inverser pour avoir les plus anciens en premier
|
||||
hasMore: messages.length === limit,
|
||||
cursor: messages.length > 0 ? messages[0].id : null,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des messages:', error);
|
||||
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// POST - Envoyer un message dans une conversation
|
||||
export async function POST(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const conversation = await prisma.conversation.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
participants: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!conversation) {
|
||||
return NextResponse.json({ error: 'Conversation non trouvée' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Vérifier que l'utilisateur est participant
|
||||
const isParticipant = conversation.participants.some((p) => p.userId === user.id);
|
||||
if (!isParticipant) {
|
||||
return NextResponse.json({ error: 'Accès non autorisé' }, { status: 403 });
|
||||
}
|
||||
|
||||
const formData = await request.formData();
|
||||
const content = formData.get('content') as string | null;
|
||||
const files = formData.getAll('files') as File[];
|
||||
|
||||
if (!content && (!files || files.length === 0)) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Le message doit contenir du texte ou au moins un fichier' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Créer le message
|
||||
const message = await prisma.message.create({
|
||||
data: {
|
||||
conversationId: params.id,
|
||||
senderId: user.id,
|
||||
content: content || null,
|
||||
},
|
||||
include: {
|
||||
sender: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
files: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Traiter les fichiers si présents
|
||||
if (files && files.length > 0) {
|
||||
const uploadDir = join(process.cwd(), 'public', 'uploads', 'messages');
|
||||
|
||||
// Créer le dossier s'il n'existe pas
|
||||
if (!existsSync(uploadDir)) {
|
||||
mkdirSync(uploadDir, { recursive: true });
|
||||
}
|
||||
|
||||
const fileRecords = await Promise.all(
|
||||
files.map(async (file) => {
|
||||
const bytes = await file.arrayBuffer();
|
||||
const buffer = Buffer.from(bytes);
|
||||
|
||||
// Générer un nom de fichier unique
|
||||
const timestamp = Date.now();
|
||||
const randomStr = Math.random().toString(36).substring(2, 15);
|
||||
const fileExtension = file.name.split('.').pop();
|
||||
const filename = `${timestamp}-${randomStr}.${fileExtension}`;
|
||||
const filepath = join(uploadDir, filename);
|
||||
|
||||
// Sauvegarder le fichier
|
||||
await writeFile(filepath, buffer);
|
||||
|
||||
// Créer l'enregistrement en base de données
|
||||
return prisma.messageFile.create({
|
||||
data: {
|
||||
messageId: message.id,
|
||||
filename: file.name,
|
||||
filepath: `/uploads/messages/${filename}`,
|
||||
fileType: file.type,
|
||||
fileSize: file.size,
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
// Récupérer le message avec les fichiers
|
||||
const messageWithFiles = await prisma.message.findUnique({
|
||||
where: { id: message.id },
|
||||
include: {
|
||||
sender: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
files: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Mettre à jour la date de mise à jour de la conversation
|
||||
await prisma.conversation.update({
|
||||
where: { id: params.id },
|
||||
data: { updatedAt: new Date() },
|
||||
});
|
||||
|
||||
return NextResponse.json(messageWithFiles, { status: 201 });
|
||||
}
|
||||
|
||||
// Mettre à jour la date de mise à jour de la conversation
|
||||
await prisma.conversation.update({
|
||||
where: { id: params.id },
|
||||
data: { updatedAt: new Date() },
|
||||
});
|
||||
|
||||
return NextResponse.json(message, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de l\'envoi du message:', error);
|
||||
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user