feat(admin): add edit dialogs for users, contents, and categories
- Implemented edit functionality for users, contents, and categories, including modals for updating records. - Enhanced table actions with edit buttons alongside delete. - Improved user, content, and category fetching with `useCallback` to optimize re-renders. - Added skeleton loaders and UI updates for better user experience.
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
import { format } from "date-fns";
|
||||
import { fr } from "date-fns/locale";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Edit, Trash2 } from "lucide-react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
@@ -17,13 +17,17 @@ import {
|
||||
} from "@/components/ui/table";
|
||||
import { UserService } from "@/services/user.service";
|
||||
import type { User } from "@/types/user";
|
||||
import { UserEditDialog } from "./user-edit-dialog";
|
||||
|
||||
export default function AdminUsersPage() {
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [totalCount, setTotalCount] = useState(0);
|
||||
const [selectedUser, setSelectedUser] = useState<User | null>(null);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUsers = useCallback(() => {
|
||||
setLoading(true);
|
||||
UserService.getUsersAdmin()
|
||||
.then((res) => {
|
||||
setUsers(res.data);
|
||||
@@ -35,6 +39,10 @@ export default function AdminUsersPage() {
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUsers();
|
||||
}, [fetchUsers]);
|
||||
|
||||
const handleDelete = async (uuid: string) => {
|
||||
if (
|
||||
!confirm(
|
||||
@@ -52,6 +60,11 @@ export default function AdminUsersPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleEdit = (user: User) => {
|
||||
setSelectedUser(user);
|
||||
setDialogOpen(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex-1 space-y-4 p-4 pt-6 md:p-8">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -68,7 +81,7 @@ export default function AdminUsersPage() {
|
||||
<TableHead>Rôle</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Date d'inscription</TableHead>
|
||||
<TableHead className="w-[50px]"></TableHead>
|
||||
<TableHead className="w-[100px]"></TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
@@ -91,11 +104,14 @@ export default function AdminUsersPage() {
|
||||
<TableCell>
|
||||
<Skeleton className="h-4 w-[100px]" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-8 w-8 rounded-full" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
) : users.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={5} className="text-center h-24">
|
||||
<TableCell colSpan={6} className="text-center h-24">
|
||||
Aucun utilisateur trouvé.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -113,7 +129,15 @@ export default function AdminUsersPage() {
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant={user.status === "active" ? "success" : "destructive"}>
|
||||
<Badge
|
||||
variant={
|
||||
user.status === "active"
|
||||
? "success"
|
||||
: user.status === "suspended"
|
||||
? "destructive"
|
||||
: "secondary"
|
||||
}
|
||||
>
|
||||
{user.status}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
@@ -121,14 +145,19 @@ export default function AdminUsersPage() {
|
||||
{format(new Date(user.createdAt), "PPP", { locale: fr })}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => handleDelete(user.uuid)}
|
||||
className="text-destructive hover:text-destructive hover:bg-destructive/10"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" size="icon" onClick={() => handleEdit(user)}>
|
||||
<Edit className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => handleDelete(user.uuid)}
|
||||
className="text-destructive hover:text-destructive hover:bg-destructive/10"
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
@@ -136,6 +165,12 @@ export default function AdminUsersPage() {
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<UserEditDialog
|
||||
user={selectedUser}
|
||||
open={dialogOpen}
|
||||
onOpenChange={setDialogOpen}
|
||||
onSuccess={fetchUsers}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user