Done on function Ban and Unban User with reason and expiration date

This commit is contained in:
2026-01-21 20:28:04 +07:00
parent e02564b5cd
commit a8745327d6
23 changed files with 511 additions and 239 deletions

View File

@@ -0,0 +1,119 @@
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 { 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 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 } });
};
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>
);
};
export default UnbanUserAction;