Refactor Header component to improve code readability by formatting Link elements and adding a new settings link for user navigation.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m12s

This commit is contained in:
Julien Froidefond
2026-02-20 13:31:23 +01:00
parent e30cfedea8
commit 65fee6baf7
3 changed files with 218 additions and 6 deletions

129
src/app/settings/page.tsx Normal file
View File

@@ -0,0 +1,129 @@
"use client";
import { useState } from "react";
import Link from "next/link";
export default function SettingsPage() {
const [currentPassword, setCurrentPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setError("");
setSuccess(false);
if (newPassword !== confirmPassword) {
setError("Les deux nouveaux mots de passe ne correspondent pas");
return;
}
if (newPassword.length < 8) {
setError("Le mot de passe doit faire au moins 8 caractères");
return;
}
setLoading(true);
try {
const res = await fetch("/api/users/me/password", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
currentPassword,
newPassword,
}),
});
const data = await res.json();
if (!res.ok) {
setError(data.error ?? "Erreur");
return;
}
setSuccess(true);
setCurrentPassword("");
setNewPassword("");
setConfirmPassword("");
} catch {
setError("Erreur de connexion");
} finally {
setLoading(false);
}
}
return (
<div className="mx-auto max-w-md">
<h1 className="mb-6 font-mono text-lg font-medium text-zinc-800 dark:text-zinc-100">
Paramètres
</h1>
<section className="rounded-lg border border-zinc-200 dark:border-zinc-600 bg-white dark:bg-zinc-800/50 p-4">
<h2 className="mb-4 font-mono text-sm font-medium text-zinc-700 dark:text-zinc-300">
Changer mon mot de passe
</h2>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label className="mb-1 block font-mono text-xs text-zinc-600 dark:text-zinc-400">
Mot de passe actuel
</label>
<input
type="password"
value={currentPassword}
onChange={(e) => setCurrentPassword(e.target.value)}
required
autoComplete="current-password"
className="w-full rounded border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:border-cyan-500 focus:ring-1 focus:ring-cyan-500/30"
/>
</div>
<div>
<label className="mb-1 block font-mono text-xs text-zinc-600 dark:text-zinc-400">
Nouveau mot de passe
</label>
<input
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
required
minLength={8}
autoComplete="new-password"
className="w-full rounded border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:border-cyan-500 focus:ring-1 focus:ring-cyan-500/30"
/>
</div>
<div>
<label className="mb-1 block font-mono text-xs text-zinc-600 dark:text-zinc-400">
Confirmer le nouveau mot de passe
</label>
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
minLength={8}
autoComplete="new-password"
className="w-full rounded border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 focus:border-cyan-500 focus:ring-1 focus:ring-cyan-500/30"
/>
</div>
{error && (
<p className="font-mono text-xs text-red-500">{error}</p>
)}
{success && (
<p className="font-mono text-xs text-emerald-600 dark:text-emerald-400">
Mot de passe modifié.
</p>
)}
<button
type="submit"
disabled={loading}
className="rounded border border-cyan-500/50 bg-cyan-500/10 px-3 py-2 font-mono text-sm text-cyan-600 dark:text-cyan-400 hover:bg-cyan-500/20 disabled:opacity-50"
>
{loading ? "..." : "Modifier le mot de passe"}
</button>
</form>
</section>
<p className="mt-6 font-mono text-xs text-zinc-500 dark:text-zinc-400">
<Link href="/dashboard" className="text-cyan-600 dark:text-cyan-400 hover:underline">
Retour au dashboard
</Link>
</p>
</div>
);
}