Update admin action functionalities and UI
This commit includes several changes to the admin functionality. Most notably, it updates the actions deleteUser and banUser to deleteAccount and updates the UI for admin actions. It also includes new variants for badges, and adds new icons to buttons. In addition, it updates the user schemas to match these changes.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { BadgeX, Ban, ShieldPlus, Trash, VenetianMask } from 'lucide-react';
|
||||
|
||||
import { Database } from '@kit/supabase/database';
|
||||
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
|
||||
@@ -67,28 +69,44 @@ async function PersonalAccountPage(props: { account: Account }) {
|
||||
<span>{props.account.name}</span>
|
||||
|
||||
<Badge variant={'outline'}>Personal Account</Badge>
|
||||
|
||||
<If condition={isBanned}>
|
||||
<Badge variant={'destructive'}>Banned</Badge>
|
||||
</If>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className={'flex space-x-2'}>
|
||||
<AdminImpersonateUserDialog userId={props.account.id}>
|
||||
<Button variant={'ghost'}>Impersonate</Button>
|
||||
</AdminImpersonateUserDialog>
|
||||
|
||||
<div className={'flex space-x-1'}>
|
||||
<If condition={isBanned}>
|
||||
<AdminReactivateUserDialog userId={props.account.id}>
|
||||
<Button variant={'ghost'}>Reactivate</Button>
|
||||
<Button size={'sm'} variant={'ghost'}>
|
||||
<ShieldPlus className={'mr-1 h-4'} />
|
||||
Reactivate
|
||||
</Button>
|
||||
</AdminReactivateUserDialog>
|
||||
</If>
|
||||
|
||||
<If condition={!isBanned}>
|
||||
<AdminBanUserDialog userId={props.account.id}>
|
||||
<Button variant={'ghost'}>Ban</Button>
|
||||
<Button size={'sm'} variant={'ghost'}>
|
||||
<Ban className={'mr-1 h-4'} />
|
||||
Ban
|
||||
</Button>
|
||||
</AdminBanUserDialog>
|
||||
|
||||
<AdminImpersonateUserDialog userId={props.account.id}>
|
||||
<Button size={'sm'} variant={'ghost'}>
|
||||
<VenetianMask className={'mr-1 h-4'} />
|
||||
Impersonate
|
||||
</Button>
|
||||
</AdminImpersonateUserDialog>
|
||||
</If>
|
||||
|
||||
<AdminDeleteUserDialog userId={props.account.id}>
|
||||
<Button variant={'destructive'}>Delete</Button>
|
||||
<Button size={'sm'} variant={'destructive'}>
|
||||
<BadgeX className={'mr-1 h-4'} />
|
||||
Delete
|
||||
</Button>
|
||||
</AdminDeleteUserDialog>
|
||||
</div>
|
||||
</PageHeader>
|
||||
@@ -134,7 +152,10 @@ async function TeamAccountPage(props: {
|
||||
}
|
||||
>
|
||||
<AdminDeleteAccountDialog accountId={props.account.id}>
|
||||
<Button variant={'destructive'}>Delete</Button>
|
||||
<Button size={'sm'} variant={'destructive'}>
|
||||
<BadgeX className={'mr-1 h-4'} />
|
||||
Delete
|
||||
</Button>
|
||||
</AdminDeleteAccountDialog>
|
||||
</PageHeader>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
import { Input } from '@kit/ui/input';
|
||||
|
||||
import { banUser } from '../lib/server/admin-server-actions';
|
||||
import { DeleteUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
import { BanUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminBanUserDialog(
|
||||
props: React.PropsWithChildren<{
|
||||
@@ -34,7 +34,7 @@ export function AdminBanUserDialog(
|
||||
}>,
|
||||
) {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(DeleteUserSchema),
|
||||
resolver: zodResolver(BanUserSchema),
|
||||
defaultValues: {
|
||||
userId: props.userId,
|
||||
confirmation: '',
|
||||
@@ -57,7 +57,9 @@ export function AdminBanUserDialog(
|
||||
<Form {...form}>
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit(banUser)}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return banUser(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
name={'confirmation'}
|
||||
|
||||
@@ -58,7 +58,9 @@ export function AdminDeleteAccountDialog(
|
||||
<Form {...form}>
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit(deleteAccount)}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return deleteAccount(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
name={'confirmation'}
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
} from '@kit/ui/form';
|
||||
import { Input } from '@kit/ui/input';
|
||||
|
||||
import { deleteUser } from '../lib/server/admin-server-actions';
|
||||
import { deleteAccount, deleteUser } from '../lib/server/admin-server-actions';
|
||||
import { DeleteUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminDeleteUserDialog(
|
||||
@@ -59,7 +59,9 @@ export function AdminDeleteUserDialog(
|
||||
<Form {...form}>
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit(deleteUser)}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return deleteAccount(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
name={'confirmation'}
|
||||
|
||||
@@ -33,7 +33,7 @@ import { Input } from '@kit/ui/input';
|
||||
import { LoadingOverlay } from '@kit/ui/loading-overlay';
|
||||
|
||||
import { impersonateUser } from '../lib/server/admin-server-actions';
|
||||
import { DeleteUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
import { ImpersonateUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminImpersonateUserDialog(
|
||||
props: React.PropsWithChildren<{
|
||||
@@ -41,7 +41,7 @@ export function AdminImpersonateUserDialog(
|
||||
}>,
|
||||
) {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(DeleteUserSchema),
|
||||
resolver: zodResolver(ImpersonateUserSchema),
|
||||
defaultValues: {
|
||||
userId: props.userId,
|
||||
confirmation: '',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
||||
@@ -24,7 +26,7 @@ import {
|
||||
import { Input } from '@kit/ui/input';
|
||||
|
||||
import { reactivateUser } from '../lib/server/admin-server-actions';
|
||||
import { DeleteUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
import { ReactivateUserSchema } from '../lib/server/schema/admin-actions.schema';
|
||||
|
||||
export function AdminReactivateUserDialog(
|
||||
props: React.PropsWithChildren<{
|
||||
@@ -32,7 +34,7 @@ export function AdminReactivateUserDialog(
|
||||
}>,
|
||||
) {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(DeleteUserSchema),
|
||||
resolver: zodResolver(ReactivateUserSchema),
|
||||
defaultValues: {
|
||||
userId: props.userId,
|
||||
confirmation: '',
|
||||
@@ -55,7 +57,9 @@ export function AdminReactivateUserDialog(
|
||||
<Form {...form}>
|
||||
<form
|
||||
className={'flex flex-col space-y-8'}
|
||||
onSubmit={form.handleSubmit(reactivateUser)}
|
||||
onSubmit={form.handleSubmit((data) => {
|
||||
return reactivateUser(data);
|
||||
})}
|
||||
>
|
||||
<FormField
|
||||
name={'confirmation'}
|
||||
|
||||
@@ -28,6 +28,10 @@ export const banUser = enhanceAdminAction(
|
||||
await service.banUser(userId);
|
||||
|
||||
revalidateAdmin();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
},
|
||||
{
|
||||
schema: BanUserSchema,
|
||||
@@ -47,6 +51,10 @@ export const reactivateUser = enhanceAdminAction(
|
||||
await service.reactivateUser(userId);
|
||||
|
||||
revalidateAdmin();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
},
|
||||
{
|
||||
schema: ReactivateUserSchema,
|
||||
@@ -83,6 +91,10 @@ export const deleteUser = enhanceAdminAction(
|
||||
await service.deleteUser(userId);
|
||||
|
||||
revalidateAdmin();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
},
|
||||
{
|
||||
schema: DeleteUserSchema,
|
||||
@@ -102,6 +114,10 @@ export const deleteAccount = enhanceAdminAction(
|
||||
await service.deleteAccount(accountId);
|
||||
|
||||
revalidateAdmin();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
},
|
||||
{
|
||||
schema: DeleteAccountSchema,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const confirmationSchema = z.object({
|
||||
confirmation: z.custom((value) => value === 'CONFIRM'),
|
||||
const ConfirmationSchema = z.object({
|
||||
confirmation: z.custom<string>((value) => value === 'CONFIRM'),
|
||||
});
|
||||
|
||||
const UserIdSchema = confirmationSchema.extend({
|
||||
const UserIdSchema = ConfirmationSchema.extend({
|
||||
userId: z.string().uuid(),
|
||||
});
|
||||
|
||||
@@ -13,6 +13,6 @@ export const ReactivateUserSchema = UserIdSchema;
|
||||
export const ImpersonateUserSchema = UserIdSchema;
|
||||
export const DeleteUserSchema = UserIdSchema;
|
||||
|
||||
export const DeleteAccountSchema = confirmationSchema.extend({
|
||||
export const DeleteAccountSchema = ConfirmationSchema.extend({
|
||||
accountId: z.string().uuid(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user