131 lines
4.2 KiB
TypeScript
131 lines
4.2 KiB
TypeScript
import useHasPermission from '@/hooks/use-has-permission';
|
|
import usePreventAutoFocus from '@/hooks/use-prevent-auto-focus';
|
|
import { m } from '@/paraglide/messages';
|
|
import { usersQueries } from '@/service/queries';
|
|
import { unbanUser } from '@/service/user.api';
|
|
import { ReturnError } from '@/types/common';
|
|
import { LockOpenIcon, ShieldWarningIcon } from '@phosphor-icons/react';
|
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { useRouteContext } from '@tanstack/react-router';
|
|
import { UserWithRole } from 'better-auth/plugins';
|
|
import { useState } from 'react';
|
|
import { toast } from 'sonner';
|
|
import DisplayBreakLineMessage from '../DisplayBreakLineMessage';
|
|
import { Button } from '../ui/button';
|
|
import {
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from '../ui/dialog';
|
|
import { Label } from '../ui/label';
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
|
|
|
|
type UnbanUserProps = {
|
|
data: UserWithRole;
|
|
};
|
|
|
|
const UnbanUserAction = ({ data }: UnbanUserProps) => {
|
|
const { session } = useRouteContext({ from: '__root__' });
|
|
const isCurrentUser = session?.user.id === data.id;
|
|
const { hasPermission, isLoading } = useHasPermission('user', 'ban');
|
|
const queryClient = useQueryClient();
|
|
|
|
const [_open, _setOpen] = useState(false);
|
|
const prevent = usePreventAutoFocus();
|
|
|
|
const { mutate: unbanMutation } = useMutation({
|
|
mutationFn: unbanUser,
|
|
onSuccess: () => {
|
|
queryClient.refetchQueries({
|
|
queryKey: usersQueries.all,
|
|
});
|
|
_setOpen(false);
|
|
toast.success(
|
|
m.users_page_message_unbanned_success({ name: data.name }),
|
|
{
|
|
richColors: true,
|
|
},
|
|
);
|
|
},
|
|
onError: (error: ReturnError) => {
|
|
console.error(error);
|
|
toast.error(m.backend_message({ code: error.code }), {
|
|
richColors: true,
|
|
});
|
|
},
|
|
});
|
|
|
|
const onConfirm = () => {
|
|
unbanMutation({ data: { id: data.id } });
|
|
};
|
|
|
|
if (isCurrentUser || isLoading) return null;
|
|
|
|
if (hasPermission) {
|
|
return (
|
|
<Dialog open={_open} onOpenChange={_setOpen}>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<DialogTrigger asChild>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="icon"
|
|
className="rounded-full cursor-pointer text-green-500 hover:bg-green-100 hover:text-green-600"
|
|
>
|
|
<LockOpenIcon size={16} />
|
|
<span className="sr-only">{m.ui_unban_btn()}</span>
|
|
</Button>
|
|
</DialogTrigger>
|
|
</TooltipTrigger>
|
|
<TooltipContent className="bg-green-500 [&_svg]:bg-green-500 [&_svg]:fill-green-500 text-white">
|
|
<Label>{m.ui_unban_btn()}</Label>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
<DialogContent
|
|
showCloseButton={false}
|
|
{...prevent}
|
|
onPointerDownOutside={(e) => e.preventDefault()}
|
|
>
|
|
<DialogHeader>
|
|
<DialogTitle className="flex items-center gap-3 text-lg font-bold text-green-500">
|
|
<div className="rounded-full bg-green-100 p-3">
|
|
<ShieldWarningIcon size={30} />
|
|
</div>
|
|
{m.users_page_ui_dialog_alert_title()}
|
|
</DialogTitle>
|
|
<DialogDescription className="sr-only">
|
|
{m.users_page_ui_dialog_alert_title()}
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<DisplayBreakLineMessage>
|
|
{m.users_page_ui_dialog_alert_description({
|
|
name: data.name,
|
|
email: data.email,
|
|
})}
|
|
</DisplayBreakLineMessage>
|
|
<DialogFooter className="bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4">
|
|
<DialogClose asChild>
|
|
<Button variant="outline" type="button">
|
|
{m.ui_cancel_btn()}
|
|
</Button>
|
|
</DialogClose>
|
|
<Button variant="destructive" type="button" onClick={onConfirm}>
|
|
{m.ui_confirm_btn()}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
export default UnbanUserAction;
|