Refactor API routes and component logic: Remove unused event and user management routes, streamline feedback handling in components, and enhance state management with transitions for improved user experience. Update service layer methods for better organization and maintainability across the application.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m38s

This commit is contained in:
Julien Froidefond
2025-12-12 16:28:07 +01:00
parent 494ac3f503
commit db01c25de7
26 changed files with 747 additions and 743 deletions

View File

@@ -1,84 +0,0 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { eventService } from "@/services/events/event.service";
import { Role } from "@/prisma/generated/prisma/client";
import { ValidationError, NotFoundError } from "@/services/errors";
export async function PUT(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user || session.user.role !== Role.ADMIN) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
const { id } = await params;
const body = await request.json();
const { date, name, description, type, room, time, maxPlaces } = body;
// Le statut est ignoré s'il est fourni, il sera calculé automatiquement
const event = await eventService.validateAndUpdateEvent(id, {
date,
name,
description,
type,
room,
time,
maxPlaces,
});
return NextResponse.json(event);
} catch (error) {
console.error("Error updating event:", error);
if (error instanceof ValidationError) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
if (error instanceof NotFoundError) {
return NextResponse.json({ error: error.message }, { status: 404 });
}
return NextResponse.json(
{ error: "Erreur lors de la mise à jour de l'événement" },
{ status: 500 }
);
}
}
export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user || session.user.role !== Role.ADMIN) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
const { id } = await params;
// Vérifier que l'événement existe
const existingEvent = await eventService.getEventById(id);
if (!existingEvent) {
return NextResponse.json(
{ error: "Événement non trouvé" },
{ status: 404 }
);
}
await eventService.deleteEvent(id);
return NextResponse.json({ success: true });
} catch (error) {
console.error("Error deleting event:", error);
return NextResponse.json(
{ error: "Erreur lors de la suppression de l'événement" },
{ status: 500 }
);
}
}

View File

@@ -2,7 +2,6 @@ import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { eventService } from "@/services/events/event.service";
import { Role } from "@/prisma/generated/prisma/client";
import { ValidationError } from "@/services/errors";
export async function GET() {
try {
@@ -40,38 +39,3 @@ export async function GET() {
}
}
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 body = await request.json();
const { date, name, description, type, room, time, maxPlaces } = body;
const event = await eventService.validateAndCreateEvent({
date,
name,
description,
type,
room,
time,
maxPlaces,
});
return NextResponse.json(event);
} catch (error) {
console.error("Error creating event:", error);
if (error instanceof ValidationError) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
return NextResponse.json(
{ error: "Erreur lors de la création de l'événement" },
{ status: 500 }
);
}
}

View File

@@ -23,30 +23,3 @@ export async function GET() {
);
}
}
export async function PUT(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 body = await request.json();
const { homeBackground, eventsBackground, leaderboardBackground } = body;
const preferences = await sitePreferencesService.updateSitePreferences({
homeBackground,
eventsBackground,
leaderboardBackground,
});
return NextResponse.json(preferences);
} catch (error) {
console.error("Error updating admin preferences:", error);
return NextResponse.json(
{ error: "Erreur lors de la mise à jour des préférences" },
{ status: 500 }
);
}
}

View File

@@ -1,102 +0,0 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { userService } from "@/services/users/user.service";
import { userStatsService } from "@/services/users/user-stats.service";
import { Role } from "@/prisma/generated/prisma/client";
import {
ValidationError,
NotFoundError,
ConflictError,
} from "@/services/errors";
export async function PUT(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user || session.user.role !== Role.ADMIN) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
const { id } = await params;
const body = await request.json();
const { username, avatar, hpDelta, xpDelta, score, level, role } = body;
// Valider username si fourni
if (username !== undefined) {
try {
await userService.validateAndUpdateUserProfile(id, { username });
} catch (error) {
if (
error instanceof ValidationError ||
error instanceof ConflictError
) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
throw error;
}
}
// Mettre à jour stats et profil
const updatedUser = await userStatsService.updateUserStatsAndProfile(
id,
{ username, avatar, hpDelta, xpDelta, score, level, role },
{
id: true,
username: true,
email: true,
role: true,
score: true,
level: true,
hp: true,
maxHp: true,
xp: true,
maxXp: true,
avatar: true,
}
);
return NextResponse.json(updatedUser);
} catch (error) {
console.error("Error updating user:", error);
return NextResponse.json(
{ error: "Erreur lors de la mise à jour de l'utilisateur" },
{ status: 500 }
);
}
}
export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user || session.user.role !== Role.ADMIN) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
const { id } = await params;
await userService.validateAndDeleteUser(id, session.user.id);
return NextResponse.json({ success: true });
} catch (error) {
console.error("Error deleting user:", error);
if (error instanceof ValidationError) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
if (error instanceof NotFoundError) {
return NextResponse.json({ error: error.message }, { status: 404 });
}
return NextResponse.json(
{ error: "Erreur lors de la suppression de l'utilisateur" },
{ status: 500 }
);
}
}

View File

@@ -1,88 +1,7 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { eventRegistrationService } from "@/services/events/event-registration.service";
import {
ValidationError,
NotFoundError,
ConflictError,
} from "@/services/errors";
export async function POST(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json(
{ error: "Vous devez être connecté pour vous inscrire" },
{ status: 401 }
);
}
const { id: eventId } = await params;
const registration = await eventRegistrationService.validateAndRegisterUser(
session.user.id,
eventId
);
return NextResponse.json(
{ message: "Inscription réussie", registration },
{ status: 201 }
);
} catch (error) {
console.error("Registration error:", error);
if (
error instanceof ValidationError ||
error instanceof ConflictError
) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
if (error instanceof NotFoundError) {
return NextResponse.json({ error: error.message }, { status: 404 });
}
return NextResponse.json(
{ error: "Une erreur est survenue lors de l'inscription" },
{ status: 500 }
);
}
}
export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json(
{ error: "Vous devez être connecté" },
{ status: 401 }
);
}
const { id: eventId } = await params;
// Supprimer l'inscription
await eventRegistrationService.unregisterUserFromEvent(
session.user.id,
eventId
);
return NextResponse.json({ message: "Inscription annulée" });
} catch (error) {
console.error("Unregistration error:", error);
return NextResponse.json(
{ error: "Une erreur est survenue lors de l'annulation" },
{ status: 500 }
);
}
}
export async function GET(
request: Request,

View File

@@ -1,48 +1,7 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { eventFeedbackService } from "@/services/events/event-feedback.service";
import {
ValidationError,
NotFoundError,
} from "@/services/errors";
export async function POST(
request: Request,
{ params }: { params: Promise<{ eventId: string }> }
) {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
}
const { eventId } = await params;
const body = await request.json();
const { rating, comment } = body;
const feedback = await eventFeedbackService.validateAndCreateFeedback(
session.user.id,
eventId,
{ rating, comment }
);
return NextResponse.json({ success: true, feedback });
} catch (error) {
console.error("Error saving feedback:", error);
if (error instanceof ValidationError) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
if (error instanceof NotFoundError) {
return NextResponse.json({ error: error.message }, { status: 404 });
}
return NextResponse.json(
{ error: "Erreur lors de l'enregistrement du feedback" },
{ status: 500 }
);
}
}
export async function GET(
request: Request,

View File

@@ -1,40 +0,0 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { userService } from "@/services/users/user.service";
import { ValidationError, NotFoundError } from "@/services/errors";
export async function PUT(request: Request) {
try {
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
}
const body = await request.json();
const { currentPassword, newPassword, confirmPassword } = body;
await userService.validateAndUpdatePassword(
session.user.id,
currentPassword,
newPassword,
confirmPassword
);
return NextResponse.json({ message: "Mot de passe modifié avec succès" });
} catch (error) {
console.error("Error updating password:", error);
if (error instanceof ValidationError) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
if (error instanceof NotFoundError) {
return NextResponse.json({ error: error.message }, { status: 404 });
}
return NextResponse.json(
{ error: "Erreur lors de la modification du mot de passe" },
{ status: 500 }
);
}
}

View File

@@ -1,11 +1,6 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { userService } from "@/services/users/user.service";
import {
ValidationError,
ConflictError,
NotFoundError,
} from "@/services/errors";
export async function GET() {
try {
@@ -48,47 +43,3 @@ export async function GET() {
}
}
export async function PUT(request: Request) {
try {
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
}
const body = await request.json();
const { username, avatar, bio, characterClass } = body;
const updatedUser = await userService.validateAndUpdateUserProfile(
session.user.id,
{ username, avatar, bio, characterClass },
{
id: true,
email: true,
username: true,
avatar: true,
bio: true,
characterClass: true,
hp: true,
maxHp: true,
xp: true,
maxXp: true,
level: true,
score: true,
}
);
return NextResponse.json(updatedUser);
} catch (error) {
console.error("Error updating profile:", error);
if (error instanceof ValidationError || error instanceof ConflictError) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
return NextResponse.json(
{ error: "Erreur lors de la mise à jour du profil" },
{ status: 500 }
);
}
}

View File

@@ -1,9 +1,10 @@
"use client";
import { useState, useEffect, type FormEvent } from "react";
import { useState, useEffect, useTransition, type FormEvent } from "react";
import { useSession } from "next-auth/react";
import { useRouter, useParams } from "next/navigation";
import Navigation from "@/components/Navigation";
import { createFeedback } from "@/actions/events/feedback";
interface Event {
id: string;
@@ -38,6 +39,7 @@ export default function FeedbackPageClient({
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
const [, startTransition] = useTransition();
const [rating, setRating] = useState(0);
const [comment, setComment] = useState("");
@@ -95,37 +97,38 @@ export default function FeedbackPageClient({
setSubmitting(true);
try {
const response = await fetch(`/api/feedback/${eventId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
startTransition(async () => {
try {
const result = await createFeedback(eventId, {
rating,
comment: comment.trim() || null,
}),
});
});
const data = await response.json();
if (!result.success) {
setError(result.error || "Erreur lors de l'enregistrement");
setSubmitting(false);
return;
}
if (!response.ok) {
setError(data.error || "Erreur lors de l&apos;enregistrement");
return;
setSuccess(true);
if (result.data) {
setExistingFeedback({
id: result.data.id,
rating: result.data.rating,
comment: result.data.comment,
});
}
// Rediriger après 2 secondes
setTimeout(() => {
router.push("/events");
}, 2000);
} catch {
setError("Erreur lors de l'enregistrement");
} finally {
setSubmitting(false);
}
setSuccess(true);
setExistingFeedback(data.feedback);
// Rediriger après 2 secondes
setTimeout(() => {
router.push("/events");
}, 2000);
} catch {
setError("Erreur lors de l&apos;enregistrement");
} finally {
setSubmitting(false);
}
});
};
if (status === "loading" || loading) {
@@ -262,4 +265,3 @@ export default function FeedbackPageClient({
</main>
);
}