karbe/src/app/admin/users/[id]/_components/UserActions.tsx

120 lines
4 KiB
TypeScript

"use client";
import { useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { UserRole } from "@/generated/prisma/enums";
import { toggleUserActiveAction, updateUserRoleAction } from "../../actions";
const ROLE_OPTIONS: { value: string; label: string }[] = [
{ value: UserRole.OWNER, label: "Propriétaire" },
{ value: UserRole.CE_MANAGER, label: "CE — Manager" },
{ value: UserRole.CE_MEMBER, label: "CE — Membre" },
{ value: UserRole.TOURIST, label: "Touriste" },
{ value: UserRole.ADMIN, label: "Admin" },
];
export function UserActions({
id,
role,
isActive,
}: {
id: string;
role: string;
isActive: boolean;
}) {
const router = useRouter();
const [pending, startTransition] = useTransition();
const [error, setError] = useState<string | null>(null);
const [selectedRole, setSelectedRole] = useState(role);
const [confirmDeactivate, setConfirmDeactivate] = useState(false);
function changeRole(next: string) {
setError(null);
setSelectedRole(next);
startTransition(async () => {
const res = await updateUserRoleAction(id, next);
if (res && res.ok === false) {
setError(res.error);
setSelectedRole(role);
}
router.refresh();
});
}
function toggleActive(next: boolean) {
setError(null);
startTransition(async () => {
const res = await toggleUserActiveAction(id, next);
if (res && res.ok === false) setError(res.error);
setConfirmDeactivate(false);
router.refresh();
});
}
return (
<div className="space-y-3">
<div className="flex flex-wrap items-center gap-3">
<label className="text-[11px] uppercase tracking-wider text-zinc-500">Rôle</label>
<select
value={selectedRole}
disabled={pending}
onChange={(e) => changeRole(e.target.value)}
className="rounded-md border border-zinc-300 bg-white px-2 py-1.5 text-sm focus:border-zinc-900 focus:outline-none disabled:opacity-50"
>
{ROLE_OPTIONS.map((o) => (
<option key={o.value} value={o.value}>{o.label}</option>
))}
</select>
</div>
<div className="flex flex-wrap items-center gap-2">
<span className="text-[11px] uppercase tracking-wider text-zinc-500">État du compte</span>
{isActive ? (
confirmDeactivate ? (
<div className="flex items-center gap-2 rounded border border-amber-300 bg-amber-50 px-2 py-1">
<span className="text-xs text-amber-900">Désactiver ce compte ?</span>
<button
type="button"
onClick={() => toggleActive(false)}
disabled={pending}
className="rounded bg-amber-700 px-2 py-1 text-[11px] font-semibold text-white hover:bg-amber-800 disabled:opacity-50"
>
Oui, désactiver
</button>
<button
type="button"
onClick={() => setConfirmDeactivate(false)}
disabled={pending}
className="text-[11px] text-zinc-500 hover:text-zinc-900"
>
Annuler
</button>
</div>
) : (
<button
type="button"
onClick={() => setConfirmDeactivate(true)}
disabled={pending}
className="rounded-md border border-rose-300 bg-rose-50 px-3 py-1.5 text-xs font-semibold text-rose-700 hover:bg-rose-100 disabled:opacity-50"
>
Désactiver
</button>
)
) : (
<button
type="button"
onClick={() => toggleActive(true)}
disabled={pending}
className="rounded-md bg-emerald-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-emerald-700 disabled:opacity-50"
>
Réactiver
</button>
)}
</div>
{error ? (
<div className="rounded border border-rose-200 bg-rose-50 px-3 py-2 text-sm text-rose-700">{error}</div>
) : null}
</div>
);
}