Added new design to modals
This commit is contained in:
@@ -4,6 +4,7 @@ import { getCurrentUser } from '@/lib/auth';
|
||||
import { writeFile } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { existsSync, mkdirSync } from 'fs';
|
||||
import { createNotification } from '@/lib/notifications';
|
||||
|
||||
// GET - Récupérer les messages d'une conversation
|
||||
export async function GET(
|
||||
@@ -23,7 +24,17 @@ export async function GET(
|
||||
const conversation = await prisma.conversation.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
participants: true,
|
||||
participants: {
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -101,7 +112,17 @@ export async function POST(
|
||||
const conversation = await prisma.conversation.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
participants: true,
|
||||
participants: {
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -197,13 +218,44 @@ export async function POST(
|
||||
},
|
||||
});
|
||||
|
||||
// Mettre à jour la date de mise à jour de la conversation
|
||||
await prisma.conversation.update({
|
||||
where: { id: params.id },
|
||||
data: { updatedAt: new Date() },
|
||||
});
|
||||
// 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 });
|
||||
// Créer des notifications pour tous les participants sauf l'expéditeur
|
||||
const participants = conversation.participants.filter((p) => p.userId !== user.id);
|
||||
|
||||
// Récupérer le nom de la conversation
|
||||
let conversationName = '';
|
||||
if (conversation.type === 'group') {
|
||||
conversationName = conversation.name || 'Groupe';
|
||||
} else {
|
||||
// Pour une conversation directe, utiliser le nom de l'autre participant
|
||||
const otherParticipant = participants.find((p) => p.user);
|
||||
conversationName = otherParticipant?.user?.name || otherParticipant?.user?.email || 'Utilisateur';
|
||||
}
|
||||
|
||||
const messagePreview = content
|
||||
? (content.length > 100 ? content.substring(0, 100) + '...' : content)
|
||||
: files.length > 0
|
||||
? `${files.length} fichier${files.length > 1 ? 's' : ''}`
|
||||
: 'Nouveau message';
|
||||
|
||||
await Promise.all(
|
||||
participants.map((participant) =>
|
||||
createNotification({
|
||||
userId: participant.userId,
|
||||
type: 'message',
|
||||
title: conversationName,
|
||||
message: messagePreview,
|
||||
link: `/dashboard/messagerie?conversation=${params.id}`,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return NextResponse.json(messageWithFiles, { status: 201 });
|
||||
}
|
||||
|
||||
// Mettre à jour la date de mise à jour de la conversation
|
||||
@@ -212,6 +264,35 @@ export async function POST(
|
||||
data: { updatedAt: new Date() },
|
||||
});
|
||||
|
||||
// Créer des notifications pour tous les participants sauf l'expéditeur
|
||||
const participants = conversation.participants.filter((p) => p.userId !== user.id);
|
||||
|
||||
// Récupérer le nom de la conversation
|
||||
let conversationName = '';
|
||||
if (conversation.type === 'group') {
|
||||
conversationName = conversation.name || 'Groupe';
|
||||
} else {
|
||||
// Pour une conversation directe, utiliser le nom de l'autre participant
|
||||
const otherParticipant = participants.find((p) => p.user);
|
||||
conversationName = otherParticipant?.user?.name || otherParticipant?.user?.email || 'Utilisateur';
|
||||
}
|
||||
|
||||
const messagePreview = content
|
||||
? (content.length > 100 ? content.substring(0, 100) + '...' : content)
|
||||
: 'Nouveau message';
|
||||
|
||||
await Promise.all(
|
||||
participants.map((participant) =>
|
||||
createNotification({
|
||||
userId: participant.userId,
|
||||
type: 'message',
|
||||
title: conversationName,
|
||||
message: messagePreview,
|
||||
link: `/dashboard/messagerie?conversation=${params.id}`,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return NextResponse.json(message, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de l\'envoi du message:', error);
|
||||
|
||||
115
app/api/notifications/route.ts
Normal file
115
app/api/notifications/route.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// GET - Récupérer les notifications 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 searchParams = request.nextUrl.searchParams;
|
||||
const limit = parseInt(searchParams.get('limit') || '50');
|
||||
const unreadOnly = searchParams.get('unreadOnly') === 'true';
|
||||
|
||||
const where: any = {
|
||||
userId: user.id,
|
||||
};
|
||||
|
||||
if (unreadOnly) {
|
||||
where.read = false;
|
||||
}
|
||||
|
||||
const notifications = await prisma.notification.findMany({
|
||||
where,
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
take: limit,
|
||||
});
|
||||
|
||||
const unreadCount = await prisma.notification.count({
|
||||
where: {
|
||||
userId: user.id,
|
||||
read: false,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
notifications,
|
||||
unreadCount,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des notifications:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// POST - Marquer une notification comme lue
|
||||
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 { notificationId, markAllAsRead } = body;
|
||||
|
||||
if (markAllAsRead) {
|
||||
// Marquer toutes les notifications comme lues
|
||||
await prisma.notification.updateMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
read: false,
|
||||
},
|
||||
data: {
|
||||
read: true,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
}
|
||||
|
||||
if (!notificationId) {
|
||||
return NextResponse.json(
|
||||
{ error: 'ID de notification requis' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier que la notification appartient à l'utilisateur
|
||||
const notification = await prisma.notification.findFirst({
|
||||
where: {
|
||||
id: notificationId,
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!notification) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Notification non trouvée' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
// Marquer comme lue
|
||||
await prisma.notification.update({
|
||||
where: { id: notificationId },
|
||||
data: { read: true },
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la mise à jour de la notification:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { createNotificationForAllUsers } from '@/lib/notifications';
|
||||
|
||||
// GET - Récupérer un trajet spécifique
|
||||
export async function GET(
|
||||
@@ -103,6 +104,57 @@ export async function PUT(
|
||||
},
|
||||
});
|
||||
|
||||
// Créer une notification si le statut a changé
|
||||
if (statut) {
|
||||
const oldTrajet = await prisma.trajet.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
adherent: {
|
||||
select: {
|
||||
nom: true,
|
||||
prenom: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (oldTrajet && oldTrajet.statut !== statut) {
|
||||
const dateFormatted = new Date(trajet.date).toLocaleDateString('fr-FR', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
|
||||
let notificationType: 'trajet_cancelled' | 'trajet_completed' | null = null;
|
||||
let notificationTitle = '';
|
||||
let notificationMessage = '';
|
||||
|
||||
if (statut === 'Annulé') {
|
||||
notificationType = 'trajet_cancelled';
|
||||
notificationTitle = 'Trajet annulé';
|
||||
notificationMessage = `Le trajet pour ${trajet.adherent.prenom} ${trajet.adherent.nom} du ${dateFormatted} a été annulé`;
|
||||
} else if (statut === 'Terminé') {
|
||||
notificationType = 'trajet_completed';
|
||||
notificationTitle = 'Trajet terminé';
|
||||
notificationMessage = `Le trajet pour ${trajet.adherent.prenom} ${trajet.adherent.nom} du ${dateFormatted} est terminé`;
|
||||
}
|
||||
|
||||
if (notificationType) {
|
||||
await createNotificationForAllUsers(
|
||||
{
|
||||
type: notificationType,
|
||||
title: notificationTitle,
|
||||
message: notificationMessage,
|
||||
link: '/dashboard/calendrier',
|
||||
},
|
||||
user.id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(trajet);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la mise à jour du trajet:', error);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { createNotificationForAllUsers } from '@/lib/notifications';
|
||||
|
||||
// GET - Liste tous les trajets avec leurs relations
|
||||
export async function GET(request: NextRequest) {
|
||||
@@ -125,6 +126,25 @@ export async function POST(request: NextRequest) {
|
||||
},
|
||||
});
|
||||
|
||||
// Créer une notification pour tous les utilisateurs sauf celui qui a créé le trajet
|
||||
const dateFormatted = new Date(date).toLocaleDateString('fr-FR', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
|
||||
await createNotificationForAllUsers(
|
||||
{
|
||||
type: 'trajet_created',
|
||||
title: 'Nouveau trajet programmé',
|
||||
message: `Trajet programmé pour ${trajet.adherent.prenom} ${trajet.adherent.nom} le ${dateFormatted}`,
|
||||
link: '/dashboard/calendrier',
|
||||
},
|
||||
user.id
|
||||
);
|
||||
|
||||
return NextResponse.json(trajet, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la création du trajet:', error);
|
||||
|
||||
@@ -67,7 +67,7 @@ export default function Error({ error, reset }: ErrorProps) {
|
||||
|
||||
{/* Footer */}
|
||||
<div className="mt-12 text-center text-xs text-gray-500">
|
||||
© 2025 MAD - <a href="https://legouix.dev" target="_blank" className="text-lblue hover:text-dblue">Propulsé par LGX</a>
|
||||
© {new Date().getFullYear()} MAD - <a href="https://legouix.dev" target="_blank" className="text-lblue hover:text-dblue">Propulsé par LGX</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@ export default async function LoginPage() {
|
||||
|
||||
{/* Footer */}
|
||||
<div className="mt-8 text-center text-xs text-gray-500">
|
||||
© 2025 MAD - <a href="https://legouix.dev" target="_blank" className="text-lblue hover:text-dblue">Propulsé par LGX</a>
|
||||
© {new Date().getFullYear()} MAD - <a href="https://legouix.dev" target="_blank" className="text-lblue hover:text-dblue">Propulsé par LGX</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@ export default function NotFound() {
|
||||
|
||||
{/* Footer */}
|
||||
<div className="mt-12 text-center text-xs text-gray-500">
|
||||
© 2025 MAD - <a href="https://legouix.dev" target="_blank" className="text-lblue hover:text-dblue">Propulsé par LGX</a>
|
||||
© {new Date().getFullYear()} MAD - <a href="https://legouix.dev" target="_blank" className="text-lblue hover:text-dblue">Propulsé par LGX</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user