"use client"; import { useState } from "react"; import { Eye, EyeOff, Lock, Check, KeyRound } from "lucide-react"; import Modal from "../ui/Modal"; import Button from "../ui/Button"; import toast from "react-hot-toast"; interface ChangePasswordModalProps { isOpen: boolean; onClose: () => void; } function strength(pwd: string): { score: number; label: string; bar: string } { if (!pwd) return { score: 0, label: "", bar: "bg-gray-300" }; let s = 0; if (pwd.length >= 8) s++; if (pwd.length >= 12) s++; if (/[A-Z]/.test(pwd) && /[a-z]/.test(pwd)) s++; if (/\d/.test(pwd)) s++; if (/[^A-Za-z0-9]/.test(pwd)) s++; const labels = ["", "Très faible", "Faible", "Moyen", "Bon", "Excellent"]; const bars = ["bg-gray-300", "bg-rose-500", "bg-orange-500", "bg-amber-500", "bg-emerald-500", "bg-emerald-500"]; return { score: s, label: labels[s], bar: bars[s] }; } function Field({ label, value, onChange, show, onToggle, placeholder, autoFocus, extraClass = "", onEnter, showToggle = true, trailing, }: { label: string; value: string; onChange: (v: string) => void; show?: boolean; onToggle?: () => void; placeholder: string; autoFocus?: boolean; extraClass?: string; onEnter?: () => void; showToggle?: boolean; trailing?: React.ReactNode; }): React.ReactElement { return (
onChange(e.target.value)} onKeyDown={(e) => e.key === "Enter" && onEnter?.()} placeholder={placeholder} className={`field pl-10 pr-11 h-11 ${extraClass}`} autoFocus={autoFocus} autoComplete={label.includes("actuel") ? "current-password" : "new-password"} /> {trailing} {showToggle && onToggle && ( )}
); } export default function ChangePasswordModal({ isOpen, onClose }: ChangePasswordModalProps) { const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [showCurrent, setShowCurrent] = useState(false); const [showNew, setShowNew] = useState(false); const [loading, setLoading] = useState(false); const handleClose = () => { setCurrentPassword(""); setNewPassword(""); setConfirmPassword(""); setShowCurrent(false); setShowNew(false); onClose(); }; const passwordsMatch = newPassword && confirmPassword && newPassword === confirmPassword; const newPasswordValid = newPassword.length >= 6; const canSubmit = currentPassword && newPasswordValid && passwordsMatch; const st = strength(newPassword); const handleSubmit = async () => { if (!canSubmit) return; setLoading(true); try { const res = await fetch("/api/auth/change-password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ currentPassword, newPassword }), }); const data = await res.json(); if (res.ok) { toast.success("Mot de passe modifié avec succès"); handleClose(); } else { toast.error(data.error || "Erreur"); } } catch { toast.error("Erreur réseau"); } finally { setLoading(false); } }; return ( } >
setShowCurrent(!showCurrent)} placeholder="••••••••" autoFocus />
setShowNew(!showNew)} placeholder="Min. 6 caractères" extraClass={newPassword && !newPasswordValid ? "!border-rose-400" : ""} /> {newPassword && (
{Array.from({ length: 5 }).map((_, i) => ( ))}
{st.label}
)} {newPassword && !newPasswordValid &&

Au moins 6 caractères requis

}
: undefined} /> {confirmPassword && !passwordsMatch &&

Les mots de passe ne correspondent pas

}
); }