181 lines
4.7 KiB
TypeScript
181 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import { Button } from "@/components/ui/button";
|
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
import MemberDialog, { Member } from "./member-dialog";
|
|
import { useApi } from "@/hooks/use-api";
|
|
import request from "@/lib/request";
|
|
import { Loader2, MoreHorizontal, UserRoundPlus } from "lucide-react";
|
|
import IUser from "@/interfaces/IUser";
|
|
import hasPermissions from "@/lib/hasPermissions";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
} from "./ui/dropdown-menu";
|
|
|
|
export default function MembersTable({ user }: { user: IUser }) {
|
|
const {
|
|
data: members,
|
|
error,
|
|
mutate,
|
|
success,
|
|
isLoading,
|
|
} = useApi<Member[]>("/users", undefined, true, false);
|
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
const [currentMember, setCurrentMember] = useState<Member | null>(null);
|
|
|
|
const { users } = hasPermissions(user.roles, {
|
|
users: ["delete", "update", "insert"],
|
|
} as const);
|
|
|
|
const handleOpenDialog = (member: Member | null) => {
|
|
setCurrentMember(member);
|
|
setDialogOpen(true);
|
|
};
|
|
|
|
const handleSaveMember = async (savedMember: Member) => {
|
|
if (savedMember.userId) {
|
|
const dif = DiffUtils.getDifferences(currentMember!, savedMember);
|
|
if (DiffUtils.isEmpty(dif)) return;
|
|
const res = await request<unknown>(
|
|
`/users/${savedMember.userId}/update`,
|
|
{
|
|
body: dif,
|
|
requiresAuth: true,
|
|
method: "PATCH",
|
|
},
|
|
);
|
|
if (res.status === "Success") mutate();
|
|
// Update existing member
|
|
// setMembers((prev) =>
|
|
// prev.map((m) =>
|
|
// m.user_id === savedMember.user_id ? savedMember : m,
|
|
// ),
|
|
// );
|
|
} else {
|
|
delete savedMember.userId;
|
|
const res = await request<unknown>("/users/new", {
|
|
body: savedMember,
|
|
method: "POST",
|
|
requiresAuth: true,
|
|
});
|
|
if (res.status === "Success") mutate();
|
|
}
|
|
};
|
|
|
|
const handleDelete = async (userId: string) => {
|
|
const res = await request<unknown>(`/users/${userId}/delete`, {
|
|
method: "DELETE",
|
|
requiresAuth: true,
|
|
});
|
|
if (res.status === "Success") mutate();
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex justify-between">
|
|
{users.insert && (
|
|
<Button onClick={() => handleOpenDialog(null)}>
|
|
<UserRoundPlus />
|
|
</Button>
|
|
)}
|
|
</div>
|
|
<div className="relative">
|
|
{isLoading && <Loader2 className="animate-spin" />}
|
|
<ScrollArea className="h-full rounded-md border">
|
|
<Table>
|
|
<TableHeader className="sticky top-0 bg-background z-10 shadow-sm">
|
|
<TableRow>
|
|
<TableHead>Prénom</TableHead>
|
|
<TableHead>Nom</TableHead>
|
|
<TableHead>Email</TableHead>
|
|
<TableHead>Téléphone</TableHead>
|
|
<TableHead>Rôles</TableHead>
|
|
<TableHead className="text-right">
|
|
Actions
|
|
</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{members &&
|
|
members.map((_member) => (
|
|
<TableRow key={_member.userId}>
|
|
<TableCell>
|
|
{_member.firstname}
|
|
</TableCell>
|
|
<TableCell>
|
|
{_member.lastname}
|
|
</TableCell>
|
|
<TableCell>{_member.email}</TableCell>
|
|
<TableCell>{_member.phone}</TableCell>
|
|
<TableCell>
|
|
{_member.roles
|
|
?.map((r) => r.name)
|
|
.join(", ")}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button
|
|
variant="ghost"
|
|
className="h-8 w-8 p-0"
|
|
>
|
|
<span className="sr-only">
|
|
Ouvrir le menu
|
|
</span>
|
|
<MoreHorizontal className="h-4 w-4" />
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end">
|
|
{users.update && (
|
|
<DropdownMenuItem
|
|
onClick={() =>
|
|
handleOpenDialog(
|
|
_member,
|
|
)
|
|
}
|
|
>
|
|
Mettre à jour
|
|
</DropdownMenuItem>
|
|
)}
|
|
{users.delete && (
|
|
<DropdownMenuItem
|
|
onClick={() =>
|
|
handleDelete(
|
|
_member.userId!,
|
|
)
|
|
}
|
|
>
|
|
Supprimer
|
|
</DropdownMenuItem>
|
|
)}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</ScrollArea>
|
|
</div>
|
|
<MemberDialog
|
|
isOpen={dialogOpen}
|
|
onClose={() => setDialogOpen(false)}
|
|
member={currentMember}
|
|
onSave={handleSaveMember}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|