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:
committed by
GitHub
parent
b3acbbe801
commit
9fae142f2d
@@ -17,7 +17,7 @@
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@types/node": "^24.3.0"
|
||||
"@types/node": "^24.3.1"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@types/react": "19.1.12",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-react": "^0.542.0",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"./components": "./src/components/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stripe/react-stripe-js": "^3.9.2",
|
||||
"@stripe/react-stripe-js": "^4.0.0",
|
||||
"@stripe/stripe-js": "^7.9.0",
|
||||
"stripe": "^18.5.0"
|
||||
},
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/wordpress": "workspace:*",
|
||||
"@types/node": "^24.3.0"
|
||||
"@types/node": "^24.3.1"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@types/node": "^24.3.0",
|
||||
"@types/node": "^24.3.1",
|
||||
"@types/react": "19.1.12",
|
||||
"react": "19.1.1",
|
||||
"zod": "^3.25.74"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@types/node": "^24.3.0",
|
||||
"@types/node": "^24.3.1",
|
||||
"@types/react": "19.1.12",
|
||||
"wp-types": "^4.68.1"
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/team-accounts": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"zod": "^3.25.74"
|
||||
},
|
||||
"typesVersions": {
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"@types/react": "19.1.12",
|
||||
"@types/react-dom": "19.1.9",
|
||||
"lucide-react": "^0.542.0",
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
"@kit/ui": "workspace:*",
|
||||
"@makerkit/data-loader-supabase-core": "^0.0.10",
|
||||
"@makerkit/data-loader-supabase-nextjs": "^1.2.5",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"@types/react": "19.1.12",
|
||||
"lucide-react": "^0.542.0",
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
"@kit/ui": "workspace:*",
|
||||
"@marsidev/react-turnstile": "^1.3.0",
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"@types/react": "19.1.12",
|
||||
"lucide-react": "^0.542.0",
|
||||
"next": "15.5.2",
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"@types/react": "19.1.12",
|
||||
"lucide-react": "^0.542.0",
|
||||
"react": "19.1.1",
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"@types/react": "19.1.12",
|
||||
"@types/react-dom": "19.1.9",
|
||||
|
||||
@@ -21,6 +21,13 @@ import {
|
||||
AlertDialogTrigger,
|
||||
} from '@kit/ui/alert-dialog';
|
||||
import { Button } from '@kit/ui/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@kit/ui/card';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -64,7 +71,11 @@ export function TeamAccountDangerZone({
|
||||
|
||||
if (userIsPrimaryOwner) {
|
||||
if (features.enableTeamDeletion) {
|
||||
return <DeleteTeamContainer account={account} />;
|
||||
return (
|
||||
<DangerZoneCard>
|
||||
<DeleteTeamContainer account={account} />
|
||||
</DangerZoneCard>
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -72,7 +83,11 @@ export function TeamAccountDangerZone({
|
||||
|
||||
// A primary owner can't leave the team account
|
||||
// but other members can
|
||||
return <LeaveTeamContainer account={account} />;
|
||||
return (
|
||||
<DangerZoneCard>
|
||||
<LeaveTeamContainer account={account} />
|
||||
</DangerZoneCard>
|
||||
);
|
||||
}
|
||||
|
||||
function DeleteTeamContainer(props: {
|
||||
@@ -411,3 +426,21 @@ function DeleteTeamErrorAlert() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DangerZoneCard({ children }: React.PropsWithChildren) {
|
||||
return (
|
||||
<Card className={'border-destructive border'}>
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
<Trans i18nKey={'teams:settings.dangerZone'} />
|
||||
</CardTitle>
|
||||
|
||||
<CardDescription>
|
||||
<Trans i18nKey={'teams:settings.dangerZoneDescription'} />
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>{children}</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,25 +67,11 @@ export function TeamAccountSettingsContainer(props: {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className={'border-destructive border'}>
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
<Trans i18nKey={'teams:settings.dangerZone'} />
|
||||
</CardTitle>
|
||||
|
||||
<CardDescription>
|
||||
<Trans i18nKey={'teams:settings.dangerZoneDescription'} />
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<TeamAccountDangerZone
|
||||
primaryOwnerUserId={props.account.primaryOwnerUserId}
|
||||
account={props.account}
|
||||
features={props.features}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<TeamAccountDangerZone
|
||||
primaryOwnerUserId={props.account.primaryOwnerUserId}
|
||||
account={props.account}
|
||||
features={props.features}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"next": "15.5.2",
|
||||
"react": "19.1.1",
|
||||
"react-dom": "19.1.1",
|
||||
"react-i18next": "^15.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"i18next": "25.4.2",
|
||||
"i18next": "25.5.2",
|
||||
"i18next-browser-languagedetector": "8.2.0",
|
||||
"i18next-resources-to-backend": "^1.2.1"
|
||||
},
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@kit/resend": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@types/node": "^24.3.0",
|
||||
"@types/node": "^24.3.1",
|
||||
"zod": "^3.25.74"
|
||||
},
|
||||
"typesVersions": {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"nodemailer": "^7.0.5"
|
||||
"nodemailer": "^7.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"@kit/mailers-shared": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@types/node": "^24.3.0",
|
||||
"@types/node": "^24.3.1",
|
||||
"zod": "^3.25.74"
|
||||
},
|
||||
"typesVersions": {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"./config/server": "./src/sentry.client.server.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/nextjs": "^10.8.0",
|
||||
"@sentry/nextjs": "^10.10.0",
|
||||
"import-in-the-middle": "1.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"next": "15.5.2",
|
||||
"zod": "^3.25.74"
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@types/react": "19.1.12",
|
||||
"@types/react-dom": "19.1.9",
|
||||
"react": "19.1.1",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"@types/react": "19.1.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"pino": "^9.8.0"
|
||||
"pino": "^9.9.4"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@supabase/ssr": "^0.7.0",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"@types/react": "19.1.12",
|
||||
"next": "15.5.2",
|
||||
"react": "19.1.1",
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@supabase/supabase-js": "2.55.0",
|
||||
"@tanstack/react-query": "5.85.5",
|
||||
"@supabase/supabase-js": "2.57.2",
|
||||
"@tanstack/react-query": "5.87.1",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"@types/react": "19.1.12",
|
||||
"@types/react-dom": "19.1.9",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"eslint": "^9.34.0",
|
||||
"eslint": "^9.35.0",
|
||||
"next": "15.5.2",
|
||||
"next-themes": "0.4.6",
|
||||
"prettier": "^3.6.2",
|
||||
@@ -40,7 +40,7 @@
|
||||
"react-hook-form": "^7.62.0",
|
||||
"react-i18next": "^15.7.3",
|
||||
"sonner": "^2.0.7",
|
||||
"tailwindcss": "4.1.12",
|
||||
"tailwindcss": "4.1.13",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript": "^5.9.2",
|
||||
"zod": "^3.25.74"
|
||||
|
||||
@@ -364,12 +364,12 @@ export function DataTable<RecordData extends DataItem>({
|
||||
? 'hover:bg-accent/50 -mx-3 cursor-pointer rounded px-3 py-1 select-none'
|
||||
: '',
|
||||
)}
|
||||
onClick={header.column.getToggleSortingHandler()}
|
||||
>
|
||||
{flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext(),
|
||||
)}
|
||||
|
||||
{header.column.getCanSort() && (
|
||||
<div className="flex flex-col">
|
||||
<ChevronUp
|
||||
@@ -503,7 +503,6 @@ export function DataTable<RecordData extends DataItem>({
|
||||
<div className={'px-2.5 py-1.5'}>
|
||||
<Pagination
|
||||
table={table}
|
||||
pageSize={pageSize}
|
||||
totalCount={
|
||||
pageCount && pageSize ? pageCount * pageSize : undefined
|
||||
}
|
||||
@@ -519,19 +518,26 @@ export function DataTable<RecordData extends DataItem>({
|
||||
function Pagination<T>({
|
||||
table,
|
||||
totalCount,
|
||||
pageSize,
|
||||
}: React.PropsWithChildren<{
|
||||
table: ReactTable<T>;
|
||||
totalCount?: number;
|
||||
pageSize?: number;
|
||||
}>) {
|
||||
const currentPageIndex = table.getState().pagination.pageIndex;
|
||||
const currentPageSize = table.getState().pagination.pageSize;
|
||||
const rows = table.getRowModel().rows;
|
||||
|
||||
// Calculate what records are being shown on this page
|
||||
const startRecord = currentPageIndex * currentPageSize + 1;
|
||||
const endRecord = startRecord + rows.length - 1;
|
||||
|
||||
return (
|
||||
<div className="flex items-center space-x-4">
|
||||
<span className="text-muted-foreground flex items-center text-xs">
|
||||
<Trans
|
||||
i18nKey={'common:pageOfPages'}
|
||||
values={{
|
||||
page: table.getState().pagination.pageIndex + 1,
|
||||
page: currentPageIndex + 1,
|
||||
total: table.getPageCount(),
|
||||
}}
|
||||
/>
|
||||
@@ -583,12 +589,9 @@ function Pagination<T>({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<If condition={totalCount}>
|
||||
<If condition={totalCount && rows.length > 0}>
|
||||
<span className="text-muted-foreground flex items-center text-xs">
|
||||
<Trans
|
||||
i18nKey={'common:showingRecordCount'}
|
||||
values={{ totalCount, pageSize }}
|
||||
/>
|
||||
Showing {startRecord} to {endRecord} of {totalCount} rows
|
||||
</span>
|
||||
</If>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user