correct user settings manager (and password reset)

This commit is contained in:
LathanDevers
2026-08-04 16:51:00 +02:00
parent 84d7b7e847
commit 85adfaab2d
11 changed files with 339 additions and 78 deletions
@@ -0,0 +1,145 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { KeyRound, AlertCircle, ShieldCheck } from "lucide-react";
import { Card } from '@/components/ui/Card';
import { Input } from '@/components/ui/Input';
import { Button } from '@/components/ui/Button';
import { pb } from '@/services/pocketbase';
import BackButton from '@/components/ui/BackButton';
import { NEUMORPHISM } from '@/styles/Neumorphism';
export default function UpdatePasswordPage() {
const navigate = useNavigate();
const [isUpdating, setIsUpdating] = useState(false);
const [feedback, setFeedback] = useState<{ type: 'error' | 'success', message: string } | null>(null);
const [formData, setFormData] = useState({
oldPassword: '',
newPassword: '',
confirmPassword: ''
});
const handlePasswordChange = async (e: React.FormEvent) => {
e.preventDefault();
setIsUpdating(true);
setFeedback(null);
if (formData.newPassword !== formData.confirmPassword) {
setFeedback({ type: 'error', message: "Les nouveaux mots de passe ne correspondent pas." });
setIsUpdating(false);
return;
}
if (formData.newPassword.length < 8) {
setFeedback({ type: 'error', message: "Le mot de passe doit contenir au moins 8 caractères minimum." });
setIsUpdating(false);
return;
}
try {
const userId = pb.authStore.model?.id;
if (!userId) throw new Error("Non authentifié.");
await pb.collection("users").update(userId, {
oldPassword: formData.oldPassword,
password: formData.newPassword,
passwordConfirm: formData.confirmPassword,
});
setFeedback({ type: 'success', message: "Votre mot de passe a été modifié avec succès." });
setFormData({ oldPassword: '', newPassword: '', confirmPassword: '' });
// Retour automatique après 2.5 secondes
setTimeout(() => navigate(-1), 2500);
} catch {
setFeedback({ type: 'error', message: "Ancien mot de passe incorrect ou erreur réseau." });
} finally {
setIsUpdating(false);
}
};
const insetNeu = "shadow-[inset_2px_2px_4px_#c5c5c5,inset_-2px_-2px_4px_#ffffff] dark:shadow-[inset_2px_2px_4px_#121926,inset_-2px_-2px_4px_#2a3850]";
return (
<div className="max-w-4xl mx-auto py-8 px-4 space-y-6">
{/* BOUTON DE RETOUR EXTRAIT */}
<BackButton to="/account" label="Retour aux paramètres" />
{/* LE FORMULAIRE */}
<Card className="p-8 sm:p-10">
<div className="flex items-center gap-4 mb-8 pb-6 border-b border-slate-300/30 dark:border-slate-700/30">
<div className="p-4 rounded-2xl bg-[#e8e8e8] dark:bg-[#1e293b] shadow-[3px_3px_6px_#c5c5c5,-3px_-3px_6px_#ffffff] dark:shadow-[3px_3px_6px_#121926,-3px_-3px_6px_#2a3850]">
<KeyRound className="w-8 h-8 text-slate-700 dark:text-slate-200" />
</div>
<div>
<h1 className="text-2xl font-black text-slate-800 dark:text-slate-100 tracking-tight">
Renouvellement du mot de passe
</h1>
<p className="text-slate-500 dark:text-slate-400 font-medium mt-1">
Veuillez choisir un mot de passe fort et unique pour sécuriser votre accès AEGIS.
</p>
</div>
</div>
<form onSubmit={handlePasswordChange} className="space-y-6">
<div className="space-y-2">
<Input
label="Mot de passe actuel"
type="password"
required
placeholder="••••••••"
value={formData.oldPassword}
onChange={(e) => setFormData({ ...formData, oldPassword: e.target.value })}
/>
</div>
<div className="grid sm:grid-cols-2 gap-6 pt-4">
<Input
label="Nouveau mot de passe"
type="password"
required
placeholder="••••••••"
value={formData.newPassword}
onChange={(e) => setFormData({ ...formData, newPassword: e.target.value })}
/>
<Input
label="Confirmez le nouveau mot de passe"
type="password"
required
placeholder="••••••••"
value={formData.confirmPassword}
onChange={(e) => setFormData({ ...formData, confirmPassword: e.target.value })}
/>
</div>
{/* Zone de Feedback */}
{feedback && (
<div className={`p-4 mt-4 rounded-xl flex items-center gap-3 text-sm font-bold ${feedback.type === 'error'
? `bg-rose-50/50 dark:bg-rose-950/20 text-rose-600 dark:text-rose-400 ${NEUMORPHISM.insetLight} ${NEUMORPHISM.insetDark}`
: `bg-emerald-50/50 dark:bg-emerald-950/20 text-emerald-600 dark:text-emerald-400 ${NEUMORPHISM.insetLight} ${NEUMORPHISM.insetDark}`
}`}>
{feedback.type === 'error' ? <AlertCircle className="w-5 h-5 shrink-0" /> : <ShieldCheck className="w-5 h-5 shrink-0" />}
{feedback.message}
{feedback.type === 'success' && <span className="ml-auto font-normal text-xs animate-pulse">Redirection...</span>}
</div>
)}
<div className="pt-6 flex justify-center">
<Button
type="submit"
variant="primary"
size="lg"
isLoading={isUpdating}
disabled={!formData.oldPassword || !formData.newPassword || !formData.confirmPassword}
>
Valider le nouveau mot de passe
</Button>
</div>
</form>
</Card>
</div>
);
}