222 lines
5.8 KiB
TypeScript
222 lines
5.8 KiB
TypeScript
"use client";
|
|
|
|
import { UserIcon, Building, X } from "lucide-react";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent } from "@/components/ui/card";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { Role, User } from "@/types/types";
|
|
import { useParams } from "next/navigation";
|
|
import { useApi } from "@/hooks/use-api";
|
|
import { useState } from "react";
|
|
import request from "@/lib/request";
|
|
|
|
export default function UserDetailsPage() {
|
|
const { uuid } = useParams<{ uuid: string }>();
|
|
const user = useApi<User>(`/users/${uuid}`, {}, true);
|
|
|
|
const availableRoles = useApi<Role[]>("/roles", {}, true);
|
|
availableRoles.data ??= [];
|
|
const [selectedRole, setSelectedRole] = useState<Role | null>(null);
|
|
// const [selectedOrg, setSelectedOrg] = useState("");
|
|
|
|
const addRole = async (role: Role) => {
|
|
const res = await request(
|
|
`/users/${user.data?.userId}/roles/${role.id}/add`,
|
|
{ method: "PATCH", requiresAuth: true },
|
|
);
|
|
if (res.status === "Success") {
|
|
setSelectedRole(null);
|
|
user.mutate();
|
|
}
|
|
};
|
|
|
|
const removeRole = async (role: Role) => {
|
|
const res = await request(
|
|
`/users/${user.data?.userId}/roles/${role.id}/remove`,
|
|
{ method: "PATCH", requiresAuth: true },
|
|
);
|
|
if (res.status === "Success") user.mutate();
|
|
};
|
|
|
|
const addOrganization = () => {
|
|
// if (selectedOrg && !user.organizations.includes(selectedOrg)) {
|
|
// setUser((prevUser) => ({
|
|
// ...prevUser,
|
|
// organizations: [...prevUser.organizations, selectedOrg],
|
|
// }));
|
|
// setSelectedOrg("");
|
|
// }
|
|
};
|
|
|
|
const removeOrganization = (orgToRemove: string) => {
|
|
// setUser((prevUser) => ({
|
|
// ...prevUser,
|
|
// organizations: prevUser.organizations.filter(
|
|
// (org) => org !== orgToRemove,
|
|
// ),
|
|
// }));
|
|
};
|
|
|
|
if (!user.data || !user.success) return <p>Error</p>;
|
|
|
|
return (
|
|
<div className="container mx-auto py-10">
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<div className="grid gap-6">
|
|
<div className="flex items-center space-x-4">
|
|
<UserIcon className="h-12 w-12 text-gray-400" />
|
|
<div>
|
|
<h2 className="text-xl font-semibold">
|
|
{user.data.firstname} {user.data.lastname}
|
|
</h2>
|
|
<p className="text-sm text-gray-500">
|
|
{user.data.email}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid gap-6 md:grid-cols-2">
|
|
<div>
|
|
<h3 className="text-lg font-semibold mb-2">
|
|
Rôles
|
|
</h3>
|
|
<div className="flex flex-wrap gap-2">
|
|
{user.data.roles?.map((role) => (
|
|
<Badge
|
|
key={role.id}
|
|
variant="secondary"
|
|
className="text-sm py-1 px-2"
|
|
>
|
|
{role.name}
|
|
<button
|
|
onClick={() => removeRole(role)}
|
|
className="ml-2 text-gray-500 hover:text-gray-700"
|
|
>
|
|
<X className="h-3 w-3" />
|
|
</button>
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
|
|
<div className="mt-2 flex space-x-2">
|
|
<Select
|
|
value={
|
|
selectedRole
|
|
? selectedRole.name
|
|
: ""
|
|
}
|
|
onValueChange={(s) => {
|
|
const r = availableRoles.data?.find(
|
|
(r) => r.name === s,
|
|
);
|
|
console.log(r);
|
|
if (r) setSelectedRole(r);
|
|
}}
|
|
>
|
|
<SelectTrigger className="w-[180px]">
|
|
<SelectValue placeholder="Sélectionner un rôle" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{availableRoles.data
|
|
.filter(
|
|
(org) =>
|
|
!user.data?.roles?.includes(
|
|
org,
|
|
),
|
|
)
|
|
.map((role) => (
|
|
<SelectItem
|
|
key={role.id}
|
|
value={role.name}
|
|
>
|
|
{role.name}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<Button
|
|
disabled={!user.data || !selectedRole}
|
|
onClick={() => addRole(selectedRole!)}
|
|
className="flex items-center"
|
|
>
|
|
<Building className="mr-2 h-4 w-4" />
|
|
Ajouter le rôle
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/*<div>
|
|
<h3 className="text-lg font-semibold mb-2">
|
|
Organizations
|
|
</h3>
|
|
<div className="flex flex-wrap gap-2">
|
|
{user.data.organizations.map((org) => (
|
|
<Badge
|
|
key={org}
|
|
variant="outline"
|
|
className="text-sm py-1 px-2"
|
|
>
|
|
{org}
|
|
<button
|
|
onClick={() =>
|
|
removeOrganization(org)
|
|
}
|
|
className="ml-2 text-gray-500 hover:text-gray-700"
|
|
>
|
|
<X className="h-3 w-3" />
|
|
</button>
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
<div className="mt-2 flex space-x-2">
|
|
<Select
|
|
value={selectedOrg}
|
|
onValueChange={setSelectedOrg}
|
|
>
|
|
<SelectTrigger className="w-[180px]">
|
|
<SelectValue placeholder="Select an organization" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{availableOrganizations
|
|
.filter(
|
|
(org) =>
|
|
!user.organizations.includes(
|
|
org,
|
|
),
|
|
)
|
|
.map((org) => (
|
|
<SelectItem
|
|
key={org}
|
|
value={org}
|
|
>
|
|
{org}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<Button
|
|
onClick={addOrganization}
|
|
className="flex items-center"
|
|
>
|
|
<Building className="mr-2 h-4 w-4" />
|
|
Add Org
|
|
</Button>
|
|
</div>
|
|
</div> */}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|