- Events: {preferences?.eventsBackground || "Par défaut"}
+
+
+ Events:
+
+ {preferences?.eventsBackground ? (
+
+

{
+ e.currentTarget.src = "/got-2.jpg";
+ }}
+ />
+
+ {preferences.eventsBackground}
+
+
+ ) : (
+
Par défaut
+ )}
-
- Leaderboard:{" "}
- {preferences?.leaderboardBackground || "Par défaut"}
+
+
+ Leaderboard:
+
+ {preferences?.leaderboardBackground ? (
+
+

{
+ e.currentTarget.src = "/got-2.jpg";
+ }}
+ />
+
+ {preferences.leaderboardBackground}
+
+
+ ) : (
+
Par défaut
+ )}
)}
diff --git a/app/api/profile/password/route.ts b/app/api/profile/password/route.ts
new file mode 100644
index 0000000..a6cf37a
--- /dev/null
+++ b/app/api/profile/password/route.ts
@@ -0,0 +1,80 @@
+import { NextResponse } from "next/server";
+import { auth } from "@/lib/auth";
+import { prisma } from "@/lib/prisma";
+import bcrypt from "bcryptjs";
+
+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;
+
+ // Validation
+ if (!currentPassword || !newPassword || !confirmPassword) {
+ return NextResponse.json(
+ { error: "Tous les champs sont requis" },
+ { status: 400 }
+ );
+ }
+
+ if (newPassword.length < 6) {
+ return NextResponse.json(
+ { error: "Le nouveau mot de passe doit contenir au moins 6 caractères" },
+ { status: 400 }
+ );
+ }
+
+ if (newPassword !== confirmPassword) {
+ return NextResponse.json(
+ { error: "Les mots de passe ne correspondent pas" },
+ { status: 400 }
+ );
+ }
+
+ // Récupérer l'utilisateur avec le mot de passe
+ const user = await prisma.user.findUnique({
+ where: { id: session.user.id },
+ select: { password: true },
+ });
+
+ if (!user) {
+ return NextResponse.json(
+ { error: "Utilisateur non trouvé" },
+ { status: 404 }
+ );
+ }
+
+ // Vérifier l'ancien mot de passe
+ const isPasswordValid = await bcrypt.compare(currentPassword, user.password);
+
+ if (!isPasswordValid) {
+ return NextResponse.json(
+ { error: "Mot de passe actuel incorrect" },
+ { status: 400 }
+ );
+ }
+
+ // Hasher le nouveau mot de passe
+ const hashedPassword = await bcrypt.hash(newPassword, 10);
+
+ // Mettre à jour le mot de passe
+ await prisma.user.update({
+ where: { id: session.user.id },
+ data: { password: hashedPassword },
+ });
+
+ return NextResponse.json({ message: "Mot de passe modifié avec succès" });
+ } catch (error) {
+ console.error("Error updating password:", error);
+ return NextResponse.json(
+ { error: "Erreur lors de la modification du mot de passe" },
+ { status: 500 }
+ );
+ }
+}
+
diff --git a/app/profile/page.tsx b/app/profile/page.tsx
index 7a12a54..1acbe1f 100644
--- a/app/profile/page.tsx
+++ b/app/profile/page.tsx
@@ -38,6 +38,13 @@ export default function ProfilePage() {
const [avatar, setAvatar] = useState
(null);
const fileInputRef = useRef(null);
const [uploadingAvatar, setUploadingAvatar] = useState(false);
+
+ // Password change form state
+ const [showPasswordForm, setShowPasswordForm] = useState(false);
+ const [currentPassword, setCurrentPassword] = useState("");
+ const [newPassword, setNewPassword] = useState("");
+ const [confirmPassword, setConfirmPassword] = useState("");
+ const [changingPassword, setChangingPassword] = useState(false);
useEffect(() => {
if (status === "unauthenticated") {
@@ -140,6 +147,44 @@ export default function ProfilePage() {
}
};
+ const handlePasswordChange = async (e: React.FormEvent) => {
+ e.preventDefault();
+ setChangingPassword(true);
+ setError(null);
+ setSuccess(null);
+
+ try {
+ const response = await fetch("/api/profile/password", {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ currentPassword,
+ newPassword,
+ confirmPassword,
+ }),
+ });
+
+ if (response.ok) {
+ setSuccess("Mot de passe modifié avec succès");
+ setCurrentPassword("");
+ setNewPassword("");
+ setConfirmPassword("");
+ setShowPasswordForm(false);
+ setTimeout(() => setSuccess(null), 3000);
+ } else {
+ const errorData = await response.json();
+ setError(errorData.error || "Erreur lors de la modification du mot de passe");
+ }
+ } catch (err) {
+ console.error("Error changing password:", err);
+ setError("Erreur lors de la modification du mot de passe");
+ } finally {
+ setChangingPassword(false);
+ }
+ };
+
if (loading || status === "loading") {
return (
@@ -356,6 +401,95 @@ export default function ProfilePage() {
+
+ {/* Password Change Section - Separate form */}
+
+
+
+ Mot de passe
+
+ {!showPasswordForm && (
+
+ )}
+
+
+ {showPasswordForm && (
+
+ )}
+