Files
Dashboard/components/dashboard/delete-user.tsx
2025-10-08 10:14:38 +02:00

321 lines
9.8 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useState } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { UserMinus, Loader2, CheckCircle, AlertCircle, Trash2 } from "lucide-react";
interface DeleteUserResult {
success: boolean;
message: string;
deletedUser?: {
id: string;
name: string;
email: string;
role: string;
};
balanceDeleted?: boolean;
error?: string;
}
interface FoundUser {
_id: string;
name: string;
email: string;
role: string;
createdAt: string;
}
export default function DeleteUser() {
const [searchData, setSearchData] = useState({
email: "",
userId: "",
});
const [isLoading, setIsLoading] = useState(false);
const [result, setResult] = useState<DeleteUserResult | null>(null);
const [confirmDelete, setConfirmDelete] = useState(false);
const [foundUser, setFoundUser] = useState<FoundUser | null>(null);
const handleInputChange = (field: string, value: string) => {
setSearchData((prev) => ({ ...prev, [field]: value }));
// Réinitialiser les résultats quand l'utilisateur modifie le formulaire
if (result) {
setResult(null);
}
if (confirmDelete) {
setConfirmDelete(false);
}
if (foundUser) {
setFoundUser(null);
}
};
const validateForm = () => {
if (!searchData.email.trim() && !searchData.userId.trim()) {
return "Email ou ID utilisateur requis";
}
if (searchData.email && searchData.userId) {
return "Veuillez utiliser soit l'email soit l'ID, pas les deux";
}
if (searchData.email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(searchData.email)) {
return "Format d&apos;email invalide";
}
}
return null;
};
const handleSearch = async (e: React.FormEvent) => {
e.preventDefault();
const validationError = validateForm();
if (validationError) {
setResult({
success: false,
message: validationError,
});
return;
}
setIsLoading(true);
setResult(null);
setFoundUser(null);
try {
// D'abord, chercher l'utilisateur pour confirmation
const searchParams = new URLSearchParams();
if (searchData.email) {
searchParams.append("email", searchData.email.trim().toLowerCase());
}
if (searchData.userId) {
searchParams.append("id", searchData.userId.trim());
}
const response = await fetch(`/api/collections/users?${searchParams.toString()}`);
const data = await response.json();
if (response.ok && data.data && data.data.length > 0) {
setFoundUser(data.data[0]);
setResult({
success: true,
message: "Utilisateur trouvé. Confirmez la suppression ci-dessous.",
});
} else {
setResult({
success: false,
message: "Utilisateur non trouvé",
});
}
} catch (error) {
console.error("Erreur lors de la recherche:", error);
setResult({
success: false,
message: "Erreur de connexion au serveur",
});
} finally {
setIsLoading(false);
}
};
const handleDelete = async () => {
if (!foundUser) return;
setIsLoading(true);
setResult(null);
try {
const response = await fetch("/api/delete-user", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userId: foundUser._id,
}),
});
const data = await response.json();
if (response.ok) {
setResult({
success: true,
message: data.message,
deletedUser: data.deletedUser,
balanceDeleted: data.balanceDeleted,
});
// Réinitialiser le formulaire
setSearchData({
email: "",
userId: "",
});
setFoundUser(null);
setConfirmDelete(false);
} else {
setResult({
success: false,
message: data.error || "Erreur lors de la suppression de l&apos;utilisateur",
});
}
} catch (error) {
console.error("Erreur lors de la suppression:", error);
setResult({
success: false,
message: "Erreur de connexion au serveur",
});
} finally {
setIsLoading(false);
}
};
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2 text-red-600">
<UserMinus className="h-5 w-5" />
Supprimer un utilisateur
</CardTitle>
</CardHeader>
<CardContent>
<form onSubmit={handleSearch} className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="email">Adresse email</Label>
<Input
id="email"
type="email"
placeholder="Ex: jean.dupont@example.com"
value={searchData.email}
onChange={(e) => handleInputChange("email", e.target.value)}
disabled={isLoading || !!searchData.userId}
/>
</div>
<div className="space-y-2">
<Label htmlFor="userId">ID Utilisateur</Label>
<Input
id="userId"
type="text"
placeholder="Ex: 507f1f77bcf86cd799439011"
value={searchData.userId}
onChange={(e) => handleInputChange("userId", e.target.value)}
disabled={isLoading || !!searchData.email}
/>
</div>
</div>
{!foundUser && (
<div className="flex justify-end">
<Button type="submit" disabled={isLoading} variant="outline">
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Recherche...
</>
) : (
<>
Rechercher l&apos;utilisateur
</>
)}
</Button>
</div>
)}
</form>
{foundUser && (
<div className="mt-6 p-4 border rounded-lg bg-yellow-50 border-yellow-200">
<h4 className="font-medium mb-2 text-yellow-800">Utilisateur trouvé :</h4>
<div className="text-sm space-y-1 text-yellow-700">
<p><strong>ID:</strong> {foundUser._id}</p>
<p><strong>Nom:</strong> {foundUser.name}</p>
<p><strong>Email:</strong> {foundUser.email}</p>
<p><strong>Rôle:</strong> {foundUser.role}</p>
<p><strong>Créé le:</strong> {new Date(foundUser.createdAt).toLocaleDateString()}</p>
</div>
<div className="mt-4 flex gap-2">
{!confirmDelete ? (
<Button
onClick={() => setConfirmDelete(true)}
variant="destructive"
size="sm"
>
<Trash2 className="mr-2 h-4 w-4" />
Supprimer cet utilisateur
</Button>
) : (
<div className="flex gap-2">
<Button
onClick={handleDelete}
disabled={isLoading}
variant="destructive"
size="sm"
>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Suppression...
</>
) : (
<>
<Trash2 className="mr-2 h-4 w-4" />
Confirmer la suppression
</>
)}
</Button>
<Button
onClick={() => setConfirmDelete(false)}
variant="outline"
size="sm"
disabled={isLoading}
>
Annuler
</Button>
</div>
)}
</div>
</div>
)}
{result && (
<Alert variant={result.success ? "default" : "destructive"} className="mt-4">
{result.success ? (
<CheckCircle className="h-4 w-4" />
) : (
<AlertCircle className="h-4 w-4" />
)}
<AlertDescription>
{result.message}
{result.success && result.deletedUser && (
<div className="mt-2 text-sm">
<strong>Utilisateur supprimé:</strong>
<br />
Nom: {result.deletedUser.name}
<br />
Email: {result.deletedUser.email}
<br />
Rôle: {result.deletedUser.role}
<br />
Solde supprimé: {result.balanceDeleted ? "Oui" : "Non"}
</div>
)}
</AlertDescription>
</Alert>
)}
<div className="mt-6 p-4 bg-red-50 rounded-lg border border-red-200">
<h4 className="font-medium mb-2 text-red-800"> Attention :</h4>
<ul className="text-sm text-red-700 space-y-1">
<li> Cette action est irréversible</li>
<li> L&apos;utilisateur et son solde seront définitivement supprimés</li>
<li> Toutes les données associées seront perdues</li>
<li> Utilisez cette fonction avec précaution</li>
</ul>
</div>
</CardContent>
</Card>
);
}