Refactor admin preferences management to use global site preferences, update UI components for better user experience, and implement image selection for background settings.

This commit is contained in:
Julien Froidefond
2025-12-09 08:37:52 +01:00
parent 4486f305f2
commit 8c326bdd20
21 changed files with 1853 additions and 199 deletions

View File

@@ -0,0 +1,48 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { Role } from "@/prisma/generated/prisma/client";
import { readdir } from "fs/promises";
import { join } from "path";
import { existsSync } from "fs";
export async function GET() {
try {
const session = await auth();
if (!session?.user || session.user.role !== Role.ADMIN) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
const images: string[] = [];
// Lister les images dans public/
const publicDir = join(process.cwd(), "public");
if (existsSync(publicDir)) {
const files = await readdir(publicDir);
const imageFiles = files.filter(
(file) =>
file.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i) && !file.startsWith(".")
);
images.push(...imageFiles.map((file) => `/${file}`));
}
// Lister les images dans public/uploads/
const uploadsDir = join(publicDir, "uploads");
if (existsSync(uploadsDir)) {
const uploadFiles = await readdir(uploadsDir);
const imageFiles = uploadFiles.filter((file) =>
file.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i)
);
images.push(...imageFiles.map((file) => `/uploads/${file}`));
}
return NextResponse.json({ images });
} catch (error) {
console.error("Error listing images:", error);
return NextResponse.json(
{ error: "Erreur lors de la récupération des images" },
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,58 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { Role } from "@/prisma/generated/prisma/client";
import { writeFile, mkdir } from "fs/promises";
import { join } from "path";
import { existsSync } from "fs";
export async function POST(request: Request) {
try {
const session = await auth();
if (!session?.user || session.user.role !== Role.ADMIN) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
const formData = await request.formData();
const file = formData.get("file") as File;
if (!file) {
return NextResponse.json({ error: "Aucun fichier fourni" }, { status: 400 });
}
// Vérifier le type de fichier
if (!file.type.startsWith("image/")) {
return NextResponse.json(
{ error: "Le fichier doit être une image" },
{ status: 400 }
);
}
// Créer le dossier uploads s'il n'existe pas
const uploadsDir = join(process.cwd(), "public", "uploads");
if (!existsSync(uploadsDir)) {
await mkdir(uploadsDir, { recursive: true });
}
// Générer un nom de fichier unique
const timestamp = Date.now();
const filename = `${timestamp}-${file.name}`;
const filepath = join(uploadsDir, filename);
// Convertir le fichier en buffer et l'écrire
const bytes = await file.arrayBuffer();
const buffer = Buffer.from(bytes);
await writeFile(filepath, buffer);
// Retourner l'URL de l'image
const imageUrl = `/uploads/${filename}`;
return NextResponse.json({ url: imageUrl });
} catch (error) {
console.error("Error uploading image:", error);
return NextResponse.json(
{ error: "Erreur lors de l'upload de l'image" },
{ status: 500 }
);
}
}

View File

@@ -11,20 +11,24 @@ export async function GET() {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
// Récupérer toutes les préférences utilisateur
const preferences = await prisma.userPreferences.findMany({
include: {
user: {
select: {
id: true,
username: true,
email: true,
},
},
},
// Récupérer les préférences globales du site
let sitePreferences = await prisma.sitePreferences.findUnique({
where: { id: "global" },
});
return NextResponse.json(preferences);
// Si elles n'existent pas, créer une entrée par défaut
if (!sitePreferences) {
sitePreferences = await prisma.sitePreferences.create({
data: {
id: "global",
homeBackground: null,
eventsBackground: null,
leaderboardBackground: null,
},
});
}
return NextResponse.json(sitePreferences);
} catch (error) {
console.error("Error fetching admin preferences:", error);
return NextResponse.json(
@@ -43,25 +47,27 @@ export async function PUT(request: Request) {
}
const body = await request.json();
const { userId, homeBackground, eventsBackground, leaderboardBackground } =
body;
const { homeBackground, eventsBackground, leaderboardBackground } = body;
if (!userId) {
return NextResponse.json({ error: "userId requis" }, { status: 400 });
}
const preferences = await prisma.userPreferences.upsert({
where: { userId },
const preferences = await prisma.sitePreferences.upsert({
where: { id: "global" },
update: {
homeBackground: homeBackground ?? undefined,
eventsBackground: eventsBackground ?? undefined,
leaderboardBackground: leaderboardBackground ?? undefined,
homeBackground:
homeBackground === "" ? null : homeBackground ?? undefined,
eventsBackground:
eventsBackground === "" ? null : eventsBackground ?? undefined,
leaderboardBackground:
leaderboardBackground === ""
? null
: leaderboardBackground ?? undefined,
},
create: {
userId,
homeBackground: homeBackground ?? null,
eventsBackground: eventsBackground ?? null,
leaderboardBackground: leaderboardBackground ?? null,
id: "global",
homeBackground: homeBackground === "" ? null : homeBackground ?? null,
eventsBackground:
eventsBackground === "" ? null : eventsBackground ?? null,
leaderboardBackground:
leaderboardBackground === "" ? null : leaderboardBackground ?? null,
},
});