Deps Update + Table improvements (#351)

* fix: enhance DataTable pagination examples and improve display logic

- Added a note in the DataTableStory component to clarify that examples show only the first page of data for demonstration purposes.
- Adjusted pagination examples to reflect smaller datasets, changing the displayed data slices for better clarity and testing.
- Updated the Pagination component to calculate and display the current record range more accurately based on the current page index and size.

* chore(dependencies): update package versions for improved compatibility

- Upgraded `@supabase/supabase-js` from `2.55.0` to `2.57.0` for enhanced functionality and performance.
- Bumped `@tanstack/react-query` from `5.85.5` to `5.85.9` to incorporate the latest improvements.
- Updated `ai` from `5.0.28` to `5.0.30` for better performance.
- Incremented `nodemailer` from `7.0.5` to `7.0.6` for stability.
- Updated `typescript-eslint` from `8.41.0` to `8.42.0` for improved type definitions and linting capabilities.
- Adjusted various package dependencies across multiple components to ensure compatibility and stability.

* chore(dependencies): update package versions for improved compatibility

- Upgraded `@ai-sdk/openai` from `2.0.23` to `2.0.24` for enhanced functionality.
- Bumped `@tanstack/react-query` from `5.85.9` to `5.86.0` to incorporate the latest improvements.
- Updated `ai` from `5.0.30` to `5.0.33` for better performance.
- Incremented `@types/node` from `24.3.0` to `24.3.1` for type safety enhancements.
- Updated `dotenv` from `17.2.1` to `17.2.2` for stability.
- Adjusted `tailwindcss` and related packages to `4.1.13` for improved styling capabilities.
- Updated `react-i18next` from `15.7.3` to `15.7.3` to include the latest localization fixes.
- Incremented `@sentry/nextjs` from `10.8.0` to `10.10.0` for enhanced monitoring features.
- Updated various package dependencies across multiple components to ensure compatibility and stability.

* fix(config): conditionally disable `devIndicators` in CI environment

* feat(settings): encapsulate danger zone actions in a styled card component

- Introduced a new `DangerZoneCard` component to enhance the visual presentation of danger zone actions in the team account settings.
- Updated `TeamAccountDangerZone` to wrap deletion and leave actions within the `DangerZoneCard` for improved user experience.
- Removed redundant card structure from `TeamAccountSettingsContainer` to streamline the component hierarchy.

* fix(e2e): improve admin account tests for response handling and visibility checks

- Enhanced the admin test suite by adding a check for the POST request method when waiting for the response from the `/admin/accounts` endpoint.
- Reduced wait times in the `filterAccounts` function for improved test performance.
- Updated the `selectAccount` function to ensure the account link is visible before clicking, enhancing reliability in the test flow.

* chore(dependencies): update package versions for improved compatibility

- Upgraded `@supabase/supabase-js` from `2.57.0` to `2.57.2` for enhanced functionality and performance.
- Bumped `@tanstack/react-query` from `5.86.0` to `5.87.1` to incorporate the latest improvements.
- Updated `i18next` from `25.5.1` to `25.5.2` for better localization support.
- Incremented `eslint` from `9.34.0` to `9.35.0` for improved linting capabilities.
- Adjusted various package dependencies across multiple components to ensure compatibility and stability.

* feat(admin): enhance user ban and reactivation actions with success handling

- Updated `AdminBanUserDialog` and `AdminReactivateUserDialog` components to handle success states based on the results of the respective actions.
- Modified `banUserAction` and `reactivateUserAction` to return success status and log errors if the actions fail.
- Introduced `revalidatePage` function to refresh the user account page after banning or reactivating a user.
- Improved error handling in the dialogs to provide better feedback to the admin user.

* feat(admin): refactor user ban and reactivation dialogs for improved structure and error handling

- Introduced `BanUserForm` and `ReactivateUserForm` components to encapsulate form logic within the respective dialogs, enhancing readability and maintainability.
- Updated the `AdminBanUserDialog` and `AdminReactivateUserDialog` components to utilize the new form components, streamlining the user interface.
- Enhanced error handling to provide clearer feedback to the admin user during ban and reactivation actions.
- Removed unnecessary revalidation calls in the server actions to optimize performance and maintain clarity in the action flow.
- Added `@types/react-dom` dependency for improved type definitions.

* refactor(admin): streamline user dialogs and server actions for improved clarity

- Removed unnecessary `useRouter` imports from `AdminBanUserDialog` and `AdminReactivateUserDialog` components to simplify the code.
- Updated `revalidateAdmin` function calls to use `revalidatePath` with specific paths, enhancing clarity in the server actions.
- Ensured that the user dialogs maintain a clean structure while focusing on form logic and error handling.
This commit is contained in:
Giancarlo Buomprisco
2025-09-06 17:30:09 +07:00
committed by GitHub
parent b3acbbe801
commit 9fae142f2d
37 changed files with 2293 additions and 2313 deletions

View File

@@ -37,17 +37,6 @@ export function AdminBanUserDialog(
userId: string;
}>,
) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(BanUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<AlertDialog>
<AlertDialogTrigger asChild>{props.children}</AlertDialogTrigger>
@@ -62,72 +51,86 @@ export function AdminBanUserDialog(
</AlertDialogDescription>
</AlertDialogHeader>
<Form {...form}>
<form
data-test={'admin-ban-user-form'}
className={'flex flex-col space-y-8'}
onSubmit={form.handleSubmit((data) => {
startTransition(async () => {
try {
await banUserAction(data);
setError(false);
} catch {
setError(true);
}
});
})}
>
<If condition={error}>
<Alert variant={'destructive'}>
<AlertTitle>Error</AlertTitle>
<AlertDescription>
There was an error banning the user. Please check the server
logs to see what went wrong.
</AlertDescription>
</Alert>
</If>
<FormField
name={'confirmation'}
render={({ field }) => (
<FormItem>
<FormLabel>
Type <b>CONFIRM</b> to confirm
</FormLabel>
<FormControl>
<Input
required
pattern={'CONFIRM'}
placeholder={'Type CONFIRM to confirm'}
{...field}
/>
</FormControl>
<FormDescription>
Are you sure you want to do this?
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<Button
disabled={pending}
type={'submit'}
variant={'destructive'}
>
Ban User
</Button>
</AlertDialogFooter>
</form>
</Form>
<BanUserForm userId={props.userId} />
</AlertDialogContent>
</AlertDialog>
);
}
function BanUserForm(props: { userId: string }) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(BanUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<Form {...form}>
<form
data-test={'admin-ban-user-form'}
className={'flex flex-col space-y-8'}
onSubmit={form.handleSubmit((data) => {
startTransition(async () => {
try {
const result = await banUserAction(data);
setError(!result.success);
} catch {
setError(true);
}
});
})}
>
<If condition={error}>
<Alert variant={'destructive'}>
<AlertTitle>Error</AlertTitle>
<AlertDescription>
There was an error banning the user. Please check the server logs
to see what went wrong.
</AlertDescription>
</Alert>
</If>
<FormField
name={'confirmation'}
render={({ field }) => (
<FormItem>
<FormLabel>
Type <b>CONFIRM</b> to confirm
</FormLabel>
<FormControl>
<Input
required
pattern={'CONFIRM'}
placeholder={'Type CONFIRM to confirm'}
{...field}
/>
</FormControl>
<FormDescription>
Are you sure you want to do this?
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<AlertDialogFooter>
<AlertDialogCancel disabled={pending}>Cancel</AlertDialogCancel>
<Button disabled={pending} type={'submit'} variant={'destructive'}>
{pending ? 'Banning...' : 'Ban User'}
</Button>
</AlertDialogFooter>
</form>
</Form>
);
}

View File

@@ -37,17 +37,6 @@ export function AdminReactivateUserDialog(
userId: string;
}>,
) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(ReactivateUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<AlertDialog>
<AlertDialogTrigger asChild>{props.children}</AlertDialogTrigger>
@@ -61,68 +50,86 @@ export function AdminReactivateUserDialog(
</AlertDialogDescription>
</AlertDialogHeader>
<Form {...form}>
<form
data-test={'admin-reactivate-user-form'}
className={'flex flex-col space-y-8'}
onSubmit={form.handleSubmit((data) => {
startTransition(async () => {
try {
await reactivateUserAction(data);
setError(false);
} catch {
setError(true);
}
});
})}
>
<If condition={error}>
<Alert variant={'destructive'}>
<AlertTitle>Error</AlertTitle>
<AlertDescription>
There was an error reactivating the user. Please check the
server logs to see what went wrong.
</AlertDescription>
</Alert>
</If>
<FormField
name={'confirmation'}
render={({ field }) => (
<FormItem>
<FormLabel>
Type <b>CONFIRM</b> to confirm
</FormLabel>
<FormControl>
<Input
required
pattern={'CONFIRM'}
placeholder={'Type CONFIRM to confirm'}
{...field}
/>
</FormControl>
<FormDescription>
Are you sure you want to do this?
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<Button disabled={pending} type={'submit'}>
{pending ? 'Reactivating...' : 'Reactivate User'}
</Button>
</AlertDialogFooter>
</form>
</Form>
<ReactivateUserForm userId={props.userId} />
</AlertDialogContent>
</AlertDialog>
);
}
function ReactivateUserForm(props: { userId: string }) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(ReactivateUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<Form {...form}>
<form
data-test={'admin-reactivate-user-form'}
className={'flex flex-col space-y-8'}
onSubmit={form.handleSubmit((data) => {
startTransition(async () => {
try {
const result = await reactivateUserAction(data);
setError(!result.success);
} catch {
setError(true);
}
});
})}
>
<If condition={error}>
<Alert variant={'destructive'}>
<AlertTitle>Error</AlertTitle>
<AlertDescription>
There was an error reactivating the user. Please check the server
logs to see what went wrong.
</AlertDescription>
</Alert>
</If>
<FormField
name={'confirmation'}
render={({ field }) => (
<FormItem>
<FormLabel>
Type <b>CONFIRM</b> to confirm
</FormLabel>
<FormControl>
<Input
required
pattern={'CONFIRM'}
placeholder={'Type CONFIRM to confirm'}
{...field}
/>
</FormControl>
<FormDescription>
Are you sure you want to do this?
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<AlertDialogFooter>
<AlertDialogCancel disabled={pending}>Cancel</AlertDialogCancel>
<Button disabled={pending} type={'submit'}>
{pending ? 'Reactivating...' : 'Reactivate User'}
</Button>
</AlertDialogFooter>
</form>
</Form>
);
}

View File

@@ -33,7 +33,15 @@ export const banUserAction = adminAction(
logger.info({ userId }, `Super Admin is banning user...`);
await service.banUser(userId);
const { error } = await service.banUser(userId);
if (error) {
logger.error({ error }, `Error banning user`);
return {
success: false,
};
}
logger.info({ userId }, `Super Admin has successfully banned user`);
@@ -61,12 +69,20 @@ export const reactivateUserAction = adminAction(
logger.info({ userId }, `Super Admin is reactivating user...`);
await service.reactivateUser(userId);
const { error } = await service.reactivateUser(userId);
logger.info({ userId }, `Super Admin has successfully reactivated user`);
if (error) {
logger.error({ error }, `Error reactivating user`);
return {
success: false,
};
}
revalidateAdmin();
logger.info({ userId }, `Super Admin has successfully reactivated user`);
return {
success: true,
};
@@ -113,8 +129,6 @@ export const deleteUserAction = adminAction(
logger.info({ userId }, `Super Admin has successfully deleted user`);
revalidateAdmin();
return redirect('/admin/accounts');
},
{
@@ -137,13 +151,13 @@ export const deleteAccountAction = adminAction(
await service.deleteAccount(accountId);
revalidateAdmin();
logger.info(
{ accountId },
`Super Admin has successfully deleted account`,
);
revalidateAdmin();
return redirect('/admin/accounts');
},
{
@@ -180,7 +194,7 @@ export const createUserAction = adminAction(
`Super Admin has successfully created a new user`,
);
revalidateAdmin();
revalidatePath(`/admin/accounts`);
return {
success: true,
@@ -212,8 +226,6 @@ export const resetPasswordAction = adminAction(
`Super Admin has successfully sent password reset email`,
);
revalidateAdmin();
return result;
},
{
@@ -223,7 +235,7 @@ export const resetPasswordAction = adminAction(
);
function revalidateAdmin() {
revalidatePath('/admin', 'layout');
revalidatePath(`/admin/accounts/[id]`, 'page');
}
function getAdminAuthService() {

View File

@@ -153,7 +153,7 @@ class AdminAuthUserService {
}
private async setBanDuration(userId: string, banDuration: string) {
await this.adminClient.auth.admin.updateUserById(userId, {
return this.adminClient.auth.admin.updateUserById(userId, {
ban_duration: banDuration,
});
}