Files
fintrack/components/settings/password-card.tsx

204 lines
7.0 KiB
TypeScript

"use client";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Lock, Eye, EyeOff } from "lucide-react";
import { toast } from "sonner";
export function PasswordCard() {
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [showOldPassword, setShowOldPassword] = useState(false);
const [showNewPassword, setShowNewPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [loading, setLoading] = useState(false);
const [open, setOpen] = useState(false);
const handleChangePassword = async () => {
if (!oldPassword || !newPassword || !confirmPassword) {
toast.error("Veuillez remplir tous les champs");
return;
}
if (newPassword.length < 4) {
toast.error("Le mot de passe doit contenir au moins 4 caractères");
return;
}
if (newPassword !== confirmPassword) {
toast.error("Les mots de passe ne correspondent pas");
return;
}
setLoading(true);
try {
const response = await fetch("/api/auth/change-password", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
oldPassword,
newPassword,
}),
});
const data = await response.json();
if (data.success) {
toast.success("Mot de passe modifié avec succès");
setOldPassword("");
setNewPassword("");
setConfirmPassword("");
setOpen(false);
} else {
toast.error(data.error || "Erreur lors du changement de mot de passe");
}
} catch (error) {
console.error("Error changing password:", error);
toast.error("Erreur lors du changement de mot de passe");
} finally {
setLoading(false);
}
};
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Lock className="w-5 h-5" />
Mot de passe
</CardTitle>
<CardDescription>
Modifiez le mot de passe d'accès à l'application
</CardDescription>
</CardHeader>
<CardContent>
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogTrigger asChild>
<Button variant="outline">Changer le mot de passe</Button>
</AlertDialogTrigger>
<AlertDialogContent className="sm:max-w-md">
<AlertDialogHeader>
<AlertDialogTitle>Changer le mot de passe</AlertDialogTitle>
<AlertDialogDescription>
Entrez votre mot de passe actuel et le nouveau mot de passe.
</AlertDialogDescription>
</AlertDialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="old-password">Mot de passe actuel</Label>
<div className="relative">
<Input
id="old-password"
type={showOldPassword ? "text" : "password"}
value={oldPassword}
onChange={(e) => setOldPassword(e.target.value)}
placeholder="Mot de passe actuel"
disabled={loading}
/>
<Button
type="button"
variant="ghost"
size="sm"
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
onClick={() => setShowOldPassword(!showOldPassword)}
>
{showOldPassword ? (
<EyeOff className="h-4 w-4" />
) : (
<Eye className="h-4 w-4" />
)}
</Button>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="new-password">Nouveau mot de passe</Label>
<div className="relative">
<Input
id="new-password"
type={showNewPassword ? "text" : "password"}
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
placeholder="Nouveau mot de passe"
disabled={loading}
/>
<Button
type="button"
variant="ghost"
size="sm"
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
onClick={() => setShowNewPassword(!showNewPassword)}
>
{showNewPassword ? (
<EyeOff className="h-4 w-4" />
) : (
<Eye className="h-4 w-4" />
)}
</Button>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="confirm-password">
Confirmer le mot de passe
</Label>
<div className="relative">
<Input
id="confirm-password"
type={showConfirmPassword ? "text" : "password"}
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
placeholder="Confirmer le mot de passe"
disabled={loading}
/>
<Button
type="button"
variant="ghost"
size="sm"
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
>
{showConfirmPassword ? (
<EyeOff className="h-4 w-4" />
) : (
<Eye className="h-4 w-4" />
)}
</Button>
</div>
</div>
</div>
<AlertDialogFooter>
<AlertDialogCancel disabled={loading}>Annuler</AlertDialogCancel>
<AlertDialogAction
onClick={handleChangePassword}
disabled={loading}
>
{loading ? "Modification..." : "Modifier"}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</CardContent>
</Card>
);
}