Added few configurations & mores
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
|
||||
// GET - Récupérer l'utilisateur actuel
|
||||
export async function GET() {
|
||||
@@ -8,7 +9,26 @@ export async function GET() {
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
return NextResponse.json(user);
|
||||
|
||||
// Récupérer l'utilisateur avec son rôle
|
||||
const userWithRole = await prisma.user.findUnique({
|
||||
where: { id: user.id },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
roleId: true,
|
||||
role: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
description: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(userWithRole);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération de l\'utilisateur:', error);
|
||||
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
|
||||
131
app/api/dashboard/stats/route.ts
Normal file
131
app/api/dashboard/stats/route.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// GET - Récupérer les statistiques du dashboard
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||
const endOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999);
|
||||
|
||||
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
|
||||
|
||||
const startOfLastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
||||
const endOfLastMonth = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59, 999);
|
||||
|
||||
const startOfYesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
||||
const endOfYesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, 23, 59, 59, 999);
|
||||
|
||||
// 1. Participations du mois (montant total des trajets validés/terminés + nombre de factures)
|
||||
// Pour l'instant, on considère qu'un trajet terminé = une facture
|
||||
// Montant estimé : 6.80€ par trajet (valeur moyenne basée sur l'image)
|
||||
const trajetsMois = await prisma.trajet.findMany({
|
||||
where: {
|
||||
archived: false,
|
||||
statut: {
|
||||
in: ['Terminé', 'Validé'],
|
||||
},
|
||||
date: {
|
||||
gte: startOfMonth,
|
||||
lte: endOfMonth,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const montantMoyenParTrajet = 6.80; // Montant moyen par trajet en euros
|
||||
const participationsMois = trajetsMois.length * montantMoyenParTrajet;
|
||||
const nombreFactures = trajetsMois.length;
|
||||
|
||||
// 2. Trajets aujourd'hui
|
||||
const trajetsAujourdhui = await prisma.trajet.count({
|
||||
where: {
|
||||
archived: false,
|
||||
date: {
|
||||
gte: startOfToday,
|
||||
lte: endOfToday,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Trajets hier pour comparaison
|
||||
const trajetsHier = await prisma.trajet.count({
|
||||
where: {
|
||||
archived: false,
|
||||
date: {
|
||||
gte: startOfYesterday,
|
||||
lte: endOfYesterday,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const differenceAujourdhui = trajetsAujourdhui - trajetsHier;
|
||||
|
||||
// 3. Trajets réalisés ce mois (terminés)
|
||||
const trajetsRealisesMois = await prisma.trajet.count({
|
||||
where: {
|
||||
archived: false,
|
||||
statut: 'Terminé',
|
||||
date: {
|
||||
gte: startOfMonth,
|
||||
lte: endOfMonth,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Trajets réalisés le mois dernier pour comparaison
|
||||
const trajetsRealisesMoisDernier = await prisma.trajet.count({
|
||||
where: {
|
||||
archived: false,
|
||||
statut: 'Terminé',
|
||||
date: {
|
||||
gte: startOfLastMonth,
|
||||
lte: endOfLastMonth,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const pourcentageEvolution = trajetsRealisesMoisDernier > 0
|
||||
? Math.round(((trajetsRealisesMois - trajetsRealisesMoisDernier) / trajetsRealisesMoisDernier) * 100)
|
||||
: trajetsRealisesMois > 0 ? 100 : 0;
|
||||
|
||||
// 4. Chauffeurs actifs (disponibles)
|
||||
const totalChauffeurs = await prisma.chauffeur.count();
|
||||
const chauffeursActifs = await prisma.chauffeur.count({
|
||||
where: {
|
||||
status: 'Disponible',
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
participationsMois: {
|
||||
montant: participationsMois,
|
||||
nombreFactures: nombreFactures,
|
||||
},
|
||||
trajetsAujourdhui: {
|
||||
nombre: trajetsAujourdhui,
|
||||
difference: differenceAujourdhui,
|
||||
},
|
||||
trajetsRealisesMois: {
|
||||
nombre: trajetsRealisesMois,
|
||||
pourcentageEvolution: pourcentageEvolution,
|
||||
},
|
||||
chauffeursActifs: {
|
||||
nombre: chauffeursActifs,
|
||||
total: totalChauffeurs,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des statistiques:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
74
app/api/permissions/route.ts
Normal file
74
app/api/permissions/route.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// GET - Liste toutes les permissions disponibles
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const permissions = await prisma.permission.findMany({
|
||||
orderBy: {
|
||||
name: 'asc',
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(permissions);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des permissions:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// POST - Créer une nouvelle permission
|
||||
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 { name, description } = body;
|
||||
|
||||
if (!name) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Le nom de la permission est requis' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si la permission existe déjà
|
||||
const existing = await prisma.permission.findUnique({
|
||||
where: { name },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Cette permission existe déjà' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const permission = await prisma.permission.create({
|
||||
data: {
|
||||
name,
|
||||
description: description || null,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(permission, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la création de la permission:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
205
app/api/roles/[id]/route.ts
Normal file
205
app/api/roles/[id]/route.ts
Normal file
@@ -0,0 +1,205 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// GET - Récupérer un rôle avec ses permissions
|
||||
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 role = await prisma.role.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
permissions: {
|
||||
include: {
|
||||
permission: true,
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!role) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Rôle non trouvé' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json(role);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération du rôle:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// PUT - Modifier un rôle
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { name, description, permissionIds } = body;
|
||||
|
||||
const role = await prisma.role.findUnique({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
if (!role) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Rôle non trouvé' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si le nouveau nom existe déjà (si changé)
|
||||
if (name && name !== role.name) {
|
||||
const existing = await prisma.role.findUnique({
|
||||
where: { name },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Ce nom de rôle existe déjà' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour le rôle
|
||||
const updatedRole = await prisma.role.update({
|
||||
where: { id: params.id },
|
||||
data: {
|
||||
name: name || role.name,
|
||||
description: description !== undefined ? description : role.description,
|
||||
},
|
||||
include: {
|
||||
permissions: {
|
||||
include: {
|
||||
permission: true,
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Mettre à jour les permissions si fournies
|
||||
if (permissionIds !== undefined) {
|
||||
// Supprimer toutes les permissions actuelles
|
||||
await prisma.rolePermission.deleteMany({
|
||||
where: { roleId: params.id },
|
||||
});
|
||||
|
||||
// Ajouter les nouvelles permissions
|
||||
if (permissionIds.length > 0) {
|
||||
await prisma.rolePermission.createMany({
|
||||
data: permissionIds.map((permissionId: string) => ({
|
||||
roleId: params.id,
|
||||
permissionId,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
// Récupérer le rôle mis à jour avec les nouvelles permissions
|
||||
const roleWithPermissions = await prisma.role.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
permissions: {
|
||||
include: {
|
||||
permission: true,
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(roleWithPermissions);
|
||||
}
|
||||
|
||||
return NextResponse.json(updatedRole);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la modification du rôle:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE - Supprimer un rôle
|
||||
export async function DELETE(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const role = await prisma.role.findUnique({
|
||||
where: { id: params.id },
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!role) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Rôle non trouvé' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si le rôle est utilisé
|
||||
if (role._count.users > 0) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Ce rôle est attribué à des utilisateurs. Veuillez d\'abord retirer le rôle de ces utilisateurs.' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
await prisma.role.delete({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la suppression du rôle:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
106
app/api/roles/route.ts
Normal file
106
app/api/roles/route.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// GET - Liste tous les rôles avec leurs permissions
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const roles = await prisma.role.findMany({
|
||||
include: {
|
||||
permissions: {
|
||||
include: {
|
||||
permission: true,
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc',
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(roles);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des rôles:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// POST - Créer un nouveau rôle
|
||||
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 { name, description, permissionIds } = body;
|
||||
|
||||
if (!name) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Le nom du rôle est requis' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si le rôle existe déjà
|
||||
const existing = await prisma.role.findUnique({
|
||||
where: { name },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Ce rôle existe déjà' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Créer le rôle avec ses permissions
|
||||
const role = await prisma.role.create({
|
||||
data: {
|
||||
name,
|
||||
description: description || null,
|
||||
permissions: permissionIds && permissionIds.length > 0
|
||||
? {
|
||||
create: permissionIds.map((permissionId: string) => ({
|
||||
permissionId,
|
||||
})),
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
include: {
|
||||
permissions: {
|
||||
include: {
|
||||
permission: true,
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(role, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la création du rôle:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
106
app/api/settings/adherent-options/[id]/route.ts
Normal file
106
app/api/settings/adherent-options/[id]/route.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// PUT - Modifier une option
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { value, order } = body;
|
||||
|
||||
if (!value) {
|
||||
return NextResponse.json(
|
||||
{ error: 'La valeur est requise' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si l'option existe
|
||||
const existing = await prisma.adherentOption.findUnique({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Option non trouvée' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si une autre option avec le même type et valeur existe
|
||||
const duplicate = await prisma.adherentOption.findFirst({
|
||||
where: {
|
||||
type: existing.type,
|
||||
value,
|
||||
id: { not: params.id },
|
||||
},
|
||||
});
|
||||
|
||||
if (duplicate) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Cette option existe déjà' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const option = await prisma.adherentOption.update({
|
||||
where: { id: params.id },
|
||||
data: {
|
||||
value,
|
||||
order: order !== undefined ? order : existing.order,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(option);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la modification de l\'option:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE - Supprimer une option
|
||||
export async function DELETE(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const option = await prisma.adherentOption.findUnique({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
if (!option) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Option non trouvée' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
await prisma.adherentOption.delete({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la suppression de l\'option:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
105
app/api/settings/adherent-options/route.ts
Normal file
105
app/api/settings/adherent-options/route.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// GET - Récupérer toutes les options par type
|
||||
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 type = searchParams.get('type'); // "situation", "prescripteur", "facturation"
|
||||
|
||||
const where: any = {};
|
||||
if (type) {
|
||||
where.type = type;
|
||||
}
|
||||
|
||||
const options = await prisma.adherentOption.findMany({
|
||||
where,
|
||||
orderBy: [
|
||||
{ type: 'asc' },
|
||||
{ order: 'asc' },
|
||||
{ value: 'asc' },
|
||||
],
|
||||
});
|
||||
|
||||
// Grouper par type
|
||||
const grouped = options.reduce((acc, option) => {
|
||||
if (!acc[option.type]) {
|
||||
acc[option.type] = [];
|
||||
}
|
||||
acc[option.type].push(option);
|
||||
return acc;
|
||||
}, {} as Record<string, typeof options>);
|
||||
|
||||
return NextResponse.json(type ? options : grouped);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des options:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// POST - Créer une nouvelle option
|
||||
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 { type, value, order } = body;
|
||||
|
||||
if (!type || !value) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Le type et la valeur sont requis' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
if (!['situation', 'prescripteur', 'facturation'].includes(type)) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Type invalide. Doit être: situation, prescripteur ou facturation' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si l'option existe déjà
|
||||
const existing = await prisma.adherentOption.findFirst({
|
||||
where: {
|
||||
type,
|
||||
value,
|
||||
},
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Cette option existe déjà' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const option = await prisma.adherentOption.create({
|
||||
data: {
|
||||
type,
|
||||
value,
|
||||
order: order || 0,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(option, { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la création de l\'option:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
21
app/api/user/pages/route.ts
Normal file
21
app/api/user/pages/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { getUserAccessiblePages } from '@/lib/permissions';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const accessiblePages = await getUserAccessiblePages(user.id);
|
||||
return NextResponse.json({ pages: accessiblePages });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des pages accessibles:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
74
app/api/users/[id]/role/route.ts
Normal file
74
app/api/users/[id]/role/route.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// PUT - Attribuer ou modifier le rôle d'un utilisateur
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const currentUser = await getCurrentUser();
|
||||
if (!currentUser) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { roleId } = body;
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Utilisateur non trouvé' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier que le rôle existe si fourni
|
||||
if (roleId) {
|
||||
const role = await prisma.role.findUnique({
|
||||
where: { id: roleId },
|
||||
});
|
||||
|
||||
if (!role) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Rôle non trouvé' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour le rôle de l'utilisateur
|
||||
const updatedUser = await prisma.user.update({
|
||||
where: { id: params.id },
|
||||
data: {
|
||||
roleId: roleId || null,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
roleId: true,
|
||||
role: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
description: true,
|
||||
},
|
||||
},
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(updatedUser);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de l\'attribution du rôle:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
93
app/api/users/[id]/route.ts
Normal file
93
app/api/users/[id]/route.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
// DELETE - Supprimer un utilisateur
|
||||
export async function DELETE(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const currentUser = await getCurrentUser();
|
||||
if (!currentUser) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
// Empêcher la suppression de son propre compte
|
||||
if (currentUser.id === params.id) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Vous ne pouvez pas supprimer votre propre compte' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Utilisateur non trouvé' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
await prisma.user.delete({
|
||||
where: { id: params.id },
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la suppression de l\'utilisateur:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// PUT - Réinitialiser le mot de passe d'un utilisateur
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const currentUser = await getCurrentUser();
|
||||
if (!currentUser) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { action } = body;
|
||||
|
||||
if (action === 'reset-password') {
|
||||
// Générer un nouveau mot de passe aléatoire
|
||||
const newPassword = Math.random().toString(36).slice(-12) + Math.random().toString(36).slice(-12);
|
||||
const hashedPassword = await bcrypt.hash(newPassword, 10);
|
||||
|
||||
await prisma.user.update({
|
||||
where: { id: params.id },
|
||||
data: {
|
||||
password: hashedPassword,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
newPassword, // Retourner le mot de passe en clair pour l'affichage
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: 'Action non reconnue' },
|
||||
{ status: 400 }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la réinitialisation du mot de passe:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
|
||||
// GET - Liste tous les utilisateurs (pour sélectionner des participants)
|
||||
// GET - Liste tous les utilisateurs
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
@@ -10,33 +10,32 @@ export async function GET(request: NextRequest) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
|
||||
}
|
||||
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const search = searchParams.get('search');
|
||||
|
||||
const where: any = {};
|
||||
if (search) {
|
||||
where.OR = [
|
||||
{ name: { contains: search } },
|
||||
{ email: { contains: search } },
|
||||
];
|
||||
}
|
||||
|
||||
const users = await prisma.user.findMany({
|
||||
where,
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
roleId: true,
|
||||
role: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
description: true,
|
||||
},
|
||||
},
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc',
|
||||
createdAt: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(users);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des utilisateurs:', error);
|
||||
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
|
||||
return NextResponse.json(
|
||||
{ error: 'Erreur serveur' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import AdherentsTable from '@/components/AdherentsTable';
|
||||
|
||||
@@ -10,6 +11,11 @@ export default async function AdherentsPage() {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/adherents');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<div className="p-6">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import { redirect } from 'next/navigation';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import ArchivesTrajets from '@/components/ArchivesTrajets';
|
||||
@@ -9,6 +10,11 @@ export default async function ArchivesPage() {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/archives');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<div className="p-8">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import CalendrierPageContent from '@/components/CalendrierPageContent';
|
||||
|
||||
@@ -10,6 +11,11 @@ export default async function CalendrierPage() {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/calendrier');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<div className="p-8">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import ChauffeursTable from '@/components/ChauffeursTable';
|
||||
|
||||
@@ -10,6 +11,11 @@ export default async function ChauffeursPage() {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/chauffeurs');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<div className="p-6">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import Messagerie from '@/components/Messagerie';
|
||||
|
||||
@@ -10,6 +11,11 @@ export default async function MessageriePage() {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/messagerie');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<div className="h-full">
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import DashboardContent from '@/components/DashboardContent';
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const user = await getCurrentUser();
|
||||
@@ -9,46 +11,15 @@ export default async function DashboardPage() {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
// Vérifier les permissions
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres'); // Rediriger vers une page accessible ou afficher une erreur
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<div className="p-6">
|
||||
<h1 className="text-3xl font-semibold text-cblack mb-1">
|
||||
Content de vous revoir <span className="text-dyellow">{user.name || user.email}</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-sm text-cgray mb-6">
|
||||
Bienvenue sur votre tableau de bord.
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Bienvenue
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
{user.name || user.email}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Statistiques
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
Contenu à venir
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Activité récente
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
Contenu à venir
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DashboardContent userName={user.name} />
|
||||
</DashboardLayout>
|
||||
);
|
||||
}
|
||||
|
||||
24
app/dashboard/parametres/configuration/page.tsx
Normal file
24
app/dashboard/parametres/configuration/page.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import ConfigurationContent from '@/components/ConfigurationContent';
|
||||
|
||||
export default async function ConfigurationPage() {
|
||||
const user = await getCurrentUser();
|
||||
|
||||
if (!user) {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/parametres/configuration');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<ConfigurationContent />
|
||||
</DashboardLayout>
|
||||
);
|
||||
}
|
||||
24
app/dashboard/parametres/page.tsx
Normal file
24
app/dashboard/parametres/page.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import ParametresContent from '@/components/ParametresContent';
|
||||
|
||||
export default async function ParametresPage() {
|
||||
const user = await getCurrentUser();
|
||||
|
||||
if (!user) {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/parametres');
|
||||
if (!hasAccess) {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<ParametresContent />
|
||||
</DashboardLayout>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getCurrentUser } from '@/lib/auth';
|
||||
import { hasPageAccess } from '@/lib/permissions';
|
||||
import DashboardLayout from '@/components/DashboardLayout';
|
||||
import UniversProTable from '@/components/UniversProTable';
|
||||
|
||||
@@ -10,6 +11,11 @@ export default async function UniversProPage() {
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
const hasAccess = await hasPageAccess(user.id, '/dashboard/univers-pro');
|
||||
if (!hasAccess) {
|
||||
redirect('/dashboard/parametres');
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardLayout user={user}>
|
||||
<div className="p-6">
|
||||
|
||||
Reference in New Issue
Block a user